@@ -84,6 +84,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
8484
8585 translation_items : RefCell < FnvHashSet < TransItem < ' tcx > > > ,
8686 trait_cache : RefCell < DepTrackingMap < TraitSelectionCache < ' tcx > > > ,
87+ project_cache : RefCell < DepTrackingMap < ProjectionCache < ' tcx > > > ,
8788}
8889
8990/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@@ -195,6 +196,46 @@ impl<'tcx> DepTrackingMapConfig for MirCache<'tcx> {
195196 }
196197}
197198
199+ // # Global Cache
200+
201+ pub struct ProjectionCache < ' gcx > {
202+ data : PhantomData < & ' gcx ( ) >
203+ }
204+
205+ impl < ' gcx > DepTrackingMapConfig for ProjectionCache < ' gcx > {
206+ type Key = Ty < ' gcx > ;
207+ type Value = Ty < ' gcx > ;
208+ fn to_dep_node ( key : & Self :: Key ) -> DepNode < DefId > {
209+ // Ideally, we'd just put `key` into the dep-node, but we
210+ // can't put full types in there. So just collect up all the
211+ // def-ids of structs/enums as well as any traits that we
212+ // project out of. It doesn't matter so much what we do here,
213+ // except that if we are too coarse, we'll create overly
214+ // coarse edges between impls and the trans. For example, if
215+ // we just used the def-id of things we are projecting out of,
216+ // then the key for `<Foo as SomeTrait>::T` and `<Bar as
217+ // SomeTrait>::T` would both share a dep-node
218+ // (`TraitSelect(SomeTrait)`), and hence the impls for both
219+ // `Foo` and `Bar` would be considered inputs. So a change to
220+ // `Bar` would affect things that just normalized `Foo`.
221+ // Anyway, this heuristic is not ideal, but better than
222+ // nothing.
223+ let def_ids: Vec < DefId > =
224+ key. walk ( )
225+ . filter_map ( |t| match t. sty {
226+ ty:: TyStruct ( adt_def, _) |
227+ ty:: TyEnum ( adt_def, _) =>
228+ Some ( adt_def. did ) ,
229+ ty:: TyProjection ( ref proj) =>
230+ Some ( proj. trait_ref . def_id ) ,
231+ _ =>
232+ None
233+ } )
234+ . collect ( ) ;
235+ DepNode :: TraitSelect ( def_ids)
236+ }
237+ }
238+
198239/// This list owns a number of LocalCrateContexts and binds them to their common
199240/// SharedCrateContext. This type just exists as a convenience, something to
200241/// pass around all LocalCrateContexts with and get an iterator over them.
@@ -496,6 +537,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
496537 use_dll_storage_attrs : use_dll_storage_attrs,
497538 translation_items : RefCell :: new ( FnvHashSet ( ) ) ,
498539 trait_cache : RefCell :: new ( DepTrackingMap :: new ( tcx. dep_graph . clone ( ) ) ) ,
540+ project_cache : RefCell :: new ( DepTrackingMap :: new ( tcx. dep_graph . clone ( ) ) ) ,
499541 }
500542 }
501543
@@ -519,6 +561,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
519561 & self . trait_cache
520562 }
521563
564+ pub fn project_cache ( & self ) -> & RefCell < DepTrackingMap < ProjectionCache < ' tcx > > > {
565+ & self . project_cache
566+ }
567+
522568 pub fn link_meta < ' a > ( & ' a self ) -> & ' a LinkMeta {
523569 & self . link_meta
524570 }
0 commit comments