-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Properly record metavar spans for other expansions other than TT #134478
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
pub fn freeze_and_get_read_spans(&self) -> UnordMap<Span, Span> { | ||||||
self.0.freeze().items().filter(|(_, (_, b))| *b).map(|(s1, (s2, _))| (*s1, *s2)).collect() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we ever use this twice? if not, could also poison the lock after extracting the spans we care about. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Poison the lock on the whole map? |
||||||
} | ||||||
} | ||||||
|
||||||
#[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(); | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Orthogonal to this PR, but It's not clear to me that it's good keeping the previously inserted spans in the map if one of the later ones in this chain fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more spans the better, so the best logic here would be
But it probably doesn't matter anyway, because
b{1,2,3}
always (or almost always) have the same value in practice, and the metavar span retrieval is best effort anyway.