@@ -33,6 +33,22 @@ use crate::{
3333 BlockId , DefWithBodyId , HasModule , Lookup ,
3434} ;
3535
36+ /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
37+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
38+ pub struct HygieneId ( span:: SyntaxContextId ) ;
39+
40+ impl HygieneId {
41+ pub const ROOT : Self = Self ( span:: SyntaxContextId :: ROOT ) ;
42+
43+ pub fn new ( ctx : span:: SyntaxContextId ) -> Self {
44+ Self ( ctx)
45+ }
46+
47+ fn is_root ( self ) -> bool {
48+ self . 0 . is_root ( )
49+ }
50+ }
51+
3652/// The body of an item (function, const etc.).
3753#[ derive( Debug , Eq , PartialEq ) ]
3854pub struct Body {
@@ -55,6 +71,22 @@ pub struct Body {
5571 pub body_expr : ExprId ,
5672 /// Block expressions in this body that may contain inner items.
5773 block_scopes : Vec < BlockId > ,
74+
75+ /// A map from binding to its hygiene ID.
76+ ///
77+ /// Bindings that don't come from macro expansion are not allocated to save space, so not all bindings appear here.
78+ /// If a binding does not appear here it has `SyntaxContextId::ROOT`.
79+ ///
80+ /// Note that this may not be the direct `SyntaxContextId` of the binding's expansion, because transparent
81+ /// expansions are attributed to their parent expansion (recursively).
82+ binding_hygiene : FxHashMap < BindingId , HygieneId > ,
83+ /// A map from an variable usages to their hygiene ID.
84+ ///
85+ /// Expressions that can be recorded here are single segment path, although not all single segments path refer
86+ /// to variables and have hygiene (some refer to items, we don't know at this stage).
87+ expr_hygiene : FxHashMap < ExprId , HygieneId > ,
88+ /// A map from a destructuring assignment possible variable usages to their hygiene ID.
89+ pat_hygiene : FxHashMap < PatId , HygieneId > ,
5890}
5991
6092pub type ExprPtr = AstPtr < ast:: Expr > ;
@@ -107,10 +139,11 @@ pub struct BodySourceMap {
107139 field_map_back : FxHashMap < ExprId , FieldSource > ,
108140 pat_field_map_back : FxHashMap < PatId , PatFieldSource > ,
109141
142+ // FIXME: Make this a sane struct.
110143 template_map : Option <
111144 Box < (
112145 // format_args!
113- FxHashMap < ExprId , Vec < ( syntax:: TextRange , Name ) > > ,
146+ FxHashMap < ExprId , ( HygieneId , Vec < ( syntax:: TextRange , Name ) > ) > ,
114147 // asm!
115148 FxHashMap < ExprId , Vec < Vec < ( syntax:: TextRange , usize ) > > > ,
116149 ) > ,
@@ -268,13 +301,19 @@ impl Body {
268301 pats,
269302 bindings,
270303 binding_owners,
304+ binding_hygiene,
305+ expr_hygiene,
306+ pat_hygiene,
271307 } = self ;
272308 block_scopes. shrink_to_fit ( ) ;
273309 exprs. shrink_to_fit ( ) ;
274310 labels. shrink_to_fit ( ) ;
275311 pats. shrink_to_fit ( ) ;
276312 bindings. shrink_to_fit ( ) ;
277313 binding_owners. shrink_to_fit ( ) ;
314+ binding_hygiene. shrink_to_fit ( ) ;
315+ expr_hygiene. shrink_to_fit ( ) ;
316+ pat_hygiene. shrink_to_fit ( ) ;
278317 }
279318
280319 pub fn walk_bindings_in_pat ( & self , pat_id : PatId , mut f : impl FnMut ( BindingId ) ) {
@@ -467,6 +506,25 @@ impl Body {
467506 }
468507 } ) ;
469508 }
509+
510+ fn binding_hygiene ( & self , binding : BindingId ) -> HygieneId {
511+ self . binding_hygiene . get ( & binding) . copied ( ) . unwrap_or ( HygieneId :: ROOT )
512+ }
513+
514+ pub fn expr_path_hygiene ( & self , expr : ExprId ) -> HygieneId {
515+ self . expr_hygiene . get ( & expr) . copied ( ) . unwrap_or ( HygieneId :: ROOT )
516+ }
517+
518+ pub fn pat_path_hygiene ( & self , pat : PatId ) -> HygieneId {
519+ self . pat_hygiene . get ( & pat) . copied ( ) . unwrap_or ( HygieneId :: ROOT )
520+ }
521+
522+ pub fn expr_or_pat_path_hygiene ( & self , id : ExprOrPatId ) -> HygieneId {
523+ match id {
524+ ExprOrPatId :: ExprId ( id) => self . expr_path_hygiene ( id) ,
525+ ExprOrPatId :: PatId ( id) => self . pat_path_hygiene ( id) ,
526+ }
527+ }
470528}
471529
472530impl Default for Body {
@@ -481,6 +539,9 @@ impl Default for Body {
481539 block_scopes : Default :: default ( ) ,
482540 binding_owners : Default :: default ( ) ,
483541 self_param : Default :: default ( ) ,
542+ binding_hygiene : Default :: default ( ) ,
543+ expr_hygiene : Default :: default ( ) ,
544+ pat_hygiene : Default :: default ( ) ,
484545 }
485546 }
486547}
@@ -594,13 +655,11 @@ impl BodySourceMap {
594655 pub fn implicit_format_args (
595656 & self ,
596657 node : InFile < & ast:: FormatArgsExpr > ,
597- ) -> Option < & [ ( syntax:: TextRange , Name ) ] > {
658+ ) -> Option < ( HygieneId , & [ ( syntax:: TextRange , Name ) ] ) > {
598659 let src = node. map ( AstPtr :: new) . map ( AstPtr :: upcast :: < ast:: Expr > ) ;
599- self . template_map
600- . as_ref ( ) ?
601- . 0
602- . get ( & self . expr_map . get ( & src) ?. as_expr ( ) ?)
603- . map ( std:: ops:: Deref :: deref)
660+ let ( hygiene, names) =
661+ self . template_map . as_ref ( ) ?. 0 . get ( & self . expr_map . get ( & src) ?. as_expr ( ) ?) ?;
662+ Some ( ( * hygiene, & * * names) )
604663 }
605664
606665 pub fn asm_template_args (
@@ -649,13 +708,4 @@ impl BodySourceMap {
649708 diagnostics. shrink_to_fit ( ) ;
650709 binding_definitions. shrink_to_fit ( ) ;
651710 }
652-
653- pub fn template_map (
654- & self ,
655- ) -> Option < & (
656- FxHashMap < Idx < Expr > , Vec < ( tt:: TextRange , Name ) > > ,
657- FxHashMap < Idx < Expr > , Vec < Vec < ( tt:: TextRange , usize ) > > > ,
658- ) > {
659- self . template_map . as_deref ( )
660- }
661711}
0 commit comments