]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #41141 - michaelwoerister:direct-metadata-ich-final, r=nikomatsakis
authorTim Neumann <mail@timnn.me>
Wed, 12 Apr 2017 12:45:42 +0000 (14:45 +0200)
committerGitHub <noreply@github.com>
Wed, 12 Apr 2017 12:45:42 +0000 (14:45 +0200)
ICH: Replace old, transitive metadata hashing with direct hashing approach.

This PR replaces the old crate metadata hashing strategy with a new one that directly (but stably) hashes all values we encode into the metadata. Previously we would track what data got accessed during metadata encoding and then hash the input nodes (HIR and upstream metadata) that were transitively reachable from the accessed data. While this strategy was sound, it had two major downsides:

1. It was susceptible to generating false positives, i.e. some input node might have changed without actually affecting the content of the metadata. That metadata entry would still show up as changed.
2. It was susceptible to quadratic blow-up when many metadata nodes shared the same input nodes, which would then get hashed over and over again.

The new method does not have these disadvantages and it's also a first step towards caching more intermediate results in the compiler.

Metadata hashing/cross-crate incremental compilation is still kept behind the `-Zincremental-cc` flag even after this PR. Once the new method has proven itself with more tests, we can remove the flag and enable cross-crate support by default again.

r? @nikomatsakis
cc @rust-lang/compiler

36 files changed:
src/librustc/ich/hcx.rs
src/librustc/ich/impls_ty.rs
src/librustc/ich/mod.rs
src/librustc/lib.rs
src/librustc/middle/cstore.rs
src/librustc/middle/free_region.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/blake2b.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_driver/driver.rs
src/librustc_incremental/persist/data.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/preds/mod.rs
src/librustc_incremental/persist/save.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index_builder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/schema.rs
src/librustc_trans/back/link.rs
src/librustc_trans/base.rs
src/librustc_trans/lib.rs
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/extern_mods.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/hashes/trait_impls.rs
src/test/incremental/unchecked_dirty_clean_metadata.rs
src/tools/compiletest/src/runtest.rs

index 5ef30550f1155ec017d1eb3b713d248a85560807..3a6367c353c1eec7cdcc32a756281ef81c8f528e 100644 (file)
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty;
+use util::nodemap::NodeMap;
 
 use std::hash as std_hash;
+use std::collections::{HashMap, HashSet};
 
 use syntax::ast;
 use syntax::attr;
@@ -296,3 +298,53 @@ fn hash_stable<W: StableHasherResult>(&self,
         }
     }
 }
+
+pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                                        hasher: &mut StableHasher<W>,
+                                                        map: &HashMap<K, V, R>,
+                                                        extract_stable_key: F)
+    where K: Eq + std_hash::Hash,
+          V: HashStable<StableHashingContext<'a, 'tcx>>,
+          R: std_hash::BuildHasher,
+          SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
+          F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
+          W: StableHasherResult,
+{
+    let mut keys: Vec<_> = map.keys()
+                              .map(|k| (extract_stable_key(hcx, k), k))
+                              .collect();
+    keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
+    keys.len().hash_stable(hcx, hasher);
+    for (stable_key, key) in keys {
+        stable_key.hash_stable(hcx, hasher);
+        map[key].hash_stable(hcx, hasher);
+    }
+}
+
+pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                                     hasher: &mut StableHasher<W>,
+                                                     set: &HashSet<K, R>,
+                                                     extract_stable_key: F)
+    where K: Eq + std_hash::Hash,
+          R: std_hash::BuildHasher,
+          SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
+          F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
+          W: StableHasherResult,
+{
+    let mut keys: Vec<_> = set.iter()
+                              .map(|k| extract_stable_key(hcx, k))
+                              .collect();
+    keys.sort_unstable();
+    keys.hash_stable(hcx, hasher);
+}
+
+pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                           hasher: &mut StableHasher<W>,
+                                           map: &NodeMap<V>)
+    where V: HashStable<StableHashingContext<'a, 'tcx>>,
+          W: StableHasherResult,
+{
+    hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| {
+        hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
+    });
+}
index 7b6f3af2a11ec88582d572128185e17c029b4a43..46d1e7ef0c7c474a26a40ceb1d923bc3ceb6d425 100644 (file)
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::StableHashingContext;
+use ich::{self, StableHashingContext, NodeIdHashingMode};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
+use syntax_pos::symbol::InternedString;
 use ty;
 
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let type_hash = hcx.tcx().type_id_hash(*self);
-        type_hash.hash_stable(hcx, hasher);
-    }
-}
-
 impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
 
-impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for &'tcx ty::Slice<T>
     where T: HashStable<StableHashingContext<'a, 'tcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        (&**self).hash_stable(hcx, hasher);
+        (&self[..]).hash_stable(hcx, hasher);
     }
 }
 
@@ -67,9 +58,13 @@ fn hash_stable<W: StableHasherResult>(&self,
                 index.hash_stable(hcx, hasher);
                 name.hash_stable(hcx, hasher);
             }
+            ty::ReScope(code_extent) => {
+                code_extent.hash_stable(hcx, hasher);
+            }
+            ty::ReFree(ref free_region) => {
+                free_region.hash_stable(hcx, hasher);
+            }
             ty::ReLateBound(..) |
-            ty::ReFree(..) |
-            ty::ReScope(..) |
             ty::ReVar(..) |
             ty::ReSkolemized(..) => {
                 bug!("TypeIdHasher: unexpected region {:?}", *self)
@@ -127,7 +122,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     MutBorrow
 });
 
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
@@ -223,7 +217,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
     fn hash_stable<W: StableHasherResult>(&self,
                                           _: &mut StableHashingContext<'a, 'tcx>,
@@ -280,9 +273,14 @@ fn hash_stable<W: StableHasherResult>(&self,
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            ConstVal::Struct(ref _name_value_map) => {
-                // BTreeMap<ast::Name, ConstVal<'tcx>>),
-                panic!("Ordering still unstable")
+            ConstVal::Struct(ref name_value_map) => {
+                let mut values: Vec<(InternedString, &ConstVal)> =
+                    name_value_map.iter()
+                                  .map(|(name, val)| (name.as_str(), val))
+                                  .collect();
+
+                values.sort_unstable_by_key(|&(ref name, _)| name.clone());
+                values.hash_stable(hcx, hasher);
             }
             ConstVal::Tuple(ref value) => {
                 value.hash_stable(hcx, hasher);
@@ -303,7 +301,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 
-
 impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     parent,
     predicates
@@ -413,3 +410,265 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ty::DebruijnIndex {
     depth
 });
+
+impl_stable_hash_for!(enum ty::cast::CastKind {
+    CoercionCast,
+    PtrPtrCast,
+    PtrAddrCast,
+    AddrPtrCast,
+    NumericCast,
+    EnumCast,
+    PrimIntCast,
+    U8CharCast,
+    ArrayPtrCast,
+    FnPtrPtrCast,
+    FnPtrAddrCast
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            hcx.tcx().region_maps.code_extent_data(*self).hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use middle::region::CodeExtentData;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            CodeExtentData::Misc(node_id) |
+            CodeExtentData::DestructionScope(node_id) => {
+                node_id.hash_stable(hcx, hasher);
+            }
+            CodeExtentData::CallSiteScope { fn_id, body_id } |
+            CodeExtentData::ParameterScope { fn_id, body_id } => {
+                fn_id.hash_stable(hcx, hasher);
+                body_id.hash_stable(hcx, hasher);
+            }
+            CodeExtentData::Remainder(block_remainder) => {
+                block_remainder.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
+    block,
+    first_statement_index
+});
+
+impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
+    custom_kind
+});
+
+impl_stable_hash_for!(struct ty::FreeRegion {
+    scope,
+    bound_region
+});
+
+impl_stable_hash_for!(enum ty::BoundRegion {
+    BrAnon(index),
+    BrNamed(def_id, name),
+    BrFresh(index),
+    BrEnv
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeVariants<'tcx>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use ty::TypeVariants::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            TyBool  |
+            TyChar  |
+            TyStr   |
+            TyNever => {
+                // Nothing more to hash.
+            }
+            TyInt(int_ty) => {
+                int_ty.hash_stable(hcx, hasher);
+            }
+            TyUint(uint_ty) => {
+                uint_ty.hash_stable(hcx, hasher);
+            }
+            TyFloat(float_ty)  => {
+                float_ty.hash_stable(hcx, hasher);
+            }
+            TyAdt(adt_def, substs) => {
+                adt_def.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+            }
+            TyArray(inner_ty, len) => {
+                inner_ty.hash_stable(hcx, hasher);
+                len.hash_stable(hcx, hasher);
+            }
+            TySlice(inner_ty) => {
+                inner_ty.hash_stable(hcx, hasher);
+            }
+            TyRawPtr(pointee_ty) => {
+                pointee_ty.hash_stable(hcx, hasher);
+            }
+            TyRef(region, pointee_ty) => {
+                region.hash_stable(hcx, hasher);
+                pointee_ty.hash_stable(hcx, hasher);
+            }
+            TyFnDef(def_id, substs, ref sig) => {
+                def_id.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+                sig.hash_stable(hcx, hasher);
+            }
+            TyFnPtr(ref sig) => {
+                sig.hash_stable(hcx, hasher);
+            }
+            TyDynamic(ref existential_predicates, region) => {
+                existential_predicates.hash_stable(hcx, hasher);
+                region.hash_stable(hcx, hasher);
+            }
+            TyClosure(def_id, closure_substs) => {
+                def_id.hash_stable(hcx, hasher);
+                closure_substs.hash_stable(hcx, hasher);
+            }
+            TyTuple(inner_tys, from_diverging_type_var) => {
+                inner_tys.hash_stable(hcx, hasher);
+                from_diverging_type_var.hash_stable(hcx, hasher);
+            }
+            TyProjection(ref projection_ty) => {
+                projection_ty.hash_stable(hcx, hasher);
+            }
+            TyAnon(def_id, substs) => {
+                def_id.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+            }
+            TyParam(param_ty) => {
+                param_ty.hash_stable(hcx, hasher);
+            }
+
+            TyError     |
+            TyInfer(..) => {
+                bug!("ty::TypeVariants::hash_stable() - Unexpected variant.")
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ty::ParamTy {
+    idx,
+    name
+});
+
+impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
+    ty,
+    mutbl
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::ExistentialPredicate<'tcx>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            ty::ExistentialPredicate::Trait(ref trait_ref) => {
+                trait_ref.hash_stable(hcx, hasher);
+            }
+            ty::ExistentialPredicate::Projection(ref projection) => {
+                projection.hash_stable(hcx, hasher);
+            }
+            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                def_id.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> {
+    def_id,
+    substs
+});
+
+impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
+    trait_ref,
+    item_name,
+    ty
+});
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::TypeckTables {
+            ref type_relative_path_defs,
+            ref node_types,
+            ref item_substs,
+            ref adjustments,
+            ref method_map,
+            ref upvar_capture_map,
+            ref closure_tys,
+            ref closure_kinds,
+            ref liberated_fn_sigs,
+            ref fru_field_types,
+
+            ref cast_kinds,
+
+            // FIXME(#41184): This is still ignored at the moment.
+            lints: _,
+            ref used_trait_imports,
+            tainted_by_errors,
+            ref free_region_map,
+        } = *self;
+
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
+            ich::hash_stable_nodemap(hcx, hasher, node_types);
+            ich::hash_stable_nodemap(hcx, hasher, item_substs);
+            ich::hash_stable_nodemap(hcx, hasher, adjustments);
+
+            ich::hash_stable_hashmap(hcx, hasher, method_map, |hcx, method_call| {
+                let ty::MethodCall {
+                    expr_id,
+                    autoderef
+                } = *method_call;
+
+                let def_id = hcx.tcx().hir.local_def_id(expr_id);
+                (hcx.def_path_hash(def_id), autoderef)
+            });
+
+            ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
+                let ty::UpvarId {
+                    var_id,
+                    closure_expr_id
+                } = *up_var_id;
+
+                let var_def_id = hcx.tcx().hir.local_def_id(var_id);
+                let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id);
+                (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id))
+            });
+
+            ich::hash_stable_nodemap(hcx, hasher, closure_tys);
+            ich::hash_stable_nodemap(hcx, hasher, closure_kinds);
+            ich::hash_stable_nodemap(hcx, hasher, liberated_fn_sigs);
+            ich::hash_stable_nodemap(hcx, hasher, fru_field_types);
+            ich::hash_stable_nodemap(hcx, hasher, cast_kinds);
+
+            ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
+                hcx.def_path_hash(*def_id)
+            });
+
+            tainted_by_errors.hash_stable(hcx, hasher);
+            free_region_map.hash_stable(hcx, hasher);
+        })
+    }
+}
index f932c90a331e145509f86322f3692ee8cefcdf4c..d70ed051ac4107ad2d3b31ca3d8fc2c1ed6183ac 100644 (file)
@@ -12,8 +12,8 @@
 
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
-pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
-
+pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
+                    hash_stable_hashset, hash_stable_nodemap};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
index 3b002fd4dfc1a210e8445eb9e2cd8469beac0c68..1f96330d51da556241475daac6875ba2f84b9324 100644 (file)
@@ -42,6 +42,7 @@
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
+#![feature(sort_unstable)]
 
 extern crate arena;
 extern crate core;
index 694321812836b2b943cebea312515ab54118ec5a..81cf24e58dda4f52bbf3394bee721eae3358570a 100644 (file)
@@ -27,6 +27,7 @@
 use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
 use hir::svh::Svh;
+use ich;
 use middle::lang_items;
 use ty::{self, TyCtxt};
 use session::Session;
@@ -161,6 +162,20 @@ pub struct ExternCrate {
     pub path_len: usize,
 }
 
+pub struct EncodedMetadata {
+    pub raw_data: Vec<u8>,
+    pub hashes: Vec<EncodedMetadataHash>,
+}
+
+/// The hash for some metadata that (when saving) will be exported
+/// from this crate, or which (when importing) was exported by an
+/// upstream crate.
+#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub struct EncodedMetadataHash {
+    pub def_index: DefIndex,
+    pub hash: ich::Fingerprint,
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 pub trait CrateStore {
@@ -258,7 +273,8 @@ fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8>;
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata;
     fn metadata_encoding_version(&self) -> &[u8];
 }
 
@@ -417,7 +433,10 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8> { vec![] }
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata {
+        bug!("encode_metadata")
+    }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
 }
 
index cdb081ab40098655ab325fec2aa5bc29a0c2a3d2..a8eb6a1074383a5ece01e6fcdd7995c9629e89ef 100644 (file)
@@ -180,3 +180,7 @@ fn lub() {
     map.relate_free_regions(frs[1], frs[2]);
     assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2]));
 }
+
+impl_stable_hash_for!(struct FreeRegionMap {
+    relation
+});
index a2c356c20db09d563afa0e532dc964c39f139138..23f35d3bdd7929e262e1a56313ed7edf88dfe48d 100644 (file)
@@ -452,6 +452,23 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::TyS {
+            ref sty,
+
+            // The other fields just provide fast access to information that is
+            // also contained in `sty`, so no need to hash them.
+            flags: _,
+            region_depth: _,
+        } = *self;
+
+        sty.hash_stable(hcx, hasher);
+    }
+}
+
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
 impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
index fd8191303a9a60cb92e9f1bb9bd1340daba448f5..c650ffe302762a1f39bab14f24e9feb429b81d4b 100644 (file)
@@ -13,7 +13,7 @@
 use hir::def_id::{DefId, LOCAL_CRATE};
 use hir::map::DefPathData;
 use infer::InferCtxt;
-// use hir::map as hir_map;
+use ich::{StableHashingContext, NodeIdHashingMode};
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
 use ty::ParameterEnvironment;
@@ -25,8 +25,8 @@
 use middle::lang_items;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
-use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult};
-
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
 use std::cell::RefCell;
 use std::cmp;
 use std::hash::Hash;
@@ -187,6 +187,22 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+    /// Creates a hash of the type `Ty` which will be the same no matter what crate
+    /// context it's calculated within. This is used by the `type_id` intrinsic.
+    pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
+        let mut hasher = StableHasher::new();
+        let mut hcx = StableHashingContext::new(self);
+
+        hcx.while_hashing_spans(false, |hcx| {
+            hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                ty.hash_stable(hcx, &mut hasher);
+            });
+        });
+        hasher.finish()
+    }
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
@@ -339,14 +355,6 @@ pub fn required_region_bounds(self,
             .collect()
     }
 
-    /// Creates a hash of the type `Ty` which will be the same no matter what crate
-    /// context it's calculated within. This is used by the `type_id` intrinsic.
-    pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
-        let mut hasher = TypeIdHasher::new(self);
-        hasher.visit_ty(ty);
-        hasher.finish()
-    }
-
     /// Calculate the destructor of a given type.
     pub fn calculate_dtor(
         self,
index adb22197226023fcb80731626f1ecc97255275f7..848e5a076bb9a3fee2b12dad3dbd8b61d8418962 100644 (file)
@@ -40,6 +40,12 @@ pub unsafe trait Array {
     const LEN: usize = 8;
 }
 
+unsafe impl<T> Array for [T; 32] {
+    type Element = T;
+    type PartialStorage = [ManuallyDrop<T>; 32];
+    const LEN: usize = 32;
+}
+
 pub struct ArrayVec<A: Array> {
     count: usize,
     values: A::PartialStorage
index 9d97a83f693c32f7cb528def5b49ff3ac47f1178..bdef9fefd41e4ab07535ab83a00c466eac1c5d0f 100644 (file)
@@ -29,16 +29,23 @@ pub struct Blake2bCtx {
     t: [u64; 2],
     c: usize,
     outlen: u16,
-    finalized: bool
+    finalized: bool,
+
+    #[cfg(debug_assertions)]
+    fnv_hash: u64,
 }
 
+#[cfg(debug_assertions)]
 impl ::std::fmt::Debug for Blake2bCtx {
-    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
-        try!(write!(fmt, "hash: "));
-        for v in &self.h {
-            try!(write!(fmt, "{:x}", v));
-        }
-        Ok(())
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(fmt, "{:x}", self.fnv_hash)
+    }
+}
+
+#[cfg(not(debug_assertions))]
+impl ::std::fmt::Debug for Blake2bCtx {
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(fmt, "Enable debug_assertions() for more info.")
     }
 }
 
@@ -157,6 +164,9 @@ fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx {
         c: 0,
         outlen: outlen as u16,
         finalized: false,
+
+        #[cfg(debug_assertions)]
+        fnv_hash: 0xcbf29ce484222325,
     };
 
     ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64);
@@ -194,6 +204,16 @@ fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) {
         checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy);
         ctx.c += bytes_to_copy;
     }
+
+    #[cfg(debug_assertions)]
+    {
+        // compute additional FNV hash for simpler to read debug output
+        const MAGIC_PRIME: u64 = 0x00000100000001b3;
+
+        for &byte in data {
+            ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME);
+        }
+    }
 }
 
 fn blake2b_final(ctx: &mut Blake2bCtx)
index 72c533a74618b8185eae1cb22807539ef56cdb4f..00c46d992bfd5a05498e6b58b5c84f40b1952a0a 100644 (file)
@@ -40,6 +40,7 @@
 #![feature(discriminant_value)]
 #![feature(specialization)]
 #![feature(manually_drop)]
+#![feature(struct_field_attributes)]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index dc412a0763ef70f196eed9134bfa930f21a40570..95f063976d491018a44cc55c149d40dec931a1ed 100644 (file)
 /// This hasher currently always uses the stable Blake2b algorithm
 /// and allows for variable output lengths through its type
 /// parameter.
-#[derive(Debug)]
 pub struct StableHasher<W> {
     state: Blake2bHasher,
     bytes_hashed: u64,
     width: PhantomData<W>,
 }
 
+impl<W: StableHasherResult> ::std::fmt::Debug for StableHasher<W> {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(f, "{:?}", self.state)
+    }
+}
+
 pub trait StableHasherResult: Sized {
     fn finish(hasher: StableHasher<Self>) -> Self;
 }
index 2bce7faf08cec45b91c9654ed4244b0d64383ef3..2631108aeb5fa3563c6f004d791927b8a2d080c5 100644 (file)
@@ -9,11 +9,14 @@
 // except according to those terms.
 
 use bitvec::BitMatrix;
+use stable_hasher::{HashStable, StableHasher, StableHasherResult};
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 use std::cell::RefCell;
 use std::fmt::Debug;
 use std::mem;
 
+
+
 #[derive(Clone)]
 pub struct TransitiveRelation<T: Debug + PartialEq> {
     // List of elements. This is used to map from a T to a usize.  We
@@ -334,6 +337,49 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
     }
 }
 
+impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
+    where T: HashStable<CTX> + PartialEq + Debug
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        // We are assuming here that the relation graph has been built in a
+        // deterministic way and we can just hash it the way it is.
+        let TransitiveRelation {
+            ref elements,
+            ref edges,
+            // "closure" is just a copy of the data above
+            closure: _
+        } = *self;
+
+        elements.hash_stable(hcx, hasher);
+        edges.hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> HashStable<CTX> for Edge {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let Edge {
+            ref source,
+            ref target,
+        } = *self;
+
+        source.hash_stable(hcx, hasher);
+        target.hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> HashStable<CTX> for Index {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let Index(idx) = *self;
+        idx.hash_stable(hcx, hasher);
+    }
+}
+
 #[test]
 fn test_one_step() {
     let mut relation = TransitiveRelation::new();
index 7556aa707526717524fe2063d0b8370beee80705..21888ba94b3498a748c9c8dd4599582ce89c35f7 100644 (file)
@@ -1084,6 +1084,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
          "serialize dep graph",
          || rustc_incremental::save_dep_graph(tcx,
                                               &incremental_hashes_map,
+                                              &translation.metadata.hashes,
                                               translation.link.crate_hash));
     translation
 }
index d900907395656d9c140df0839fe0ee52bcab30b9..8a1af5dd08d74d7dfb85dac9ff9d94e5acbbcd9b 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use rustc::hir::def_id::DefIndex;
 use rustc::ich::Fingerprint;
+use rustc::middle::cstore::EncodedMetadataHash;
 use std::sync::Arc;
 use rustc_data_structures::fx::FxHashMap;
 
@@ -98,7 +99,7 @@ pub struct SerializedMetadataHashes {
     /// where `X` refers to some item in this crate. That `X` will be
     /// a `DefPathIndex` that gets retracted to the current `DefId`
     /// (matching the one found in this structure).
-    pub hashes: Vec<SerializedMetadataHash>,
+    pub hashes: Vec<EncodedMetadataHash>,
 
     /// For each DefIndex (as it occurs in SerializedMetadataHash), this
     /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so
@@ -112,14 +113,3 @@ pub struct SerializedMetadataHashes {
     /// the DefIndex.
     pub index_map: FxHashMap<DefIndex, DefPathIndex>
 }
-
-/// The hash for some metadata that (when saving) will be exported
-/// from this crate, or which (when importing) was exported by an
-/// upstream crate.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
-pub struct SerializedMetadataHash {
-    pub def_index: DefIndex,
-
-    /// the hash itself, computed by `calculate_item_hash`
-    pub hash: Fingerprint,
-}
index d931f64d579e1a7f254baab3bddce755221dcc12..af5c1f05bd1fcdd82ad0393b6c93b9b46e3cf4cc 100644 (file)
@@ -215,9 +215,11 @@ fn visit_impl_item(&mut self, item: &hir::ImplItem) {
     }
 }
 
-pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  prev_metadata_hashes: &FxHashMap<DefId, Fingerprint>,
-                                  current_metadata_hashes: &FxHashMap<DefId, Fingerprint>) {
+pub fn check_dirty_clean_metadata<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    prev_metadata_hashes: &FxHashMap<DefId, Fingerprint>,
+    current_metadata_hashes: &FxHashMap<DefId, Fingerprint>)
+{
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return;
     }
@@ -230,7 +232,7 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             current_metadata_hashes: current_metadata_hashes,
             checked_attrs: FxHashSet(),
         };
-        krate.visit_all_item_likes(&mut dirty_clean_visitor);
+        intravisit::walk_crate(&mut dirty_clean_visitor, krate);
 
         let mut all_attrs = FindAllAttrs {
             tcx: tcx,
@@ -246,30 +248,58 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     });
 }
 
-pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> {
+pub struct DirtyCleanMetadataVisitor<'a, 'tcx: 'a, 'm> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     prev_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
     current_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
     checked_attrs: FxHashSet<ast::AttrId>,
 }
 
-impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
+impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+        intravisit::NestedVisitorMap::All(&self.tcx.hir)
+    }
+
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.check_item(item.id, item.span);
+        intravisit::walk_item(self, item);
+    }
 
-        if let hir::ItemEnum(ref def, _) = item.node {
-            for v in &def.variants {
-                self.check_item(v.node.data.id(), v.span);
-            }
+    fn visit_variant_data(&mut self,
+                          variant_data: &'tcx hir::VariantData,
+                          _: ast::Name,
+                          _: &'tcx hir::Generics,
+                          _parent_id: ast::NodeId,
+                          span: Span) {
+        if self.tcx.hir.find(variant_data.id()).is_some() {
+            // VariantData that represent structs or tuples don't have a
+            // separate entry in the HIR map and checking them would error,
+            // so only check if this is an enum or union variant.
+            self.check_item(variant_data.id(), span);
         }
+
+        intravisit::walk_struct_def(self, variant_data);
     }
 
-    fn visit_trait_item(&mut self, item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
         self.check_item(item.id, item.span);
+        intravisit::walk_trait_item(self, item);
     }
 
-    fn visit_impl_item(&mut self, item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
         self.check_item(item.id, item.span);
+        intravisit::walk_impl_item(self, item);
+    }
+
+    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
+        self.check_item(i.id, i.span);
+        intravisit::walk_foreign_item(self, i);
+    }
+
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+        self.check_item(s.id, s.span);
+        intravisit::walk_struct_field(self, s);
     }
 }
 
@@ -281,13 +311,15 @@ fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
         for attr in self.tcx.get_attrs(def_id).iter() {
             if attr.check_name(ATTR_DIRTY_METADATA) {
                 if check_config(self.tcx, attr) {
-                    self.checked_attrs.insert(attr.id);
-                    self.assert_state(false, def_id, item_span);
+                    if self.checked_attrs.insert(attr.id) {
+                        self.assert_state(false, def_id, item_span);
+                    }
                 }
             } else if attr.check_name(ATTR_CLEAN_METADATA) {
                 if check_config(self.tcx, attr) {
-                    self.checked_attrs.insert(attr.id);
-                    self.assert_state(true, def_id, item_span);
+                    if self.checked_attrs.insert(attr.id) {
+                        self.assert_state(true, def_id, item_span);
+                    }
                 }
             }
         }
index fe8cf72996e15d8b1359e20a4338c6746f81cc0e..e769641a4cadf2094e42e6fc14fc3004667e014d 100644 (file)
@@ -44,16 +44,18 @@ impl<'q> Predecessors<'q> {
     pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
         let tcx = hcx.tcx;
 
-        let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc ||
-            tcx.sess.opts.debugging_opts.query_dep_graph;
-
         // Find the set of "start nodes". These are nodes that we will
         // possibly query later.
         let is_output = |node: &DepNode<DefId>| -> bool {
             match *node {
                 DepNode::WorkProduct(_) => true,
-                DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(),
-
+                DepNode::MetaData(ref def_id) => {
+                    // We do *not* create dep-nodes for the current crate's
+                    // metadata anymore, just for metadata that we import/read
+                    // from other crates.
+                    debug_assert!(!def_id.is_local());
+                    false
+                }
                 // if -Z query-dep-graph is passed, save more extended data
                 // to enable better unit testing
                 DepNode::TypeckTables(_) |
@@ -75,6 +77,22 @@ pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
                   .or_insert_with(|| hcx.hash(input).unwrap());
         }
 
+        if tcx.sess.opts.debugging_opts.query_dep_graph {
+            // Not all inputs might have been reachable from an output node,
+            // but we still want their hash for our unit tests.
+            let hir_nodes = query.graph.all_nodes().iter().filter_map(|node| {
+                match node.data {
+                    DepNode::Hir(_) => Some(&node.data),
+                    _ => None,
+                }
+            });
+
+            for node in hir_nodes {
+                hashes.entry(node)
+                      .or_insert_with(|| hcx.hash(node).unwrap());
+            }
+        }
+
         let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
             (0 .. graph.len_nodes())
             .map(NodeIndex)
index 1591503865e817a6180a0ea86c884a9cbe3886ed..1864009fbdf21f119b2ff80dec63f02c2118ea19 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
+use rustc::middle::cstore::EncodedMetadataHash;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::graph::{NodeIndex, INCOMING};
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
-use std::hash::Hash;
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
 use std::path::PathBuf;
 use super::dirty_clean;
 use super::file_format;
 use super::work_product;
-use calculate_svh::IchHasher;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 incremental_hashes_map: &IncrementalHashesMap,
+                                metadata_hashes: &[EncodedMetadataHash],
                                 svh: Svh) {
     debug!("save_dep_graph()");
     let _ignore = tcx.dep_graph.in_ignore();
@@ -56,16 +55,16 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let preds = Predecessors::new(&query, &mut hcx);
     let mut current_metadata_hashes = FxHashMap();
 
+    // IMPORTANT: We are saving the metadata hashes *before* the dep-graph,
+    //            since metadata-encoding might add new entries to the
+    //            DefIdDirectory (which is saved in the dep-graph file).
     if sess.opts.debugging_opts.incremental_cc ||
        sess.opts.debugging_opts.query_dep_graph {
-        // IMPORTANT: We are saving the metadata hashes *before* the dep-graph,
-        //            since metadata-encoding might add new entries to the
-        //            DefIdDirectory (which is saved in the dep-graph file).
         save_in(sess,
                 metadata_hash_export_path(sess),
                 |e| encode_metadata_hashes(tcx,
                                            svh,
-                                           &preds,
+                                           metadata_hashes,
                                            &mut builder,
                                            &mut current_metadata_hashes,
                                            e));
@@ -241,80 +240,16 @@ pub fn encode_dep_graph(preds: &Predecessors,
 
 pub fn encode_metadata_hashes(tcx: TyCtxt,
                               svh: Svh,
-                              preds: &Predecessors,
+                              metadata_hashes: &[EncodedMetadataHash],
                               builder: &mut DefIdDirectoryBuilder,
                               current_metadata_hashes: &mut FxHashMap<DefId, Fingerprint>,
                               encoder: &mut Encoder)
                               -> io::Result<()> {
-    // For each `MetaData(X)` node where `X` is local, accumulate a
-    // hash.  These are the metadata items we export. Downstream
-    // crates will want to see a hash that tells them whether we might
-    // have changed the metadata for a given item since they last
-    // compiled.
-    //
-    // (I initially wrote this with an iterator, but it seemed harder to read.)
     let mut serialized_hashes = SerializedMetadataHashes {
-        hashes: vec![],
+        hashes: metadata_hashes.to_vec(),
         index_map: FxHashMap()
     };
 
-    for (index, target) in preds.reduced_graph.all_nodes().iter().enumerate() {
-        let index = NodeIndex(index);
-        let def_id = match *target.data {
-            DepNode::MetaData(def_id) if def_id.is_local() => def_id,
-            _ => continue,
-        };
-
-        // To create the hash for each item `X`, we don't hash the raw
-        // bytes of the metadata (though in principle we
-        // could). Instead, we walk the predecessors of `MetaData(X)`
-        // from the dep-graph. This corresponds to all the inputs that
-        // were read to construct the metadata. To create the hash for
-        // the metadata, we hash (the hash of) all of those inputs.
-        debug!("save: computing metadata hash for {:?}", def_id);
-
-        // Create a vector containing a pair of (source-id, hash).
-        // The source-id is stored as a `DepNode<u64>`, where the u64
-        // is the det. hash of the def-path. This is convenient
-        // because we can sort this to get a stable ordering across
-        // compilations, even if the def-ids themselves have changed.
-        let mut hashes: Vec<(DepNode<u64>, Fingerprint)> =
-            preds.reduced_graph
-                 .depth_traverse(index, INCOMING)
-                 .map(|index| preds.reduced_graph.node_data(index))
-                 .filter(|dep_node| HashContext::is_hashable(dep_node))
-                 .map(|dep_node| {
-                     let hash_dep_node = dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id)))
-                                                 .unwrap();
-                     let hash = preds.hashes[dep_node];
-                     (hash_dep_node, hash)
-                 })
-                 .collect();
-
-        hashes.sort();
-        let mut state = IchHasher::new();
-        hashes.hash(&mut state);
-        let hash = state.finish();
-
-        debug!("save: metadata hash for {:?} is {}", def_id, hash);
-
-        if tcx.sess.opts.debugging_opts.incremental_dump_hash {
-            println!("metadata hash for {:?} is {}", def_id, hash);
-            for pred_index in preds.reduced_graph.depth_traverse(index, INCOMING) {
-                let dep_node = preds.reduced_graph.node_data(pred_index);
-                if HashContext::is_hashable(&dep_node) {
-                    println!("metadata hash for {:?} depends on {:?} with hash {}",
-                             def_id, dep_node, preds.hashes[dep_node]);
-                }
-            }
-        }
-
-        serialized_hashes.hashes.push(SerializedMetadataHash {
-            def_index: def_id.index,
-            hash: hash,
-        });
-    }
-
     if tcx.sess.opts.debugging_opts.query_dep_graph {
         for serialized_hash in &serialized_hashes.hashes {
             let def_id = DefId::local(serialized_hash.def_index);
index 459132eb9c61394f637b9cd210ec03281c9fbdbf..d9008ce555cc17afa48a0e4924f3dba299450dc9 100644 (file)
 
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 
-use encoder::EncodeContext;
+use index_builder::EntryBuilder;
 use schema::*;
 
 use rustc::hir;
 use rustc::ty;
 
-use rustc_serialize::Encodable;
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     pub body: Lazy<hir::Body>,
@@ -26,7 +24,14 @@ pub struct Ast<'tcx> {
     pub rvalue_promotable_to_static: bool,
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl_stable_hash_for!(struct Ast<'tcx> {
+    body,
+    tables,
+    nested_bodies,
+    rvalue_promotable_to_static
+});
+
+impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> {
     pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let body = self.tcx.hir.body(body_id);
         let lazy_body = self.lazy(body);
@@ -34,15 +39,12 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let tables = self.tcx.body_tables(body_id);
         let lazy_tables = self.lazy(tables);
 
-        let nested_pos = self.position();
-        let nested_count = {
-            let mut visitor = NestedBodyEncodingVisitor {
-                ecx: self,
-                count: 0,
-            };
-            visitor.visit_body(body);
-            visitor.count
+        let mut visitor = NestedBodyCollector {
+            tcx: self.tcx,
+            bodies_found: Vec::new(),
         };
+        visitor.visit_body(body);
+        let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
 
         let rvalue_promotable_to_static =
             self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
@@ -50,27 +52,25 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         self.lazy(&Ast {
             body: lazy_body,
             tables: lazy_tables,
-            nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
+            nested_bodies: lazy_nested_bodies,
             rvalue_promotable_to_static: rvalue_promotable_to_static
         })
     }
 }
 
-struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    ecx: &'a mut EncodeContext<'b, 'tcx>,
-    count: usize,
+struct NestedBodyCollector<'a, 'tcx: 'a> {
+    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    bodies_found: Vec<&'tcx hir::Body>,
 }
 
-impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
+impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::None
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let body = self.ecx.tcx.hir.body(body);
-        body.encode(self.ecx).unwrap();
-        self.count += 1;
-
+        let body = self.tcx.hir.body(body);
+        self.bodies_found.push(body);
         self.visit_body(body);
     }
 }
index 37984e4c3718fd96231832ea22bae1f8f47e409d..3239dfb937b5e79bd170036a0d232252d159f450 100644 (file)
@@ -14,8 +14,9 @@
 use schema;
 
 use rustc::dep_graph::DepTrackingMapConfig;
-use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
-use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
+use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
+                            ExternCrate, NativeLibrary, LinkMeta,
+                            LinkagePreference, LoadedMacro, EncodedMetadata};
 use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
 use rustc::session::Session;
@@ -498,7 +499,8 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8>
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata
     {
         encoder::encode_metadata(tcx, self, link_meta, reachable)
     }
index 38d774992a55111b8d901b75a5d192730f76ba38..ffe68094c6afc0d46b130e82a23e71333af414f7 100644 (file)
@@ -12,7 +12,8 @@
 use index::Index;
 use schema::*;
 
-use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
+use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
+                            EncodedMetadata, EncodedMetadataHash};
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::middle::dependency_format::Linkage;
@@ -42,7 +43,7 @@
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 use rustc::hir::intravisit;
 
-use super::index_builder::{FromId, IndexBuilder, Untracked};
+use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder};
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder<'a>,
@@ -54,6 +55,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+
+    pub metadata_hashes: Vec<EncodedMetadataHash>,
 }
 
 macro_rules! encoder_methods {
@@ -172,7 +175,7 @@ pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> {
         })
     }
 
-    fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
+    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = T>,
               T: Encodable
     {
@@ -184,7 +187,7 @@ fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
         })
     }
 
-    fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
+    pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = &'b T>,
               T: 'b + Encodable
     {
@@ -233,15 +236,20 @@ fn encode_with_shorthand<T, U, M>(&mut self,
 
         Ok(())
     }
+}
 
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
+        debug!("EntryBuilder::encode_item_variances({:?})", def_id);
         let tcx = self.tcx;
-        self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
+        self.lazy_seq_from_slice(&tcx.item_variances(def_id))
     }
 
     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
         let tcx = self.tcx;
-        self.lazy(&tcx.item_type(def_id))
+        let ty = tcx.item_type(def_id);
+        debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty);
+        self.lazy(&ty)
     }
 
     /// Encode data for the given variant of the given ADT. The
@@ -256,6 +264,7 @@ fn encode_enum_variant_info(&mut self,
         let def = tcx.lookup_adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.did;
+        debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -302,10 +311,13 @@ fn encode_info_for_mod(&mut self,
                            -> Entry<'tcx> {
         let tcx = self.tcx;
         let def_id = tcx.hir.local_def_id(id);
+        debug!("EntryBuilder::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
             reexports: match tcx.export_map.get(&id) {
-                Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
+                Some(exports) if *vis == hir::Public => {
+                    self.lazy_seq_from_slice(exports.as_slice())
+                }
                 _ => LazySeq::empty(),
             },
         };
@@ -339,14 +351,14 @@ fn encode_fields(&mut self, adt_def_id: DefId) {
         for (variant_index, variant) in def.variants.iter().enumerate() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
-                            EncodeContext::encode_field,
+                            EntryBuilder::encode_field,
                             (adt_def_id, Untracked((variant_index, field_index))));
             }
         }
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     /// Encode data for the given field of the given variant of the
     /// given ADT. The indices of the variant/field are untracked:
     /// this is ok because we will have to lookup the adt-def by its
@@ -363,6 +375,8 @@ fn encode_field(&mut self,
         let field = &variant.fields[field_index];
 
         let def_id = field.did;
+        debug!("EntryBuilder::encode_field({:?})", def_id);
+
         let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap();
         let variant_data = tcx.hir.expect_variant_data(variant_id);
 
@@ -387,6 +401,7 @@ fn encode_field(&mut self,
     }
 
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let variant = tcx.lookup_adt_def(adt_def_id).struct_variant();
 
@@ -429,16 +444,19 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
     }
 
     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
+        debug!("EntryBuilder::encode_generics({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(tcx.item_generics(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
+        debug!("EntryBuilder::encode_predicates({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.item_predicates(def_id))
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
         let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -521,6 +539,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id);
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.hir.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
@@ -607,11 +626,13 @@ fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
     }
 
     fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
+        debug!("EntryBuilder::encode_mir({:?})", def_id);
         self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
     }
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
+        debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id);
         match self.tcx.maps.inherent_impls.borrow().get(&def_id) {
             None => LazySeq::empty(),
             Some(implementations) => {
@@ -624,18 +645,19 @@ fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex
     }
 
     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
+        debug!("EntryBuilder::encode_stability({:?})", def_id);
         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
+        debug!("EntryBuilder::encode_deprecation({:?})", def_id);
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("encoding info for item at {}",
-               tcx.sess.codemap().span_to_string(item.span));
+        debug!("EntryBuilder::encode_info_for_item({:?})", def_id);
 
         let kind = match item.node {
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
@@ -907,7 +929,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 let def = self.tcx.lookup_adt_def(def_id);
                 for (i, variant) in def.variants.iter().enumerate() {
                     self.record(variant.did,
-                                EncodeContext::encode_enum_variant_info,
+                                EntryBuilder::encode_enum_variant_info,
                                 (def_id, Untracked(i)));
                 }
             }
@@ -918,7 +940,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 if !struct_def.is_struct() {
                     let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
                     self.record(ctor_def_id,
-                                EncodeContext::encode_struct_ctor,
+                                EntryBuilder::encode_struct_ctor,
                                 (def_id, ctor_def_id));
                 }
             }
@@ -928,14 +950,14 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemImpl(..) => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(trait_item_def_id,
-                                EncodeContext::encode_info_for_impl_item,
+                                EntryBuilder::encode_info_for_impl_item,
                                 trait_item_def_id);
                 }
             }
             hir::ItemTrait(..) => {
                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(item_def_id,
-                                EncodeContext::encode_info_for_trait_item,
+                                EntryBuilder::encode_info_for_trait_item,
                                 item_def_id);
                 }
             }
@@ -943,13 +965,13 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_foreign_item(&mut self,
                                     (def_id, nitem): (DefId, &hir::ForeignItem))
                                     -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
+        debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id);
 
         let kind = match nitem.node {
             hir::ForeignItemFn(_, ref names, _) => {
@@ -1002,7 +1024,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
             hir::ItemExternCrate(_) |
             hir::ItemUse(..) => (), // ignore these
-            _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
+            _ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)),
         }
         self.index.encode_addl_info_for_item(item);
     }
@@ -1010,7 +1032,7 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
         let def_id = self.index.tcx.hir.local_def_id(ni.id);
         self.index.record(def_id,
-                          EncodeContext::encode_info_for_foreign_item,
+                          EntryBuilder::encode_info_for_foreign_item,
                           (def_id, ni));
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
@@ -1023,7 +1045,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
     }
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
         let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
-        self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
+        self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def);
     }
 }
 
@@ -1032,14 +1054,14 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
         for ty_param in &generics.ty_params {
             let def_id = self.tcx.hir.local_def_id(ty_param.id);
             let has_default = Untracked(ty_param.default.is_some());
-            self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
+            self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default));
         }
     }
 
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyImplTrait(_) = ty.node {
             let def_id = self.tcx.hir.local_def_id(ty.id);
-            self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id);
+            self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id);
         }
     }
 
@@ -1047,17 +1069,18 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
             hir::ExprClosure(..) => {
                 let def_id = self.tcx.hir.local_def_id(expr.id);
-                self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
+                self.record(def_id, EntryBuilder::encode_info_for_closure, def_id);
             }
             _ => {}
         }
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_ty_param(&mut self,
                                 (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
                                 -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id);
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
@@ -1084,6 +1107,7 @@ fn encode_info_for_ty_param(&mut self,
     }
 
     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id);
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
@@ -1106,6 +1130,7 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
 
         let data = ClosureData {
@@ -1133,11 +1158,20 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
         }
     }
 
+    fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
+        // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
+        //       we really on the HashStable specialization for [Attribute]
+        //       to properly filter things out.
+        self.lazy_seq_from_slice(attrs)
+    }
+}
+
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_items(&mut self) -> Index {
         let krate = self.tcx.hir.krate();
         let mut index = IndexBuilder::new(self);
         index.record(DefId::local(CRATE_DEF_INDEX),
-                     EncodeContext::encode_info_for_mod,
+                     EntryBuilder::encode_info_for_mod,
                      FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
         let mut visitor = EncodeVisitor { index: index };
         krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
@@ -1147,10 +1181,6 @@ fn encode_info_for_items(&mut self) -> Index {
         visitor.index.into_items()
     }
 
-    fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
-        self.lazy_seq_ref(attrs)
-    }
-
     fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
         fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
             // Pull the cnums and name,vers,hash out of cstore
@@ -1298,7 +1328,9 @@ fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreferenc
             None => LazySeq::empty(),
         }
     }
+}
 
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         let mut i = self.position();
         let crate_deps = self.encode_crate_deps();
@@ -1431,14 +1463,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cstore: &cstore::CStore,
                                  link_meta: &LinkMeta,
                                  exported_symbols: &NodeSet)
-                                 -> Vec<u8> {
+                                 -> EncodedMetadata
+{
     let mut cursor = Cursor::new(vec![]);
     cursor.write_all(METADATA_HEADER).unwrap();
 
     // Will be filed with the root position after encoding everything.
     cursor.write_all(&[0, 0, 0, 0]).unwrap();
 
-    let root = {
+    let (root, metadata_hashes) = {
         let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
             tcx: tcx,
@@ -1448,6 +1481,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
+            metadata_hashes: Vec::new(),
         };
 
         // Encode the rustc version string in a predictable location.
@@ -1455,7 +1489,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Encode all the entries and extra information in the crate,
         // culminating in the `CrateRoot` which points to all of it.
-        ecx.encode_crate_root()
+        let root = ecx.encode_crate_root();
+        (root, ecx.metadata_hashes)
     };
     let mut result = cursor.into_inner();
 
@@ -1467,7 +1502,10 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     result[header + 2] = (pos >> 8) as u8;
     result[header + 3] = (pos >> 0) as u8;
 
-    result
+    EncodedMetadata {
+        raw_data: result,
+        hashes: metadata_hashes,
+    }
 }
 
 pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
index a811f72bc956cbe1408c0ff27753d0583ce0f111..01f948866b85081b8ba42889f7bcdf3598d5c270 100644 (file)
 use index::Index;
 use schema::*;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc::middle::cstore::EncodedMetadataHash;
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
 use std::ops::{Deref, DerefMut};
 
+use rustc_data_structures::accumulate_vec::AccumulateVec;
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+use rustc_serialize::Encodable;
+
 /// Builder that can encode new items, adding them into the index.
 /// Item encoding cannot be nested.
 pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
@@ -112,16 +117,45 @@ pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
     /// holds, and that it is therefore not gaining "secret" access to
     /// bits of HIR or other state that would not be trackd by the
     /// content system.
-    pub fn record<DATA>(&mut self,
-                        id: DefId,
-                        op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>,
-                        data: DATA)
+    pub fn record<'x, DATA>(&'x mut self,
+                            id: DefId,
+                            op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
+                            data: DATA)
         where DATA: DepGraphRead
     {
-        let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
-        data.read(self.tcx);
-        let entry = op(&mut self.ecx, data);
-        self.items.record(id, self.ecx.lazy(&entry));
+        assert!(id.is_local());
+        let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
+
+        // We don't track this since we are explicitly computing the incr. comp.
+        // hashes anyway. In theory we could do some tracking here and use it to
+        // avoid rehashing things (and instead cache the hashes) but it's
+        // unclear whether that would be a win since hashing is cheap enough.
+        let _task = tcx.dep_graph.in_ignore();
+
+        let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
+                           tcx.sess.opts.debugging_opts.incremental_cc) &&
+                           tcx.sess.opts.build_dep_graph();
+
+        let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx;
+        let mut entry_builder = EntryBuilder {
+            tcx: tcx,
+            ecx: ecx,
+            hcx: if compute_ich {
+                Some((StableHashingContext::new(tcx), StableHasher::new()))
+            } else {
+                None
+            }
+        };
+
+        let entry = op(&mut entry_builder, data);
+
+        if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx {
+            entry.hash_stable(hcx, hasher);
+        }
+
+        let entry = entry_builder.ecx.lazy(&entry);
+        entry_builder.finish(id);
+        self.items.record(id, entry);
     }
 
     pub fn into_items(self) -> Index {
@@ -223,3 +257,91 @@ fn read(&self, tcx: TyCtxt) {
         tcx.hir.read(self.0);
     }
 }
+
+pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> {
+    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
+    ecx: &'a mut EncodeContext<'b, 'tcx>,
+    hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher<Fingerprint>)>,
+}
+
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
+
+    pub fn finish(self, def_id: DefId) {
+        if let Some((_, hasher)) = self.hcx {
+            let hash = hasher.finish();
+            self.ecx.metadata_hashes.push(EncodedMetadataHash {
+                def_index: def_id.index,
+                hash: hash,
+            });
+        }
+    }
+
+    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            value.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy(value)
+    }
+
+    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
+        where I: IntoIterator<Item = T>,
+              T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            let iter = iter.into_iter();
+            let (lower_bound, upper_bound) = iter.size_hint();
+
+            if upper_bound == Some(lower_bound) {
+                lower_bound.hash_stable(hcx, hasher);
+                let mut num_items_hashed = 0;
+                let ret = self.ecx.lazy_seq(iter.inspect(|item| {
+                    item.hash_stable(hcx, hasher);
+                    num_items_hashed += 1;
+                }));
+
+                // Sometimes items in a sequence are filtered out without being
+                // hashed (e.g. for &[ast::Attribute]) and this code path cannot
+                // handle that correctly, so we want to make sure we didn't hit
+                // it by accident.
+                if lower_bound != num_items_hashed {
+                    bug!("Hashed a different number of items ({}) than expected ({})",
+                         num_items_hashed,
+                         lower_bound);
+                }
+                debug!("metadata-hash: {:?}", hasher);
+                ret
+            } else {
+                // Collect into a vec so we know the length of the sequence
+                let items: AccumulateVec<[T; 32]> = iter.collect();
+                items.hash_stable(hcx, hasher);
+                debug!("metadata-hash: {:?}", hasher);
+                self.ecx.lazy_seq(items)
+            }
+        } else {
+            self.ecx.lazy_seq(iter)
+        }
+    }
+
+    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter())
+    }
+
+    pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
+    }
+}
index 2fbdb8c0de676dec7f7921e3037e9c6410811c0f..b9e142ac65072e18dd2c256a4a418067700d0553 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(rustc_private)]
 #![feature(specialization)]
 #![feature(staged_api)]
+#![feature(discriminant_value)]
 
 #[macro_use]
 extern crate log;
index abb482a50ebc2621487e53fb43c3af4c5e8f7b73..53d6a9ec10df2fca11c8cef3f8a0b5ffe89379b0 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
 use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::ich::StableHashingContext;
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
 use rustc::middle::lang_items;
 use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
+use std::mem;
+
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
+                                           StableHasherResult};
 
 pub fn rustc_version() -> String {
     format!("rustc {}",
@@ -100,6 +105,15 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
 
+impl<CTX, T> HashStable<CTX> for Lazy<T> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut CTX,
+                                          _: &mut StableHasher<W>) {
+        // There's nothing to do. Whatever got encoded within this Lazy<>
+        // wrapper has already been hashed.
+    }
+}
+
 /// A sequence of type T referred to by its absolute position
 /// in the metadata and length, and which can be decoded lazily.
 /// The sequence is a single node for the purposes of `Lazy`.
@@ -148,6 +162,15 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
 
+impl<CTX, T> HashStable<CTX> for LazySeq<T> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut CTX,
+                                          _: &mut StableHasher<W>) {
+        // There's nothing to do. Whatever got encoded within this Lazy<>
+        // wrapper has already been hashed.
+    }
+}
+
 /// Encoding / decoding state for `Lazy` and `LazySeq`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum LazyState {
@@ -219,6 +242,23 @@ pub struct Entry<'tcx> {
     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
 }
 
+impl_stable_hash_for!(struct Entry<'tcx> {
+    kind,
+    visibility,
+    span,
+    attributes,
+    children,
+    stability,
+    deprecation,
+    ty,
+    inherent_impls,
+    variances,
+    generics,
+    predicates,
+    ast,
+    mir
+});
+
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
     Const(u8),
@@ -246,22 +286,91 @@ pub enum EntryKind<'tcx> {
     AssociatedConst(AssociatedContainer, u8),
 }
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            EntryKind::ImmStatic        |
+            EntryKind::MutStatic        |
+            EntryKind::ForeignImmStatic |
+            EntryKind::ForeignMutStatic |
+            EntryKind::ForeignMod       |
+            EntryKind::Field |
+            EntryKind::Type => {
+                // Nothing else to hash here.
+            }
+            EntryKind::Const(qualif) => {
+                qualif.hash_stable(hcx, hasher);
+            }
+            EntryKind::Enum(ref repr_options) => {
+                repr_options.hash_stable(hcx, hasher);
+            }
+            EntryKind::Variant(ref variant_data) => {
+                variant_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Struct(ref variant_data, ref repr_options) |
+            EntryKind::Union(ref variant_data, ref repr_options)  => {
+                variant_data.hash_stable(hcx, hasher);
+                repr_options.hash_stable(hcx, hasher);
+            }
+            EntryKind::Fn(ref fn_data) |
+            EntryKind::ForeignFn(ref fn_data) => {
+                fn_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Mod(ref mod_data) => {
+                mod_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::MacroDef(ref macro_def) => {
+                macro_def.hash_stable(hcx, hasher);
+            }
+            EntryKind::Closure(closure_data) => {
+                closure_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Trait(ref trait_data) => {
+                trait_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::DefaultImpl(ref impl_data) |
+            EntryKind::Impl(ref impl_data) => {
+                impl_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Method(ref method_data) => {
+                method_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::AssociatedType(associated_container) => {
+                associated_container.hash_stable(hcx, hasher);
+            }
+            EntryKind::AssociatedConst(associated_container, qualif) => {
+                associated_container.hash_stable(hcx, hasher);
+                qualif.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export>,
 }
 
+impl_stable_hash_for!(struct ModData { reexports });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct MacroDef {
     pub body: String,
 }
 
+impl_stable_hash_for!(struct MacroDef { body });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct FnData {
     pub constness: hir::Constness,
     pub arg_names: LazySeq<ast::Name>,
 }
 
+impl_stable_hash_for!(struct FnData { constness, arg_names });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
@@ -273,6 +382,13 @@ pub struct VariantData<'tcx> {
     pub struct_ctor: Option<DefIndex>,
 }
 
+impl_stable_hash_for!(struct VariantData<'tcx> {
+    ctor_kind,
+    discr,
+    evaluated_discr,
+    struct_ctor
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
@@ -281,6 +397,13 @@ pub struct TraitData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
+impl_stable_hash_for!(struct TraitData<'tcx> {
+    unsafety,
+    paren_sugar,
+    has_default_impl,
+    super_predicates
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
@@ -291,6 +414,14 @@ pub struct ImplData<'tcx> {
     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
 }
 
+impl_stable_hash_for!(struct ImplData<'tcx> {
+    polarity,
+    parent_impl,
+    coerce_unsized_info,
+    trait_ref
+});
+
+
 /// Describes whether the container of an associated item
 /// is a trait or an impl and whether, in a trait, it has
 /// a default, or an in impl, whether it's marked "default".
@@ -302,6 +433,13 @@ pub enum AssociatedContainer {
     ImplFinal,
 }
 
+impl_stable_hash_for!(enum ::schema::AssociatedContainer {
+    TraitRequired,
+    TraitWithDefault,
+    ImplDefault,
+    ImplFinal
+});
+
 impl AssociatedContainer {
     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
         match *self {
@@ -335,9 +473,11 @@ pub struct MethodData {
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
+impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub kind: ty::ClosureKind,
     pub ty: Lazy<ty::PolyFnSig<'tcx>>,
 }
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
index 66380079a8b29038538e18324455f68bce83deb4..0ffa7a79408e12913acbd02a7fbbb920ebba500e 100644 (file)
@@ -443,7 +443,10 @@ fn archive_config<'a>(sess: &'a Session,
 }
 
 fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) {
-    let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata));
+    let result = fs::File::create(out_filename).and_then(|mut f| {
+        f.write_all(&trans.metadata.raw_data)
+    });
+
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
     }
index 574b345218be9def7543abb1534eb700aae1e23b..f76e816bcf0c9580a18aa81d4b3646905db77521 100644 (file)
@@ -36,6 +36,7 @@
 use llvm;
 use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
+use middle::cstore::EncodedMetadata;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
 use rustc::hir::map as hir_map;
@@ -724,7 +725,8 @@ fn contains_null(s: &str) -> bool {
 }
 
 fn write_metadata(cx: &SharedCrateContext,
-                  exported_symbols: &NodeSet) -> Vec<u8> {
+                  exported_symbols: &NodeSet)
+                  -> EncodedMetadata {
     use flate;
 
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -748,7 +750,10 @@ enum MetadataKind {
     }).max().unwrap();
 
     if kind == MetadataKind::None {
-        return Vec::new();
+        return EncodedMetadata {
+            raw_data: vec![],
+            hashes: vec![],
+        };
     }
 
     let cstore = &cx.tcx().sess.cstore;
@@ -761,7 +766,7 @@ enum MetadataKind {
 
     assert!(kind == MetadataKind::Compressed);
     let mut compressed = cstore.metadata_encoding_version().to_vec();
-    compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
+    compressed.extend_from_slice(&flate::deflate_bytes(&metadata.raw_data));
 
     let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed);
     let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
index 5c3b17c889760bba085ae4ec87ce9719b991c0d3..628d46f8e7059f27317e247af2cfe449b2f128e4 100644 (file)
@@ -168,7 +168,7 @@ pub struct CrateTranslation {
     pub modules: Vec<ModuleTranslation>,
     pub metadata_module: ModuleTranslation,
     pub link: middle::cstore::LinkMeta,
-    pub metadata: Vec<u8>,
+    pub metadata: middle::cstore::EncodedMetadata,
     pub exported_symbols: back::symbol_export::ExportedSymbols,
     pub no_builtins: bool,
     pub windows_subsystem: Option<String>,
index 048ccb529a24fc9a516eaeea9667189c55c454fd..37c6ef58f5e56bf680c07ca33d956b044f7917ac 100644 (file)
@@ -38,8 +38,13 @@ enum EnumVisibility { A }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-pub enum EnumVisibility { A }
+pub enum EnumVisibility {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    A
+}
 
 
 
@@ -56,7 +61,10 @@ enum EnumChangeNameCStyleVariant {
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeNameCStyleVariant {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     Variant1,
+    #[rustc_metadata_clean(cfg="cfail3")]
     Variant2Changed,
 }
 
@@ -259,10 +267,13 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeTupleStyleVariant {
-    Variant1(u32, u64),
+    Variant1(u32,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u64),
 }
 
 
@@ -277,11 +288,16 @@ enum EnumChangeFieldTypeStructStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
-    Variant2 { a: u32, b: u64 },
+    Variant2 {
+        a: u32,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        b: u64
+    },
 }
 
 
@@ -312,10 +328,16 @@ enum EnumChangeOrderTupleStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeOrderTupleStyleVariant {
-    Variant1(u64, u32),
+    Variant1(
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u64,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u32),
 }
 
 
@@ -611,11 +633,23 @@ enum EnumSwapUsageTypeParameters<A, B> {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumSwapUsageTypeParameters<A, B> {
-    Variant1 { a: B },
-    Variant2 { a: A },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant1 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: B
+    },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant2 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: A
+    },
 }
 
 
@@ -630,11 +664,23 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
-    Variant1 { a: &'b u32 },
-    Variant2 { b: &'a u32 },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant1 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: &'b u32
+    },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant2 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        b: &'a u32
+    },
 }
 
 
@@ -653,10 +699,16 @@ mod change_field_type_indirectly_tuple_style {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     enum TupleStyle {
-        Variant1(FieldType)
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        Variant1(
+            #[rustc_metadata_dirty(cfg="cfail2")]
+            #[rustc_metadata_clean(cfg="cfail3")]
+            FieldType
+        )
     }
 }
 
@@ -671,10 +723,16 @@ mod change_field_type_indirectly_struct_style {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     enum StructStyle {
-        Variant1 { a: FieldType }
+        #[rustc_metadata_clean(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        Variant1 {
+            #[rustc_metadata_dirty(cfg="cfail2")]
+            #[rustc_metadata_clean(cfg="cfail3")]
+            a: FieldType
+        }
     }
 }
 
index 03e621fedbeb4d49bc3dd5a5af34c874f7dd0874..1d26e6c07d15bc9ab081d7f57a33053dfd7f5800 100644 (file)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_return_type(c: i32) -> i8;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_return_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn make_function_variadic(c: i32, ...);
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern "rust-call" {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_calling_convention(c: i32);
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn make_function_public(c: i32);
 }
 
@@ -246,9 +262,11 @@ mod indirectly_change_parameter_type {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     extern {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         pub fn indirectly_change_parameter_type(c: c_int);
     }
 }
@@ -264,9 +282,11 @@ mod indirectly_change_return_type {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     extern {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         pub fn indirectly_change_return_type() -> c_int;
     }
 }
index 93d94cd1a19c4b83e20c16bfef8dc6c9921e4139..2fe3f0d5d1fe03911aaa08cd7e87874665c89ffc 100644 (file)
@@ -50,7 +50,7 @@ fn add_return_type() {}
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")] // The type doesn't change, so metadata is the same
 #[rustc_metadata_clean(cfg="cfail3")]
 fn add_return_type() -> () {}
 
@@ -154,7 +154,7 @@ fn lifetime_parameter() {}
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+// #[rustc_metadata_dirty(cfg="cfail2")] -- Unused lifetime params don't show up in the type?
 #[rustc_metadata_clean(cfg="cfail3")]
 fn lifetime_parameter<'a>() {}
 
@@ -315,16 +315,16 @@ fn return_impl_trait() -> impl Clone {
 
 #[cfg(cfail1)]
 fn change_return_impl_trait() -> impl Clone {
-    0
+    0u32
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")] // The actual type is the same, so: clean
 #[rustc_metadata_clean(cfg="cfail3")]
 fn change_return_impl_trait() -> impl Copy {
-    0
+    0u32
 }
 
 
index fd9ac61046e3a978add0ffde467dc65a420c9d60..899aefa24a033b0e3d4eeeb666b96c7e3b9c86d2 100644 (file)
@@ -107,7 +107,7 @@ pub fn method_privacy() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -126,7 +126,7 @@ pub fn method_selfness() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -171,7 +171,7 @@ pub fn add_method_to_impl1(&self) { }
 impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_method_to_impl1(&self) { }
 
@@ -219,9 +219,7 @@ impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    // At the moment we explicitly ignore argument names in metadata, since they
-    // are not used in downstream crates (except in rustdoc)
-    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -287,9 +285,7 @@ impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    // At the moment we explicitly ignore argument names in metadata, since they
-    // are not used in downstream crates (except in rustdoc)
-    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -373,7 +369,7 @@ pub fn add_lifetime_parameter_to_method(&self) { }
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type.
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
@@ -544,7 +540,7 @@ pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 impl<T: 'static> Bar<T> {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
@@ -565,7 +561,7 @@ pub fn add_trait_bound_to_impl_parameter(&self) { }
 impl<T: Clone> Bar<T> {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
index 2d79987823f2036c1c944fdd412c6e22b9a39b13..17a5dc16783678fe8326ade18b0d643f035d08e3 100644 (file)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct TupleStructFieldType(u32);
+struct TupleStructFieldType(
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    u32
+);
 
 
 // Tuple Struct Add Field ------------------------------------------------------
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct TupleStructAddField(i32, u32);
+struct TupleStructAddField(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    i32,
+    #[rustc_metadata_clean(cfg="cfail3")]
+    u32
+);
 
 
 // Tuple Struct Field Visibility -----------------------------------------------
@@ -101,9 +111,13 @@ struct RecordStructFieldType { x: f32 }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructFieldType { x: u64 }
+struct RecordStructFieldType {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    x: u64
+}
 
 
 // Record Struct Field Name ----------------------------------------------------
@@ -129,7 +143,12 @@ struct RecordStructAddField { x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructAddField { x: f32, y: () }
+struct RecordStructAddField {
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    x: f32,
+    #[rustc_metadata_clean(cfg="cfail3")]
+    y: () }
 
 
 // Record Struct Field Visibility ----------------------------------------------
@@ -142,7 +161,11 @@ struct RecordStructFieldVisibility { x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructFieldVisibility { pub x: f32 }
+struct RecordStructFieldVisibility {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub x: f32
+}
 
 
 // Add Lifetime Parameter ------------------------------------------------------
@@ -168,7 +191,14 @@ struct RecordStructFieldVisibility { pub x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddLifetimeParameterBound<'a, 'b: 'a>(&'a f32, &'b f64);
+struct AddLifetimeParameterBound<'a, 'b: 'a>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'a f32,
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'b f64
+);
 
 #[cfg(cfail1)]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
@@ -178,7 +208,13 @@ struct RecordStructFieldVisibility { pub x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
+struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'a f32,
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'b f64)
     where 'b: 'a;
 
 
@@ -192,7 +228,16 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameter<T1, T2>(T1, T2);
+struct AddTypeParameter<T1, T2>(
+     // The field contains the parent's Generics, so it's dirty even though its
+     // type hasn't changed.
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T1,
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T2
+);
 
 
 // Add Type Parameter Bound ----------------------------------------------------
@@ -205,7 +250,11 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameterBound<T: Send>(T);
+struct AddTypeParameterBound<T: Send>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T
+);
 
 
 #[cfg(cfail1)]
@@ -216,7 +265,11 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameterBoundWhereClause<T>(T) where T: Sync;
+struct AddTypeParameterBoundWhereClause<T>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T
+) where T: Sync;
 
 
 // Empty struct ----------------------------------------------------------------
@@ -234,6 +287,7 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub struct Visibility;
 
@@ -252,9 +306,13 @@ mod tuple_struct_change_field_type_indirectly {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    struct TupleStruct(FieldType);
+    struct TupleStruct(
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        FieldType
+    );
 }
 
 
@@ -267,9 +325,11 @@ mod record_struct_change_field_type_indirectly {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     struct RecordStruct {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         _x: FieldType
     }
 }
index 94698506ec53fd6df782c9fcb32fe7775a6a177e..61a2be054a51a61e8758f837d3d67a3344b235b9 100644 (file)
@@ -100,7 +100,7 @@ trait TraitAddReturnType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddReturnType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -121,7 +121,7 @@ trait TraitChangeReturnType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeReturnType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -142,7 +142,7 @@ trait TraitAddParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -164,7 +164,7 @@ fn with_default(x: i32) {}
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
@@ -194,7 +194,7 @@ trait TraitChangeMethodParameterType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -215,7 +215,7 @@ trait TraitChangeMethodParameterTypeRef {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -236,7 +236,7 @@ trait TraitChangeMethodParametersOrder {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -257,9 +257,13 @@ trait TraitAddMethodDefaultImplementation {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddMethodDefaultImplementation {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() { }
 }
 
@@ -293,7 +297,7 @@ trait TraitChangeModeSelfRefToMut {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -335,7 +339,7 @@ trait TraitChangeModeSelfOwnToRef {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -356,7 +360,7 @@ trait TraitAddUnsafeModifier {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddUnsafeModifier {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -377,7 +381,7 @@ trait TraitAddExternModifier {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddExternModifier {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -398,7 +402,7 @@ trait TraitChangeExternCToRustIntrinsic {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -419,7 +423,7 @@ trait TraitAddTypeParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -440,12 +444,12 @@ trait TraitAddLifetimeParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type?
     #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a>();
 }
@@ -465,7 +469,7 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -486,7 +490,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -507,7 +511,7 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -528,7 +532,7 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -549,7 +553,7 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -570,7 +574,7 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -585,7 +589,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 // Add associated type ------------------------------------------------------------
 #[cfg(cfail1)]
 trait TraitAddAssociatedType {
-    fn mathod();
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -596,7 +605,7 @@ trait TraitAddAssociatedType {
 trait TraitAddAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -606,9 +615,12 @@ trait TraitAddAssociatedType {
 trait TraitAddTraitBoundToAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
+
+// Apparently the type bound contributes to the predicates of the trait, but
+// does not change the associated item itself.
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
@@ -617,11 +629,11 @@ trait TraitAddTraitBoundToAssociatedType {
 trait TraitAddTraitBoundToAssociatedType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -631,7 +643,7 @@ trait TraitAddTraitBoundToAssociatedType {
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -642,11 +654,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: 'a;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -656,18 +668,22 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 trait TraitAddDefaultToAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddDefaultToAssociatedType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated = ReferenceType0;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -675,7 +691,7 @@ trait TraitAddDefaultToAssociatedType {
 // Add associated constant --------------------------------------------------------
 #[cfg(cfail1)]
 trait TraitAddAssociatedConstant {
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -686,7 +702,7 @@ trait TraitAddAssociatedConstant {
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -696,18 +712,26 @@ trait TraitAddAssociatedConstant {
 trait TraitAddInitializerToAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddInitializerToAssociatedConstant {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     const Value: u32 = 1;
 
-    fn mathod();
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 
@@ -717,13 +741,13 @@ trait TraitAddInitializerToAssociatedConstant {
 trait TraitChangeTypeOfAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -732,7 +756,11 @@ trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_metadata_clean(cfg="cfail3")]
     const Value: f64;
 
-    fn mathod();
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 
@@ -1111,9 +1139,6 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
-
-// EDIT: Some more cases ----------------------------------------------------------
-
 // Change return type of method indirectly by modifying a use statement------------
 mod change_return_type_of_method_indirectly_use {
     #[cfg(cfail1)]
@@ -1123,7 +1148,7 @@ mod change_return_type_of_method_indirectly_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeReturnType {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1145,7 +1170,7 @@ mod change_method_parameter_type_indirectly_by_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeArgType {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1167,7 +1192,7 @@ mod change_method_parameter_type_bound_indirectly_by_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1190,7 +1215,7 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
index 30e376f04fb87ff78b0a4fa7d4f4db82306c4516..06c8eb6a878f06e96a88451a87cbb9ad69a9f8de 100644 (file)
@@ -120,7 +120,7 @@ impl ChangeMethodBodyTraitInlined for Foo {
     #[rustc_metadata_clean(cfg="cfail3")]
     #[inline]
     fn method_name() {
-        ()
+        panic!()
     }
 }
 
@@ -144,7 +144,7 @@ pub trait ChangeMethodSelfnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeMethodSelfnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -176,16 +176,14 @@ pub trait RemoveMethodSelfnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl RemoveMethodSelfnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn method_name() {
-        ()
-    }
+    fn method_name() {}
 }
 
 // Change Method Selfmutness -----------------------------------------------------------
@@ -208,16 +206,14 @@ pub trait ChangeMethodSelfmutnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeMethodSelfmutnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn method_name(&mut self) {
-        ()
-    }
+    fn method_name(&mut self) {}
 }
 
 // Change item kind -----------------------------------------------------------
@@ -317,16 +313,20 @@ fn method_name() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub trait ChangeHasValueTrait {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
@@ -346,32 +346,16 @@ fn method_name() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl AddDefaultTrait for Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     default fn method_name() { }
 }
 
-// Remove default
-
-pub trait RemoveDefaultTrait {
-    fn method_name();
-}
-
-#[cfg(cfail1)]
-impl RemoveDefaultTrait for Foo {
-    default fn method_name() { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
-#[rustc_metadata_clean(cfg="cfail3")]
-impl RemoveDefaultTrait for Foo {
-    fn method_name() { }
-}
-
 // Add arguments
 
 #[cfg(cfail1)]
@@ -392,7 +376,7 @@ pub trait AddArgumentTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl AddArgumentTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -422,7 +406,7 @@ pub trait ChangeArgumentTypeTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeArgumentTypeTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -504,7 +488,7 @@ fn id(self) -> Self { self }
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
@@ -529,7 +513,7 @@ fn id(self) -> Self { self }
 impl<T: Clone> AddTraitBoundToImplParameter for T {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
index 4017b4d4ba9aee6085c31b165248d9bae6133e40..917c2c9dbce4f10434ebb49e6b7984d7414785f9 100644 (file)
@@ -33,13 +33,3 @@ fn main() {
     }
 }
 
-struct _Struct {
-    #[rustc_metadata_dirty(cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
-    _field1: i32,
-
-    #[rustc_metadata_clean(cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
-    _field2: i32,
-}
-
index 2865fa6a79253862af85e76ee76bba779a30c8c0..7fb296c19f6ed9183e758e21f6c5b0e28c0c592c 100644 (file)
@@ -1589,8 +1589,14 @@ fn lib_path_cmd_prefix(path: &str) -> String {
     }
 
     fn dump_output(&self, out: &str, err: &str) {
-        self.dump_output_file(out, "out");
-        self.dump_output_file(err, "err");
+        let revision = if let Some(r) = self.revision {
+            format!("{}.", r)
+        } else {
+            String::new()
+        };
+
+        self.dump_output_file(out, &format!("{}out", revision));
+        self.dump_output_file(err, &format!("{}err", revision));
         self.maybe_dump_to_stdout(out, err);
     }