about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-04-17 12:35:53 -0400
committerNiko Matsakis <niko@alum.mit.edu>2017-04-21 17:26:53 -0400
commitf4c183b742cf08c5d06d50b4fbada3561722af81 (patch)
treeca7e0426a573623dff194fd8fc5908c25cfbedca
parente48a759f51ae23f817339eda1485fa3afe6d8d04 (diff)
downloadrust-f4c183b742cf08c5d06d50b4fbada3561722af81.tar.gz
rust-f4c183b742cf08c5d06d50b4fbada3561722af81.zip
move the trans trait caches into tcx
Arguably these could become custom queries, but I chose not to do that
because the relationship of queries and trait system is not yet fleshed
out enough. For now it seems fine to have them be `DepTrackingMap` using
the memoize pattern.
-rw-r--r--src/librustc/traits/mod.rs1
-rw-r--r--src/librustc/traits/trans/mod.rs73
-rw-r--r--src/librustc/ty/context.rs3
-rw-r--r--src/librustc_trans/context.rs66
-rw-r--r--src/librustc_trans/monomorphize.rs24
5 files changed, 89 insertions, 78 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 0ff379b30ff..18f0a749f70 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -55,6 +55,7 @@ mod object_safety;
 mod select;
 mod specialize;
 mod structural_impls;
+pub mod trans;
 mod util;
 
 /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for
diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs
new file mode 100644
index 00000000000..8517f573e60
--- /dev/null
+++ b/src/librustc/traits/trans/mod.rs
@@ -0,0 +1,73 @@
+use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
+use hir::def_id::DefId;
+use std::cell::RefCell;
+use std::marker::PhantomData;
+use traits::Vtable;
+use ty::{self, Ty};
+
+/// Specializes caches used in trans -- in particular, they assume all
+/// types are fully monomorphized and that free regions can be erased.
+pub struct TransTraitCaches<'tcx> {
+    pub trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
+    pub project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
+}
+
+impl<'tcx> TransTraitCaches<'tcx> {
+    pub fn new(graph: DepGraph) -> Self {
+        TransTraitCaches {
+            trait_cache: RefCell::new(DepTrackingMap::new(graph.clone())),
+            project_cache: RefCell::new(DepTrackingMap::new(graph)),
+        }
+    }
+}
+
+// Implement DepTrackingMapConfig for `trait_cache`
+pub struct TraitSelectionCache<'tcx> {
+    data: PhantomData<&'tcx ()>
+}
+
+impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
+    type Key = ty::PolyTraitRef<'tcx>;
+    type Value = Vtable<'tcx, ()>;
+    fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
+        key.to_poly_trait_predicate().dep_node()
+    }
+}
+
+// # 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::TyAdt(adt_def, _) => Some(adt_def.did),
+                   ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
+                   _ => None,
+               })
+               .collect();
+
+        DepNode::ProjectionCache { def_ids: def_ids }
+    }
+}
+
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index a4162925871..e836bf23a5a 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -407,6 +407,8 @@ pub struct GlobalCtxt<'tcx> {
 
     pub specializes_cache: RefCell<traits::SpecializesCache>,
 
+    pub trans_trait_caches: traits::trans::TransTraitCaches<'tcx>,
+
     pub dep_graph: DepGraph,
 
     /// Common types, pre-interned for your convenience.
@@ -689,6 +691,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         providers[LOCAL_CRATE] = local_providers;
         tls::enter_global(GlobalCtxt {
             sess: s,
+            trans_trait_caches: traits::trans::TransTraitCaches::new(dep_graph.clone()),
             specializes_cache: RefCell::new(traits::SpecializesCache::new()),
             global_arenas: arenas,
             global_interners: interners,
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 3769c8b026d..ceb292c13c1 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -10,7 +10,7 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, DepTrackingMapConfig};
+use rustc::dep_graph::{DepGraph, DepGraphSafe};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::traits;
@@ -34,7 +34,6 @@ use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
-use std::marker::PhantomData;
 use std::ptr;
 use std::iter;
 use std::str;
@@ -84,9 +83,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     check_overflow: bool,
 
     use_dll_storage_attrs: bool,
-
-    trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
-    project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -171,56 +167,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
     symbol_cache: &'a SymbolCache<'a, 'tcx>,
 }
 
-// Implement DepTrackingMapConfig for `trait_cache`
-pub struct TraitSelectionCache<'tcx> {
-    data: PhantomData<&'tcx ()>
-}
-
-impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
-    type Key = ty::PolyTraitRef<'tcx>;
-    type Value = traits::Vtable<'tcx, ()>;
-    fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
-        key.to_poly_trait_predicate().dep_node()
-    }
-}
-
-// # 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::TyAdt(adt_def, _) => Some(adt_def.did),
-                   ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
-                   _ => None,
-               })
-               .collect();
-
-        DepNode::ProjectionCache { def_ids: def_ids }
-    }
-}
-
 /// A CrateContext value binds together one LocalCrateContext with the
 /// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
 /// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
@@ -382,8 +328,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
             tcx: tcx,
             check_overflow: check_overflow,
             use_dll_storage_attrs: use_dll_storage_attrs,
-            trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
-            project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
         }
     }
 
@@ -403,14 +347,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
         &self.exported_symbols
     }
 
-    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 tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.tcx
     }
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 382ca8ef010..33626e7c39f 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -117,7 +117,7 @@ fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     // Remove any references to regions; this helps improve caching.
     let trait_ref = tcx.erase_regions(&trait_ref);
 
-    scx.trait_cache().memoize(trait_ref, || {
+    tcx.trans_trait_caches.trait_cache.memoize(trait_ref, || {
         debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
                trait_ref, trait_ref.def_id());
 
@@ -307,7 +307,7 @@ pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
     debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
     let substituted = value.subst(tcx, param_substs);
     let substituted = scx.tcx().erase_regions(&substituted);
-    AssociatedTypeNormalizer::new(scx).fold(&substituted)
+    AssociatedTypeNormalizer::new(tcx).fold(&substituted)
 }
 
 /// Returns the normalized type of a struct field
@@ -319,15 +319,13 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tcx.normalize_associated_type(&f.ty(tcx, param_substs))
 }
 
-struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> {
-    shared: &'a SharedCrateContext<'b, 'gcx>,
+struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
 }
 
-impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> {
-    fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self {
-        AssociatedTypeNormalizer {
-            shared: shared,
-        }
+impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
+    fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
+        AssociatedTypeNormalizer { tcx }
     }
 
     fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
@@ -339,18 +337,18 @@ impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> {
     }
 }
 
-impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> {
+impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
     fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
-        self.shared.tcx()
+        self.tcx
     }
 
     fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
         if !ty.has_projection_types() {
             ty
         } else {
-            self.shared.project_cache().memoize(ty, || {
+            self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
                 debug!("AssociatedTypeNormalizer: ty={:?}", ty);
-                self.shared.tcx().normalize_associated_type(&ty)
+                self.tcx.normalize_associated_type(&ty)
             })
         }
     }