diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index a4b44423c6eda..1892ddcf05a1a 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -13,7 +13,7 @@ use rustc_parse::parser::ParseNtResult; use rustc_session::parse::{ParseSess, SymbolGallery}; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::{ - Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, sym, with_metavar_spans_mut, + Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, sym, with_metavar_spans, }; use smallvec::{SmallVec, smallvec}; @@ -283,13 +283,17 @@ pub(super) fn transcribe<'a>( } MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { marker.visit_span(&mut sp); - with_metavar_spans_mut(|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_mut(|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) } @@ -299,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_mut(|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(..) => { @@ -415,16 +421,17 @@ fn maybe_use_metavar_location( return orig_tt.clone(); } - let insert = |mspans: &mut UnordMap<_, _>, 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_mut(|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_mut(|mspans| { + 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) @@ -439,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_mut(|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_mut(|mspans| { + 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); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 7039aac465a73..2c3839e137bb7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -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}; @@ -1122,7 +1123,14 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { // and combining it with other hashes here. resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher); with_metavar_spans(|mspans| { - mspans.hash_stable(&mut hcx, &mut stable_hasher); + // 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() }); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 8eab28cce8238..7fdc0fe7d7e0d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -103,7 +103,7 @@ pub struct SessionGlobals { span_interner: Lock, /// 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: FreezeLock>, + metavar_spans: FreezeLock>, hygiene_data: Lock, /// The session's source map, if there is one. This field should only be @@ -178,13 +178,8 @@ pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); #[inline] -pub fn with_metavar_spans_mut(f: impl FnOnce(&mut UnordMap) -> R) -> R { - with_session_globals(|session_globals| f(&mut session_globals.metavar_spans.write())) -} - -#[inline] -pub fn with_metavar_spans(f: impl FnOnce(&UnordMap) -> R) -> R { - with_session_globals(|session_globals| f(&session_globals.metavar_spans.read())) +pub fn with_metavar_spans(f: impl FnOnce(&FreezeLock>) -> R) -> R { + with_session_globals(|session_globals| f(&session_globals.metavar_spans)) } #[inline] @@ -884,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: &UnordMap<_, _>, s| mspans.get(&s).copied(); + let get = |mspans: &FreezeLock>, 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) => {