@@ -16,6 +16,9 @@ use std::iter::repeat;
1616use syntax:: ast:: { NodeId , CRATE_NODE_ID } ;
1717use syntax_pos:: Span ;
1818
19+ use ich:: StableHashingContext ;
20+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , StableHasherResult } ;
21+
1922/// A Visitor that walks over the HIR and collects Nodes into a HIR map
2023pub ( super ) struct NodeCollector < ' a , ' hir > {
2124 /// The crate
@@ -26,36 +29,99 @@ pub(super) struct NodeCollector<'a, 'hir> {
2629 parent_node : NodeId ,
2730
2831 current_dep_node_owner : DefIndex ,
29- current_dep_node_index : DepNodeIndex ,
32+ current_signature_dep_index : DepNodeIndex ,
33+ current_full_dep_index : DepNodeIndex ,
34+ currently_in_body : bool ,
3035
3136 dep_graph : & ' a DepGraph ,
3237 definitions : & ' a definitions:: Definitions ,
38+
39+ hcx : StableHashingContext < ' a > ,
40+
41+ hir_body_nodes : Vec < DefPathHash > ,
3342}
3443
3544impl < ' a , ' hir > NodeCollector < ' a , ' hir > {
3645 pub ( super ) fn root ( krate : & ' hir Crate ,
37- dep_graph : & ' a DepGraph ,
38- definitions : & ' a definitions:: Definitions )
46+ dep_graph : & ' a DepGraph ,
47+ definitions : & ' a definitions:: Definitions ,
48+ hcx : StableHashingContext < ' a > )
3949 -> NodeCollector < ' a , ' hir > {
4050 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) ;
51+
52+ // Allocate DepNodes for the root module
53+ let ( root_mod_sig_dep_index, root_mod_full_dep_index) ;
54+ {
55+ let Crate {
56+ ref module,
57+ // Crate attributes are not copied over to the root `Mod`, so hash
58+ // them explicitly here.
59+ ref attrs,
60+ span,
61+
62+ // These fields are handled separately:
63+ exported_macros : _,
64+ items : _,
65+ trait_items : _,
66+ impl_items : _,
67+ bodies : _,
68+ trait_impls : _,
69+ trait_default_impl : _,
70+ body_ids : _,
71+ } = * krate;
72+
73+ root_mod_sig_dep_index = dep_graph. with_task (
74+ root_mod_def_path_hash. to_dep_node ( DepKind :: Hir ) ,
75+ & hcx,
76+ HirItemLike { item_like : ( module, attrs, span) , hash_bodies : false } ,
77+ identity_fn
78+ ) . 1 ;
79+ root_mod_full_dep_index = dep_graph. with_task (
80+ root_mod_def_path_hash. to_dep_node ( DepKind :: HirBody ) ,
81+ & hcx,
82+ HirItemLike { item_like : ( module, attrs, span) , hash_bodies : true } ,
83+ identity_fn
84+ ) . 1 ;
85+ }
86+
87+ let hir_body_nodes = vec ! [ root_mod_def_path_hash] ;
4388
4489 let mut collector = NodeCollector {
4590 krate,
4691 map : vec ! [ ] ,
4792 parent_node : CRATE_NODE_ID ,
48- current_dep_node_index : root_mod_dep_node_index,
93+ current_signature_dep_index : root_mod_sig_dep_index,
94+ current_full_dep_index : root_mod_full_dep_index,
4995 current_dep_node_owner : CRATE_DEF_INDEX ,
96+ currently_in_body : false ,
5097 dep_graph,
5198 definitions,
99+ hcx,
100+ hir_body_nodes,
52101 } ;
53- collector. insert_entry ( CRATE_NODE_ID , RootCrate ( root_mod_dep_node_index ) ) ;
102+ collector. insert_entry ( CRATE_NODE_ID , RootCrate ( root_mod_sig_dep_index ) ) ;
54103
55104 collector
56105 }
57106
58- pub ( super ) fn into_map ( self ) -> Vec < MapEntry < ' hir > > {
107+ pub ( super ) fn finalize_and_compute_crate_hash ( self ,
108+ crate_disambiguator : & str )
109+ -> Vec < MapEntry < ' hir > > {
110+ let mut node_hashes: Vec < _ > = self
111+ . hir_body_nodes
112+ . iter ( )
113+ . map ( |& def_path_hash| {
114+ let dep_node = def_path_hash. to_dep_node ( DepKind :: HirBody ) ;
115+ ( def_path_hash, self . dep_graph . fingerprint_of ( & dep_node) )
116+ } )
117+ . collect ( ) ;
118+
119+ node_hashes. sort_unstable_by ( |& ( ref d1, _) , & ( ref d2, _) | d1. cmp ( d2) ) ;
120+
121+ self . dep_graph . with_task ( DepNode :: new_no_params ( DepKind :: Krate ) ,
122+ & self . hcx ,
123+ ( node_hashes, crate_disambiguator) ,
124+ identity_fn) ;
59125 self . map
60126 }
61127
@@ -70,7 +136,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
70136
71137 fn insert ( & mut self , id : NodeId , node : Node < ' hir > ) {
72138 let parent = self . parent_node ;
73- let dep_node_index = self . current_dep_node_index ;
139+ let dep_node_index = if self . currently_in_body {
140+ self . current_full_dep_index
141+ } else {
142+ self . current_signature_dep_index
143+ } ;
74144
75145 let entry = match node {
76146 NodeItem ( n) => EntryItem ( parent, dep_node_index, n) ,
@@ -91,6 +161,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
91161 NodeTyParam ( n) => EntryTyParam ( parent, dep_node_index, n) ,
92162 NodeVisibility ( n) => EntryVisibility ( parent, dep_node_index, n) ,
93163 NodeLocal ( n) => EntryLocal ( parent, dep_node_index, n) ,
164+ NodeMacroDef ( n) => EntryMacroDef ( dep_node_index, n) ,
94165 } ;
95166
96167 // Make sure that the DepNode of some node coincides with the HirId
@@ -127,22 +198,41 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
127198 self . parent_node = parent_node;
128199 }
129200
130- fn with_dep_node_owner < F : FnOnce ( & mut Self ) > ( & mut self ,
201+ fn with_dep_node_owner < T : HashStable < StableHashingContext < ' a > > ,
202+ F : FnOnce ( & mut Self ) > ( & mut self ,
131203 dep_node_owner : DefIndex ,
204+ item_like : & T ,
132205 f : F ) {
133206 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) ;
207+ let prev_signature_dep_index = self . current_signature_dep_index ;
208+ let prev_full_dep_index = self . current_signature_dep_index ;
209+ let prev_in_body = self . currently_in_body ;
210+
211+ let def_path_hash = self . definitions . def_path_hash ( dep_node_owner) ;
212+
213+ self . current_signature_dep_index = self . dep_graph . with_task (
214+ def_path_hash. to_dep_node ( DepKind :: Hir ) ,
215+ & self . hcx ,
216+ HirItemLike { item_like, hash_bodies : false } ,
217+ identity_fn
218+ ) . 1 ;
219+
220+ self . current_full_dep_index = self . dep_graph . with_task (
221+ def_path_hash. to_dep_node ( DepKind :: HirBody ) ,
222+ & self . hcx ,
223+ HirItemLike { item_like, hash_bodies : true } ,
224+ identity_fn
225+ ) . 1 ;
226+
227+ self . hir_body_nodes . push ( def_path_hash) ;
228+
142229 self . current_dep_node_owner = dep_node_owner;
230+ self . currently_in_body = false ;
143231 f ( self ) ;
144- self . current_dep_node_index = prev_index ;
232+ self . currently_in_body = prev_in_body ;
145233 self . current_dep_node_owner = prev_owner;
234+ self . current_full_dep_index = prev_full_dep_index;
235+ self . current_signature_dep_index = prev_signature_dep_index;
146236 }
147237}
148238
@@ -169,24 +259,17 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
169259 }
170260
171261 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) ;
262+ let prev_in_body = self . currently_in_body ;
263+ self . currently_in_body = true ;
181264 self . visit_body ( self . krate . body ( id) ) ;
182- self . current_dep_node_index = prev_index ;
265+ self . currently_in_body = prev_in_body ;
183266 }
184267
185268 fn visit_item ( & mut self , i : & ' hir Item ) {
186269 debug ! ( "visit_item: {:?}" , i) ;
187270 debug_assert_eq ! ( i. hir_id. owner,
188271 self . definitions. opt_def_index( i. id) . unwrap( ) ) ;
189- self . with_dep_node_owner ( i. hir_id . owner , |this| {
272+ self . with_dep_node_owner ( i. hir_id . owner , i , |this| {
190273 this. insert ( i. id , NodeItem ( i) ) ;
191274 this. with_parent ( i. id , |this| {
192275 match i. node {
@@ -222,7 +305,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
222305 fn visit_trait_item ( & mut self , ti : & ' hir TraitItem ) {
223306 debug_assert_eq ! ( ti. hir_id. owner,
224307 self . definitions. opt_def_index( ti. id) . unwrap( ) ) ;
225- self . with_dep_node_owner ( ti. hir_id . owner , |this| {
308+ self . with_dep_node_owner ( ti. hir_id . owner , ti , |this| {
226309 this. insert ( ti. id , NodeTraitItem ( ti) ) ;
227310
228311 this. with_parent ( ti. id , |this| {
@@ -234,7 +317,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
234317 fn visit_impl_item ( & mut self , ii : & ' hir ImplItem ) {
235318 debug_assert_eq ! ( ii. hir_id. owner,
236319 self . definitions. opt_def_index( ii. id) . unwrap( ) ) ;
237- self . with_dep_node_owner ( ii. hir_id . owner , |this| {
320+ self . with_dep_node_owner ( ii. hir_id . owner , ii , |this| {
238321 this. insert ( ii. id , NodeImplItem ( ii) ) ;
239322
240323 this. with_parent ( ii. id , |this| {
@@ -328,7 +411,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
328411 }
329412
330413 fn visit_macro_def ( & mut self , macro_def : & ' hir MacroDef ) {
331- self . insert_entry ( macro_def. id , NotPresent ) ;
414+ let def_index = self . definitions . opt_def_index ( macro_def. id ) . unwrap ( ) ;
415+
416+ self . with_dep_node_owner ( def_index, macro_def, |this| {
417+ this. insert ( macro_def. id , NodeMacroDef ( macro_def) ) ;
418+ } ) ;
332419 }
333420
334421 fn visit_variant ( & mut self , v : & ' hir Variant , g : & ' hir Generics , item_id : NodeId ) {
@@ -375,3 +462,25 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
375462 self . visit_nested_impl_item ( id) ;
376463 }
377464}
465+
466+
467+ fn identity_fn < T > ( _: & StableHashingContext , item_like : T ) -> T {
468+ item_like
469+ }
470+
471+ struct HirItemLike < T > {
472+ item_like : T ,
473+ hash_bodies : bool ,
474+ }
475+
476+ impl < ' hir , T > HashStable < StableHashingContext < ' hir > > for HirItemLike < T >
477+ where T : HashStable < StableHashingContext < ' hir > >
478+ {
479+ fn hash_stable < W : StableHasherResult > ( & self ,
480+ hcx : & mut StableHashingContext < ' hir > ,
481+ hasher : & mut StableHasher < W > ) {
482+ hcx. while_hashing_hir_bodies ( self . hash_bodies , |hcx| {
483+ self . item_like . hash_stable ( hcx, hasher) ;
484+ } ) ;
485+ }
486+ }
0 commit comments