@@ -67,25 +67,21 @@ pub struct SyntaxContextData {
6767 outer_transparency : Transparency ,
6868 parent : SyntaxContext ,
6969 /// This context, but with all transparent and semi-transparent expansions filtered away.
70- opaque : SyntaxContext ,
70+ opaque : Option < SyntaxContext > ,
7171 /// This context, but with all transparent expansions filtered away.
72- opaque_and_semitransparent : SyntaxContext ,
72+ opaque_and_semitransparent : Option < SyntaxContext > ,
7373 /// Name of the crate to which `$crate` with this context would resolve.
7474 dollar_crate_name : Symbol ,
7575}
7676
7777impl 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 {
8379 SyntaxContextData {
8480 outer_expn,
8581 outer_transparency,
8682 parent,
87- opaque,
88- opaque_and_semitransparent,
83+ opaque : None ,
84+ opaque_and_semitransparent : None ,
8985 dollar_crate_name : kw:: DollarCrate ,
9086 }
9187 }
@@ -95,8 +91,8 @@ impl SyntaxContextData {
9591 outer_expn : ExpnId :: root ( ) ,
9692 outer_transparency : Transparency :: Opaque ,
9793 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 ( ) ) ,
10096 dollar_crate_name : kw:: DollarCrate ,
10197 }
10298 }
@@ -462,14 +458,43 @@ impl HygieneData {
462458 }
463459 }
464460
465- fn normalize_to_macros_2_0 ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
461+ fn normalize_to_macros_2_0 ( & mut self , ctxt : SyntaxContext ) -> SyntaxContext {
466462 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
468476 }
469477
470- fn normalize_to_macro_rules ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
478+ fn normalize_to_macro_rules ( & mut self , ctxt : SyntaxContext ) -> SyntaxContext {
471479 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
473498 }
474499
475500 fn outer_expn ( & self , ctxt : SyntaxContext ) -> ExpnId {
@@ -597,45 +622,11 @@ impl HygieneData {
597622 ) -> SyntaxContext {
598623 debug_assert ! ( !self . syntax_context_data[ parent. 0 as usize ] . is_decode_placeholder( ) ) ;
599624
600- // Look into the cache first.
601625 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+ } )
639630 }
640631}
641632
0 commit comments