Skip to content

Commit c455274

Browse files
committed
hygiene: Evaluate SyntaxContextData::opaque{_and_semitransparent} on demand
1 parent 7363822 commit c455274

File tree

1 file changed

+44
-53
lines changed

1 file changed

+44
-53
lines changed

compiler/rustc_span/src/hygiene.rs

+44-53
Original file line numberDiff line numberDiff line change
@@ -67,25 +67,21 @@ pub struct SyntaxContextData {
6767
outer_transparency: Transparency,
6868
parent: SyntaxContext,
6969
/// This context, but with all transparent and semi-transparent expansions filtered away.
70-
opaque: SyntaxContext,
70+
opaque: Option<SyntaxContext>,
7171
/// This context, but with all transparent expansions filtered away.
72-
opaque_and_semitransparent: SyntaxContext,
72+
opaque_and_semitransparent: Option<SyntaxContext>,
7373
/// Name of the crate to which `$crate` with this context would resolve.
7474
dollar_crate_name: Symbol,
7575
}
7676

7777
impl SyntaxContextData {
78-
fn new(
79-
(parent, outer_expn, outer_transparency): SyntaxContextKey,
80-
opaque: SyntaxContext,
81-
opaque_and_semitransparent: SyntaxContext,
82-
) -> SyntaxContextData {
78+
fn from_key((parent, outer_expn, outer_transparency): SyntaxContextKey) -> SyntaxContextData {
8379
SyntaxContextData {
8480
outer_expn,
8581
outer_transparency,
8682
parent,
87-
opaque,
88-
opaque_and_semitransparent,
83+
opaque: None,
84+
opaque_and_semitransparent: None,
8985
dollar_crate_name: kw::DollarCrate,
9086
}
9187
}
@@ -95,8 +91,8 @@ impl SyntaxContextData {
9591
outer_expn: ExpnId::root(),
9692
outer_transparency: Transparency::Opaque,
9793
parent: SyntaxContext::root(),
98-
opaque: SyntaxContext::root(),
99-
opaque_and_semitransparent: SyntaxContext::root(),
94+
opaque: Some(SyntaxContext::root()),
95+
opaque_and_semitransparent: Some(SyntaxContext::root()),
10096
dollar_crate_name: kw::DollarCrate,
10197
}
10298
}
@@ -462,14 +458,43 @@ impl HygieneData {
462458
}
463459
}
464460

465-
fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
461+
fn normalize_to_macros_2_0(&mut self, ctxt: SyntaxContext) -> SyntaxContext {
466462
debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
467-
self.syntax_context_data[ctxt.0 as usize].opaque
463+
if let Some(opaque) = self.syntax_context_data[ctxt.0 as usize].opaque {
464+
return opaque;
465+
}
466+
467+
let SyntaxContextData { outer_expn, outer_transparency, parent, .. } =
468+
self.syntax_context_data[ctxt.0 as usize];
469+
let parent_opaque = self.normalize_to_macros_2_0(parent);
470+
let opaque = match outer_transparency {
471+
Transparency::Transparent | Transparency::SemiTransparent => parent_opaque,
472+
Transparency::Opaque => self.alloc_ctxt(parent_opaque, outer_expn, outer_transparency),
473+
};
474+
self.syntax_context_data[ctxt.0 as usize].opaque = Some(opaque);
475+
opaque
468476
}
469477

470-
fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
478+
fn normalize_to_macro_rules(&mut self, ctxt: SyntaxContext) -> SyntaxContext {
471479
debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
472-
self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
480+
if let Some(opaque_and_semitransparent) =
481+
self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
482+
{
483+
return opaque_and_semitransparent;
484+
}
485+
486+
let SyntaxContextData { outer_expn, outer_transparency, parent, .. } =
487+
self.syntax_context_data[ctxt.0 as usize];
488+
let parent_opaque_and_semitransparent = self.normalize_to_macro_rules(parent);
489+
let opaque_and_semitransparent = match outer_transparency {
490+
Transparency::Transparent => parent_opaque_and_semitransparent,
491+
Transparency::SemiTransparent | Transparency::Opaque => {
492+
self.alloc_ctxt(parent_opaque_and_semitransparent, outer_expn, outer_transparency)
493+
}
494+
};
495+
self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent =
496+
Some(opaque_and_semitransparent);
497+
opaque_and_semitransparent
473498
}
474499

475500
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
@@ -597,45 +622,11 @@ impl HygieneData {
597622
) -> SyntaxContext {
598623
debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
599624

600-
// Look into the cache first.
601625
let key = (parent, expn_id, transparency);
602-
if let Some(ctxt) = self.syntax_context_map.get(&key) {
603-
return *ctxt;
604-
}
605-
606-
// Reserve a new syntax context.
607-
let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len());
608-
self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
609-
self.syntax_context_map.insert(key, ctxt);
610-
611-
// Opaque and semi-transparent versions of the parent. Note that they may be equal to the
612-
// parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
613-
// and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
614-
// and semi-transparents.
615-
let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
616-
let parent_opaque_and_semitransparent =
617-
self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
618-
619-
// Evaluate opaque and semi-transparent versions of the new syntax context.
620-
let (opaque, opaque_and_semitransparent) = match transparency {
621-
Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
622-
Transparency::SemiTransparent => (
623-
parent_opaque,
624-
// Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
625-
self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
626-
),
627-
Transparency::Opaque => (
628-
// Will be the same as `ctxt` if the expn chain contains only opaques.
629-
self.alloc_ctxt(parent_opaque, expn_id, transparency),
630-
// Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
631-
self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
632-
),
633-
};
634-
635-
// Fill the full data, now that we have it.
636-
self.syntax_context_data[ctxt.as_u32() as usize] =
637-
SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
638-
ctxt
626+
*self.syntax_context_map.entry(key).or_insert_with(|| {
627+
self.syntax_context_data.push(SyntaxContextData::from_key(key));
628+
SyntaxContext::from_usize(self.syntax_context_data.len() - 1)
629+
})
639630
}
640631
}
641632

0 commit comments

Comments
 (0)