]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/context.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / librustc_trans / context.rs
index c31dbf8943e08972e2daee47d320e78d97c74a70..2422b9f30069b16a38bbc0fa1817bf4c0b86ce85 100644 (file)
@@ -53,9 +53,7 @@ pub struct Stats {
     pub n_glues_created: Cell<usize>,
     pub n_null_glues: Cell<usize>,
     pub n_real_glues: Cell<usize>,
-    pub n_fallback_instantiations: Cell<usize>,
     pub n_fns: Cell<usize>,
-    pub n_monos: Cell<usize>,
     pub n_inlines: Cell<usize>,
     pub n_closures: Cell<usize>,
     pub n_llvm_insns: Cell<usize>,
@@ -79,7 +77,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     stats: Stats,
     check_overflow: bool,
-    check_drop_flag_for_sanity: bool,
     mir_map: &'a MirMap<'tcx>,
     mir_cache: RefCell<DepTrackingMap<MirCache<'tcx>>>,
 
@@ -87,6 +84,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
 
     translation_items: RefCell<FnvHashSet<TransItem<'tcx>>>,
     trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
+    project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -104,7 +102,6 @@ pub struct LocalCrateContext<'tcx> {
     drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
-    monomorphizing: RefCell<DefIdMap<usize>>,
     /// Cache generated vtables
     vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
     /// Cache of constant strings,
@@ -199,6 +196,46 @@ fn to_dep_node(key: &DefId) -> DepNode<DefId> {
     }
 }
 
+// # Global Cache
+
+pub struct ProjectionCache<'gcx> {
+    data: PhantomData<&'gcx ()>
+}
+
+impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
+    type Key = Ty<'gcx>;
+    type Value = Ty<'gcx>;
+    fn to_dep_node(key: &Self::Key) -> DepNode<DefId> {
+        // Ideally, we'd just put `key` into the dep-node, but we
+        // can't put full types in there. So just collect up all the
+        // def-ids of structs/enums as well as any traits that we
+        // project out of. It doesn't matter so much what we do here,
+        // except that if we are too coarse, we'll create overly
+        // coarse edges between impls and the trans. For example, if
+        // we just used the def-id of things we are projecting out of,
+        // then the key for `<Foo as SomeTrait>::T` and `<Bar as
+        // SomeTrait>::T` would both share a dep-node
+        // (`TraitSelect(SomeTrait)`), and hence the impls for both
+        // `Foo` and `Bar` would be considered inputs. So a change to
+        // `Bar` would affect things that just normalized `Foo`.
+        // Anyway, this heuristic is not ideal, but better than
+        // nothing.
+        let def_ids: Vec<DefId> =
+            key.walk()
+               .filter_map(|t| match t.sty {
+                   ty::TyStruct(adt_def, _) |
+                   ty::TyEnum(adt_def, _) =>
+                       Some(adt_def.did),
+                   ty::TyProjection(ref proj) =>
+                       Some(proj.trait_ref.def_id),
+                   _ =>
+                       None
+               })
+               .collect();
+        DepNode::TraitSelect(def_ids)
+    }
+}
+
 /// This list owns a number of LocalCrateContexts and binds them to their common
 /// SharedCrateContext. This type just exists as a convenience, something to
 /// pass around all LocalCrateContexts with and get an iterator over them.
@@ -424,8 +461,7 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                symbol_hasher: Sha256,
                link_meta: LinkMeta,
                reachable: NodeSet,
-               check_overflow: bool,
-               check_drop_flag_for_sanity: bool)
+               check_overflow: bool)
                -> SharedCrateContext<'b, 'tcx> {
         let (metadata_llcx, metadata_llmod) = unsafe {
             create_context_and_module(&tcx.sess, "metadata")
@@ -490,9 +526,7 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                 n_glues_created: Cell::new(0),
                 n_null_glues: Cell::new(0),
                 n_real_glues: Cell::new(0),
-                n_fallback_instantiations: Cell::new(0),
                 n_fns: Cell::new(0),
-                n_monos: Cell::new(0),
                 n_inlines: Cell::new(0),
                 n_closures: Cell::new(0),
                 n_llvm_insns: Cell::new(0),
@@ -500,10 +534,10 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                 fn_stats: RefCell::new(Vec::new()),
             },
             check_overflow: check_overflow,
-            check_drop_flag_for_sanity: check_drop_flag_for_sanity,
             use_dll_storage_attrs: use_dll_storage_attrs,
             translation_items: RefCell::new(FnvHashSet()),
             trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
+            project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
         }
     }
 
@@ -527,6 +561,10 @@ pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>
         &self.trait_cache
     }
 
+    pub fn project_cache(&self) -> &RefCell<DepTrackingMap<ProjectionCache<'tcx>>> {
+        &self.project_cache
+    }
+
     pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
         &self.link_meta
     }
@@ -571,7 +609,9 @@ pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'tcx>>> {
     /// Given the def-id of some item that has no type parameters, make
     /// a suitable "empty substs" for it.
     pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
-        Substs::for_item(self.tcx(), item_def_id, |_, _| ty::ReErased, |_, _| {
+        Substs::for_item(self.tcx(), item_def_id,
+                         |_, _| self.tcx().mk_region(ty::ReErased),
+                         |_, _| {
             bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
         })
     }
@@ -629,7 +669,6 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
                 fn_pointer_shims: RefCell::new(FnvHashMap()),
                 drop_glues: RefCell::new(FnvHashMap()),
                 instances: RefCell::new(FnvHashMap()),
-                monomorphizing: RefCell::new(DefIdMap()),
                 vtables: RefCell::new(FnvHashMap()),
                 const_cstr_cache: RefCell::new(FnvHashMap()),
                 const_unsized: RefCell::new(FnvHashMap()),
@@ -833,10 +872,6 @@ pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRe
         &self.local().instances
     }
 
-    pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<usize>> {
-        &self.local().monomorphizing
-    }
-
     pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
         &self.local().vtables
     }
@@ -960,15 +995,16 @@ pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> {
         TypeOfDepthLock(self.local())
     }
 
-    pub fn check_overflow(&self) -> bool {
-        self.shared.check_overflow
+    pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout {
+        self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| {
+            ty.layout(&infcx).unwrap_or_else(|e| {
+                bug!("failed to get layout for `{}`: {}", ty, e);
+            })
+        })
     }
 
-    pub fn check_drop_flag_for_sanity(&self) -> bool {
-        // This controls whether we emit a conditional llvm.debugtrap
-        // guarded on whether the dropflag is one of its (two) valid
-        // values.
-        self.shared.check_drop_flag_for_sanity
+    pub fn check_overflow(&self) -> bool {
+        self.shared.check_overflow
     }
 
     pub fn use_dll_storage_attrs(&self) -> bool {