]> git.lizzy.rs Git - rust.git/commitdiff
Make sure that projection bounds in ty::TraitObject are sorted in a way that is stabl...
authorMichael Woerister <michaelwoerister@posteo.net>
Mon, 12 Sep 2016 22:09:49 +0000 (18:09 -0400)
committerMichael Woerister <michaelwoerister@posteo.net>
Tue, 13 Sep 2016 19:22:51 +0000 (15:22 -0400)
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/ty/trait_def.rs
src/librustc_metadata/decoder.rs
src/librustc_typeck/collect.rs

index 20601493d68f3e16bf5ee5936fc6e754b2c02fa5..6d7a2d6cba1c761640e53bde00f84c17b0cec0ca 100644 (file)
@@ -1303,7 +1303,7 @@ pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'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))
     }
 
index f634c8e37d7bd054db2dbe297aeb03fd99612128..14eb2fb7914c36f30dd03f60ac26415dce349f74 100644 (file)
@@ -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> {
index a755dd056cd8483a07ca03ef0498ed690f14de11..5fdc7abc0af5b0631f1b804bd6bfcfae28aaa586 100644 (file)
@@ -23,7 +23,7 @@
 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 @@ pub fn item_name(&self) -> Name {
         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>,
index 61285e8f8b0a597ef378b284e9410f644ccdc80f..268b2fcaa4adbb8687b833a9a06ee6f4cdddab90 100644 (file)
@@ -70,7 +70,11 @@ pub struct TraitDef<'tcx> {
     pub specialization_graph: RefCell<traits::specialization_graph::Graph>,
 
     /// Various flags
-    pub flags: Cell<TraitFlags>
+    pub flags: Cell<TraitFlags>,
+
+    /// 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 @@ pub fn new(unsafety: hir::Unsafety,
                paren_sugar: bool,
                generics: &'tcx ty::Generics<'tcx>,
                trait_ref: ty::TraitRef<'tcx>,
-               associated_type_names: Vec<Name>)
+               associated_type_names: Vec<Name>,
+               def_path_hash: u64)
                -> TraitDef<'tcx> {
         TraitDef {
             paren_sugar: paren_sugar,
@@ -90,6 +95,7 @@ pub fn new(unsafety: hir::Unsafety,
             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,
         }
     }
 
index d2840fbe4fe463dff187897c3dfe5eca54e5b8e1..824e892072f57a1995aff41bb538564e2c9f0b1a 100644 (file)
@@ -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,
index 7d111cdc4156f66d5f88960edcf4cdafdfb0b980..04aca8c0947caa7e603a9bbfd8efe499c965d4df 100644 (file)
@@ -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)
 }