@@ -128,13 +128,62 @@ struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
128
128
ccx : & ' a CrateCtxt < ' a , ' tcx >
129
129
}
130
130
131
+ impl < ' a , ' tcx > CollectItemTypesVisitor < ' a , ' tcx > {
132
+ /// Collect item types is structured into two tasks. The outer
133
+ /// task, `CollectItem`, walks the entire content of an item-like
134
+ /// thing, including its body. It also spawns an inner task,
135
+ /// `CollectItemSig`, which walks only the signature. This inner
136
+ /// task is the one that writes the item-type into the various
137
+ /// maps. This setup ensures that the item body is never
138
+ /// accessible to the task that computes its signature, so that
139
+ /// changes to the body don't affect the signature.
140
+ ///
141
+ /// Consider an example function `foo` that also has a closure in its body:
142
+ ///
143
+ /// ```
144
+ /// fn foo(<sig>) {
145
+ /// ...
146
+ /// let bar = || ...; // we'll label this closure as "bar" below
147
+ /// }
148
+ /// ```
149
+ ///
150
+ /// This results in a dep-graph like so. I've labeled the edges to
151
+ /// document where they arise.
152
+ ///
153
+ /// ```
154
+ /// [HirBody(foo)] -2--> [CollectItem(foo)] -4-> [ItemSignature(bar)]
155
+ /// ^ ^
156
+ /// 1 3
157
+ /// [Hir(foo)] -----------+-6-> [CollectItemSig(foo)] -5-> [ItemSignature(foo)]
158
+ /// ```
159
+ ///
160
+ /// 1. This is added by the `visit_all_item_likes_in_krate`.
161
+ /// 2. This is added when we fetch the item body.
162
+ /// 3. This is added because `CollectItem` launches `CollectItemSig`.
163
+ /// - it is arguably false; if we refactor the `with_task` system;
164
+ /// we could get probably rid of it, but it is also harmless enough.
165
+ /// 4. This is added by the code in `visit_expr` when we write to `item_types`.
166
+ /// 5. This is added by the code in `convert_item` when we write to `item_types`;
167
+ /// note that this write occurs inside the `CollectItemSig` task.
168
+ /// 6. Added by explicit `read` below
169
+ fn with_collect_item_sig < OP > ( & self , id : ast:: NodeId , op : OP )
170
+ where OP : FnOnce ( )
171
+ {
172
+ let def_id = self . ccx . tcx . map . local_def_id ( id) ;
173
+ self . ccx . tcx . dep_graph . with_task ( DepNode :: CollectItemSig ( def_id) , || {
174
+ self . ccx . tcx . map . read ( id) ;
175
+ op ( ) ;
176
+ } ) ;
177
+ }
178
+ }
179
+
131
180
impl < ' a , ' tcx > Visitor < ' tcx > for CollectItemTypesVisitor < ' a , ' tcx > {
132
181
fn nested_visit_map ( & mut self ) -> Option < ( & hir:: map:: Map < ' tcx > , NestedVisitMode ) > {
133
182
Some ( ( & self . ccx . tcx . map , NestedVisitMode :: OnlyBodies ) )
134
183
}
135
184
136
185
fn visit_item ( & mut self , item : & ' tcx hir:: Item ) {
137
- convert_item ( self . ccx , item) ;
186
+ self . with_collect_item_sig ( item . id , || convert_item ( self . ccx , item) ) ;
138
187
intravisit:: walk_item ( self , item) ;
139
188
}
140
189
@@ -154,7 +203,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
154
203
}
155
204
156
205
fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem ) {
157
- convert_impl_item ( self . ccx , impl_item) ;
206
+ self . with_collect_item_sig ( impl_item. id , || {
207
+ convert_impl_item ( self . ccx , impl_item)
208
+ } ) ;
158
209
intravisit:: walk_impl_item ( self , impl_item) ;
159
210
}
160
211
}
0 commit comments