about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs7
-rw-r--r--compiler/rustc_middle/src/ich/hcx.rs7
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs48
-rw-r--r--compiler/rustc_resolve/src/lib.rs10
-rw-r--r--compiler/rustc_span/src/lib.rs20
5 files changed, 76 insertions, 16 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index fa14764c42a..9232be8ea2b 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -165,6 +165,8 @@ struct LoweringContext<'a, 'hir: 'a> {
 pub trait ResolverAstLowering {
     fn def_key(&mut self, id: DefId) -> DefKey;
 
+    fn def_span(&self, id: LocalDefId) -> Span;
+
     fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
 
     fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
@@ -216,6 +218,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
     }
 
     #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
+    #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
     }
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 32ccdafaeb4..efb1fc68ce1 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -12,7 +12,7 @@ use rustc_hir::definitions::{DefPathHash, Definitions};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
 
 use smallvec::SmallVec;
 use std::cmp::Ord;
@@ -229,6 +229,11 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
         self.def_path_hash(def_id)
     }
 
+    #[inline]
+    fn def_span(&self, def_id: LocalDefId) -> Span {
+        self.definitions.def_span(def_id)
+    }
+
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index be305e60a0a..63000a295f6 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -23,7 +23,7 @@ use rustc_span::hygiene::{
 };
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::CachingSourceMapView;
-use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP};
+use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
 use std::collections::hash_map::Entry;
 use std::mem;
 
@@ -33,6 +33,7 @@ const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 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_RELATIVE_SPAN: u8 = 2;
 
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
@@ -829,11 +830,25 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let ctxt = SyntaxContext::decode(decoder)?;
+        let parent = Option::<LocalDefId>::decode(decoder)?;
         let tag: u8 = Decodable::decode(decoder)?;
 
         if tag == TAG_PARTIAL_SPAN {
-            let ctxt = SyntaxContext::decode(decoder)?;
-            return Ok(DUMMY_SP.with_ctxt(ctxt));
+            return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent));
+        } else if tag == TAG_RELATIVE_SPAN {
+            let dlo = u32::decode(decoder)?;
+            let dto = u32::decode(decoder)?;
+
+            let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data();
+            let span = Span::new(
+                enclosing.lo + BytePos::from_u32(dlo),
+                enclosing.lo + BytePos::from_u32(dto),
+                ctxt,
+                parent,
+            );
+
+            return Ok(span);
         } else {
             debug_assert_eq!(tag, TAG_FULL_SPAN);
         }
@@ -842,13 +857,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
         let line_lo = usize::decode(decoder)?;
         let col_lo = BytePos::decode(decoder)?;
         let len = BytePos::decode(decoder)?;
-        let ctxt = SyntaxContext::decode(decoder)?;
 
         let file_lo = decoder.file_index_to_file(file_lo_index);
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
-        Ok(Span::new(lo, hi, ctxt, None))
+        Ok(Span::new(lo, hi, ctxt, parent))
     }
 }
 
@@ -1009,9 +1023,21 @@ where
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         let span_data = self.data();
-        if self.is_dummy() {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+        span_data.ctxt.encode(s)?;
+        span_data.parent.encode(s)?;
+
+        if span_data.is_dummy() {
+            return TAG_PARTIAL_SPAN.encode(s);
+        }
+
+        if let Some(parent) = span_data.parent {
+            let enclosing = s.tcx.definitions_untracked().def_span(parent).data();
+            if enclosing.contains(span_data) {
+                TAG_RELATIVE_SPAN.encode(s)?;
+                (span_data.lo - enclosing.lo).to_u32().encode(s)?;
+                (span_data.hi - enclosing.lo).to_u32().encode(s)?;
+                return Ok(());
+            }
         }
 
         let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
@@ -1021,8 +1047,7 @@ where
         };
 
         if partial_span {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+            return TAG_PARTIAL_SPAN.encode(s);
         }
 
         let (file_lo, line_lo, col_lo) = pos.unwrap();
@@ -1035,8 +1060,7 @@ where
         source_file_index.encode(s)?;
         line_lo.encode(s)?;
         col_lo.encode(s)?;
-        len.encode(s)?;
-        span_data.ctxt.encode(s)
+        len.encode(s)
     }
 }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ead3ca9fcde..787c7a625d5 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1114,6 +1114,11 @@ impl ResolverAstLowering for Resolver<'_> {
         }
     }
 
+    #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.definitions.def_span(id)
+    }
+
     fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
         if let Some(def_id) = def_id.as_local() {
             self.item_generics_num_lifetimes[&def_id]
@@ -1222,6 +1227,11 @@ impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> {
     }
 
     #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
+    #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
     }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index d744ad4014a..de08c5d8a55 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -2001,6 +2001,7 @@ impl InnerSpan {
 pub trait HashStableContext {
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
     fn hash_spans(&self) -> bool;
+    fn def_span(&self, def_id: LocalDefId) -> Span;
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
@@ -2024,22 +2025,35 @@ where
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         const TAG_VALID_SPAN: u8 = 0;
         const TAG_INVALID_SPAN: u8 = 1;
+        const TAG_RELATIVE_SPAN: u8 = 2;
 
         if !ctx.hash_spans() {
             return;
         }
 
-        self.ctxt().hash_stable(ctx, hasher);
+        let span = self.data();
+        span.ctxt.hash_stable(ctx, hasher);
+        span.parent.hash_stable(ctx, hasher);
 
-        if self.is_dummy() {
+        if span.is_dummy() {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
             return;
         }
 
+        if let Some(parent) = span.parent {
+            let def_span = ctx.def_span(parent).data();
+            if def_span.contains(span) {
+                // This span is enclosed in a definition: only hash the relative position.
+                Hash::hash(&TAG_RELATIVE_SPAN, hasher);
+                (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                return;
+            }
+        }
+
         // If this is not an empty or invalid span, we want to hash the last
         // position that belongs to it, as opposed to hashing the first
         // position past it.
-        let span = self.data();
         let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
         {
             Some(pos) => pos,