10
10
11
11
use super :: * ;
12
12
13
+ use dep_graph:: { DepGraph , DepKind , DepNodeIndex } ;
13
14
use hir:: intravisit:: { Visitor , NestedVisitorMap } ;
14
15
use std:: iter:: repeat;
15
16
use syntax:: ast:: { NodeId , CRATE_NODE_ID } ;
16
17
use syntax_pos:: Span ;
17
18
18
19
/// 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 > {
20
21
/// The crate
21
- pub krate : & ' hir Crate ,
22
+ krate : & ' hir Crate ,
22
23
/// The node map
23
- pub ( super ) map : Vec < MapEntry < ' hir > > ,
24
+ map : Vec < MapEntry < ' hir > > ,
24
25
/// 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 ,
26
33
}
27
34
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
+
30
44
let mut collector = NodeCollector {
31
45
krate,
32
46
map : vec ! [ ] ,
33
47
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,
34
52
} ;
35
- collector. insert_entry ( CRATE_NODE_ID , RootCrate ) ;
53
+ collector. insert_entry ( CRATE_NODE_ID , RootCrate ( root_mod_dep_node_index ) ) ;
36
54
37
55
collector
38
56
}
39
57
58
+ pub ( super ) fn into_map ( self ) -> Vec < MapEntry < ' hir > > {
59
+ self . map
60
+ }
61
+
40
62
fn insert_entry ( & mut self , id : NodeId , entry : MapEntry < ' hir > ) {
41
63
debug ! ( "hir_map: {:?} => {:?}" , id, entry) ;
42
64
let len = self . map . len ( ) ;
@@ -47,8 +69,55 @@ impl<'hir> NodeCollector<'hir> {
47
69
}
48
70
49
71
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
+
51
119
self . insert_entry ( id, entry) ;
120
+
52
121
}
53
122
54
123
fn with_parent < F : FnOnce ( & mut Self ) > ( & mut self , parent_id : NodeId , f : F ) {
@@ -57,9 +126,27 @@ impl<'hir> NodeCollector<'hir> {
57
126
f ( self ) ;
58
127
self . parent_node = parent_node;
59
128
}
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
+ }
60
147
}
61
148
62
- impl < ' hir > Visitor < ' hir > for NodeCollector < ' hir > {
149
+ impl < ' a , ' hir > Visitor < ' hir > for NodeCollector < ' a , ' hir > {
63
150
/// Because we want to track parent items and so forth, enable
64
151
/// deep walking so that we walk nested items in the context of
65
152
/// their outer items.
@@ -82,25 +169,37 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
82
169
}
83
170
84
171
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) ;
85
181
self . visit_body ( self . krate . body ( id) ) ;
182
+ self . current_dep_node_index = prev_index;
86
183
}
87
184
88
185
fn visit_item ( & mut self , i : & ' hir Item ) {
89
186
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
+ }
99
198
}
199
+ _ => { }
100
200
}
101
- _ => { }
102
- }
103
- intravisit:: walk_item ( this, i) ;
201
+ intravisit:: walk_item ( this, i) ;
202
+ } ) ;
104
203
} ) ;
105
204
}
106
205
@@ -121,18 +220,26 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
121
220
}
122
221
123
222
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
+ } ) ;
128
231
} ) ;
129
232
}
130
233
131
234
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
+ } ) ;
136
243
} ) ;
137
244
}
138
245
@@ -238,4 +345,33 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
238
345
intravisit:: walk_struct_field ( this, field) ;
239
346
} ) ;
240
347
}
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
+ }
241
377
}
0 commit comments