about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-11-22 13:41:27 +0100
committerMichael Woerister <michaelwoerister@posteo>2017-12-01 13:48:19 +0100
commit409e39285d2189eb8bb656a93074473f9f186cc5 (patch)
tree10e756d650ef39b7d25b66bf0026a528faee7b67 /src
parent315fbf7518dbcace5b92eabab746ba0a2c5531fa (diff)
downloadrust-409e39285d2189eb8bb656a93074473f9f186cc5.tar.gz
rust-409e39285d2189eb8bb656a93074473f9f186cc5.zip
incr.comp.: Properly hash and encode macro expansion information.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/hcx.rs2
-rw-r--r--src/librustc/ich/impls_syntax.rs24
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs86
-rw-r--r--src/libsyntax_pos/hygiene.rs33
4 files changed, 138 insertions, 7 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index f204d352842..6d7322fdafd 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -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);
         }
     }
 }
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index fea4e283db1..c414349c8ff 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -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>,
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index 01f2374033d..6ca787ad19e 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -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;
@@ -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
@@ -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`.
@@ -90,6 +96,8 @@ 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,
@@ -97,6 +105,7 @@ impl<'sess> OnDiskCache<'sess> {
                 codemap: sess.codemap(),
                 prev_filemap_starts: &header.prev_filemap_starts,
                 cnum_map: &IndexVec::new(),
+                synthetic_expansion_infos: &mut synthetic_expansion_infos,
             };
 
             // Decode Diagnostics
@@ -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),
         }
     }
 
@@ -148,6 +158,7 @@ impl<'sess> OnDiskCache<'sess> {
             codemap,
             current_diagnostics: RefCell::new(FxHashMap()),
             query_result_index: FxHashMap(),
+            synthetic_expansion_infos: RefCell::new(FxHashMap()),
         }
     }
 
@@ -166,6 +177,7 @@ impl<'sess> OnDiskCache<'sess> {
             encoder,
             type_shorthands: FxHashMap(),
             predicate_shorthands: FxHashMap(),
+            expn_info_shorthands: FxHashMap(),
         };
 
 
@@ -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) {
@@ -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> {
@@ -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));
             }
         }
 
@@ -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)?;
@@ -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)?))
     }
@@ -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>
@@ -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
 {
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 4790fa0a7ed..9358e654a9f 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -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| {
@@ -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 {}`
@@ -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,
@@ -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),
@@ -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,