diff options
| author | bors <bors@rust-lang.org> | 2025-01-22 14:46:41 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-01-22 14:46:41 +0000 |
| commit | dee7d0e730a3a3ed98c89dd33c4ac16edc82de8a (patch) | |
| tree | 3d6e80304bba9a0899e5ecb00f8a378c72514c68 /compiler/rustc_span/src/lib.rs | |
| parent | b2728d5426bab1d8c39709768c7e22b7f66dde5d (diff) | |
| parent | 2de21ad7d4a14894463816ac5dedc337ae3a2941 (diff) | |
| download | rust-dee7d0e730a3a3ed98c89dd33c4ac16edc82de8a.tar.gz rust-dee7d0e730a3a3ed98c89dd33c4ac16edc82de8a.zip | |
Auto merge of #134478 - compiler-errors:attr-span, r=oli-obk
Properly record metavar spans for other expansions other than TT This properly records metavar spans for nonterminals other than tokentree. This means that we operations like `span.to(other_span)` work correctly for macros. As you can see, other diagnostics involving metavars have improved as a result. Fixes #132908 Alternative to #133270 cc `@ehuss` cc `@petrochenkov`
Diffstat (limited to 'compiler/rustc_span/src/lib.rs')
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f932d3c8073..51d809bd65d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -25,6 +25,7 @@ #![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(let_chains)] +#![feature(map_try_insert)] #![feature(negative_impls)] #![feature(read_buf)] #![feature(round_char_boundary)] @@ -85,9 +86,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; @@ -103,7 +104,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: MetavarSpansMap, hygiene_data: Lock<hygiene::HygieneData>, /// The session's source map, if there is one. This field should only be @@ -177,9 +178,42 @@ pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R { // deserialization. scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); +#[derive(Default)] +pub struct MetavarSpansMap(FreezeLock<UnordMap<Span, (Span, bool)>>); + +impl MetavarSpansMap { + pub fn insert(&self, span: Span, var_span: Span) -> bool { + match self.0.write().try_insert(span, (var_span, false)) { + Ok(_) => true, + Err(entry) => entry.entry.get().0 == var_span, + } + } + + /// Read a span and record that it was read. + pub fn get(&self, span: Span) -> Option<Span> { + if let Some(mut mspans) = self.0.try_write() { + if let Some((var_span, read)) = mspans.get_mut(&span) { + *read = true; + Some(*var_span) + } else { + None + } + } else { + if let Some((span, true)) = self.0.read().get(&span) { Some(*span) } else { None } + } + } + + /// Freeze the set, and return the spans which have been read. + /// + /// After this is frozen, no spans that have not been read can be read. + pub fn freeze_and_get_read_spans(&self) -> UnordMap<Span, Span> { + self.0.freeze().items().filter(|(_, (_, b))| *b).map(|(s1, (s2, _))| (*s1, *s2)).collect() + } +} + #[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(&MetavarSpansMap) -> R) -> R { + with_session_globals(|session_globals| f(&session_globals.metavar_spans)) } // FIXME: We should use this enum or something like it to get rid of the @@ -872,8 +906,7 @@ 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(); - match with_metavar_spans(|mspans| (get(mspans, a_orig), get(mspans, b_orig))) { + match with_metavar_spans(|mspans| (mspans.get(a_orig), mspans.get(b_orig))) { (None, None) => {} (Some(meta_a), None) => { let meta_a = meta_a.data(); |
