Skip to content

Commit 7c74474

Browse files
committed
hygiene: Rewrite apply_mark_internal to be more understandable
1 parent 2a06022 commit 7c74474

File tree

2 files changed

+71
-70
lines changed

2 files changed

+71
-70
lines changed

compiler/rustc_span/src/hygiene.rs

+61-60
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ pub struct SyntaxContextData {
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 {
83+
SyntaxContextData {
84+
outer_expn,
85+
outer_transparency,
86+
parent,
87+
opaque,
88+
opaque_and_semitransparent,
89+
dollar_crate_name: kw::DollarCrate,
90+
}
91+
}
92+
7893
fn root() -> SyntaxContextData {
7994
SyntaxContextData {
8095
outer_expn: ExpnId::root(),
@@ -543,7 +558,7 @@ impl HygieneData {
543558
) -> SyntaxContext {
544559
assert_ne!(expn_id, ExpnId::root());
545560
if transparency == Transparency::Opaque {
546-
return self.apply_mark_internal(ctxt, expn_id, transparency);
561+
return self.alloc_ctxt(ctxt, expn_id, transparency);
547562
}
548563

549564
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
@@ -554,7 +569,7 @@ impl HygieneData {
554569
};
555570

556571
if call_site_ctxt.is_root() {
557-
return self.apply_mark_internal(ctxt, expn_id, transparency);
572+
return self.alloc_ctxt(ctxt, expn_id, transparency);
558573
}
559574

560575
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
@@ -567,74 +582,60 @@ impl HygieneData {
567582
//
568583
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
569584
for (expn_id, transparency) in self.marks(ctxt) {
570-
call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
585+
call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
571586
}
572-
self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
587+
self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
573588
}
574589

575-
fn apply_mark_internal(
590+
/// Allocate a new context with the given key, or retrieve it from cache if the given key
591+
/// already exists. The auxiliary fields are calculated from the key.
592+
fn alloc_ctxt(
576593
&mut self,
577-
ctxt: SyntaxContext,
594+
parent: SyntaxContext,
578595
expn_id: ExpnId,
579596
transparency: Transparency,
580597
) -> 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-
}
598+
debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
605599

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-
});
600+
// Look into the cache first.
601+
let key = (parent, expn_id, transparency);
602+
if let Some(ctxt) = self.syntax_context_map.get(&key) {
603+
return *ctxt;
624604
}
625605

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)
637-
})
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
638639
}
639640
}
640641

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

+10-10
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)