@@ -43,21 +43,41 @@ pub struct Mark(u32);
4343#[ derive( Debug ) ]
4444struct MarkData {
4545 parent : Mark ,
46- kind : MarkKind ,
46+ transparency : Transparency ,
47+ is_builtin : bool ,
4748 expn_info : Option < ExpnInfo > ,
4849}
4950
51+ /// A property of a macro expansion that determines how identifiers
52+ /// produced by that expansion are resolved.
5053#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
51- pub enum MarkKind {
52- Modern ,
53- Builtin ,
54- Legacy ,
54+ pub enum Transparency {
55+ /// Identifier produced by a transparent expansion is always resolved at call-site.
56+ /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
57+ /// (Not used yet.)
58+ Transparent ,
59+ /// Identifier produced by a semi-transparent expansion may be resolved
60+ /// either at call-site or at definition-site.
61+ /// If it's a local variable, label or `$crate` then it's resolved at def-site.
62+ /// Otherwise it's resolved at call-site.
63+ /// `macro_rules` macros behave like this, built-in macros currently behave like this too,
64+ /// but that's an implementation detail.
65+ SemiTransparent ,
66+ /// Identifier produced by an opaque expansion is always resolved at definition-site.
67+ /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
68+ Opaque ,
5569}
5670
5771impl Mark {
5872 pub fn fresh ( parent : Mark ) -> Self {
5973 HygieneData :: with ( |data| {
60- data. marks . push ( MarkData { parent : parent, kind : MarkKind :: Legacy , expn_info : None } ) ;
74+ data. marks . push ( MarkData {
75+ parent,
76+ // By default expansions behave like `macro_rules`.
77+ transparency : Transparency :: SemiTransparent ,
78+ is_builtin : false ,
79+ expn_info : None ,
80+ } ) ;
6181 Mark ( data. marks . len ( ) as u32 - 1 )
6282 } )
6383 }
@@ -97,23 +117,31 @@ impl Mark {
97117
98118 pub fn modern ( mut self ) -> Mark {
99119 HygieneData :: with ( |data| {
100- loop {
101- if self == Mark :: root ( ) || data. marks [ self . 0 as usize ] . kind == MarkKind :: Modern {
102- return self ;
103- }
120+ while data. marks [ self . 0 as usize ] . transparency != Transparency :: Opaque {
104121 self = data. marks [ self . 0 as usize ] . parent ;
105122 }
123+ self
106124 } )
107125 }
108126
109127 #[ inline]
110- pub fn kind ( self ) -> MarkKind {
111- HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . kind )
128+ pub fn transparency ( self ) -> Transparency {
129+ HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . transparency )
130+ }
131+
132+ #[ inline]
133+ pub fn set_transparency ( self , transparency : Transparency ) {
134+ HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . transparency = transparency)
135+ }
136+
137+ #[ inline]
138+ pub fn is_builtin ( self ) -> bool {
139+ HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . is_builtin )
112140 }
113141
114142 #[ inline]
115- pub fn set_kind ( self , kind : MarkKind ) {
116- HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . kind = kind )
143+ pub fn set_is_builtin ( self , is_builtin : bool ) {
144+ HygieneData :: with ( |data| data. marks [ self . 0 as usize ] . is_builtin = is_builtin )
117145 }
118146
119147 pub fn is_descendant_of ( mut self , ancestor : Mark ) -> bool {
@@ -169,7 +197,10 @@ impl HygieneData {
169197 HygieneData {
170198 marks : vec ! [ MarkData {
171199 parent: Mark :: root( ) ,
172- kind: MarkKind :: Builtin ,
200+ // If the root is opaque, then loops searching for an opaque mark
201+ // will automatically stop after reaching it.
202+ transparency: Transparency :: Opaque ,
203+ is_builtin: true ,
173204 expn_info: None ,
174205 } ] ,
175206 syntax_contexts : vec ! [ SyntaxContextData {
@@ -215,8 +246,9 @@ impl SyntaxContext {
215246 HygieneData :: with ( |data| {
216247 data. marks . push ( MarkData {
217248 parent : Mark :: root ( ) ,
218- kind : MarkKind :: Legacy ,
219- expn_info : Some ( expansion_info)
249+ transparency : Transparency :: SemiTransparent ,
250+ is_builtin : false ,
251+ expn_info : Some ( expansion_info) ,
220252 } ) ;
221253
222254 let mark = Mark ( data. marks . len ( ) as u32 - 1 ) ;
@@ -232,7 +264,7 @@ impl SyntaxContext {
232264
233265 /// Extend a syntax context with a given mark
234266 pub fn apply_mark ( self , mark : Mark ) -> SyntaxContext {
235- if mark. kind ( ) == MarkKind :: Modern {
267+ if mark. transparency ( ) == Transparency :: Opaque {
236268 return self . apply_mark_internal ( mark) ;
237269 }
238270
@@ -262,7 +294,7 @@ impl SyntaxContext {
262294 HygieneData :: with ( |data| {
263295 let syntax_contexts = & mut data. syntax_contexts ;
264296 let mut modern = syntax_contexts[ self . 0 as usize ] . modern ;
265- if data. marks [ mark. 0 as usize ] . kind == MarkKind :: Modern {
297+ if data. marks [ mark. 0 as usize ] . transparency == Transparency :: Opaque {
266298 modern = * data. markings . entry ( ( modern, mark) ) . or_insert_with ( || {
267299 let len = syntax_contexts. len ( ) as u32 ;
268300 syntax_contexts. push ( SyntaxContextData {
0 commit comments