Hash only the spans that we care ended up reading in Span::try_metavars
This commit is contained in:
parent
69b2fc3e2f
commit
2de21ad7d4
5 changed files with 52 additions and 41 deletions
|
@ -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)]
|
||||
|
@ -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: FreezeLock<UnordMap<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,21 +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);
|
||||
|
||||
#[inline]
|
||||
pub fn with_metavar_spans_mut<R>(f: impl FnOnce(&mut UnordMap<Span, Span>) -> R) -> R {
|
||||
with_session_globals(|session_globals| f(&mut session_globals.metavar_spans.write()))
|
||||
#[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(&UnordMap<Span, Span>) -> R) -> R {
|
||||
with_session_globals(|session_globals| f(&session_globals.metavar_spans.read()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn freeze_metavar_spans() {
|
||||
with_session_globals(|session_globals| {
|
||||
session_globals.metavar_spans.freeze();
|
||||
});
|
||||
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
|
||||
|
@ -884,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: &UnordMap<_, _>, 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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue