@@ -14,6 +14,8 @@ use self::MapEntry::*;
14
14
use self :: collector:: NodeCollector ;
15
15
pub use self :: definitions:: { Definitions , DefKey , DefPath , DefPathData , DisambiguatedDefPathData } ;
16
16
17
+ use dep_graph:: { DepGraph , DepNode } ;
18
+
17
19
use middle:: cstore:: InlinedItem ;
18
20
use middle:: cstore:: InlinedItem as II ;
19
21
use middle:: def_id:: DefId ;
@@ -228,19 +230,22 @@ impl<'ast> MapEntry<'ast> {
228
230
229
231
/// Stores a crate and any number of inlined items from other crates.
230
232
pub struct Forest {
231
- pub krate : Crate ,
233
+ krate : Crate ,
234
+ pub dep_graph : DepGraph ,
232
235
inlined_items : TypedArena < InlinedParent >
233
236
}
234
237
235
238
impl Forest {
236
- pub fn new ( krate : Crate ) -> Forest {
239
+ pub fn new ( krate : Crate , dep_graph : DepGraph ) -> Forest {
237
240
Forest {
238
241
krate : krate,
242
+ dep_graph : dep_graph,
239
243
inlined_items : TypedArena :: new ( )
240
244
}
241
245
}
242
246
243
247
pub fn krate < ' ast > ( & ' ast self ) -> & ' ast Crate {
248
+ self . dep_graph . read ( DepNode :: Krate ) ;
244
249
& self . krate
245
250
}
246
251
}
@@ -252,6 +257,10 @@ pub struct Map<'ast> {
252
257
/// The backing storage for all the AST nodes.
253
258
pub forest : & ' ast Forest ,
254
259
260
+ /// Same as the dep_graph in forest, just available with one fewer
261
+ /// deref. This is a gratuitious micro-optimization.
262
+ pub dep_graph : DepGraph ,
263
+
255
264
/// NodeIds are sequential integers from 0, so we can be
256
265
/// super-compact by storing them in a vector. Not everything with
257
266
/// a NodeId is in the map, but empirically the occupancy is about
@@ -267,6 +276,60 @@ pub struct Map<'ast> {
267
276
}
268
277
269
278
impl < ' ast > Map < ' ast > {
279
+ /// Registers a read in the dependency graph of the AST node with
280
+ /// the given `id`. This needs to be called each time a public
281
+ /// function returns the HIR for a node -- in other words, when it
282
+ /// "reveals" the content of a node to the caller (who might not
283
+ /// otherwise have had access to those contents, and hence needs a
284
+ /// read recorded). If the function just returns a DefId or
285
+ /// NodeId, no actual content was returned, so no read is needed.
286
+ fn read ( & self , id : NodeId ) {
287
+ self . dep_graph . read ( self . dep_node ( id) ) ;
288
+ }
289
+
290
+ fn dep_node ( & self , id0 : NodeId ) -> DepNode {
291
+ let map = self . map . borrow ( ) ;
292
+ let mut id = id0;
293
+ loop {
294
+ match map[ id as usize ] {
295
+ EntryItem ( _, item) => {
296
+ let def_id = self . local_def_id ( item. id ) ;
297
+ // NB ^~~~~~~
298
+ //
299
+ // You would expect that `item.id == id`, but this
300
+ // is not always the case. In particular, for a
301
+ // ViewPath item like `use self::{mem, foo}`, we
302
+ // map the ids for `mem` and `foo` to the
303
+ // enclosing view path item. This seems mega super
304
+ // ultra wrong, but then who am I to judge?
305
+ // -nmatsakis
306
+ return DepNode :: Hir ( def_id) ;
307
+ }
308
+
309
+ EntryForeignItem ( p, _) |
310
+ EntryTraitItem ( p, _) |
311
+ EntryImplItem ( p, _) |
312
+ EntryVariant ( p, _) |
313
+ EntryExpr ( p, _) |
314
+ EntryStmt ( p, _) |
315
+ EntryLocal ( p, _) |
316
+ EntryPat ( p, _) |
317
+ EntryBlock ( p, _) |
318
+ EntryStructCtor ( p, _) |
319
+ EntryLifetime ( p, _) |
320
+ EntryTyParam ( p, _) =>
321
+ id = p,
322
+
323
+ RootCrate |
324
+ RootInlinedParent ( _) => // FIXME(#2369) clarify story about cross-crate dep tracking
325
+ return DepNode :: Krate ,
326
+
327
+ NotPresent =>
328
+ panic ! ( "Walking parents from `{}` led to `NotPresent` at `{}`" , id0, id) ,
329
+ }
330
+ }
331
+ }
332
+
270
333
pub fn num_local_def_ids ( & self ) -> usize {
271
334
self . definitions . borrow ( ) . len ( )
272
335
}
@@ -309,26 +372,30 @@ impl<'ast> Map<'ast> {
309
372
}
310
373
311
374
pub fn krate ( & self ) -> & ' ast Crate {
312
- & self . forest . krate
375
+ self . forest . krate ( )
313
376
}
314
377
315
378
/// Retrieve the Node corresponding to `id`, panicking if it cannot
316
379
/// be found.
317
380
pub fn get ( & self , id : NodeId ) -> Node < ' ast > {
318
381
match self . find ( id) {
319
- Some ( node) => node,
382
+ Some ( node) => node, // read recorded by `find`
320
383
None => panic ! ( "couldn't find node id {} in the AST map" , id)
321
384
}
322
385
}
323
386
324
387
pub fn get_if_local ( & self , id : DefId ) -> Option < Node < ' ast > > {
325
- self . as_local_node_id ( id) . map ( |id| self . get ( id) )
388
+ self . as_local_node_id ( id) . map ( |id| self . get ( id) ) // read recorded by `get`
326
389
}
327
390
328
391
/// Retrieve the Node corresponding to `id`, returning None if
329
392
/// cannot be found.
330
393
pub fn find ( & self , id : NodeId ) -> Option < Node < ' ast > > {
331
- self . find_entry ( id) . and_then ( |x| x. to_node ( ) )
394
+ let result = self . find_entry ( id) . and_then ( |x| x. to_node ( ) ) ;
395
+ if result. is_some ( ) {
396
+ self . read ( id) ;
397
+ }
398
+ result
332
399
}
333
400
334
401
/// Similar to get_parent, returns the parent node id or id if there is no
@@ -459,22 +526,25 @@ impl<'ast> Map<'ast> {
459
526
_ => None
460
527
} ;
461
528
match abi {
462
- Some ( abi) => abi,
529
+ Some ( abi) => {
530
+ self . read ( id) ; // reveals some of the content of a node
531
+ abi
532
+ }
463
533
None => panic ! ( "expected foreign mod or inlined parent, found {}" ,
464
534
self . node_to_string( parent) )
465
535
}
466
536
}
467
537
468
538
pub fn get_foreign_vis ( & self , id : NodeId ) -> Visibility {
469
- let vis = self . expect_foreign_item ( id) . vis ;
470
- match self . find ( self . get_parent ( id) ) {
539
+ let vis = self . expect_foreign_item ( id) . vis ; // read recorded by `expect_foreign_item`
540
+ match self . find ( self . get_parent ( id) ) { // read recorded by `find`
471
541
Some ( NodeItem ( i) ) => vis. inherit_from ( i. vis ) ,
472
542
_ => vis
473
543
}
474
544
}
475
545
476
546
pub fn expect_item ( & self , id : NodeId ) -> & ' ast Item {
477
- match self . find ( id) {
547
+ match self . find ( id) { // read recorded by `find`
478
548
Some ( NodeItem ( item) ) => item,
479
549
_ => panic ! ( "expected item, found {}" , self . node_to_string( id) )
480
550
}
@@ -521,7 +591,7 @@ impl<'ast> Map<'ast> {
521
591
}
522
592
523
593
pub fn expect_expr ( & self , id : NodeId ) -> & ' ast Expr {
524
- match self . find ( id) {
594
+ match self . find ( id) { // read recorded by find
525
595
Some ( NodeExpr ( expr) ) => expr,
526
596
_ => panic ! ( "expected expr, found {}" , self . node_to_string( id) )
527
597
}
@@ -571,6 +641,11 @@ impl<'ast> Map<'ast> {
571
641
fn with_path_next < T , F > ( & self , id : NodeId , next : LinkedPath , f : F ) -> T where
572
642
F : FnOnce ( PathElems ) -> T ,
573
643
{
644
+ // This function reveals the name of the item and hence is a
645
+ // kind of read. This is inefficient, since it walks ancestors
646
+ // and we are walking them anyhow, but whatever.
647
+ self . read ( id) ;
648
+
574
649
let parent = self . get_parent ( id) ;
575
650
let parent = match self . find_entry ( id) {
576
651
Some ( EntryForeignItem ( ..) ) => {
@@ -602,6 +677,7 @@ impl<'ast> Map<'ast> {
602
677
/// Given a node ID, get a list of attributes associated with the AST
603
678
/// corresponding to the Node ID
604
679
pub fn attrs ( & self , id : NodeId ) -> & ' ast [ ast:: Attribute ] {
680
+ self . read ( id) ; // reveals attributes on the node
605
681
let attrs = match self . find ( id) {
606
682
Some ( NodeItem ( i) ) => Some ( & i. attrs [ ..] ) ,
607
683
Some ( NodeForeignItem ( fi) ) => Some ( & fi. attrs [ ..] ) ,
@@ -655,6 +731,7 @@ impl<'ast> Map<'ast> {
655
731
}
656
732
657
733
pub fn span ( & self , id : NodeId ) -> Span {
734
+ self . read ( id) ; // reveals span from node
658
735
self . opt_span ( id)
659
736
. unwrap_or_else ( || panic ! ( "AstMap.span: could not find span for id {:?}" , id) )
660
737
}
@@ -833,6 +910,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
833
910
834
911
Map {
835
912
forest : forest,
913
+ dep_graph : forest. dep_graph . clone ( ) ,
836
914
map : RefCell :: new ( map) ,
837
915
definitions : RefCell :: new ( definitions) ,
838
916
}
0 commit comments