diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 20601493d68f3..6d7a2d6cba1c7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1303,7 +1303,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { - obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); + obj.projection_bounds.sort_by_key(|b| b.sort_key(self)); self.mk_ty(TyTrait(box obj)) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f634c8e37d7bd..14eb2fb7914c3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1018,10 +1018,6 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { pub fn item_name(&self) -> Name { self.0.projection_ty.item_name // safe to skip the binder to access a name } - - pub fn sort_key(&self) -> (DefId, Name) { - self.0.projection_ty.sort_key() - } } pub trait ToPolyTraitRef<'tcx> { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a755dd056cd84..5fdc7abc0af5b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -23,7 +23,7 @@ use std::mem; use std::ops; use syntax::abi; use syntax::ast::{self, Name}; -use syntax::parse::token::keywords; +use syntax::parse::token::{keywords, InternedString}; use serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -440,12 +440,6 @@ pub struct ProjectionTy<'tcx> { pub item_name: Name, } -impl<'tcx> ProjectionTy<'tcx> { - pub fn sort_key(&self) -> (DefId, Name) { - (self.trait_ref.def_id, self.item_name) - } -} - #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct BareFnTy<'tcx> { pub unsafety: hir::Unsafety, @@ -738,8 +732,17 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { self.0.item_name // safe to skip the binder to access a name } - pub fn sort_key(&self) -> (DefId, Name) { - (self.0.trait_ref.def_id, self.0.item_name) + pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) { + // We want something here that is stable across crate boundaries. + // The DefId isn't but the `deterministic_hash` of the corresponding + // DefPath is. + let trait_def = tcx.lookup_trait_def(self.0.trait_ref.def_id); + let def_path_hash = trait_def.def_path_hash; + + // An `ast::Name` is also not stable (it's just an index into an + // interning table), so map to the corresponding `InternedString`. + let item_name = self.0.item_name.as_str(); + (def_path_hash, item_name) } pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 61285e8f8b0a5..268b2fcaa4adb 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -70,7 +70,11 @@ pub struct TraitDef<'tcx> { pub specialization_graph: RefCell, /// Various flags - pub flags: Cell + pub flags: Cell, + + /// The ICH of this trait's DefPath, cached here so it doesn't have to be + /// recomputed all the time. + pub def_path_hash: u64, } impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { @@ -78,7 +82,8 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { paren_sugar: bool, generics: &'tcx ty::Generics<'tcx>, trait_ref: ty::TraitRef<'tcx>, - associated_type_names: Vec) + associated_type_names: Vec, + def_path_hash: u64) -> TraitDef<'tcx> { TraitDef { paren_sugar: paren_sugar, @@ -90,6 +95,7 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { blanket_impls: RefCell::new(vec![]), flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS), specialization_graph: RefCell::new(traits::specialization_graph::Graph::new()), + def_path_hash: def_path_hash, } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d2840fbe4fe46..824e892072f57 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -385,12 +385,14 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, let unsafety = parse_unsafety(item_doc); let associated_type_names = parse_associated_type_names(item_doc); let paren_sugar = parse_paren_sugar(item_doc); + let def_path = def_path(cdata, item_id); ty::TraitDef::new(unsafety, paren_sugar, generics, item_trait_ref(item_doc, tcx, cdata), - associated_type_names) + associated_type_names, + def_path.deterministic_hash(tcx)) } pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7d111cdc4156f..04aca8c0947ca 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1290,12 +1290,15 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }).collect(); + let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx); + let trait_ref = ty::TraitRef::new(def_id, substs); let trait_def = ty::TraitDef::new(unsafety, paren_sugar, ty_generics, trait_ref, - associated_type_names); + associated_type_names, + def_path_hash); tcx.intern_trait_def(trait_def) }