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`
}
}
+// # 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.
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())),
}
}
&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
}
/// 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)
})
}
TypeOfDepthLock(self.local())
}
+ 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_overflow(&self) -> bool {
self.shared.check_overflow
}