about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2021-01-03 10:09:32 -0500
committerAaron Hill <aa1ronham@gmail.com>2021-01-13 15:20:29 -0500
commit482a67d20f3c7059c33368df424f781585ead7cc (patch)
tree18062afb585364430c33ada59740403a208a3198
parentfd2df74902fa98bcb71f85fd548c3eb399e6a96a (diff)
downloadrust-482a67d20f3c7059c33368df424f781585ead7cc.tar.gz
rust-482a67d20f3c7059c33368df424f781585ead7cc.zip
Properly handle `SyntaxContext` of dummy spans in incr comp
Fixes #80336

Due to macro expansion, we may end up with spans with an invalid
location and non-root `SyntaxContext`. This commits preserves the
`SyntaxContext` of such spans in the incremental cache, and ensures
that we always hash the `SyntaxContext` when computing the `Fingerprint`
of a `Span`

Previously, we would discard the `SyntaxContext` during serialization to
the incremental cache, causing the span's `Fingerprint` to change across
compilation sessions.
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs32
-rw-r--r--compiler/rustc_span/src/lib.rs3
-rw-r--r--src/test/incremental/issue-80336-invalid-span.rs10
3 files changed, 32 insertions, 13 deletions
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index abe58aacbb1..6003509780a 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -32,8 +32,10 @@ use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
-const TAG_VALID_SPAN: u8 = 0;
-const TAG_INVALID_SPAN: u8 = 1;
+// A normal span encoded with both location information and a `SyntaxContext`
+const TAG_FULL_SPAN: u8 = 0;
+// A partial span with no location information, encoded only with a `SyntaxContext`
+const TAG_PARTIAL_SPAN: u8 = 1;
 
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
@@ -864,10 +866,11 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let tag: u8 = Decodable::decode(decoder)?;
 
-        if tag == TAG_INVALID_SPAN {
-            return Ok(DUMMY_SP);
+        if tag == TAG_PARTIAL_SPAN {
+            let ctxt = SyntaxContext::decode(decoder)?;
+            return Ok(DUMMY_SP.with_ctxt(ctxt));
         } else {
-            debug_assert_eq!(tag, TAG_VALID_SPAN);
+            debug_assert_eq!(tag, TAG_FULL_SPAN);
         }
 
         let file_lo_index = SourceFileIndex::decode(decoder)?;
@@ -1057,24 +1060,29 @@ where
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         if *self == DUMMY_SP {
-            return TAG_INVALID_SPAN.encode(s);
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return SyntaxContext::root().encode(s);
         }
 
         let span_data = self.data();
-        let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
-            Some(pos) => pos,
-            None => return TAG_INVALID_SPAN.encode(s),
+        let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
+        let partial_span = match &pos {
+            Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
+            None => true,
         };
 
-        if !file_lo.contains(span_data.hi) {
-            return TAG_INVALID_SPAN.encode(s);
+        if partial_span {
+            TAG_PARTIAL_SPAN.encode(s)?;
+            return span_data.ctxt.encode(s);
         }
 
+        let (file_lo, line_lo, col_lo) = pos.unwrap();
+
         let len = span_data.hi - span_data.lo;
 
         let source_file_index = s.source_file_index(file_lo);
 
-        TAG_VALID_SPAN.encode(s)?;
+        TAG_FULL_SPAN.encode(s)?;
         source_file_index.encode(s)?;
         line_lo.encode(s)?;
         col_lo.encode(s)?;
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f0f9f940446..50cb1555486 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1899,8 +1899,9 @@ where
             return;
         }
 
-        if *self == DUMMY_SP {
+        if self.is_dummy() {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
+            self.ctxt().hash_stable(ctx, hasher);
             return;
         }
 
diff --git a/src/test/incremental/issue-80336-invalid-span.rs b/src/test/incremental/issue-80336-invalid-span.rs
new file mode 100644
index 00000000000..7757d915911
--- /dev/null
+++ b/src/test/incremental/issue-80336-invalid-span.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #80336
+// Test that we properly handle encoding, decoding, and hashing
+// of spans with an invalid location and non-root `SyntaxContext`
+
+// revisions:rpass1 rpass2
+// only-x86_64
+
+pub fn main() {
+    let _ = is_x86_feature_detected!("avx2");
+}