@@ -33,14 +33,17 @@ pub struct SyntaxContext(pub(super) u32);
33
33
pub struct SyntaxContextData {
34
34
pub outer_mark : Mark ,
35
35
pub prev_ctxt : SyntaxContext ,
36
- pub modern : SyntaxContext ,
36
+ // This context, but with all transparent and semi-transparent marks filtered away.
37
+ pub opaque : SyntaxContext ,
38
+ // This context, but with all transparent marks filtered away.
39
+ pub opaque_and_semitransparent : SyntaxContext ,
37
40
}
38
41
39
42
/// A mark is a unique id associated with a macro expansion.
40
43
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug , RustcEncodable , RustcDecodable ) ]
41
44
pub struct Mark ( u32 ) ;
42
45
43
- #[ derive( Debug ) ]
46
+ #[ derive( Clone , Debug ) ]
44
47
struct MarkData {
45
48
parent : Mark ,
46
49
transparency : Transparency ,
@@ -50,7 +53,7 @@ struct MarkData {
50
53
51
54
/// A property of a macro expansion that determines how identifiers
52
55
/// produced by that expansion are resolved.
53
- #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
56
+ #[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Debug ) ]
54
57
pub enum Transparency {
55
58
/// Identifier produced by a transparent expansion is always resolved at call-site.
56
59
/// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
@@ -69,16 +72,26 @@ pub enum Transparency {
69
72
}
70
73
71
74
impl Mark {
75
+ fn fresh_with_data ( mark_data : MarkData , data : & mut HygieneData ) -> Self {
76
+ data. marks . push ( mark_data) ;
77
+ Mark ( data. marks . len ( ) as u32 - 1 )
78
+ }
79
+
72
80
pub fn fresh ( parent : Mark ) -> Self {
73
81
HygieneData :: with ( |data| {
74
- data . marks . push ( MarkData {
82
+ Mark :: fresh_with_data ( MarkData {
75
83
parent,
76
84
// By default expansions behave like `macro_rules`.
77
85
transparency : Transparency :: SemiTransparent ,
78
86
is_builtin : false ,
79
87
expn_info : None ,
80
- } ) ;
81
- Mark ( data. marks . len ( ) as u32 - 1 )
88
+ } , data)
89
+ } )
90
+ }
91
+
92
+ pub fn fresh_cloned ( clone_from : Mark ) -> Self {
93
+ HygieneData :: with ( |data| {
94
+ Mark :: fresh_with_data ( data. marks [ clone_from. 0 as usize ] . clone ( ) , data)
82
95
} )
83
96
}
84
97
@@ -208,7 +221,8 @@ impl HygieneData {
208
221
syntax_contexts : vec ! [ SyntaxContextData {
209
222
outer_mark: Mark :: root( ) ,
210
223
prev_ctxt: SyntaxContext ( 0 ) ,
211
- modern: SyntaxContext ( 0 ) ,
224
+ opaque: SyntaxContext ( 0 ) ,
225
+ opaque_and_semitransparent: SyntaxContext ( 0 ) ,
212
226
} ] ,
213
227
markings : HashMap :: new ( ) ,
214
228
gensym_to_ctxt : HashMap :: new ( ) ,
@@ -241,7 +255,7 @@ impl SyntaxContext {
241
255
// Allocate a new SyntaxContext with the given ExpnInfo. This is used when
242
256
// deserializing Spans from the incr. comp. cache.
243
257
// FIXME(mw): This method does not restore MarkData::parent or
244
- // SyntaxContextData::prev_ctxt or SyntaxContextData::modern . These things
258
+ // SyntaxContextData::prev_ctxt or SyntaxContextData::opaque . These things
245
259
// don't seem to be used after HIR lowering, so everything should be fine
246
260
// as long as incremental compilation does not kick in before that.
247
261
pub fn allocate_directly ( expansion_info : ExpnInfo ) -> Self {
@@ -258,7 +272,8 @@ impl SyntaxContext {
258
272
data. syntax_contexts . push ( SyntaxContextData {
259
273
outer_mark : mark,
260
274
prev_ctxt : SyntaxContext :: empty ( ) ,
261
- modern : SyntaxContext :: empty ( ) ,
275
+ opaque : SyntaxContext :: empty ( ) ,
276
+ opaque_and_semitransparent : SyntaxContext :: empty ( ) ,
262
277
} ) ;
263
278
SyntaxContext ( data. syntax_contexts . len ( ) as u32 - 1 )
264
279
} )
@@ -271,7 +286,13 @@ impl SyntaxContext {
271
286
}
272
287
273
288
let call_site_ctxt =
274
- mark. expn_info ( ) . map_or ( SyntaxContext :: empty ( ) , |info| info. call_site . ctxt ( ) ) . modern ( ) ;
289
+ mark. expn_info ( ) . map_or ( SyntaxContext :: empty ( ) , |info| info. call_site . ctxt ( ) ) ;
290
+ let call_site_ctxt = if mark. transparency ( ) == Transparency :: SemiTransparent {
291
+ call_site_ctxt. modern ( )
292
+ } else {
293
+ call_site_ctxt. modern_and_legacy ( )
294
+ } ;
295
+
275
296
if call_site_ctxt == SyntaxContext :: empty ( ) {
276
297
return self . apply_mark_internal ( mark) ;
277
298
}
@@ -295,26 +316,53 @@ impl SyntaxContext {
295
316
fn apply_mark_internal ( self , mark : Mark ) -> SyntaxContext {
296
317
HygieneData :: with ( |data| {
297
318
let syntax_contexts = & mut data. syntax_contexts ;
298
- let mut modern = syntax_contexts[ self . 0 as usize ] . modern ;
299
- if data. marks [ mark. 0 as usize ] . transparency == Transparency :: Opaque {
300
- modern = * data. markings . entry ( ( modern, mark) ) . or_insert_with ( || {
301
- let len = syntax_contexts. len ( ) as u32 ;
319
+ let transparency = data. marks [ mark. 0 as usize ] . transparency ;
320
+
321
+ let mut opaque = syntax_contexts[ self . 0 as usize ] . opaque ;
322
+ let mut opaque_and_semitransparent =
323
+ syntax_contexts[ self . 0 as usize ] . opaque_and_semitransparent ;
324
+
325
+ if transparency >= Transparency :: Opaque {
326
+ let prev_ctxt = opaque;
327
+ opaque = * data. markings . entry ( ( prev_ctxt, mark) ) . or_insert_with ( || {
328
+ let new_opaque = SyntaxContext ( syntax_contexts. len ( ) as u32 ) ;
329
+ syntax_contexts. push ( SyntaxContextData {
330
+ outer_mark : mark,
331
+ prev_ctxt,
332
+ opaque : new_opaque,
333
+ opaque_and_semitransparent : new_opaque,
334
+ } ) ;
335
+ new_opaque
336
+ } ) ;
337
+ }
338
+
339
+ if transparency >= Transparency :: SemiTransparent {
340
+ let prev_ctxt = opaque_and_semitransparent;
341
+ opaque_and_semitransparent =
342
+ * data. markings . entry ( ( prev_ctxt, mark) ) . or_insert_with ( || {
343
+ let new_opaque_and_semitransparent =
344
+ SyntaxContext ( syntax_contexts. len ( ) as u32 ) ;
302
345
syntax_contexts. push ( SyntaxContextData {
303
346
outer_mark : mark,
304
- prev_ctxt : modern,
305
- modern : SyntaxContext ( len) ,
347
+ prev_ctxt,
348
+ opaque,
349
+ opaque_and_semitransparent : new_opaque_and_semitransparent,
306
350
} ) ;
307
- SyntaxContext ( len )
351
+ new_opaque_and_semitransparent
308
352
} ) ;
309
353
}
310
354
311
- * data. markings . entry ( ( self , mark) ) . or_insert_with ( || {
355
+ let prev_ctxt = self ;
356
+ * data. markings . entry ( ( prev_ctxt, mark) ) . or_insert_with ( || {
357
+ let new_opaque_and_semitransparent_and_transparent =
358
+ SyntaxContext ( syntax_contexts. len ( ) as u32 ) ;
312
359
syntax_contexts. push ( SyntaxContextData {
313
360
outer_mark : mark,
314
- prev_ctxt : self ,
315
- modern,
361
+ prev_ctxt,
362
+ opaque,
363
+ opaque_and_semitransparent,
316
364
} ) ;
317
- SyntaxContext ( syntax_contexts . len ( ) as u32 - 1 )
365
+ new_opaque_and_semitransparent_and_transparent
318
366
} )
319
367
} )
320
368
}
@@ -454,7 +502,12 @@ impl SyntaxContext {
454
502
455
503
#[ inline]
456
504
pub fn modern ( self ) -> SyntaxContext {
457
- HygieneData :: with ( |data| data. syntax_contexts [ self . 0 as usize ] . modern )
505
+ HygieneData :: with ( |data| data. syntax_contexts [ self . 0 as usize ] . opaque )
506
+ }
507
+
508
+ #[ inline]
509
+ pub fn modern_and_legacy ( self ) -> SyntaxContext {
510
+ HygieneData :: with ( |data| data. syntax_contexts [ self . 0 as usize ] . opaque_and_semitransparent )
458
511
}
459
512
460
513
#[ inline]
0 commit comments