@@ -26,7 +26,8 @@ use std::collections::BTreeMap;
2626use std:: mem;
2727use syntax:: ast:: NodeId ;
2828use syntax:: codemap:: { CodeMap , StableFilemapId } ;
29- use syntax_pos:: { BytePos , Span , NO_EXPANSION , DUMMY_SP } ;
29+ use syntax_pos:: { BytePos , Span , DUMMY_SP } ;
30+ use syntax_pos:: hygiene:: { Mark , SyntaxContext , ExpnInfo } ;
3031use ty;
3132use ty:: codec:: { self as ty_codec, TyDecoder , TyEncoder } ;
3233use ty:: context:: TyCtxt ;
@@ -36,6 +37,10 @@ use ty::context::TyCtxt;
3637const PREV_DIAGNOSTICS_TAG : u64 = 0x1234_5678_A1A1_A1A1 ;
3738const QUERY_RESULT_INDEX_TAG : u64 = 0x1234_5678_C3C3_C3C3 ;
3839
40+ const TAG_NO_EXPANSION_INFO : u8 = 0 ;
41+ const TAG_EXPANSION_INFO_SHORTHAND : u8 = 1 ;
42+ const TAG_EXPANSION_INFO_INLINE : u8 = 2 ;
43+
3944/// `OnDiskCache` provides an interface to incr. comp. data cached from the
4045/// previous compilation session. This data will eventually include the results
4146/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
@@ -57,6 +62,7 @@ pub struct OnDiskCache<'sess> {
5762
5863 prev_filemap_starts : BTreeMap < BytePos , StableFilemapId > ,
5964 codemap : & ' sess CodeMap ,
65+ synthetic_expansion_infos : RefCell < FxHashMap < usize , SyntaxContext > > ,
6066
6167 // A map from dep-node to the position of the cached query result in
6268 // `serialized_data`.
@@ -86,13 +92,16 @@ impl<'sess> OnDiskCache<'sess> {
8692 ( header, decoder. position ( ) )
8793 } ;
8894
95+ let mut synthetic_expansion_infos = FxHashMap ( ) ;
96+
8997 let ( prev_diagnostics, query_result_index) = {
9098 let mut decoder = CacheDecoder {
9199 tcx : None ,
92100 opaque : opaque:: Decoder :: new ( & data[ ..] , post_header_pos) ,
93101 codemap : sess. codemap ( ) ,
94102 prev_filemap_starts : & header. prev_filemap_starts ,
95103 cnum_map : & IndexVec :: new ( ) ,
104+ synthetic_expansion_infos : & mut synthetic_expansion_infos,
96105 } ;
97106
98107 // Decode Diagnostics
@@ -131,6 +140,7 @@ impl<'sess> OnDiskCache<'sess> {
131140 codemap : sess. codemap ( ) ,
132141 current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
133142 query_result_index : query_result_index. into_iter ( ) . collect ( ) ,
143+ synthetic_expansion_infos : RefCell :: new ( synthetic_expansion_infos) ,
134144 }
135145 }
136146
@@ -144,6 +154,7 @@ impl<'sess> OnDiskCache<'sess> {
144154 codemap,
145155 current_diagnostics : RefCell :: new ( FxHashMap ( ) ) ,
146156 query_result_index : FxHashMap ( ) ,
157+ synthetic_expansion_infos : RefCell :: new ( FxHashMap ( ) ) ,
147158 }
148159 }
149160
@@ -162,6 +173,7 @@ impl<'sess> OnDiskCache<'sess> {
162173 encoder,
163174 type_shorthands : FxHashMap ( ) ,
164175 predicate_shorthands : FxHashMap ( ) ,
176+ expn_info_shorthands : FxHashMap ( ) ,
165177 } ;
166178
167179
@@ -265,12 +277,15 @@ impl<'sess> OnDiskCache<'sess> {
265277 * cnum_map = Some ( Self :: compute_cnum_map ( tcx, & self . prev_cnums [ ..] ) ) ;
266278 }
267279
280+ let mut synthetic_expansion_infos = self . synthetic_expansion_infos . borrow_mut ( ) ;
281+
268282 let mut decoder = CacheDecoder {
269283 tcx : Some ( tcx) ,
270284 opaque : opaque:: Decoder :: new ( & self . serialized_data [ ..] , pos) ,
271285 codemap : self . codemap ,
272286 prev_filemap_starts : & self . prev_filemap_starts ,
273287 cnum_map : cnum_map. as_ref ( ) . unwrap ( ) ,
288+ synthetic_expansion_infos : & mut * synthetic_expansion_infos,
274289 } ;
275290
276291 match decode_tagged ( & mut decoder, dep_node_index) {
@@ -346,6 +361,7 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
346361 codemap : & ' x CodeMap ,
347362 prev_filemap_starts : & ' x BTreeMap < BytePos , StableFilemapId > ,
348363 cnum_map : & ' x IndexVec < CrateNum , Option < CrateNum > > ,
364+ synthetic_expansion_infos : & ' x mut FxHashMap < usize , SyntaxContext > ,
349365}
350366
351367impl < ' a , ' tcx , ' x > CacheDecoder < ' a , ' tcx , ' x > {
@@ -453,7 +469,39 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
453469 if let Some ( current_filemap) = self . codemap . filemap_by_stable_id ( filemap_id) {
454470 let lo = ( lo + current_filemap. start_pos ) - prev_filemap_start;
455471 let hi = ( hi + current_filemap. start_pos ) - prev_filemap_start;
456- return Ok ( Span :: new ( lo, hi, NO_EXPANSION ) ) ;
472+
473+ let expn_info_tag = u8:: decode ( self ) ?;
474+
475+ let ctxt = match expn_info_tag {
476+ TAG_NO_EXPANSION_INFO => {
477+ SyntaxContext :: empty ( )
478+ }
479+ TAG_EXPANSION_INFO_INLINE => {
480+ let pos = self . position ( ) ;
481+ let expn_info: ExpnInfo = Decodable :: decode ( self ) ?;
482+ let ctxt = SyntaxContext :: allocate_directly ( expn_info) ;
483+ self . synthetic_expansion_infos . insert ( pos, ctxt) ;
484+ ctxt
485+ }
486+ TAG_EXPANSION_INFO_SHORTHAND => {
487+ let pos = usize:: decode ( self ) ?;
488+ if let Some ( ctxt) = self . synthetic_expansion_infos . get ( & pos) . cloned ( ) {
489+ ctxt
490+ } else {
491+ let expn_info = self . with_position ( pos, |this| {
492+ ExpnInfo :: decode ( this)
493+ } ) ?;
494+ let ctxt = SyntaxContext :: allocate_directly ( expn_info) ;
495+ self . synthetic_expansion_infos . insert ( pos, ctxt) ;
496+ ctxt
497+ }
498+ }
499+ _ => {
500+ unreachable ! ( )
501+ }
502+ } ;
503+
504+ return Ok ( Span :: new ( lo, hi, ctxt) ) ;
457505 }
458506 }
459507
@@ -475,6 +523,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
475523// compilation sessions. We use the DefPathHash, which is stable across
476524// sessions, to map the old DefId to the new one.
477525impl < ' a , ' tcx , ' x > SpecializedDecoder < DefId > for CacheDecoder < ' a , ' tcx , ' x > {
526+ #[ inline]
478527 fn specialized_decode ( & mut self ) -> Result < DefId , Self :: Error > {
479528 // Load the DefPathHash which is was we encoded the DefId as.
480529 let def_path_hash = DefPathHash :: decode ( self ) ?;
@@ -485,6 +534,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
485534}
486535
487536impl < ' a , ' tcx , ' x > SpecializedDecoder < LocalDefId > for CacheDecoder < ' a , ' tcx , ' x > {
537+ #[ inline]
488538 fn specialized_decode ( & mut self ) -> Result < LocalDefId , Self :: Error > {
489539 Ok ( LocalDefId :: from_def_id ( DefId :: decode ( self ) ?) )
490540 }
@@ -534,6 +584,7 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
534584 encoder : & ' enc mut E ,
535585 type_shorthands : FxHashMap < ty:: Ty < ' tcx > , usize > ,
536586 predicate_shorthands : FxHashMap < ty:: Predicate < ' tcx > , usize > ,
587+ expn_info_shorthands : FxHashMap < Mark , usize > ,
537588}
538589
539590impl < ' enc , ' a , ' tcx , E > CacheEncoder < ' enc , ' a , ' tcx , E >
@@ -560,6 +611,37 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
560611 }
561612}
562613
614+ impl < ' enc , ' a , ' tcx , E > SpecializedEncoder < Span > for CacheEncoder < ' enc , ' a , ' tcx , E >
615+ where E : ' enc + ty_codec:: TyEncoder
616+ {
617+ fn specialized_encode ( & mut self , span : & Span ) -> Result < ( ) , Self :: Error > {
618+ let span_data = span. data ( ) ;
619+
620+ span_data. lo . encode ( self ) ?;
621+ span_data. hi . encode ( self ) ?;
622+
623+ if span_data. ctxt == SyntaxContext :: empty ( ) {
624+ TAG_NO_EXPANSION_INFO . encode ( self )
625+ } else {
626+ let mark = span_data. ctxt . outer ( ) ;
627+
628+ if let Some ( expn_info) = mark. expn_info ( ) {
629+ if let Some ( pos) = self . expn_info_shorthands . get ( & mark) . cloned ( ) {
630+ TAG_EXPANSION_INFO_SHORTHAND . encode ( self ) ?;
631+ pos. encode ( self )
632+ } else {
633+ TAG_EXPANSION_INFO_INLINE . encode ( self ) ?;
634+ let pos = self . position ( ) ;
635+ self . expn_info_shorthands . insert ( mark, pos) ;
636+ expn_info. encode ( self )
637+ }
638+ } else {
639+ TAG_NO_EXPANSION_INFO . encode ( self )
640+ }
641+ }
642+ }
643+ }
644+
563645impl < ' enc , ' a , ' tcx , E > ty_codec:: TyEncoder for CacheEncoder < ' enc , ' a , ' tcx , E >
564646 where E : ' enc + ty_codec:: TyEncoder
565647{
0 commit comments