Skip to content

Commit b19ae20

Browse files
committed
Track span dependency using a callback.
1 parent e85ddeb commit b19ae20

File tree

6 files changed

+40
-5
lines changed

6 files changed

+40
-5
lines changed

compiler/rustc_interface/src/callbacks.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result
2525
})
2626
}
2727

28+
fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
29+
tls::with_opt(|tcx| {
30+
if let Some(tcx) = tcx {
31+
let _ = tcx.source_span(def_id);
32+
}
33+
})
34+
}
35+
2836
/// This is a callback from `rustc_ast` as it cannot access the implicit state
2937
/// in `rustc_middle` otherwise. It is used to when diagnostic messages are
3038
/// 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<'_>) ->
5664
/// TyCtxt in.
5765
pub fn setup_callbacks() {
5866
rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
67+
rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
5968
rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
6069
TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
6170
}

compiler/rustc_middle/src/hir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ pub fn provide(providers: &mut Providers) {
153153
index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
154154
};
155155
providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
156+
providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
156157
providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
157158
providers.fn_arg_names = |tcx, id| {
158159
let hir = tcx.hir();

compiler/rustc_middle/src/query/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ rustc_queries! {
2020
desc { "get the resolver outputs" }
2121
}
2222

23+
/// Return the span for a definition.
24+
/// Contrary to `def_span` below, this query returns the full absolute span of the definition.
25+
/// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
26+
/// of rustc_middle::hir::source_map.
27+
query source_span(key: LocalDefId) -> Span {
28+
desc { "get the source span" }
29+
}
30+
2331
/// Represents crate as a whole (as distinct from the top-level crate module).
2432
/// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
2533
/// we will have to assume that any change means that you need to be recompiled.

compiler/rustc_query_impl/src/on_disk_cache.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
840840
let dlo = u32::decode(decoder)?;
841841
let dto = u32::decode(decoder)?;
842842

843-
let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data();
843+
let enclosing = decoder.tcx.definitions_untracked().def_span(parent.unwrap()).decode();
844844
let span = Span::new(
845845
enclosing.lo + BytePos::from_u32(dlo),
846846
enclosing.lo + BytePos::from_u32(dto),
@@ -1022,7 +1022,7 @@ where
10221022
E: 'a + OpaqueEncoder,
10231023
{
10241024
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1025-
let span_data = self.data();
1025+
let span_data = self.decode();
10261026
span_data.ctxt.encode(s)?;
10271027
span_data.parent.encode(s)?;
10281028

@@ -1031,7 +1031,7 @@ where
10311031
}
10321032

10331033
if let Some(parent) = span_data.parent {
1034-
let enclosing = s.tcx.definitions_untracked().def_span(parent).data();
1034+
let enclosing = s.tcx.definitions_untracked().def_span(parent).decode();
10351035
if enclosing.contains(span_data) {
10361036
TAG_RELATIVE_SPAN.encode(s)?;
10371037
(span_data.lo - enclosing.lo).to_u32().encode(s)?;

compiler/rustc_span/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,7 @@ pub struct FileLines {
19471947

19481948
pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
19491949
AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
1950+
pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
19501951

19511952
// _____________________________________________________________________________
19521953
// SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
@@ -2031,7 +2032,7 @@ where
20312032
return;
20322033
}
20332034

2034-
let span = self.data();
2035+
let span = self.decode();
20352036
span.ctxt.hash_stable(ctx, hasher);
20362037
span.parent.hash_stable(ctx, hasher);
20372038

@@ -2041,7 +2042,7 @@ where
20412042
}
20422043

20432044
if let Some(parent) = span.parent {
2044-
let def_span = ctx.def_span(parent).data();
2045+
let def_span = ctx.def_span(parent).decode();
20452046
if def_span.contains(span) {
20462047
// This span is enclosed in a definition: only hash the relative position.
20472048
Hash::hash(&TAG_RELATIVE_SPAN, hasher);

compiler/rustc_span/src/span_encoding.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use crate::def_id::LocalDefId;
88
use crate::hygiene::SyntaxContext;
9+
use crate::SPAN_TRACK;
910
use crate::{BytePos, SpanData};
1011

1112
use rustc_data_structures::fx::FxIndexSet;
@@ -55,6 +56,10 @@ use rustc_data_structures::fx::FxIndexSet;
5556
/// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
5657
/// but larger crates might need more than 16 bits.
5758
///
59+
/// In order to reliably use parented spans in incremental compilation,
60+
/// the dependency to the parent definition's span. This is performed
61+
/// using the callback `SPAN_TRACK` to access the query engine.
62+
///
5863
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
5964
pub struct Span {
6065
base_or_index: u32,
@@ -96,6 +101,17 @@ impl Span {
96101

97102
#[inline]
98103
pub fn data(self) -> SpanData {
104+
let data = self.decode();
105+
if let Some(parent) = data.parent {
106+
(*SPAN_TRACK)(parent);
107+
}
108+
data
109+
}
110+
111+
/// Internal function to translate between an encoded span and the expanded representation.
112+
/// This function must not be used outside the incremental engine.
113+
#[inline]
114+
pub fn decode(self) -> SpanData {
99115
if self.len_or_tag != LEN_TAG {
100116
// Inline format.
101117
debug_assert!(self.len_or_tag as u32 <= MAX_LEN);

0 commit comments

Comments
 (0)