@@ -29,7 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
29
29
use rustc:: session:: config:: { self , CrateTypeProcMacro } ;
30
30
use rustc:: util:: nodemap:: { FxHashMap , NodeSet } ;
31
31
32
- use rustc_serialize:: { Encodable , Encoder , SpecializedEncoder , opaque} ;
32
+ use rustc_serialize:: { Encodable , Encoder , SpecializedEncoder , UseSpecializedEncodable , opaque} ;
33
33
34
34
use std:: hash:: Hash ;
35
35
use std:: intrinsics;
@@ -61,6 +61,13 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
61
61
62
62
pub metadata_hashes : EncodedMetadataHashes ,
63
63
pub compute_ich : bool ,
64
+ // We need to encode hygiene info after all spans and possibly other data structures
65
+ // that reference it have been encoded already, since we only encode those elements of it
66
+ // that are actually used to avoid excessive memory usage. Thus, we need to keep track of
67
+ // whether we already encoded the hygiene info (and thus committed to a specific set of
68
+ // information to encode) to make sure we can catch bugs introduced by further changes
69
+ // quickly.
70
+ already_encoded_hygiene_data : bool ,
64
71
}
65
72
66
73
macro_rules! encoder_methods {
@@ -136,6 +143,26 @@ impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext
136
143
}
137
144
}
138
145
146
+ impl < ' a , ' tcx > SpecializedEncoder < hygiene:: SyntaxContext > for EncodeContext < ' a , ' tcx > {
147
+ fn specialized_encode ( & mut self , ctxt : & hygiene:: SyntaxContext ) -> Result < ( ) , Self :: Error > {
148
+ if self . already_encoded_hygiene_data {
149
+ bug ! ( "trying to encode syntax context `{:?}` after encoding hygiene data!" , ctxt) ;
150
+ } else {
151
+ ctxt. default_encode ( self )
152
+ }
153
+ }
154
+ }
155
+
156
+ impl < ' a , ' tcx > SpecializedEncoder < hygiene:: Mark > for EncodeContext < ' a , ' tcx > {
157
+ fn specialized_encode ( & mut self , mark : & hygiene:: Mark ) -> Result < ( ) , Self :: Error > {
158
+ if self . already_encoded_hygiene_data {
159
+ bug ! ( "trying to encode mark `{:?}` after encoding hygiene data!" , mark) ;
160
+ } else {
161
+ mark. default_encode ( self )
162
+ }
163
+ }
164
+ }
165
+
139
166
impl < ' a , ' tcx > EncodeContext < ' a , ' tcx > {
140
167
141
168
pub fn position ( & self ) -> usize {
@@ -323,9 +350,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
323
350
self . lazy_seq_ref ( adapted. iter ( ) . map ( |rc| & * * rc) )
324
351
}
325
352
326
- fn encode_hygiene_data ( & mut self ) -> Lazy < hygiene:: HygieneData > {
327
- self . tcx . sess . cstore . ensure_hygiene_data_loaded ( ) ;
328
- hygiene:: HygieneData :: safe_with ( |data| self . lazy ( data) )
353
+ fn encode_hygiene_data ( & mut self ) -> Lazy < hygiene:: HygieneDataMap > {
354
+ // TODO(twk): remove the `ensure_hygiene_data_loaded` method!
355
+ hygiene:: HygieneData :: safe_with ( |data| self . lazy ( & data. to_map ( ) ) )
329
356
}
330
357
331
358
fn encode_crate_root ( & mut self ) -> Lazy < CrateRoot > {
@@ -372,11 +399,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
372
399
let codemap = self . encode_codemap ( ) ;
373
400
let codemap_bytes = self . position ( ) - i;
374
401
375
- // Encode hygiene data
376
- i = self . position ( ) ;
377
- let hygiene_data = self . encode_hygiene_data ( ) ;
378
- let hygiene_data_bytes = self . position ( ) - i;
379
-
380
402
// Encode DefPathTable
381
403
i = self . position ( ) ;
382
404
let def_path_table = self . encode_def_path_table ( ) ;
@@ -407,6 +429,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
407
429
let index = items. write_index ( & mut self . opaque . cursor ) ;
408
430
let index_bytes = self . position ( ) - i;
409
431
432
+ // Encode hygiene data
433
+ i = self . position ( ) ;
434
+ let hygiene_data = self . encode_hygiene_data ( ) ;
435
+ let hygiene_data_bytes = self . position ( ) - i;
436
+ self . already_encoded_hygiene_data = true ;
437
+
410
438
let tcx = self . tcx ;
411
439
let link_meta = self . link_meta ;
412
440
let is_proc_macro = tcx. sess . crate_types . borrow ( ) . contains ( & CrateTypeProcMacro ) ;
@@ -437,11 +465,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
437
465
lang_items_missing,
438
466
native_libraries,
439
467
codemap,
440
- hygiene_data,
441
468
def_path_table,
442
469
impls,
443
470
exported_symbols,
444
471
index,
472
+ hygiene_data,
445
473
} ) ;
446
474
447
475
let total_bytes = self . position ( ) ;
@@ -466,10 +494,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
466
494
println ! ( " codemap bytes: {}" , codemap_bytes) ;
467
495
println ! ( " impl bytes: {}" , impl_bytes) ;
468
496
println ! ( " exp. symbols bytes: {}" , exported_symbols_bytes) ;
469
- println ! ( " hygiene data bytes: {}" , hygiene_data_bytes) ;
470
497
println ! ( " def-path table bytes: {}" , def_path_table_bytes) ;
471
498
println ! ( " item bytes: {}" , item_bytes) ;
472
499
println ! ( " index bytes: {}" , index_bytes) ;
500
+ println ! ( " hygiene data bytes: {}" , hygiene_data_bytes) ;
473
501
println ! ( " zero bytes: {}" , zero_bytes) ;
474
502
println ! ( " total bytes: {}" , total_bytes) ;
475
503
}
@@ -1689,6 +1717,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1689
1717
predicate_shorthands : Default :: default ( ) ,
1690
1718
metadata_hashes : EncodedMetadataHashes :: new ( ) ,
1691
1719
compute_ich,
1720
+ already_encoded_hygiene_data : false ,
1692
1721
} ;
1693
1722
1694
1723
// Encode the rustc version string in a predictable location.
0 commit comments