@@ -67,25 +67,21 @@ pub struct SyntaxContextData {
67
67
outer_transparency : Transparency ,
68
68
parent : SyntaxContext ,
69
69
/// This context, but with all transparent and semi-transparent expansions filtered away.
70
- opaque : SyntaxContext ,
70
+ opaque : Option < SyntaxContext > ,
71
71
/// This context, but with all transparent expansions filtered away.
72
- opaque_and_semitransparent : SyntaxContext ,
72
+ opaque_and_semitransparent : Option < SyntaxContext > ,
73
73
/// Name of the crate to which `$crate` with this context would resolve.
74
74
dollar_crate_name : Symbol ,
75
75
}
76
76
77
77
impl SyntaxContextData {
78
- fn new (
79
- ( parent, outer_expn, outer_transparency) : SyntaxContextKey ,
80
- opaque : SyntaxContext ,
81
- opaque_and_semitransparent : SyntaxContext ,
82
- ) -> SyntaxContextData {
78
+ fn from_key ( ( parent, outer_expn, outer_transparency) : SyntaxContextKey ) -> SyntaxContextData {
83
79
SyntaxContextData {
84
80
outer_expn,
85
81
outer_transparency,
86
82
parent,
87
- opaque,
88
- opaque_and_semitransparent,
83
+ opaque : None ,
84
+ opaque_and_semitransparent : None ,
89
85
dollar_crate_name : kw:: DollarCrate ,
90
86
}
91
87
}
@@ -95,8 +91,8 @@ impl SyntaxContextData {
95
91
outer_expn : ExpnId :: root ( ) ,
96
92
outer_transparency : Transparency :: Opaque ,
97
93
parent : SyntaxContext :: root ( ) ,
98
- opaque : SyntaxContext :: root ( ) ,
99
- opaque_and_semitransparent : SyntaxContext :: root ( ) ,
94
+ opaque : Some ( SyntaxContext :: root ( ) ) ,
95
+ opaque_and_semitransparent : Some ( SyntaxContext :: root ( ) ) ,
100
96
dollar_crate_name : kw:: DollarCrate ,
101
97
}
102
98
}
@@ -462,14 +458,43 @@ impl HygieneData {
462
458
}
463
459
}
464
460
465
- fn normalize_to_macros_2_0 ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
461
+ fn normalize_to_macros_2_0 ( & mut self , ctxt : SyntaxContext ) -> SyntaxContext {
466
462
debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
467
- self . syntax_context_data [ ctxt. 0 as usize ] . opaque
463
+ if let Some ( opaque) = self . syntax_context_data [ ctxt. 0 as usize ] . opaque {
464
+ return opaque;
465
+ }
466
+
467
+ let SyntaxContextData { outer_expn, outer_transparency, parent, .. } =
468
+ self . syntax_context_data [ ctxt. 0 as usize ] ;
469
+ let parent_opaque = self . normalize_to_macros_2_0 ( parent) ;
470
+ let opaque = match outer_transparency {
471
+ Transparency :: Transparent | Transparency :: SemiTransparent => parent_opaque,
472
+ Transparency :: Opaque => self . alloc_ctxt ( parent_opaque, outer_expn, outer_transparency) ,
473
+ } ;
474
+ self . syntax_context_data [ ctxt. 0 as usize ] . opaque = Some ( opaque) ;
475
+ opaque
468
476
}
469
477
470
- fn normalize_to_macro_rules ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
478
+ fn normalize_to_macro_rules ( & mut self , ctxt : SyntaxContext ) -> SyntaxContext {
471
479
debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
472
- self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semitransparent
480
+ if let Some ( opaque_and_semitransparent) =
481
+ self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semitransparent
482
+ {
483
+ return opaque_and_semitransparent;
484
+ }
485
+
486
+ let SyntaxContextData { outer_expn, outer_transparency, parent, .. } =
487
+ self . syntax_context_data [ ctxt. 0 as usize ] ;
488
+ let parent_opaque_and_semitransparent = self . normalize_to_macro_rules ( parent) ;
489
+ let opaque_and_semitransparent = match outer_transparency {
490
+ Transparency :: Transparent => parent_opaque_and_semitransparent,
491
+ Transparency :: SemiTransparent | Transparency :: Opaque => {
492
+ self . alloc_ctxt ( parent_opaque_and_semitransparent, outer_expn, outer_transparency)
493
+ }
494
+ } ;
495
+ self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semitransparent =
496
+ Some ( opaque_and_semitransparent) ;
497
+ opaque_and_semitransparent
473
498
}
474
499
475
500
fn outer_expn ( & self , ctxt : SyntaxContext ) -> ExpnId {
@@ -597,45 +622,11 @@ impl HygieneData {
597
622
) -> SyntaxContext {
598
623
debug_assert ! ( !self . syntax_context_data[ parent. 0 as usize ] . is_decode_placeholder( ) ) ;
599
624
600
- // Look into the cache first.
601
625
let key = ( parent, expn_id, transparency) ;
602
- if let Some ( ctxt) = self . syntax_context_map . get ( & key) {
603
- return * ctxt;
604
- }
605
-
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
626
+ * self . syntax_context_map . entry ( key) . or_insert_with ( || {
627
+ self . syntax_context_data . push ( SyntaxContextData :: from_key ( key) ) ;
628
+ SyntaxContext :: from_usize ( self . syntax_context_data . len ( ) - 1 )
629
+ } )
639
630
}
640
631
}
641
632
0 commit comments