提交 db7bd5f8 编写于 作者: C Camille GILLOT

Fallout in other crates.

上级 6624dc40
......@@ -50,7 +50,7 @@
//! fingerprint for a given set of node parameters.
use crate::hir::map::DefPathHash;
use crate::ich::{Fingerprint, StableHashingContext};
use crate::ich::Fingerprint;
use crate::mir;
use crate::mir::interpret::{GlobalId, LitToConstInput};
use crate::traits;
......@@ -62,13 +62,13 @@
use crate::ty::subst::SubstsRef;
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::HirId;
use rustc_span::symbol::Symbol;
use std::fmt;
use std::hash::Hash;
pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
// erase!() just makes tokens go away. It's used to specify which macro argument
// is repeated (i.e., which sub-expression of the macro we are in) but don't need
// to actually use any of the arguments.
......@@ -128,7 +128,7 @@ pub fn can_reconstruct_query_key<$tcx>(&self) -> bool {
// tuple args
$({
return <$tuple_arg_ty as DepNodeParams>
return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
::CAN_RECONSTRUCT_QUERY_KEY;
})*
......@@ -212,20 +212,27 @@ pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
)*
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
RustcEncodable, RustcDecodable)]
pub struct DepNode {
pub kind: DepKind,
pub hash: Fingerprint,
pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
pub trait DepNodeExt: Sized {
/// Construct a DepNode from the given DepKind and DefPathHash. This
/// method will assert that the given DepKind actually requires a
/// single DefId/DefPathHash parameter.
fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
/// Used in testing
fn from_label_string(label: &str, def_path_hash: DefPathHash)
-> Result<Self, ()>;
/// Used in testing
fn has_label_string(label: &str) -> bool;
}
impl DepNode {
impl DepNodeExt for DepNode {
/// Construct a DepNode from the given DepKind and DefPathHash. This
/// method will assert that the given DepKind actually requires a
/// single DefId/DefPathHash parameter.
pub fn from_def_path_hash(def_path_hash: DefPathHash,
kind: DepKind)
-> DepNode {
fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
DepNode {
kind,
......@@ -233,17 +240,6 @@ pub fn from_def_path_hash(def_path_hash: DefPathHash,
}
}
/// Creates a new, parameterless DepNode. This method will assert
/// that the DepNode corresponding to the given DepKind actually
/// does not require any parameters.
pub fn new_no_params(kind: DepKind) -> DepNode {
debug_assert!(!kind.has_params());
DepNode {
kind,
hash: Fingerprint::ZERO,
}
}
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
///
......@@ -254,20 +250,8 @@ pub fn new_no_params(kind: DepKind) -> DepNode {
/// DepNode. Condition (2) might not be fulfilled if a DepNode
/// refers to something from the previous compilation session that
/// has been removed.
pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
if self.kind.can_reconstruct_query_key() {
let def_path_hash = DefPathHash(self.hash);
tcx.def_path_hash_to_def_id.as_ref()?
.get(&def_path_hash).cloned()
} else {
None
}
}
/// Used in testing
pub fn from_label_string(label: &str,
def_path_hash: DefPathHash)
-> Result<DepNode, ()> {
fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
let kind = match label {
$(
stringify!($variant) => DepKind::$variant,
......@@ -287,7 +271,7 @@ pub fn from_label_string(label: &str,
}
/// Used in testing
pub fn has_label_string(label: &str) -> bool {
fn has_label_string(label: &str) -> bool {
match label {
$(
stringify!($variant) => true,
......@@ -308,35 +292,6 @@ pub mod label_strs {
);
}
impl fmt::Debug for DepNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.kind)?;
if !self.kind.has_params() && !self.kind.is_anon() {
return Ok(());
}
write!(f, "(")?;
crate::ty::tls::with_opt(|opt_tcx| {
if let Some(tcx) = opt_tcx {
if let Some(def_id) = self.extract_def_id(tcx) {
write!(f, "{}", tcx.def_path_debug_str(def_id))?;
} else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) {
write!(f, "{}", s)?;
} else {
write!(f, "{}", self.hash)?;
}
} else {
write!(f, "{}", self.hash)?;
}
Ok(())
})?;
write!(f, ")")
}
}
rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
// We use this for most things when incr. comp. is turned off.
[] Null,
......@@ -349,58 +304,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
[] CompileCodegenUnit(Symbol),
]);
pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
const CAN_RECONSTRUCT_QUERY_KEY: bool;
/// This method turns the parameters of a DepNodeConstructor into an opaque
/// Fingerprint to be used in DepNode.
/// Not all DepNodeParams support being turned into a Fingerprint (they
/// don't need to if the corresponding DepNode is anonymous).
fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
panic!("Not implemented. Accidentally called on anonymous node?")
}
fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
format!("{:?}", self)
}
/// This method tries to recover the query key from the given `DepNode`,
/// something which is needed when forcing `DepNode`s during red-green
/// evaluation. The query system will only call this method if
/// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
/// It is always valid to return `None` here, in which case incremental
/// compilation will treat the query as having changed instead of forcing it.
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
}
impl<'tcx, T> DepNodeParams<'tcx> for T
where
T: HashStable<StableHashingContext<'tcx>> + fmt::Debug,
{
default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let mut hcx = tcx.create_stable_hashing_context();
let mut hasher = StableHasher::new();
self.hash_stable(&mut hcx, &mut hasher);
hasher.finish()
}
default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
format!("{:?}", *self)
}
default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
None
}
}
impl<'tcx> DepNodeParams<'tcx> for DefId {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.def_path_hash(*self).0
}
......@@ -409,14 +316,14 @@ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
}
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx)
tcx.extract_def_id(dep_node)
}
}
impl<'tcx> DepNodeParams<'tcx> for LocalDefId {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
self.to_def_id().to_fingerprint(tcx)
}
......@@ -425,14 +332,14 @@ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
}
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx).map(|id| id.expect_local())
tcx.extract_def_id(dep_node).map(|id| id.expect_local())
}
}
impl<'tcx> DepNodeParams<'tcx> for CrateNum {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
tcx.def_path_hash(def_id).0
}
......@@ -442,17 +349,17 @@ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
}
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx).map(|id| id.krate)
tcx.extract_def_id(dep_node).map(|id| id.krate)
}
}
impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
// We actually would not need to specialize the implementation of this
// method but it's faster to combine the hashes than to instantiate a full
// hashing context and stable-hashing state.
fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let (def_id_0, def_id_1) = *self;
let def_path_hash_0 = tcx.def_path_hash(def_id_0);
......@@ -468,13 +375,13 @@ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
}
}
impl<'tcx> DepNodeParams<'tcx> for HirId {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
// We actually would not need to specialize the implementation of this
// method but it's faster to combine the hashes than to instantiate a full
// hashing context and stable-hashing state.
fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let HirId { owner, local_id } = *self;
let def_path_hash = tcx.def_path_hash(owner.to_def_id());
......@@ -483,27 +390,3 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
def_path_hash.0.combine(local_id)
}
}
/// A "work product" corresponds to a `.o` (or other) file that we
/// save in between runs. These IDs do not have a `DefId` but rather
/// some independent path or string that persists between runs without
/// the need to be mapped or unmapped. (This ensures we can serialize
/// them even in the absence of a tcx.)
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable)]
pub struct WorkProductId {
hash: Fingerprint,
}
impl WorkProductId {
pub fn from_cgu_name(cgu_name: &str) -> WorkProductId {
let mut hasher = StableHasher::new();
cgu_name.len().hash(&mut hasher);
cgu_name.hash(&mut hasher);
WorkProductId { hash: hasher.finish() }
}
pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId {
WorkProductId { hash: fingerprint }
}
}
use crate::hir::map::definitions::DefPathHash;
use crate::ich::StableHashingContext;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::DefId;
mod dep_node;
mod safe;
pub(crate) use rustc_query_system::dep_graph::DepNodeParams;
pub use rustc_query_system::dep_graph::{
debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex,
WorkProduct, WorkProductFileKind, WorkProductId,
};
pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt};
pub use safe::AssertDepGraphSafe;
pub use safe::DepGraphSafe;
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph<DepKind>;
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
impl rustc_query_system::dep_graph::DepKind for DepKind {
fn is_eval_always(&self) -> bool {
DepKind::is_eval_always(self)
}
fn has_params(&self) -> bool {
DepKind::has_params(self)
}
fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", node.kind)?;
if !node.kind.has_params() && !node.kind.is_anon() {
return Ok(());
}
write!(f, "(")?;
ty::tls::with_opt(|opt_tcx| {
if let Some(tcx) = opt_tcx {
if let Some(def_id) = tcx.extract_def_id(node) {
write!(f, "{}", tcx.def_path_debug_str(def_id))?;
} else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*node) {
write!(f, "{}", s)?;
} else {
write!(f, "{}", node.hash)?;
}
} else {
write!(f, "{}", node.hash)?;
}
Ok(())
})?;
write!(f, ")")
}
fn assert_ignored() {
ty::tls::with_context_opt(|icx| {
let icx = if let Some(icx) = icx { icx } else { return };
assert!(icx.task_deps.is_none(), "expected no task dependency tracking");
})
}
fn with_ignore_deps<OP, R>(op: OP) -> R
where
OP: FnOnce() -> R,
{
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt { task_deps: None, ..icx.clone() };
ty::tls::enter_context(&icx, |_| op())
})
}
fn with_deps<OP, R>(task_deps: Option<&Lock<TaskDeps>>, op: OP) -> R
where
OP: FnOnce() -> R,
{
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() };
ty::tls::enter_context(&icx, |_| op())
})
}
fn read_deps<OP>(op: OP) -> ()
where
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps>>) -> (),
{
ty::tls::with_context_opt(|icx| {
let icx = if let Some(icx) = icx { icx } else { return };
op(icx.task_deps)
})
}
}
impl<'tcx> DepContext for TyCtxt<'tcx> {
type DepKind = DepKind;
type StableHashingContext = StableHashingContext<'tcx>;
fn create_stable_hashing_context(&self) -> Self::StableHashingContext {
TyCtxt::create_stable_hashing_context(*self)
}
fn force_from_dep_node(&self, node: &DepNode) -> bool {
ty::query::force_from_dep_node(*self, node)
}
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
///
/// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
/// 2. the item that the DefPath refers to exists in the current tcx.
///
/// Condition (1) is determined by the DepKind variant of the
/// DepNode. Condition (2) might not be fulfilled if a DepNode
/// refers to something from the previous compilation session that
/// has been removed.
fn extract_def_id(&self, node: &DepNode) -> Option<DefId> {
if node.kind.can_reconstruct_query_key() {
let def_path_hash = DefPathHash(node.hash);
self.def_path_hash_to_def_id.as_ref()?.get(&def_path_hash).cloned()
} else {
None
}
}
fn ensure_node_can_be_forced(&self, dep_dep_node: &DepNode) -> Option<()> {
// FIXME: This match is just a workaround for incremental bugs and should
// be removed. https://github.com/rust-lang/rust/issues/62649 is one such
// bug that must be fixed before removing this.
match dep_dep_node.kind {
DepKind::hir_owner | DepKind::hir_owner_nodes | DepKind::CrateMetadata => {
if let Some(def_id) = self.extract_def_id(dep_dep_node) {
if def_id_corresponds_to_hir_dep_node(*self, def_id) {
if dep_dep_node.kind == DepKind::CrateMetadata {
// The `DefPath` has corresponding node,
// and that node should have been marked
// either red or green in `data.colors`.
bug!(
"DepNode {:?} should have been \
pre-marked as red or green but wasn't.",
dep_dep_node
);
}
} else {
// This `DefPath` does not have a
// corresponding `DepNode` (e.g. a
// struct field), and the ` DefPath`
// collided with the `DefPath` of a
// proper item that existed in the
// previous compilation session.
//
// Since the given `DefPath` does not
// denote the item that previously
// existed, we just fail to mark green.
return None;
}
} else {
// If the node does not exist anymore, we
// just fail to mark green.
return None;
}
}
_ => {
// For other kinds of nodes it's OK to be
// forced.
}
}
Some(())
}
fn has_errors_or_delayed_span_bugs(&self) -> bool {
self.sess.has_errors_or_delayed_span_bugs()
}
fn diagnostic(&self) -> &rustc_errors::Handler {
self.sess.diagnostic()
}
// Interactions with on_disk_cache
fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) {
use crate::mir::interpret::GlobalId;
use crate::ty::query::queries;
use crate::ty::query::QueryDescription;
rustc_dep_node_try_load_from_on_disk_cache!(dep_node, *self)
}
fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
self.queries.on_disk_cache.load_diagnostics(*self, prev_dep_node_index)
}
fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<Diagnostic>) {
self.queries.on_disk_cache.store_diagnostics(dep_node_index, diagnostics)
}
fn profiler(&self) -> &SelfProfilerRef {
&self.prof
}
}
fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
def_id.index == hir_id.owner.local_def_index
}
impl rustc_query_system::HashStableContext for StableHashingContext<'_> {
fn debug_dep_tasks(&self) -> bool {
self.sess().opts.debugging_opts.dep_tasks
}
}
impl rustc_query_system::HashStableContextProvider<StableHashingContext<'tcx>> for TyCtxt<'tcx> {
fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> {
self.create_stable_hashing_context()
}
}
impl rustc_query_system::HashStableContextProvider<StableHashingContext<'a>>
for StableHashingContext<'a>
{
fn get_stable_hashing_context(&self) -> Self {
self.clone()
}
}
//! The `DepGraphSafe` trait
use crate::ty::TyCtxt;
pub use rustc_query_system::dep_graph::{AssertDepGraphSafe, DepGraphSafe};
/// The type context itself can be used to access all kinds of tracked
/// state, but those accesses should always generate read events.
impl<'tcx> DepGraphSafe for TyCtxt<'tcx> {}
......@@ -191,16 +191,3 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool
false
}
impl DepNode {
/// Check whether the query invocation corresponding to the given
/// DepNode is eligible for on-disk-caching. If so, this is method
/// will execute the query corresponding to the given DepNode.
/// Also, as a sanity check, it expects that the corresponding query
/// invocation has been marked as green already.
pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
use crate::dep_graph::DepKind;
rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
}
}
......@@ -35,7 +35,7 @@
use graphviz as dot;
use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter};
use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode};
use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt};
use rustc::hir::map::Map;
use rustc::ty::TyCtxt;
use rustc_ast::ast;
......
......@@ -13,7 +13,7 @@
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
use rustc::dep_graph::{label_strs, DepNode};
use rustc::dep_graph::{label_strs, DepContext, DepNode, DepNodeExt};
use rustc::hir::map::Map;
use rustc::ty::TyCtxt;
use rustc_ast::ast::{self, Attribute, NestedMetaItem};
......@@ -382,7 +382,7 @@ fn dep_nodes<'l>(
}
fn dep_node_str(&self, dep_node: &DepNode) -> String {
if let Some(def_id) = dep_node.extract_def_id(self.tcx) {
if let Some(def_id) = self.tcx.extract_def_id(dep_node) {
format!("{:?}({})", dep_node.kind, self.tcx.def_path_str(def_id))
} else {
format!("{:?}({:?})", dep_node.kind, dep_node.hash)
......
......@@ -430,13 +430,13 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
try_load_from_on_disk_cache_stream.extend(quote! {
DepKind::#name => {
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
debug_assert!($tcx.dep_graph
.node_color($dep_node)
.map(|c| c.is_green())
.unwrap_or(false));
let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap();
let key = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node).unwrap();
if queries::#name::cache_on_disk($tcx, key, None) {
let _ = $tcx.#name(key);
}
......@@ -487,8 +487,8 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
// Add a match arm to force the query given the dep node
dep_node_force_stream.extend(quote! {
DepKind::#name => {
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
$tcx.force_query::<crate::ty::query::queries::#name<'_>>(
key,
DUMMY_SP,
......
......@@ -4,7 +4,7 @@
use crate::rmeta::table::{FixedSizeEncoding, Table};
use crate::rmeta::*;
use rustc::dep_graph::{self, DepNode, DepNodeIndex};
use rustc::dep_graph::{self, DepNode, DepNodeExt, DepNodeIndex};
use rustc::hir::exports::Export;
use rustc::middle::cstore::{CrateSource, ExternCrate};
use rustc::middle::cstore::{ForeignModule, LinkagePreference, NativeLibrary};
......
......@@ -126,19 +126,8 @@ impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
/// some independent path or string that persists between runs without
/// the need to be mapped or unmapped. (This ensures we can serialize
/// them even in the absence of a tcx.)
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
RustcEncodable,
RustcDecodable,
HashStable_Generic
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable_Generic)]
pub struct WorkProductId {
hash: Fingerprint,
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册