Skip to content
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ impl MetaItem {
let is_first = i == 0;
if !is_first {
let mod_sep_span =
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
}
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
let if_expr = self.expr(span, if_kind, ThinVec::new());
let block = self.block_expr(self.arena.alloc(if_expr));
hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi()))
let span = self.lower_span(span.with_hi(cond.span.hi()));
let opt_label = self.lower_label(opt_label);
hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
}

/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
Expand Down
20 changes: 16 additions & 4 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>;
Expand Down Expand Up @@ -215,6 +217,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
true
}

#[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)
Expand Down Expand Up @@ -711,9 +718,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

/// Intercept all spans entering HIR.
/// For now we are not doing anything with the intercepted spans.
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
span
if self.sess.opts.debugging_opts.incremental_relative_spans {
span.with_parent(Some(self.current_hir_id_owner.0))
} else {
// Do not make spans relative when not using incremental compilation.
span
}
}

fn lower_ident(&self, ident: Ident) -> Ident {
Expand Down Expand Up @@ -781,7 +793,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
node_id,
DefPathData::LifetimeNs(str_name),
ExpnId::root(),
span,
span.with_parent(None),
);

hir::GenericParam {
Expand Down Expand Up @@ -1513,7 +1525,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_node_id,
DefPathData::LifetimeNs(name.ident().name),
ExpnId::root(),
span,
span.with_parent(None),
);

let (name, kind) = match name {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::BuiltinLintDiagnostics;
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
use rustc_session::{parse::ParseSess, Limit, Session};
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
Expand Down Expand Up @@ -843,6 +843,7 @@ pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExten

pub trait ResolverExpand {
fn next_node_id(&mut self) -> NodeId;
fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;

fn resolve_dollar_crates(&mut self);
fn visit_ast_fragment_with_placeholders(
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
// Resolve `$crate`s in the fragment for pretty-printing.
self.cx.resolver.resolve_dollar_crates();

let invocations = {
let mut invocations = {
let mut collector = InvocationCollector {
// Non-derive macro invocations cannot see the results of cfg expansion - they
// will either be removed along with the item, or invoked before the cfg/cfg_attr
Expand All @@ -613,6 +613,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx
.resolver
.visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);

if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
for (invoc, _) in invocations.iter_mut() {
let expn_id = invoc.expansion_data.id;
let parent_def = self.cx.resolver.invocation_parent(expn_id);
let span = match &mut invoc.kind {
InvocationKind::Bang { ref mut span, .. } => span,
InvocationKind::Attr { attr, .. } => &mut attr.span,
InvocationKind::Derive { path, .. } => &mut path.span,
};
*span = span.with_parent(Some(parent_def));
}
}
}

(fragment, invocations)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ impl server::Span for Rustc<'_> {
self.sess.source_map().lookup_char_pos(span.lo()).file
}
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
span.parent()
span.parent_callsite()
}
fn source(&mut self, span: Self::Span) -> Self::Span {
span.source_callsite()
Expand Down
24 changes: 23 additions & 1 deletion compiler/rustc_hir/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_data_structures::unhash::UnhashMap;
use rustc_index::vec::IndexVec;
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;

use std::fmt::{self, Write};
use std::hash::Hash;
Expand Down Expand Up @@ -107,6 +108,8 @@ pub struct Definitions {

/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,

def_id_to_span: IndexVec<LocalDefId, Span>,
}

/// A unique identifier that we can use to lookup a definition
Expand Down Expand Up @@ -324,7 +327,7 @@ impl Definitions {
}

/// Adds a root definition (no parent) and a few other reserved definitions.
pub fn new(stable_crate_id: StableCrateId) -> Definitions {
pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions {
let key = DefKey {
parent: None,
disambiguated_data: DisambiguatedDefPathData {
Expand All @@ -341,11 +344,18 @@ impl Definitions {
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);

let mut def_id_to_span = IndexVec::new();
// A relative span's parent must be an absolute span.
debug_assert_eq!(crate_span.data_untracked().parent, None);
let _root = def_id_to_span.push(crate_span);
debug_assert_eq!(_root, root);

Definitions {
table,
def_id_to_hir_id: Default::default(),
hir_id_to_def_id: Default::default(),
expansions_that_defined: Default::default(),
def_id_to_span,
}
}

Expand All @@ -361,6 +371,7 @@ impl Definitions {
data: DefPathData,
expn_id: ExpnId,
mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32,
span: Span,
) -> LocalDefId {
debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id);

Expand All @@ -385,6 +396,11 @@ impl Definitions {
self.expansions_that_defined.insert(def_id, expn_id);
}

// A relative span's parent must be an absolute span.
debug_assert_eq!(span.data_untracked().parent, None);
let _id = self.def_id_to_span.push(span);
debug_assert_eq!(_id, def_id);

def_id
}

Expand Down Expand Up @@ -412,6 +428,12 @@ impl Definitions {
self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
}

/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
#[inline]
pub fn def_span(&self, def_id: LocalDefId) -> Span {
self.def_id_to_span[def_id]
}

pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_interface/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ 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 _span = tcx.source_span(def_id);
// Sanity check: relative span's parent must be an absolute span.
debug_assert_eq!(_span.data_untracked().parent, None);
}
})
}

/// 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.
Expand Down Expand Up @@ -56,6 +66,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(&_)));
}
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
let hi =
(hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;

Ok(Span::new(lo, hi, ctxt))
// Do not try to decode parent for foreign spans.
Ok(Span::new(lo, hi, ctxt, None))
}
}

Expand Down
26 changes: 13 additions & 13 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,22 +969,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
.iter_enumerated()
.filter_map(|(def_id, hod)| {
let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
let mut hasher = StableHasher::new();
hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
.hash_stable(&mut hcx, &mut hasher);
Some((def_path_hash, hasher.finish()))
let hash = hod.as_ref()?.hash;
Some((def_path_hash, hash, def_id))
})
.collect();
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);

let node_hashes = hir_body_nodes.iter().fold(
Fingerprint::ZERO,
|combined_fingerprint, &(def_path_hash, fingerprint)| {
combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
},
);

let upstream_crates = upstream_crates(tcx);

// We hash the final, remapped names of all local source files so we
Expand All @@ -1004,7 +994,17 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
source_file_names.sort_unstable();

let mut stable_hasher = StableHasher::new();
node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
.hash_stable(&mut hcx, &mut stable_hasher);
if tcx.sess.opts.debugging_opts.incremental_relative_spans {
let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
debug_assert_eq!(span.parent(), None);
span.hash_stable(&mut hcx, &mut stable_hasher);
}
}
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_middle/src/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ fn foo(&self) -> Self::T { String::new() }
{
let (span, sugg) = if has_params {
let pos = span.hi() - BytePos(1);
let span = Span::new(pos, pos, span.ctxt());
let span = Span::new(pos, pos, span.ctxt(), span.parent());
(span, format!(", {} = {}", assoc.ident, ty))
} else {
let item_args = self.format_generic_args(assoc_substs);
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_mir_transform/src/coverage/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ impl CoverageSpan {
/// body_span), returns the macro name symbol.
pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
if let Some(current_macro) = self.current_macro() {
if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt()
if self
.expn_span
.parent_callsite()
.unwrap_or_else(|| bug!("macro must have a parent"))
.ctxt()
== body_span.ctxt()
{
return Some(current_macro);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ fn maybe_source_file_to_parser(
let mut parser = stream_to_parser(sess, stream, None);
parser.unclosed_delims = unclosed_delims;
if parser.token == token::Eof {
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
}

Ok(parser)
Expand Down
Loading