Skip to content

Commit cd2673d

Browse files
committed
Auto merge of #139146 - petrochenkov:ctxtdecod4, r=<try>
hygiene: Evaluate `SyntaxContextData::opaque{_and_semitransparent}` on demand This is unlikely to fly because these fields should be accessed more often than created, but let's see.
2 parents 45b40a7 + c455274 commit cd2673d

File tree

2 files changed

+71
-79
lines changed

2 files changed

+71
-79
lines changed

compiler/rustc_span/src/hygiene.rs

Lines changed: 61 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,32 @@ 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 from_key((parent, outer_expn, outer_transparency): SyntaxContextKey) -> SyntaxContextData {
79+
SyntaxContextData {
80+
outer_expn,
81+
outer_transparency,
82+
parent,
83+
opaque: None,
84+
opaque_and_semitransparent: None,
85+
dollar_crate_name: kw::DollarCrate,
86+
}
87+
}
88+
7889
fn root() -> SyntaxContextData {
7990
SyntaxContextData {
8091
outer_expn: ExpnId::root(),
8192
outer_transparency: Transparency::Opaque,
8293
parent: SyntaxContext::root(),
83-
opaque: SyntaxContext::root(),
84-
opaque_and_semitransparent: SyntaxContext::root(),
94+
opaque: Some(SyntaxContext::root()),
95+
opaque_and_semitransparent: Some(SyntaxContext::root()),
8596
dollar_crate_name: kw::DollarCrate,
8697
}
8798
}
@@ -447,14 +458,43 @@ impl HygieneData {
447458
}
448459
}
449460

450-
fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
461+
fn normalize_to_macros_2_0(&mut self, ctxt: SyntaxContext) -> SyntaxContext {
451462
debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
452-
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
453476
}
454477

455-
fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
478+
fn normalize_to_macro_rules(&mut self, ctxt: SyntaxContext) -> SyntaxContext {
456479
debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
457-
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
458498
}
459499

460500
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
@@ -543,7 +583,7 @@ impl HygieneData {
543583
) -> SyntaxContext {
544584
assert_ne!(expn_id, ExpnId::root());
545585
if transparency == Transparency::Opaque {
546-
return self.apply_mark_internal(ctxt, expn_id, transparency);
586+
return self.alloc_ctxt(ctxt, expn_id, transparency);
547587
}
548588

549589
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
@@ -554,7 +594,7 @@ impl HygieneData {
554594
};
555595

556596
if call_site_ctxt.is_root() {
557-
return self.apply_mark_internal(ctxt, expn_id, transparency);
597+
return self.alloc_ctxt(ctxt, expn_id, transparency);
558598
}
559599

560600
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
@@ -567,73 +607,25 @@ impl HygieneData {
567607
//
568608
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
569609
for (expn_id, transparency) in self.marks(ctxt) {
570-
call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
610+
call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
571611
}
572-
self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
612+
self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
573613
}
574614

575-
fn apply_mark_internal(
615+
/// Allocate a new context with the given key, or retrieve it from cache if the given key
616+
/// already exists. The auxiliary fields are calculated from the key.
617+
fn alloc_ctxt(
576618
&mut self,
577-
ctxt: SyntaxContext,
619+
parent: SyntaxContext,
578620
expn_id: ExpnId,
579621
transparency: Transparency,
580622
) -> SyntaxContext {
581-
let syntax_context_data = &mut self.syntax_context_data;
582-
debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
583-
let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
584-
let mut opaque_and_semitransparent =
585-
syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
586-
587-
if transparency >= Transparency::Opaque {
588-
let parent = opaque;
589-
opaque = *self
590-
.syntax_context_map
591-
.entry((parent, expn_id, transparency))
592-
.or_insert_with(|| {
593-
let new_opaque = SyntaxContext::from_usize(syntax_context_data.len());
594-
syntax_context_data.push(SyntaxContextData {
595-
outer_expn: expn_id,
596-
outer_transparency: transparency,
597-
parent,
598-
opaque: new_opaque,
599-
opaque_and_semitransparent: new_opaque,
600-
dollar_crate_name: kw::DollarCrate,
601-
});
602-
new_opaque
603-
});
604-
}
623+
debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
605624

606-
if transparency >= Transparency::SemiTransparent {
607-
let parent = opaque_and_semitransparent;
608-
opaque_and_semitransparent = *self
609-
.syntax_context_map
610-
.entry((parent, expn_id, transparency))
611-
.or_insert_with(|| {
612-
let new_opaque_and_semitransparent =
613-
SyntaxContext::from_usize(syntax_context_data.len());
614-
syntax_context_data.push(SyntaxContextData {
615-
outer_expn: expn_id,
616-
outer_transparency: transparency,
617-
parent,
618-
opaque,
619-
opaque_and_semitransparent: new_opaque_and_semitransparent,
620-
dollar_crate_name: kw::DollarCrate,
621-
});
622-
new_opaque_and_semitransparent
623-
});
624-
}
625-
626-
let parent = ctxt;
627-
*self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
628-
syntax_context_data.push(SyntaxContextData {
629-
outer_expn: expn_id,
630-
outer_transparency: transparency,
631-
parent,
632-
opaque,
633-
opaque_and_semitransparent,
634-
dollar_crate_name: kw::DollarCrate,
635-
});
636-
SyntaxContext::from_usize(syntax_context_data.len() - 1)
625+
let key = (parent, expn_id, transparency);
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)
637629
})
638630
}
639631
}

tests/ui/proc-macro/nonterminal-token-hygiene.stdout

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
55
stream: TokenStream [
66
Ident {
77
ident: "struct",
8-
span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
8+
span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
99
},
1010
Ident {
1111
ident: "S",
12-
span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
12+
span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
1313
},
1414
Punct {
1515
ch: ';',
1616
spacing: Alone,
17-
span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
17+
span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
1818
},
1919
],
20-
span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
20+
span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
2121
},
2222
]
2323
#![feature /* 0#0 */(prelude_import)]
@@ -59,7 +59,7 @@ macro_rules! outer
5959
struct S /* 0#0 */;
6060
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
6161

62-
struct S /* 0#4 */;
62+
struct S /* 0#5 */;
6363
// OK, not a duplicate definition of `S`
6464

6565
fn main /* 0#0 */() {}
@@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt:
7070
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
7171
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
7272
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
73-
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
73+
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
7474
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
7575
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
7676
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
@@ -83,9 +83,9 @@ SyntaxContexts:
8383
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
8484
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
8585
#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
86-
#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
87-
#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
86+
#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
87+
#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
8888
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
89-
#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
90-
#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
89+
#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
90+
#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
9191
*/

0 commit comments

Comments
 (0)