1515// done by the orphan and overlap modules. Then we build up various
1616// mappings. That mapping code resides here.
1717
18+ use dep_graph:: DepTrackingMap ;
1819use hir:: def_id:: DefId ;
19- use rustc:: ty:: { self , TyCtxt , TypeFoldable } ;
20+ use rustc:: ty:: { self , maps , TyCtxt , TypeFoldable } ;
2021use rustc:: ty:: { Ty , TyBool , TyChar , TyError } ;
2122use rustc:: ty:: { TyParam , TyRawPtr } ;
2223use rustc:: ty:: { TyRef , TyAdt , TyDynamic , TyNever , TyTuple } ;
@@ -29,7 +30,7 @@ use rustc::dep_graph::DepNode;
2930use rustc:: hir:: itemlikevisit:: ItemLikeVisitor ;
3031use rustc:: hir:: { Item , ItemImpl } ;
3132use rustc:: hir;
32- use rustc :: util :: nodemap :: DefIdMap ;
33+ use std :: cell :: RefMut ;
3334
3435mod builtin;
3536mod orphan;
@@ -38,7 +39,7 @@ mod unsafety;
3839
3940struct CoherenceCollect < ' a , ' tcx : ' a > {
4041 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
41- inherent_impls : DefIdMap < Vec < DefId > > ,
42+ inherent_impls : RefMut < ' a , DepTrackingMap < maps :: InherentImpls < ' tcx > > > ,
4243}
4344
4445impl < ' a , ' tcx , ' v > ItemLikeVisitor < ' v > for CoherenceCollect < ' a , ' tcx > {
@@ -56,6 +57,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> {
5657}
5758
5859impl < ' a , ' tcx > CoherenceCollect < ' a , ' tcx > {
60+ fn check ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
61+ let inherent_impls = tcx. inherent_impls . borrow_mut ( ) ;
62+ let mut this = & mut CoherenceCollect { tcx, inherent_impls } ;
63+
64+ // Check implementations and traits. This populates the tables
65+ // containing the inherent methods and extension methods. It also
66+ // builds up the trait inheritance table.
67+ tcx. visit_all_item_likes_in_krate ( DepNode :: CoherenceCheckImpl , this) ;
68+ }
69+
5970 // Returns the def ID of the base type, if there is one.
6071 fn get_base_type_def_id ( & self , span : Span , ty : Ty < ' tcx > ) -> Option < DefId > {
6172 match ty. sty {
@@ -77,18 +88,6 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
7788 }
7889 }
7990
80- fn check ( & mut self ) {
81- // Check implementations and traits. This populates the tables
82- // containing the inherent methods and extension methods. It also
83- // builds up the trait inheritance table.
84- self . tcx . visit_all_item_likes_in_krate ( DepNode :: CoherenceCheckImpl , self ) ;
85-
86- // Transfer the inherent impl lists, not that they are known, into the tcx
87- for ( ty_def_id, impl_def_ids) in self . inherent_impls . drain ( ) {
88- self . tcx . inherent_impls . borrow_mut ( ) . insert ( ty_def_id, impl_def_ids) ;
89- }
90- }
91-
9291 fn check_implementation ( & mut self , item : & Item ) {
9392 let tcx = self . tcx ;
9493 let impl_did = tcx. hir . local_def_id ( item. id ) ;
@@ -127,9 +126,18 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
127126 }
128127
129128 fn add_inherent_impl ( & mut self , base_def_id : DefId , impl_def_id : DefId ) {
130- self . inherent_impls . entry ( base_def_id)
131- . or_insert ( vec ! [ ] )
132- . push ( impl_def_id) ;
129+ // Subtle: it'd be better to collect these into a local map
130+ // and then write the vector only once all items are known,
131+ // but that leads to degenerate dep-graphs. The problem is
132+ // that the write of that big vector winds up having reads
133+ // from *all* impls in the krate, since we've lost the
134+ // precision basically. This would be ok in the firewall
135+ // model so once we've made progess towards that we can modify
136+ // the strategy here. In the meantime, using `push` is ok
137+ // because we are doing this as a pre-pass before anyone
138+ // actually reads from `inherent_impls` -- and we know this is
139+ // true beacuse we hold the refcell lock.
140+ self . inherent_impls . push ( base_def_id, impl_def_id) ;
133141 }
134142
135143 fn add_trait_impl ( & self , impl_trait_ref : ty:: TraitRef < ' tcx > , impl_def_id : DefId ) {
@@ -169,8 +177,9 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
169177}
170178
171179pub fn check_coherence ( ccx : & CrateCtxt ) {
180+ CoherenceCollect :: check ( ccx. tcx ) ;
181+
172182 let _task = ccx. tcx . dep_graph . in_task ( DepNode :: Coherence ) ;
173- CoherenceCollect { tcx : ccx. tcx , inherent_impls : DefIdMap ( ) } . check ( ) ;
174183 unsafety:: check ( ccx. tcx ) ;
175184 orphan:: check ( ccx. tcx ) ;
176185 overlap:: check ( ccx. tcx ) ;
0 commit comments