@@ -16,7 +16,7 @@ use rustc::session::Session;
16
16
use rustc:: ty:: TyCtxt ;
17
17
use rustc_data_structures:: fnv:: FnvHashMap ;
18
18
use rustc_serialize:: { Encodable as RustcEncodable } ;
19
- use std:: hash:: { Hasher , SipHasher } ;
19
+ use std:: hash:: { Hash , Hasher , SipHasher } ;
20
20
use std:: io:: { self , Cursor , Write } ;
21
21
use std:: fs:: { self , File } ;
22
22
use std:: path:: PathBuf ;
@@ -30,9 +30,14 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
30
30
debug ! ( "save_dep_graph()" ) ;
31
31
let _ignore = tcx. dep_graph . in_ignore ( ) ;
32
32
let sess = tcx. sess ;
33
+ if sess. opts . incremental . is_none ( ) {
34
+ return ;
35
+ }
33
36
let mut hcx = HashContext :: new ( tcx) ;
34
- save_in ( sess, dep_graph_path ( tcx) , |e| encode_dep_graph ( & mut hcx, e) ) ;
35
- save_in ( sess, metadata_hash_path ( tcx, LOCAL_CRATE ) , |e| encode_metadata_hashes ( & mut hcx, e) ) ;
37
+ let mut builder = DefIdDirectoryBuilder :: new ( tcx) ;
38
+ let query = tcx. dep_graph . query ( ) ;
39
+ save_in ( sess, dep_graph_path ( tcx) , |e| encode_dep_graph ( & mut hcx, & mut builder, & query, e) ) ;
40
+ save_in ( sess, metadata_hash_path ( tcx, LOCAL_CRATE ) , |e| encode_metadata_hashes ( & mut hcx, & mut builder, & query, e) ) ;
36
41
}
37
42
38
43
pub fn save_work_products ( sess : & Session , local_crate_name : & str ) {
@@ -96,21 +101,19 @@ fn save_in<F>(sess: &Session,
96
101
}
97
102
98
103
pub fn encode_dep_graph < ' a , ' tcx > ( hcx : & mut HashContext < ' a , ' tcx > ,
104
+ builder : & mut DefIdDirectoryBuilder ,
105
+ query : & DepGraphQuery < DefId > ,
99
106
encoder : & mut Encoder )
100
107
-> io:: Result < ( ) >
101
108
{
102
- let tcx = hcx. tcx ;
103
- let query = tcx. dep_graph . query ( ) ;
104
109
let ( nodes, edges) = post_process_graph ( hcx, query) ;
105
110
106
- let mut builder = DefIdDirectoryBuilder :: new ( tcx) ;
107
-
108
111
// Create hashes for inputs.
109
112
let hashes =
110
113
nodes. iter ( )
111
114
. filter_map ( |dep_node| {
112
115
hcx. hash ( dep_node)
113
- . map ( |hash| {
116
+ . map ( |( _ , hash) | {
114
117
let node = builder. map ( dep_node) ;
115
118
SerializedHash { node : node, hash : hash }
116
119
} )
@@ -133,15 +136,14 @@ pub fn encode_dep_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
133
136
debug ! ( "graph = {:#?}" , graph) ;
134
137
135
138
// Encode the directory and then the graph data.
136
- let directory = builder. into_directory ( ) ;
137
- try!( directory. encode ( encoder) ) ;
139
+ try!( builder. directory ( ) . encode ( encoder) ) ;
138
140
try!( graph. encode ( encoder) ) ;
139
141
140
142
Ok ( ( ) )
141
143
}
142
144
143
145
pub fn post_process_graph < ' a , ' tcx > ( hcx : & mut HashContext < ' a , ' tcx > ,
144
- query : DepGraphQuery < DefId > )
146
+ query : & DepGraphQuery < DefId > )
145
147
-> ( Vec < DepNode < DefId > > , Vec < ( DepNode < DefId > , DepNode < DefId > ) > )
146
148
{
147
149
let tcx = hcx. tcx ;
@@ -192,11 +194,12 @@ pub fn post_process_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
192
194
193
195
194
196
pub fn encode_metadata_hashes < ' a , ' tcx > ( hcx : & mut HashContext < ' a , ' tcx > ,
197
+ builder : & mut DefIdDirectoryBuilder ,
198
+ query : & DepGraphQuery < DefId > ,
195
199
encoder : & mut Encoder )
196
200
-> io:: Result < ( ) >
197
201
{
198
202
let tcx = hcx. tcx ;
199
- let query = tcx. dep_graph . query ( ) ;
200
203
201
204
let serialized_hashes = {
202
205
// Identify the `MetaData(X)` nodes where `X` is local. These are
@@ -224,16 +227,32 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
224
227
let dep_node = DepNode :: MetaData ( def_id) ;
225
228
let mut state = SipHasher :: new ( ) ;
226
229
debug ! ( "save: computing metadata hash for {:?}" , dep_node) ;
227
- for node in query. transitive_predecessors ( & dep_node) {
228
- if let Some ( hash) = hcx. hash ( & node) {
229
- debug ! ( "save: predecessor {:?} has hash {}" , node, hash) ;
230
- state. write_u64 ( hash. to_le ( ) ) ;
231
- } else {
232
- debug ! ( "save: predecessor {:?} cannot be hashed" , node) ;
233
- }
230
+
231
+ let predecessors = query. transitive_predecessors ( & dep_node) ;
232
+ let mut hashes: Vec < _ > =
233
+ predecessors. iter ( )
234
+ . filter_map ( |node| hcx. hash ( & node) )
235
+ . map ( |( def_id, hash) | {
236
+ let index = builder. add ( def_id) ;
237
+ let path = builder. lookup_def_path ( index) ;
238
+ ( path. to_string ( tcx) , hash) // (*)
239
+ } )
240
+ . collect ( ) ;
241
+
242
+ // (*) creating a `String` from each def-path is a bit inefficient,
243
+ // but it's the easiest way to get a deterministic ord/hash.
244
+
245
+ hashes. sort ( ) ;
246
+ state. write_usize ( hashes. len ( ) ) ;
247
+ for ( path, hash) in hashes {
248
+ debug ! ( "save: predecessor {:?} has hash {}" , path, hash) ;
249
+ path. hash ( & mut state) ;
250
+ state. write_u64 ( hash. to_le ( ) ) ;
234
251
}
252
+
235
253
let hash = state. finish ( ) ;
236
254
debug ! ( "save: metadata hash for {:?} is {}" , dep_node, hash) ;
255
+
237
256
SerializedMetadataHash {
238
257
def_index : def_id. index ,
239
258
hash : hash,
0 commit comments