Skip to content

Commit

Permalink
incr.comp.: Properly hash and encode macro expansion information.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelwoerister committed Dec 1, 2017
1 parent 315fbf7 commit 409e392
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/librustc/ich/hcx.rs
Expand Up @@ -419,7 +419,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
0u8.hash_stable(hcx, hasher);
} else {
1u8.hash_stable(hcx, hasher);
self.source_callsite().hash_stable(hcx, hasher);
span.ctxt.outer().expn_info().hash_stable(hcx, hasher);
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/librustc/ich/impls_syntax.rs
Expand Up @@ -347,6 +347,30 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
NameValue(lit)
});

impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
call_site,
callee
});

impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
format,
allow_internal_unstable,
allow_internal_unsafe,
span
});

impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
MacroAttribute(sym),
MacroBang(sym),
CompilerDesugaring(kind)
});

impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
BackArrow,
DotFill,
QuestionMark
});

impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
Expand Down
86 changes: 84 additions & 2 deletions src/librustc/ty/maps/on_disk_cache.rs
Expand Up @@ -27,7 +27,8 @@ use std::collections::BTreeMap;
use std::mem;
use syntax::ast::NodeId;
use syntax::codemap::{CodeMap, StableFilemapId};
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
use syntax_pos::{BytePos, Span, DUMMY_SP};
use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
use ty;
use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
use ty::context::TyCtxt;
Expand All @@ -40,6 +41,10 @@ const QUERY_RESULT_INDEX_TAG: u64 = 0x1234_5678_C3C3_C3C3;
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;

const TAG_NO_EXPANSION_INFO: u8 = 0;
const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1;
const TAG_EXPANSION_INFO_INLINE: u8 = 2;

/// `OnDiskCache` provides an interface to incr. comp. data cached from the
/// previous compilation session. This data will eventually include the results
/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
Expand All @@ -61,6 +66,7 @@ pub struct OnDiskCache<'sess> {

prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
codemap: &'sess CodeMap,
synthetic_expansion_infos: RefCell<FxHashMap<usize, SyntaxContext>>,

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

let mut synthetic_expansion_infos = FxHashMap();

let (prev_diagnostics, query_result_index) = {
let mut decoder = CacheDecoder {
tcx: None,
opaque: opaque::Decoder::new(&data[..], post_header_pos),
codemap: sess.codemap(),
prev_filemap_starts: &header.prev_filemap_starts,
cnum_map: &IndexVec::new(),
synthetic_expansion_infos: &mut synthetic_expansion_infos,
};

// Decode Diagnostics
Expand Down Expand Up @@ -135,6 +144,7 @@ impl<'sess> OnDiskCache<'sess> {
codemap: sess.codemap(),
current_diagnostics: RefCell::new(FxHashMap()),
query_result_index: query_result_index.into_iter().collect(),
synthetic_expansion_infos: RefCell::new(synthetic_expansion_infos),
}
}

Expand All @@ -148,6 +158,7 @@ impl<'sess> OnDiskCache<'sess> {
codemap,
current_diagnostics: RefCell::new(FxHashMap()),
query_result_index: FxHashMap(),
synthetic_expansion_infos: RefCell::new(FxHashMap()),
}
}

Expand All @@ -166,6 +177,7 @@ impl<'sess> OnDiskCache<'sess> {
encoder,
type_shorthands: FxHashMap(),
predicate_shorthands: FxHashMap(),
expn_info_shorthands: FxHashMap(),
};


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

let mut synthetic_expansion_infos = self.synthetic_expansion_infos.borrow_mut();

let mut decoder = CacheDecoder {
tcx: Some(tcx),
opaque: opaque::Decoder::new(&self.serialized_data[..], pos),
codemap: self.codemap,
prev_filemap_starts: &self.prev_filemap_starts,
cnum_map: cnum_map.as_ref().unwrap(),
synthetic_expansion_infos: &mut *synthetic_expansion_infos,
};

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

impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
Expand Down Expand Up @@ -457,7 +473,39 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
if let Some(current_filemap) = self.codemap.filemap_by_stable_id(filemap_id) {
let lo = (lo + current_filemap.start_pos) - prev_filemap_start;
let hi = (hi + current_filemap.start_pos) - prev_filemap_start;
return Ok(Span::new(lo, hi, NO_EXPANSION));

let expn_info_tag = u8::decode(self)?;

let ctxt = match expn_info_tag {
TAG_NO_EXPANSION_INFO => {
SyntaxContext::empty()
}
TAG_EXPANSION_INFO_INLINE => {
let pos = self.position();
let expn_info: ExpnInfo = Decodable::decode(self)?;
let ctxt = SyntaxContext::allocate_directly(expn_info);
self.synthetic_expansion_infos.insert(pos, ctxt);
ctxt
}
TAG_EXPANSION_INFO_SHORTHAND => {
let pos = usize::decode(self)?;
if let Some(ctxt) = self.synthetic_expansion_infos.get(&pos).cloned() {
ctxt
} else {
let expn_info = self.with_position(pos, |this| {
ExpnInfo::decode(this)
})?;
let ctxt = SyntaxContext::allocate_directly(expn_info);
self.synthetic_expansion_infos.insert(pos, ctxt);
ctxt
}
}
_ => {
unreachable!()
}
};

return Ok(Span::new(lo, hi, ctxt));
}
}

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

impl<'a, 'tcx, 'x> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx, 'x> {
#[inline]
fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
Ok(LocalDefId::from_def_id(DefId::decode(self)?))
}
Expand Down Expand Up @@ -558,6 +608,7 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
encoder: &'enc mut E,
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
expn_info_shorthands: FxHashMap<Mark, usize>,
}

impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
Expand All @@ -584,6 +635,37 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
}
}

impl<'enc, 'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'enc, 'a, 'tcx, E>
where E: 'enc + ty_codec::TyEncoder
{
fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
let span_data = span.data();

span_data.lo.encode(self)?;
span_data.hi.encode(self)?;

if span_data.ctxt == SyntaxContext::empty() {
TAG_NO_EXPANSION_INFO.encode(self)
} else {
let mark = span_data.ctxt.outer();

if let Some(expn_info) = mark.expn_info() {
if let Some(pos) = self.expn_info_shorthands.get(&mark).cloned() {
TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
pos.encode(self)
} else {
TAG_EXPANSION_INFO_INLINE.encode(self)?;
let pos = self.position();
self.expn_info_shorthands.insert(mark, pos);
expn_info.encode(self)
}
} else {
TAG_NO_EXPANSION_INFO.encode(self)
}
}
}
}

impl<'enc, 'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'a, 'tcx, E>
where E: 'enc + ty_codec::TyEncoder
{
Expand Down
33 changes: 29 additions & 4 deletions src/libsyntax_pos/hygiene.rs
Expand Up @@ -140,6 +140,31 @@ impl SyntaxContext {
SyntaxContext(0)
}

// Allocate a new SyntaxContext with the given ExpnInfo. This is used when
// deserializing Spans from the incr. comp. cache.
// FIXME(mw): This method does not restore MarkData::parent or
// SyntaxContextData::prev_ctxt or SyntaxContextData::modern. These things
// don't seem to be used after HIR lowering, so everything should be fine
// as long as incremental compilation does not kick in before that.
pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
HygieneData::with(|data| {
data.marks.push(MarkData {
parent: Mark::root(),
modern: false,
expn_info: Some(expansion_info)
});

let mark = Mark(data.marks.len() as u32 - 1);

data.syntax_contexts.push(SyntaxContextData {
outer_mark: mark,
prev_ctxt: SyntaxContext::empty(),
modern: SyntaxContext::empty(),
});
SyntaxContext(data.syntax_contexts.len() as u32 - 1)
})
}

/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
HygieneData::with(|data| {
Expand Down Expand Up @@ -286,7 +311,7 @@ impl fmt::Debug for SyntaxContext {
}

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

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

/// The source of expansion.
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum ExpnFormat {
/// e.g. #[derive(...)] <item>
MacroAttribute(Symbol),
Expand All @@ -341,7 +366,7 @@ pub enum ExpnFormat {
}

/// The kind of compiler desugaring.
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CompilerDesugaringKind {
BackArrow,
DotFill,
Expand Down

0 comments on commit 409e392

Please sign in to comment.