@@ -14,6 +14,8 @@ use self::MapEntry::*;
1414use self :: collector:: NodeCollector ;
1515pub use self :: definitions:: { Definitions , DefKey , DefPath , DefPathData , DisambiguatedDefPathData } ;
1616
17+ use dep_graph:: { DepGraph , DepNode } ;
18+
1719use middle:: cstore:: InlinedItem ;
1820use middle:: cstore:: InlinedItem as II ;
1921use middle:: def_id:: DefId ;
@@ -228,19 +230,22 @@ impl<'ast> MapEntry<'ast> {
228230
229231/// Stores a crate and any number of inlined items from other crates.
230232pub struct Forest {
231- pub krate : Crate ,
233+ krate : Crate ,
234+ pub dep_graph : DepGraph ,
232235 inlined_items : TypedArena < InlinedParent >
233236}
234237
235238impl Forest {
236- pub fn new ( krate : Crate ) -> Forest {
239+ pub fn new ( krate : Crate , dep_graph : DepGraph ) -> Forest {
237240 Forest {
238241 krate : krate,
242+ dep_graph : dep_graph,
239243 inlined_items : TypedArena :: new ( )
240244 }
241245 }
242246
243247 pub fn krate < ' ast > ( & ' ast self ) -> & ' ast Crate {
248+ self . dep_graph . read ( DepNode :: Krate ) ;
244249 & self . krate
245250 }
246251}
@@ -252,6 +257,10 @@ pub struct Map<'ast> {
252257 /// The backing storage for all the AST nodes.
253258 pub forest : & ' ast Forest ,
254259
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+
255264 /// NodeIds are sequential integers from 0, so we can be
256265 /// super-compact by storing them in a vector. Not everything with
257266 /// a NodeId is in the map, but empirically the occupancy is about
@@ -267,6 +276,60 @@ pub struct Map<'ast> {
267276}
268277
269278impl < ' 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+
270333 pub fn num_local_def_ids ( & self ) -> usize {
271334 self . definitions . borrow ( ) . len ( )
272335 }
@@ -309,26 +372,30 @@ impl<'ast> Map<'ast> {
309372 }
310373
311374 pub fn krate ( & self ) -> & ' ast Crate {
312- & self . forest . krate
375+ self . forest . krate ( )
313376 }
314377
315378 /// Retrieve the Node corresponding to `id`, panicking if it cannot
316379 /// be found.
317380 pub fn get ( & self , id : NodeId ) -> Node < ' ast > {
318381 match self . find ( id) {
319- Some ( node) => node,
382+ Some ( node) => node, // read recorded by `find`
320383 None => panic ! ( "couldn't find node id {} in the AST map" , id)
321384 }
322385 }
323386
324387 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`
326389 }
327390
328391 /// Retrieve the Node corresponding to `id`, returning None if
329392 /// cannot be found.
330393 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
332399 }
333400
334401 /// Similar to get_parent, returns the parent node id or id if there is no
@@ -459,22 +526,25 @@ impl<'ast> Map<'ast> {
459526 _ => None
460527 } ;
461528 match abi {
462- Some ( abi) => abi,
529+ Some ( abi) => {
530+ self . read ( id) ; // reveals some of the content of a node
531+ abi
532+ }
463533 None => panic ! ( "expected foreign mod or inlined parent, found {}" ,
464534 self . node_to_string( parent) )
465535 }
466536 }
467537
468538 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`
471541 Some ( NodeItem ( i) ) => vis. inherit_from ( i. vis ) ,
472542 _ => vis
473543 }
474544 }
475545
476546 pub fn expect_item ( & self , id : NodeId ) -> & ' ast Item {
477- match self . find ( id) {
547+ match self . find ( id) { // read recorded by `find`
478548 Some ( NodeItem ( item) ) => item,
479549 _ => panic ! ( "expected item, found {}" , self . node_to_string( id) )
480550 }
@@ -521,7 +591,7 @@ impl<'ast> Map<'ast> {
521591 }
522592
523593 pub fn expect_expr ( & self , id : NodeId ) -> & ' ast Expr {
524- match self . find ( id) {
594+ match self . find ( id) { // read recorded by find
525595 Some ( NodeExpr ( expr) ) => expr,
526596 _ => panic ! ( "expected expr, found {}" , self . node_to_string( id) )
527597 }
@@ -571,6 +641,11 @@ impl<'ast> Map<'ast> {
571641 fn with_path_next < T , F > ( & self , id : NodeId , next : LinkedPath , f : F ) -> T where
572642 F : FnOnce ( PathElems ) -> T ,
573643 {
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+
574649 let parent = self . get_parent ( id) ;
575650 let parent = match self . find_entry ( id) {
576651 Some ( EntryForeignItem ( ..) ) => {
@@ -602,6 +677,7 @@ impl<'ast> Map<'ast> {
602677 /// Given a node ID, get a list of attributes associated with the AST
603678 /// corresponding to the Node ID
604679 pub fn attrs ( & self , id : NodeId ) -> & ' ast [ ast:: Attribute ] {
680+ self . read ( id) ; // reveals attributes on the node
605681 let attrs = match self . find ( id) {
606682 Some ( NodeItem ( i) ) => Some ( & i. attrs [ ..] ) ,
607683 Some ( NodeForeignItem ( fi) ) => Some ( & fi. attrs [ ..] ) ,
@@ -655,6 +731,7 @@ impl<'ast> Map<'ast> {
655731 }
656732
657733 pub fn span ( & self , id : NodeId ) -> Span {
734+ self . read ( id) ; // reveals span from node
658735 self . opt_span ( id)
659736 . unwrap_or_else ( || panic ! ( "AstMap.span: could not find span for id {:?}" , id) )
660737 }
@@ -833,6 +910,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
833910
834911 Map {
835912 forest : forest,
913+ dep_graph : forest. dep_graph . clone ( ) ,
836914 map : RefCell :: new ( map) ,
837915 definitions : RefCell :: new ( definitions) ,
838916 }
0 commit comments