1010
1111use super :: * ;
1212
13+ use dep_graph:: { DepGraph , DepKind , DepNodeIndex } ;
1314use hir:: intravisit:: { Visitor , NestedVisitorMap } ;
1415use std:: iter:: repeat;
1516use syntax:: ast:: { NodeId , CRATE_NODE_ID } ;
1617use syntax_pos:: Span ;
1718
1819/// A Visitor that walks over the HIR and collects Nodes into a HIR map
19- pub struct NodeCollector < ' hir > {
20+ pub ( super ) struct NodeCollector < ' a , ' hir > {
2021 /// The crate
21- pub krate : & ' hir Crate ,
22+ krate : & ' hir Crate ,
2223 /// The node map
23- pub ( super ) map : Vec < MapEntry < ' hir > > ,
24+ map : Vec < MapEntry < ' hir > > ,
2425 /// The parent of this node
25- pub parent_node : NodeId ,
26+ parent_node : NodeId ,
27+
28+ current_dep_node_owner : DefIndex ,
29+ current_dep_node_index : DepNodeIndex ,
30+
31+ dep_graph : & ' a DepGraph ,
32+ definitions : & ' a definitions:: Definitions ,
2633}
2734
28- impl < ' hir > NodeCollector < ' hir > {
29- pub fn root ( krate : & ' hir Crate ) -> NodeCollector < ' hir > {
35+ impl < ' a , ' hir > NodeCollector < ' a , ' hir > {
36+ pub ( super ) fn root ( krate : & ' hir Crate ,
37+ dep_graph : & ' a DepGraph ,
38+ definitions : & ' a definitions:: Definitions )
39+ -> NodeCollector < ' a , ' hir > {
40+ let root_mod_def_path_hash = definitions. def_path_hash ( CRATE_DEF_INDEX ) ;
41+ let root_mod_dep_node = root_mod_def_path_hash. to_dep_node ( DepKind :: Hir ) ;
42+ let root_mod_dep_node_index = dep_graph. alloc_input_node ( root_mod_dep_node) ;
43+
3044 let mut collector = NodeCollector {
3145 krate,
3246 map : vec ! [ ] ,
3347 parent_node : CRATE_NODE_ID ,
48+ current_dep_node_index : root_mod_dep_node_index,
49+ current_dep_node_owner : CRATE_DEF_INDEX ,
50+ dep_graph,
51+ definitions,
3452 } ;
35- collector. insert_entry ( CRATE_NODE_ID , RootCrate ) ;
53+ collector. insert_entry ( CRATE_NODE_ID , RootCrate ( root_mod_dep_node_index ) ) ;
3654
3755 collector
3856 }
3957
58+ pub ( super ) fn into_map ( self ) -> Vec < MapEntry < ' hir > > {
59+ self . map
60+ }
61+
4062 fn insert_entry ( & mut self , id : NodeId , entry : MapEntry < ' hir > ) {
4163 debug ! ( "hir_map: {:?} => {:?}" , id, entry) ;
4264 let len = self . map . len ( ) ;
@@ -47,8 +69,55 @@ impl<'hir> NodeCollector<'hir> {
4769 }
4870
4971 fn insert ( & mut self , id : NodeId , node : Node < ' hir > ) {
50- let entry = MapEntry :: from_node ( self . parent_node , node) ;
72+ let parent = self . parent_node ;
73+ let dep_node_index = self . current_dep_node_index ;
74+
75+ let entry = match node {
76+ NodeItem ( n) => EntryItem ( parent, dep_node_index, n) ,
77+ NodeForeignItem ( n) => EntryForeignItem ( parent, dep_node_index, n) ,
78+ NodeTraitItem ( n) => EntryTraitItem ( parent, dep_node_index, n) ,
79+ NodeImplItem ( n) => EntryImplItem ( parent, dep_node_index, n) ,
80+ NodeVariant ( n) => EntryVariant ( parent, dep_node_index, n) ,
81+ NodeField ( n) => EntryField ( parent, dep_node_index, n) ,
82+ NodeExpr ( n) => EntryExpr ( parent, dep_node_index, n) ,
83+ NodeStmt ( n) => EntryStmt ( parent, dep_node_index, n) ,
84+ NodeTy ( n) => EntryTy ( parent, dep_node_index, n) ,
85+ NodeTraitRef ( n) => EntryTraitRef ( parent, dep_node_index, n) ,
86+ NodeBinding ( n) => EntryBinding ( parent, dep_node_index, n) ,
87+ NodePat ( n) => EntryPat ( parent, dep_node_index, n) ,
88+ NodeBlock ( n) => EntryBlock ( parent, dep_node_index, n) ,
89+ NodeStructCtor ( n) => EntryStructCtor ( parent, dep_node_index, n) ,
90+ NodeLifetime ( n) => EntryLifetime ( parent, dep_node_index, n) ,
91+ NodeTyParam ( n) => EntryTyParam ( parent, dep_node_index, n) ,
92+ NodeVisibility ( n) => EntryVisibility ( parent, dep_node_index, n) ,
93+ NodeLocal ( n) => EntryLocal ( parent, dep_node_index, n) ,
94+ } ;
95+
96+ // Make sure that the DepNode of some node coincides with the HirId
97+ // owner of that node.
98+ if cfg ! ( debug_assertions) {
99+ let hir_id_owner = self . definitions . node_to_hir_id ( id) . owner ;
100+
101+ if hir_id_owner != self . current_dep_node_owner {
102+ let node_str = match self . definitions . opt_def_index ( id) {
103+ Some ( def_index) => {
104+ self . definitions . def_path ( def_index) . to_string_no_crate ( )
105+ }
106+ None => format ! ( "{:?}" , node)
107+ } ;
108+
109+ bug ! ( "inconsistent DepNode for `{}`: \
110+ current_dep_node_owner={}, hir_id.owner={}",
111+ node_str,
112+ self . definitions
113+ . def_path( self . current_dep_node_owner)
114+ . to_string_no_crate( ) ,
115+ self . definitions. def_path( hir_id_owner) . to_string_no_crate( ) )
116+ }
117+ }
118+
51119 self . insert_entry ( id, entry) ;
120+
52121 }
53122
54123 fn with_parent < F : FnOnce ( & mut Self ) > ( & mut self , parent_id : NodeId , f : F ) {
@@ -57,9 +126,27 @@ impl<'hir> NodeCollector<'hir> {
57126 f ( self ) ;
58127 self . parent_node = parent_node;
59128 }
129+
130+ fn with_dep_node_owner < F : FnOnce ( & mut Self ) > ( & mut self ,
131+ dep_node_owner : DefIndex ,
132+ f : F ) {
133+ let prev_owner = self . current_dep_node_owner ;
134+ let prev_index = self . current_dep_node_index ;
135+
136+ // When we enter a new owner (item, impl item, or trait item), we always
137+ // start out again with DepKind::Hir.
138+ let new_dep_node = self . definitions
139+ . def_path_hash ( dep_node_owner)
140+ . to_dep_node ( DepKind :: Hir ) ;
141+ self . current_dep_node_index = self . dep_graph . alloc_input_node ( new_dep_node) ;
142+ self . current_dep_node_owner = dep_node_owner;
143+ f ( self ) ;
144+ self . current_dep_node_index = prev_index;
145+ self . current_dep_node_owner = prev_owner;
146+ }
60147}
61148
62- impl < ' hir > Visitor < ' hir > for NodeCollector < ' hir > {
149+ impl < ' a , ' hir > Visitor < ' hir > for NodeCollector < ' a , ' hir > {
63150 /// Because we want to track parent items and so forth, enable
64151 /// deep walking so that we walk nested items in the context of
65152 /// their outer items.
@@ -82,25 +169,37 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
82169 }
83170
84171 fn visit_nested_body ( & mut self , id : BodyId ) {
172+ // When we enter a body, we switch to DepKind::HirBody.
173+ // Note that current_dep_node_index might already be DepKind::HirBody,
174+ // e.g. when entering the body of a closure that is already part of a
175+ // surrounding body. That's expected and not a problem.
176+ let prev_index = self . current_dep_node_index ;
177+ let new_dep_node = self . definitions
178+ . def_path_hash ( self . current_dep_node_owner )
179+ . to_dep_node ( DepKind :: HirBody ) ;
180+ self . current_dep_node_index = self . dep_graph . alloc_input_node ( new_dep_node) ;
85181 self . visit_body ( self . krate . body ( id) ) ;
182+ self . current_dep_node_index = prev_index;
86183 }
87184
88185 fn visit_item ( & mut self , i : & ' hir Item ) {
89186 debug ! ( "visit_item: {:?}" , i) ;
90-
91- self . insert ( i. id , NodeItem ( i) ) ;
92-
93- self . with_parent ( i. id , |this| {
94- match i. node {
95- ItemStruct ( ref struct_def, _) => {
96- // If this is a tuple-like struct, register the constructor.
97- if !struct_def. is_struct ( ) {
98- this. insert ( struct_def. id ( ) , NodeStructCtor ( struct_def) ) ;
187+ debug_assert_eq ! ( i. hir_id. owner,
188+ self . definitions. opt_def_index( i. id) . unwrap( ) ) ;
189+ self . with_dep_node_owner ( i. hir_id . owner , |this| {
190+ this. insert ( i. id , NodeItem ( i) ) ;
191+ this. with_parent ( i. id , |this| {
192+ match i. node {
193+ ItemStruct ( ref struct_def, _) => {
194+ // If this is a tuple-like struct, register the constructor.
195+ if !struct_def. is_struct ( ) {
196+ this. insert ( struct_def. id ( ) , NodeStructCtor ( struct_def) ) ;
197+ }
99198 }
199+ _ => { }
100200 }
101- _ => { }
102- }
103- intravisit:: walk_item ( this, i) ;
201+ intravisit:: walk_item ( this, i) ;
202+ } ) ;
104203 } ) ;
105204 }
106205
@@ -121,18 +220,26 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
121220 }
122221
123222 fn visit_trait_item ( & mut self , ti : & ' hir TraitItem ) {
124- self . insert ( ti. id , NodeTraitItem ( ti) ) ;
125-
126- self . with_parent ( ti. id , |this| {
127- intravisit:: walk_trait_item ( this, ti) ;
223+ debug_assert_eq ! ( ti. hir_id. owner,
224+ self . definitions. opt_def_index( ti. id) . unwrap( ) ) ;
225+ self . with_dep_node_owner ( ti. hir_id . owner , |this| {
226+ this. insert ( ti. id , NodeTraitItem ( ti) ) ;
227+
228+ this. with_parent ( ti. id , |this| {
229+ intravisit:: walk_trait_item ( this, ti) ;
230+ } ) ;
128231 } ) ;
129232 }
130233
131234 fn visit_impl_item ( & mut self , ii : & ' hir ImplItem ) {
132- self . insert ( ii. id , NodeImplItem ( ii) ) ;
133-
134- self . with_parent ( ii. id , |this| {
135- intravisit:: walk_impl_item ( this, ii) ;
235+ debug_assert_eq ! ( ii. hir_id. owner,
236+ self . definitions. opt_def_index( ii. id) . unwrap( ) ) ;
237+ self . with_dep_node_owner ( ii. hir_id . owner , |this| {
238+ this. insert ( ii. id , NodeImplItem ( ii) ) ;
239+
240+ this. with_parent ( ii. id , |this| {
241+ intravisit:: walk_impl_item ( this, ii) ;
242+ } ) ;
136243 } ) ;
137244 }
138245
@@ -238,4 +345,33 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
238345 intravisit:: walk_struct_field ( this, field) ;
239346 } ) ;
240347 }
348+
349+ fn visit_trait_item_ref ( & mut self , ii : & ' hir TraitItemRef ) {
350+ // Do not visit the duplicate information in TraitItemRef. We want to
351+ // map the actual nodes, not the duplicate ones in the *Ref.
352+ let TraitItemRef {
353+ id,
354+ name : _,
355+ kind : _,
356+ span : _,
357+ defaultness : _,
358+ } = * ii;
359+
360+ self . visit_nested_trait_item ( id) ;
361+ }
362+
363+ fn visit_impl_item_ref ( & mut self , ii : & ' hir ImplItemRef ) {
364+ // Do not visit the duplicate information in ImplItemRef. We want to
365+ // map the actual nodes, not the duplicate ones in the *Ref.
366+ let ImplItemRef {
367+ id,
368+ name : _,
369+ kind : _,
370+ span : _,
371+ vis : _,
372+ defaultness : _,
373+ } = * ii;
374+
375+ self . visit_nested_impl_item ( id) ;
376+ }
241377}
0 commit comments