hygiene: Rewrite apply_mark_internal
to be more understandable
This commit is contained in:
parent
2a06022951
commit
7c74474d8d
2 changed files with 70 additions and 69 deletions
|
@ -75,6 +75,21 @@ pub struct SyntaxContextData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxContextData {
|
impl SyntaxContextData {
|
||||||
|
fn new(
|
||||||
|
(parent, outer_expn, outer_transparency): SyntaxContextKey,
|
||||||
|
opaque: SyntaxContext,
|
||||||
|
opaque_and_semitransparent: SyntaxContext,
|
||||||
|
) -> SyntaxContextData {
|
||||||
|
SyntaxContextData {
|
||||||
|
outer_expn,
|
||||||
|
outer_transparency,
|
||||||
|
parent,
|
||||||
|
opaque,
|
||||||
|
opaque_and_semitransparent,
|
||||||
|
dollar_crate_name: kw::DollarCrate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn root() -> SyntaxContextData {
|
fn root() -> SyntaxContextData {
|
||||||
SyntaxContextData {
|
SyntaxContextData {
|
||||||
outer_expn: ExpnId::root(),
|
outer_expn: ExpnId::root(),
|
||||||
|
@ -543,7 +558,7 @@ impl HygieneData {
|
||||||
) -> SyntaxContext {
|
) -> SyntaxContext {
|
||||||
assert_ne!(expn_id, ExpnId::root());
|
assert_ne!(expn_id, ExpnId::root());
|
||||||
if transparency == Transparency::Opaque {
|
if transparency == Transparency::Opaque {
|
||||||
return self.apply_mark_internal(ctxt, expn_id, transparency);
|
return self.alloc_ctxt(ctxt, expn_id, transparency);
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
|
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
|
||||||
|
@ -554,7 +569,7 @@ impl HygieneData {
|
||||||
};
|
};
|
||||||
|
|
||||||
if call_site_ctxt.is_root() {
|
if call_site_ctxt.is_root() {
|
||||||
return self.apply_mark_internal(ctxt, expn_id, transparency);
|
return self.alloc_ctxt(ctxt, expn_id, transparency);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
|
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
|
||||||
|
@ -567,74 +582,60 @@ impl HygieneData {
|
||||||
//
|
//
|
||||||
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
|
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
|
||||||
for (expn_id, transparency) in self.marks(ctxt) {
|
for (expn_id, transparency) in self.marks(ctxt) {
|
||||||
call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
|
call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
|
||||||
}
|
}
|
||||||
self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
|
self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_mark_internal(
|
/// Allocate a new context with the given key, or retrieve it from cache if the given key
|
||||||
|
/// already exists. The auxiliary fields are calculated from the key.
|
||||||
|
fn alloc_ctxt(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctxt: SyntaxContext,
|
parent: SyntaxContext,
|
||||||
expn_id: ExpnId,
|
expn_id: ExpnId,
|
||||||
transparency: Transparency,
|
transparency: Transparency,
|
||||||
) -> SyntaxContext {
|
) -> SyntaxContext {
|
||||||
let syntax_context_data = &mut self.syntax_context_data;
|
debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
|
||||||
debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
|
|
||||||
let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
|
|
||||||
let mut opaque_and_semitransparent =
|
|
||||||
syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
|
|
||||||
|
|
||||||
if transparency >= Transparency::Opaque {
|
// Look into the cache first.
|
||||||
let parent = opaque;
|
let key = (parent, expn_id, transparency);
|
||||||
opaque = *self
|
if let Some(ctxt) = self.syntax_context_map.get(&key) {
|
||||||
.syntax_context_map
|
return *ctxt;
|
||||||
.entry((parent, expn_id, transparency))
|
|
||||||
.or_insert_with(|| {
|
|
||||||
let new_opaque = SyntaxContext::from_usize(syntax_context_data.len());
|
|
||||||
syntax_context_data.push(SyntaxContextData {
|
|
||||||
outer_expn: expn_id,
|
|
||||||
outer_transparency: transparency,
|
|
||||||
parent,
|
|
||||||
opaque: new_opaque,
|
|
||||||
opaque_and_semitransparent: new_opaque,
|
|
||||||
dollar_crate_name: kw::DollarCrate,
|
|
||||||
});
|
|
||||||
new_opaque
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if transparency >= Transparency::SemiTransparent {
|
// Reserve a new syntax context.
|
||||||
let parent = opaque_and_semitransparent;
|
let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len());
|
||||||
opaque_and_semitransparent = *self
|
self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
|
||||||
.syntax_context_map
|
self.syntax_context_map.insert(key, ctxt);
|
||||||
.entry((parent, expn_id, transparency))
|
|
||||||
.or_insert_with(|| {
|
|
||||||
let new_opaque_and_semitransparent =
|
|
||||||
SyntaxContext::from_usize(syntax_context_data.len());
|
|
||||||
syntax_context_data.push(SyntaxContextData {
|
|
||||||
outer_expn: expn_id,
|
|
||||||
outer_transparency: transparency,
|
|
||||||
parent,
|
|
||||||
opaque,
|
|
||||||
opaque_and_semitransparent: new_opaque_and_semitransparent,
|
|
||||||
dollar_crate_name: kw::DollarCrate,
|
|
||||||
});
|
|
||||||
new_opaque_and_semitransparent
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = ctxt;
|
// Opaque and semi-transparent versions of the parent. Note that they may be equal to the
|
||||||
*self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
|
// parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
|
||||||
syntax_context_data.push(SyntaxContextData {
|
// and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
|
||||||
outer_expn: expn_id,
|
// and semi-transparents.
|
||||||
outer_transparency: transparency,
|
let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
|
||||||
parent,
|
let parent_opaque_and_semitransparent =
|
||||||
opaque,
|
self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
|
||||||
opaque_and_semitransparent,
|
|
||||||
dollar_crate_name: kw::DollarCrate,
|
// Evaluate opaque and semi-transparent versions of the new syntax context.
|
||||||
});
|
let (opaque, opaque_and_semitransparent) = match transparency {
|
||||||
SyntaxContext::from_usize(syntax_context_data.len() - 1)
|
Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
|
||||||
})
|
Transparency::SemiTransparent => (
|
||||||
|
parent_opaque,
|
||||||
|
// Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
|
||||||
|
self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
|
||||||
|
),
|
||||||
|
Transparency::Opaque => (
|
||||||
|
// Will be the same as `ctxt` if the expn chain contains only opaques.
|
||||||
|
self.alloc_ctxt(parent_opaque, expn_id, transparency),
|
||||||
|
// Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
|
||||||
|
self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fill the full data, now that we have it.
|
||||||
|
self.syntax_context_data[ctxt.as_u32() as usize] =
|
||||||
|
SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
|
||||||
|
ctxt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||||
stream: TokenStream [
|
stream: TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "struct",
|
ident: "struct",
|
||||||
span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
|
span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
ident: "S",
|
ident: "S",
|
||||||
span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
|
span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
|
||||||
},
|
},
|
||||||
Punct {
|
Punct {
|
||||||
ch: ';',
|
ch: ';',
|
||||||
spacing: Alone,
|
spacing: Alone,
|
||||||
span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
|
span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
|
span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
#![feature /* 0#0 */(prelude_import)]
|
#![feature /* 0#0 */(prelude_import)]
|
||||||
|
@ -59,7 +59,7 @@ macro_rules! outer
|
||||||
struct S /* 0#0 */;
|
struct S /* 0#0 */;
|
||||||
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
|
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
|
||||||
|
|
||||||
struct S /* 0#4 */;
|
struct S /* 0#5 */;
|
||||||
// OK, not a duplicate definition of `S`
|
// OK, not a duplicate definition of `S`
|
||||||
|
|
||||||
fn main /* 0#0 */() {}
|
fn main /* 0#0 */() {}
|
||||||
|
@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt:
|
||||||
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
||||||
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
|
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
|
||||||
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
|
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
|
||||||
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
|
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
|
||||||
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
||||||
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
||||||
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
|
||||||
|
@ -83,9 +83,9 @@ SyntaxContexts:
|
||||||
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
|
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
|
||||||
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
|
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
|
||||||
#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
|
#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
|
||||||
#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
|
#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
|
||||||
#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
|
#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
|
||||||
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
|
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
|
||||||
#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
|
#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
|
||||||
#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
|
#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue