Skip to content

Commit 409e392

Browse files
incr.comp.: Properly hash and encode macro expansion information.
1 parent 315fbf7 commit 409e392

File tree

4 files changed

+138
-7
lines changed

4 files changed

+138
-7
lines changed

src/librustc/ich/hcx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
419419
0u8.hash_stable(hcx, hasher);
420420
} else {
421421
1u8.hash_stable(hcx, hasher);
422-
self.source_callsite().hash_stable(hcx, hasher);
422+
span.ctxt.outer().expn_info().hash_stable(hcx, hasher);
423423
}
424424
}
425425
}

src/librustc/ich/impls_syntax.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,30 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
347347
NameValue(lit)
348348
});
349349

350+
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
351+
call_site,
352+
callee
353+
});
354+
355+
impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
356+
format,
357+
allow_internal_unstable,
358+
allow_internal_unsafe,
359+
span
360+
});
361+
362+
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
363+
MacroAttribute(sym),
364+
MacroBang(sym),
365+
CompilerDesugaring(kind)
366+
});
367+
368+
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
369+
BackArrow,
370+
DotFill,
371+
QuestionMark
372+
});
373+
350374
impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
351375
fn hash_stable<W: StableHasherResult>(&self,
352376
hcx: &mut StableHashingContext<'gcx>,

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ use std::collections::BTreeMap;
2727
use std::mem;
2828
use syntax::ast::NodeId;
2929
use syntax::codemap::{CodeMap, StableFilemapId};
30-
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
30+
use syntax_pos::{BytePos, Span, DUMMY_SP};
31+
use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
3132
use ty;
3233
use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
3334
use ty::context::TyCtxt;
@@ -40,6 +41,10 @@ const QUERY_RESULT_INDEX_TAG: u64 = 0x1234_5678_C3C3_C3C3;
4041
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
4142
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
4243

44+
const TAG_NO_EXPANSION_INFO: u8 = 0;
45+
const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1;
46+
const TAG_EXPANSION_INFO_INLINE: u8 = 2;
47+
4348
/// `OnDiskCache` provides an interface to incr. comp. data cached from the
4449
/// previous compilation session. This data will eventually include the results
4550
/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
@@ -61,6 +66,7 @@ pub struct OnDiskCache<'sess> {
6166

6267
prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
6368
codemap: &'sess CodeMap,
69+
synthetic_expansion_infos: RefCell<FxHashMap<usize, SyntaxContext>>,
6470

6571
// A map from dep-node to the position of the cached query result in
6672
// `serialized_data`.
@@ -90,13 +96,16 @@ impl<'sess> OnDiskCache<'sess> {
9096
(header, decoder.position())
9197
};
9298

99+
let mut synthetic_expansion_infos = FxHashMap();
100+
93101
let (prev_diagnostics, query_result_index) = {
94102
let mut decoder = CacheDecoder {
95103
tcx: None,
96104
opaque: opaque::Decoder::new(&data[..], post_header_pos),
97105
codemap: sess.codemap(),
98106
prev_filemap_starts: &header.prev_filemap_starts,
99107
cnum_map: &IndexVec::new(),
108+
synthetic_expansion_infos: &mut synthetic_expansion_infos,
100109
};
101110

102111
// Decode Diagnostics
@@ -135,6 +144,7 @@ impl<'sess> OnDiskCache<'sess> {
135144
codemap: sess.codemap(),
136145
current_diagnostics: RefCell::new(FxHashMap()),
137146
query_result_index: query_result_index.into_iter().collect(),
147+
synthetic_expansion_infos: RefCell::new(synthetic_expansion_infos),
138148
}
139149
}
140150

@@ -148,6 +158,7 @@ impl<'sess> OnDiskCache<'sess> {
148158
codemap,
149159
current_diagnostics: RefCell::new(FxHashMap()),
150160
query_result_index: FxHashMap(),
161+
synthetic_expansion_infos: RefCell::new(FxHashMap()),
151162
}
152163
}
153164

@@ -166,6 +177,7 @@ impl<'sess> OnDiskCache<'sess> {
166177
encoder,
167178
type_shorthands: FxHashMap(),
168179
predicate_shorthands: FxHashMap(),
180+
expn_info_shorthands: FxHashMap(),
169181
};
170182

171183

@@ -269,12 +281,15 @@ impl<'sess> OnDiskCache<'sess> {
269281
*cnum_map = Some(Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
270282
}
271283

284+
let mut synthetic_expansion_infos = self.synthetic_expansion_infos.borrow_mut();
285+
272286
let mut decoder = CacheDecoder {
273287
tcx: Some(tcx),
274288
opaque: opaque::Decoder::new(&self.serialized_data[..], pos),
275289
codemap: self.codemap,
276290
prev_filemap_starts: &self.prev_filemap_starts,
277291
cnum_map: cnum_map.as_ref().unwrap(),
292+
synthetic_expansion_infos: &mut *synthetic_expansion_infos,
278293
};
279294

280295
match decode_tagged(&mut decoder, dep_node_index) {
@@ -350,6 +365,7 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
350365
codemap: &'x CodeMap,
351366
prev_filemap_starts: &'x BTreeMap<BytePos, StableFilemapId>,
352367
cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
368+
synthetic_expansion_infos: &'x mut FxHashMap<usize, SyntaxContext>,
353369
}
354370

355371
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
@@ -457,7 +473,39 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
457473
if let Some(current_filemap) = self.codemap.filemap_by_stable_id(filemap_id) {
458474
let lo = (lo + current_filemap.start_pos) - prev_filemap_start;
459475
let hi = (hi + current_filemap.start_pos) - prev_filemap_start;
460-
return Ok(Span::new(lo, hi, NO_EXPANSION));
476+
477+
let expn_info_tag = u8::decode(self)?;
478+
479+
let ctxt = match expn_info_tag {
480+
TAG_NO_EXPANSION_INFO => {
481+
SyntaxContext::empty()
482+
}
483+
TAG_EXPANSION_INFO_INLINE => {
484+
let pos = self.position();
485+
let expn_info: ExpnInfo = Decodable::decode(self)?;
486+
let ctxt = SyntaxContext::allocate_directly(expn_info);
487+
self.synthetic_expansion_infos.insert(pos, ctxt);
488+
ctxt
489+
}
490+
TAG_EXPANSION_INFO_SHORTHAND => {
491+
let pos = usize::decode(self)?;
492+
if let Some(ctxt) = self.synthetic_expansion_infos.get(&pos).cloned() {
493+
ctxt
494+
} else {
495+
let expn_info = self.with_position(pos, |this| {
496+
ExpnInfo::decode(this)
497+
})?;
498+
let ctxt = SyntaxContext::allocate_directly(expn_info);
499+
self.synthetic_expansion_infos.insert(pos, ctxt);
500+
ctxt
501+
}
502+
}
503+
_ => {
504+
unreachable!()
505+
}
506+
};
507+
508+
return Ok(Span::new(lo, hi, ctxt));
461509
}
462510
}
463511

@@ -479,6 +527,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
479527
// compilation sessions. We use the DefPathHash, which is stable across
480528
// sessions, to map the old DefId to the new one.
481529
impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
530+
#[inline]
482531
fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
483532
// Load the DefPathHash which is was we encoded the DefId as.
484533
let def_path_hash = DefPathHash::decode(self)?;
@@ -489,6 +538,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
489538
}
490539

491540
impl<'a, 'tcx, 'x> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx, 'x> {
541+
#[inline]
492542
fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
493543
Ok(LocalDefId::from_def_id(DefId::decode(self)?))
494544
}
@@ -558,6 +608,7 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
558608
encoder: &'enc mut E,
559609
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
560610
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
611+
expn_info_shorthands: FxHashMap<Mark, usize>,
561612
}
562613

563614
impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
@@ -584,6 +635,37 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
584635
}
585636
}
586637

638+
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'enc, 'a, 'tcx, E>
639+
where E: 'enc + ty_codec::TyEncoder
640+
{
641+
fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
642+
let span_data = span.data();
643+
644+
span_data.lo.encode(self)?;
645+
span_data.hi.encode(self)?;
646+
647+
if span_data.ctxt == SyntaxContext::empty() {
648+
TAG_NO_EXPANSION_INFO.encode(self)
649+
} else {
650+
let mark = span_data.ctxt.outer();
651+
652+
if let Some(expn_info) = mark.expn_info() {
653+
if let Some(pos) = self.expn_info_shorthands.get(&mark).cloned() {
654+
TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
655+
pos.encode(self)
656+
} else {
657+
TAG_EXPANSION_INFO_INLINE.encode(self)?;
658+
let pos = self.position();
659+
self.expn_info_shorthands.insert(mark, pos);
660+
expn_info.encode(self)
661+
}
662+
} else {
663+
TAG_NO_EXPANSION_INFO.encode(self)
664+
}
665+
}
666+
}
667+
}
668+
587669
impl<'enc, 'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'a, 'tcx, E>
588670
where E: 'enc + ty_codec::TyEncoder
589671
{

src/libsyntax_pos/hygiene.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,31 @@ impl SyntaxContext {
140140
SyntaxContext(0)
141141
}
142142

143+
// Allocate a new SyntaxContext with the given ExpnInfo. This is used when
144+
// deserializing Spans from the incr. comp. cache.
145+
// FIXME(mw): This method does not restore MarkData::parent or
146+
// SyntaxContextData::prev_ctxt or SyntaxContextData::modern. These things
147+
// don't seem to be used after HIR lowering, so everything should be fine
148+
// as long as incremental compilation does not kick in before that.
149+
pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
150+
HygieneData::with(|data| {
151+
data.marks.push(MarkData {
152+
parent: Mark::root(),
153+
modern: false,
154+
expn_info: Some(expansion_info)
155+
});
156+
157+
let mark = Mark(data.marks.len() as u32 - 1);
158+
159+
data.syntax_contexts.push(SyntaxContextData {
160+
outer_mark: mark,
161+
prev_ctxt: SyntaxContext::empty(),
162+
modern: SyntaxContext::empty(),
163+
});
164+
SyntaxContext(data.syntax_contexts.len() as u32 - 1)
165+
})
166+
}
167+
143168
/// Extend a syntax context with a given mark
144169
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
145170
HygieneData::with(|data| {
@@ -286,7 +311,7 @@ impl fmt::Debug for SyntaxContext {
286311
}
287312

288313
/// Extra information for tracking spans of macro and syntax sugar expansion
289-
#[derive(Clone, Hash, Debug)]
314+
#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
290315
pub struct ExpnInfo {
291316
/// The location of the actual macro invocation or syntax sugar , e.g.
292317
/// `let x = foo!();` or `if let Some(y) = x {}`
@@ -302,7 +327,7 @@ pub struct ExpnInfo {
302327
pub callee: NameAndSpan
303328
}
304329

305-
#[derive(Clone, Hash, Debug)]
330+
#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
306331
pub struct NameAndSpan {
307332
/// The format with which the macro was invoked.
308333
pub format: ExpnFormat,
@@ -330,7 +355,7 @@ impl NameAndSpan {
330355
}
331356

332357
/// The source of expansion.
333-
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
358+
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
334359
pub enum ExpnFormat {
335360
/// e.g. #[derive(...)] <item>
336361
MacroAttribute(Symbol),
@@ -341,7 +366,7 @@ pub enum ExpnFormat {
341366
}
342367

343368
/// The kind of compiler desugaring.
344-
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
369+
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
345370
pub enum CompilerDesugaringKind {
346371
BackArrow,
347372
DotFill,

0 commit comments

Comments
 (0)