@@ -43,21 +43,41 @@ pub struct Mark(u32);
43
43
#[ derive( Debug ) ]
44
44
struct MarkData {
45
45
parent : Mark ,
46
- kind : MarkKind ,
46
+ transparency : Transparency ,
47
+ is_builtin : bool ,
47
48
expn_info : Option < ExpnInfo > ,
48
49
}
49
50
51
+ /// A property of a macro expansion that determines how identifiers
52
+ /// produced by that expansion are resolved.
50
53
#[ 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 ,
55
69
}
56
70
57
71
impl Mark {
58
72
pub fn fresh ( parent : Mark ) -> Self {
59
73
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
+ } ) ;
61
81
Mark ( data. marks . len ( ) as u32 - 1 )
62
82
} )
63
83
}
@@ -97,23 +117,31 @@ impl Mark {
97
117
98
118
pub fn modern ( mut self ) -> Mark {
99
119
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 {
104
121
self = data. marks [ self . 0 as usize ] . parent ;
105
122
}
123
+ self
106
124
} )
107
125
}
108
126
109
127
#[ 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 )
112
140
}
113
141
114
142
#[ 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 )
117
145
}
118
146
119
147
pub fn is_descendant_of ( mut self , ancestor : Mark ) -> bool {
@@ -169,7 +197,10 @@ impl HygieneData {
169
197
HygieneData {
170
198
marks : vec ! [ MarkData {
171
199
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 ,
173
204
expn_info: None ,
174
205
} ] ,
175
206
syntax_contexts : vec ! [ SyntaxContextData {
@@ -215,8 +246,9 @@ impl SyntaxContext {
215
246
HygieneData :: with ( |data| {
216
247
data. marks . push ( MarkData {
217
248
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) ,
220
252
} ) ;
221
253
222
254
let mark = Mark ( data. marks . len ( ) as u32 - 1 ) ;
@@ -232,7 +264,7 @@ impl SyntaxContext {
232
264
233
265
/// Extend a syntax context with a given mark
234
266
pub fn apply_mark ( self , mark : Mark ) -> SyntaxContext {
235
- if mark. kind ( ) == MarkKind :: Modern {
267
+ if mark. transparency ( ) == Transparency :: Opaque {
236
268
return self . apply_mark_internal ( mark) ;
237
269
}
238
270
@@ -262,7 +294,7 @@ impl SyntaxContext {
262
294
HygieneData :: with ( |data| {
263
295
let syntax_contexts = & mut data. syntax_contexts ;
264
296
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 {
266
298
modern = * data. markings . entry ( ( modern, mark) ) . or_insert_with ( || {
267
299
let len = syntax_contexts. len ( ) as u32 ;
268
300
syntax_contexts. push ( SyntaxContextData {
0 commit comments