15
15
// done by the orphan and overlap modules. Then we build up various
16
16
// mappings. That mapping code resides here.
17
17
18
+ use dep_graph:: DepTrackingMap ;
18
19
use hir:: def_id:: DefId ;
19
- use rustc:: ty:: { self , TyCtxt , TypeFoldable } ;
20
+ use rustc:: ty:: { self , maps , TyCtxt , TypeFoldable } ;
20
21
use rustc:: ty:: { Ty , TyBool , TyChar , TyError } ;
21
22
use rustc:: ty:: { TyParam , TyRawPtr } ;
22
23
use rustc:: ty:: { TyRef , TyAdt , TyDynamic , TyNever , TyTuple } ;
@@ -29,7 +30,7 @@ use rustc::dep_graph::DepNode;
29
30
use rustc:: hir:: itemlikevisit:: ItemLikeVisitor ;
30
31
use rustc:: hir:: { Item , ItemImpl } ;
31
32
use rustc:: hir;
32
- use rustc :: util :: nodemap :: DefIdMap ;
33
+ use std :: cell :: RefMut ;
33
34
34
35
mod builtin;
35
36
mod orphan;
@@ -38,7 +39,7 @@ mod unsafety;
38
39
39
40
struct CoherenceCollect < ' a , ' tcx : ' a > {
40
41
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
41
- inherent_impls : DefIdMap < Vec < DefId > > ,
42
+ inherent_impls : RefMut < ' a , DepTrackingMap < maps :: InherentImpls < ' tcx > > > ,
42
43
}
43
44
44
45
impl < ' a , ' tcx , ' v > ItemLikeVisitor < ' v > for CoherenceCollect < ' a , ' tcx > {
@@ -56,6 +57,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> {
56
57
}
57
58
58
59
impl < ' 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
+
59
70
// Returns the def ID of the base type, if there is one.
60
71
fn get_base_type_def_id ( & self , span : Span , ty : Ty < ' tcx > ) -> Option < DefId > {
61
72
match ty. sty {
@@ -77,18 +88,6 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
77
88
}
78
89
}
79
90
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
-
92
91
fn check_implementation ( & mut self , item : & Item ) {
93
92
let tcx = self . tcx ;
94
93
let impl_did = tcx. hir . local_def_id ( item. id ) ;
@@ -127,9 +126,18 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
127
126
}
128
127
129
128
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) ;
133
141
}
134
142
135
143
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
169
177
}
170
178
171
179
pub fn check_coherence ( ccx : & CrateCtxt ) {
180
+ CoherenceCollect :: check ( ccx. tcx ) ;
181
+
172
182
let _task = ccx. tcx . dep_graph . in_task ( DepNode :: Coherence ) ;
173
- CoherenceCollect { tcx : ccx. tcx , inherent_impls : DefIdMap ( ) } . check ( ) ;
174
183
unsafety:: check ( ccx. tcx ) ;
175
184
orphan:: check ( ccx. tcx ) ;
176
185
overlap:: check ( ccx. tcx ) ;
0 commit comments