Skip to content

Commit

Permalink
Hash only the spans that we care ended up reading in Span::try_metavars
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 18, 2024
1 parent 2def03d commit 4d766b5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
23 changes: 16 additions & 7 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, T
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
use rustc_parse::lexer::nfc_normalize;
use rustc_parse::parser::ParseNtResult;
Expand Down Expand Up @@ -282,13 +283,17 @@ pub(super) fn transcribe<'a>(
}
MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => {
marker.visit_span(&mut sp);
with_metavar_spans(|mspans| mspans.insert(ident.span, sp));
with_metavar_spans(|mspans| {
mspans.write().insert(ident.span, (sp, false))
});
let kind = token::NtIdent(*ident, *is_raw);
TokenTree::token_alone(kind, sp)
}
MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => {
marker.visit_span(&mut sp);
with_metavar_spans(|mspans| mspans.insert(ident.span, sp));
with_metavar_spans(|mspans| {
mspans.write().insert(ident.span, (sp, false))
});
let kind = token::NtLifetime(*ident, *is_raw);
TokenTree::token_alone(kind, sp)
}
Expand All @@ -298,7 +303,9 @@ pub(super) fn transcribe<'a>(
// `Interpolated` is currently used for such groups in rustc parser.
marker.visit_span(&mut sp);
let use_span = nt.use_span();
with_metavar_spans(|mspans| mspans.insert(use_span, sp));
with_metavar_spans(|mspans| {
mspans.write().insert(use_span, (sp, false))
});
TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp)
}
MatchedSeq(..) => {
Expand Down Expand Up @@ -414,16 +421,17 @@ fn maybe_use_metavar_location(
return orig_tt.clone();
}

let insert = |mspans: &mut FxHashMap<_, _>, s, ms| match mspans.try_insert(s, ms) {
let insert = |mspans: &mut UnordMap<_, _>, s, ms| match mspans.try_insert(s, (ms, false)) {
Ok(_) => true,
Err(err) => *err.entry.get() == ms, // Tried to insert the same span, still success
Err(err) => err.entry.get().0 == ms, // Tried to insert the same span, still success
};
marker.visit_span(&mut metavar_span);
let no_collision = match orig_tt {
TokenTree::Token(token, ..) => {
with_metavar_spans(|mspans| insert(mspans, token.span, metavar_span))
with_metavar_spans(|mspans| insert(&mut mspans.write(), token.span, metavar_span))
}
TokenTree::Delimited(dspan, ..) => with_metavar_spans(|mspans| {
let mspans = &mut mspans.write();
insert(mspans, dspan.open, metavar_span)
&& insert(mspans, dspan.close, metavar_span)
&& insert(mspans, dspan.entire(), metavar_span)
Expand All @@ -438,13 +446,14 @@ fn maybe_use_metavar_location(
match orig_tt {
TokenTree::Token(Token { kind, span }, spacing) => {
let span = metavar_span.with_ctxt(span.ctxt());
with_metavar_spans(|mspans| insert(mspans, span, metavar_span));
with_metavar_spans(|mspans| insert(&mut mspans.write(), span, metavar_span));
TokenTree::Token(Token { kind: kind.clone(), span }, *spacing)
}
TokenTree::Delimited(dspan, dspacing, delimiter, tts) => {
let open = metavar_span.with_ctxt(dspan.open.ctxt());
let close = metavar_span.with_ctxt(dspan.close.ctxt());
with_metavar_spans(|mspans| {
let mspans = &mut mspans.write();
insert(mspans, open, metavar_span) && insert(mspans, close, metavar_span)
});
let dspan = DelimSpan::from_pair(open, close);
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
Expand All @@ -12,7 +13,9 @@ use rustc_hir::*;
use rustc_hir_pretty as pprust_hir;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use rustc_span::{
ErrorGuaranteed, Ident, Span, Symbol, freeze_metavar_spans, kw, sym, with_metavar_spans,
};

use crate::hir::ModuleItems;
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
Expand Down Expand Up @@ -1087,6 +1090,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
.map(DebuggerVisualizerFile::path_erased)
.collect();

// Freeze metavars since we do not expect any more expansion after this.
freeze_metavar_spans();

let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
Expand Down Expand Up @@ -1116,6 +1122,16 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
// the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
// and combining it with other hashes here.
resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher);
with_metavar_spans(|mspans| {
// Only hash the spans we ended up using.
let filtered_spans: UnordMap<_, _> = mspans
.read()
.items()
.filter(|(_, (_, b))| *b)
.map(|(s1, (s2, _))| (*s1, *s2))
.collect();
filtered_spans.hash_stable(&mut hcx, &mut stable_hasher);
});
stable_hasher.finish()
});

Expand Down
28 changes: 23 additions & 5 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ use std::str::FromStr;
use std::{fmt, iter};

use md5::{Digest, Md5};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{Hash64, Hash128, HashStable, StableHasher};
use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock, Lrc};
use rustc_data_structures::unord::UnordMap;
use sha1::Sha1;
use sha2::Sha256;

Expand All @@ -103,7 +103,7 @@ pub struct SessionGlobals {
span_interner: Lock<span_encoding::SpanInterner>,
/// Maps a macro argument token into use of the corresponding metavariable in the macro body.
/// Collisions are possible and processed in `maybe_use_metavar_location` on best effort basis.
metavar_spans: Lock<FxHashMap<Span, Span>>,
metavar_spans: FreezeLock<UnordMap<Span, (Span, bool)>>,
hygiene_data: Lock<hygiene::HygieneData>,

/// The session's source map, if there is one. This field should only be
Expand Down Expand Up @@ -178,8 +178,15 @@ pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);

#[inline]
pub fn with_metavar_spans<R>(f: impl FnOnce(&mut FxHashMap<Span, Span>) -> R) -> R {
with_session_globals(|session_globals| f(&mut session_globals.metavar_spans.lock()))
pub fn with_metavar_spans<R>(f: impl FnOnce(&FreezeLock<UnordMap<Span, (Span, bool)>>) -> R) -> R {
with_session_globals(|session_globals| f(&session_globals.metavar_spans))
}

#[inline]
pub fn freeze_metavar_spans() {
with_session_globals(|session_globals| {
session_globals.metavar_spans.freeze();
});
}

// FIXME: We should use this enum or something like it to get rid of the
Expand Down Expand Up @@ -872,7 +879,18 @@ impl Span {

/// Check if you can select metavar spans for the given spans to get matching contexts.
fn try_metavars(a: SpanData, b: SpanData, a_orig: Span, b_orig: Span) -> (SpanData, SpanData) {
let get = |mspans: &FxHashMap<_, _>, s| mspans.get(&s).copied();
let get = |mspans: &FreezeLock<UnordMap<_, _>>, s| {
if let Some(mut mspans) = mspans.try_write() {
if let Some((span, read)) = mspans.get_mut(&s) {
*read = true;
Some(*span)
} else {
None
}
} else {
if let Some((span, true)) = mspans.read().get(&s) { Some(*span) } else { None }
}
};
match with_metavar_spans(|mspans| (get(mspans, a_orig), get(mspans, b_orig))) {
(None, None) => {}
(Some(meta_a), None) => {
Expand Down

0 comments on commit 4d766b5

Please sign in to comment.