about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2021-04-27 19:24:33 +0200
committerCamille GILLOT <gillot.camille@gmail.com>2021-09-10 20:18:18 +0200
commitb19ae20aada117a589ec238f97c97a98b483f97d (patch)
tree47dde9a7f58604722b43c70c288edd2a70f8f561
parente85ddeb474665f3af7c447445c273da6117e266d (diff)
downloadrust-b19ae20aada117a589ec238f97c97a98b483f97d.tar.gz
rust-b19ae20aada117a589ec238f97c97a98b483f97d.zip
Track span dependency using a callback.
-rw-r--r--compiler/rustc_interface/src/callbacks.rs9
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs6
-rw-r--r--compiler/rustc_span/src/lib.rs5
-rw-r--r--compiler/rustc_span/src/span_encoding.rs16
6 files changed, 40 insertions, 5 deletions
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index 3b852b8ccf9..03c75655d6a 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -25,6 +25,14 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result
     })
 }
 
+fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
+    tls::with_opt(|tcx| {
+        if let Some(tcx) = tcx {
+            let _ = tcx.source_span(def_id);
+        }
+    })
+}
+
 /// This is a callback from `rustc_ast` as it cannot access the implicit state
 /// in `rustc_middle` otherwise. It is used to when diagnostic messages are
 /// emitted and stores them in the current query, if there is one.
@@ -56,6 +64,7 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) ->
 /// TyCtxt in.
 pub fn setup_callbacks() {
     rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+    rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
     rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
     TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
 }
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 34aee4f1b3b..c8ea7454f0b 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -153,6 +153,7 @@ pub fn provide(providers: &mut Providers) {
         index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
     };
     providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
+    providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
     providers.fn_arg_names = |tcx, id| {
         let hir = tcx.hir();
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c93996162e3..d6f3b6f3248 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -20,6 +20,14 @@ rustc_queries! {
         desc { "get the resolver outputs" }
     }
 
+    /// Return the span for a definition.
+    /// Contrary to `def_span` below, this query returns the full absolute span of the definition.
+    /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
+    /// of rustc_middle::hir::source_map.
+    query source_span(key: LocalDefId) -> Span {
+        desc { "get the source span" }
+    }
+
     /// Represents crate as a whole (as distinct from the top-level crate module).
     /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
     /// we will have to assume that any change means that you need to be recompiled.
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 63000a295f6..08565812278 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -840,7 +840,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
             let dlo = u32::decode(decoder)?;
             let dto = u32::decode(decoder)?;
 
-            let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data();
+            let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).decode();
             let span = Span::new(
                 enclosing.lo + BytePos::from_u32(dlo),
                 enclosing.lo + BytePos::from_u32(dto),
@@ -1022,7 +1022,7 @@ where
     E: 'a + OpaqueEncoder,
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let span_data = self.data();
+        let span_data = self.decode();
         span_data.ctxt.encode(s)?;
         span_data.parent.encode(s)?;
 
@@ -1031,7 +1031,7 @@ where
         }
 
         if let Some(parent) = span_data.parent {
-            let enclosing = s.tcx.definitions_untracked().def_span(parent).data();
+            let enclosing = s.tcx.definitions_untracked().def_span(parent).decode();
             if enclosing.contains(span_data) {
                 TAG_RELATIVE_SPAN.encode(s)?;
                 (span_data.lo - enclosing.lo).to_u32().encode(s)?;
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index de08c5d8a55..60b5ffb1d3e 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1947,6 +1947,7 @@ pub struct FileLines {
 
 pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
     AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
 
 // _____________________________________________________________________________
 // SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
@@ -2031,7 +2032,7 @@ where
             return;
         }
 
-        let span = self.data();
+        let span = self.decode();
         span.ctxt.hash_stable(ctx, hasher);
         span.parent.hash_stable(ctx, hasher);
 
@@ -2041,7 +2042,7 @@ where
         }
 
         if let Some(parent) = span.parent {
-            let def_span = ctx.def_span(parent).data();
+            let def_span = ctx.def_span(parent).decode();
             if def_span.contains(span) {
                 // This span is enclosed in a definition: only hash the relative position.
                 Hash::hash(&TAG_RELATIVE_SPAN, hasher);
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 58d639082b0..f74c259d53d 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -6,6 +6,7 @@
 
 use crate::def_id::LocalDefId;
 use crate::hygiene::SyntaxContext;
+use crate::SPAN_TRACK;
 use crate::{BytePos, SpanData};
 
 use rustc_data_structures::fx::FxIndexSet;
@@ -55,6 +56,10 @@ use rustc_data_structures::fx::FxIndexSet;
 ///   the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
 ///   but larger crates might need more than 16 bits.
 ///
+/// In order to reliably use parented spans in incremental compilation,
+/// the dependency to the parent definition's span. This is performed
+/// using the callback `SPAN_TRACK` to access the query engine.
+///
 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
 pub struct Span {
     base_or_index: u32,
@@ -96,6 +101,17 @@ impl Span {
 
     #[inline]
     pub fn data(self) -> SpanData {
+        let data = self.decode();
+        if let Some(parent) = data.parent {
+            (*SPAN_TRACK)(parent);
+        }
+        data
+    }
+
+    /// Internal function to translate between an encoded span and the expanded representation.
+    /// This function must not be used outside the incremental engine.
+    #[inline]
+    pub fn decode(self) -> SpanData {
         if self.len_or_tag != LEN_TAG {
             // Inline format.
             debug_assert!(self.len_or_tag as u32 <= MAX_LEN);