@@ -33,6 +33,22 @@ use crate::{
33
33
BlockId , DefWithBodyId , HasModule , Lookup ,
34
34
} ;
35
35
36
+ /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
37
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
38
+ pub struct HygieneId ( pub ( crate ) 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
+ pub ( crate ) fn is_root ( self ) -> bool {
48
+ self . 0 . is_root ( )
49
+ }
50
+ }
51
+
36
52
/// The body of an item (function, const etc.).
37
53
#[ derive( Debug , Eq , PartialEq ) ]
38
54
pub struct Body {
@@ -55,6 +71,22 @@ pub struct Body {
55
71
pub body_expr : ExprId ,
56
72
/// Block expressions in this body that may contain inner items.
57
73
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 > ,
58
90
}
59
91
60
92
pub type ExprPtr = AstPtr < ast:: Expr > ;
@@ -107,10 +139,11 @@ pub struct BodySourceMap {
107
139
field_map_back : FxHashMap < ExprId , FieldSource > ,
108
140
pat_field_map_back : FxHashMap < PatId , PatFieldSource > ,
109
141
142
+ // FIXME: Make this a sane struct.
110
143
template_map : Option <
111
144
Box < (
112
145
// format_args!
113
- FxHashMap < ExprId , Vec < ( syntax:: TextRange , Name ) > > ,
146
+ FxHashMap < ExprId , ( HygieneId , Vec < ( syntax:: TextRange , Name ) > ) > ,
114
147
// asm!
115
148
FxHashMap < ExprId , Vec < Vec < ( syntax:: TextRange , usize ) > > > ,
116
149
) > ,
@@ -268,13 +301,19 @@ impl Body {
268
301
pats,
269
302
bindings,
270
303
binding_owners,
304
+ binding_hygiene,
305
+ expr_hygiene,
306
+ pat_hygiene,
271
307
} = self ;
272
308
block_scopes. shrink_to_fit ( ) ;
273
309
exprs. shrink_to_fit ( ) ;
274
310
labels. shrink_to_fit ( ) ;
275
311
pats. shrink_to_fit ( ) ;
276
312
bindings. shrink_to_fit ( ) ;
277
313
binding_owners. shrink_to_fit ( ) ;
314
+ binding_hygiene. shrink_to_fit ( ) ;
315
+ expr_hygiene. shrink_to_fit ( ) ;
316
+ pat_hygiene. shrink_to_fit ( ) ;
278
317
}
279
318
280
319
pub fn walk_bindings_in_pat ( & self , pat_id : PatId , mut f : impl FnMut ( BindingId ) ) {
@@ -381,7 +420,7 @@ impl Body {
381
420
self . walk_exprs_in_pat ( * pat, & mut f) ;
382
421
}
383
422
Statement :: Expr { expr : expression, .. } => f ( * expression) ,
384
- Statement :: Item => ( ) ,
423
+ Statement :: Item ( _ ) => ( ) ,
385
424
}
386
425
}
387
426
if let & Some ( expr) = tail {
@@ -467,6 +506,25 @@ impl Body {
467
506
}
468
507
} ) ;
469
508
}
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
+ }
470
528
}
471
529
472
530
impl Default for Body {
@@ -481,6 +539,9 @@ impl Default for Body {
481
539
block_scopes : Default :: default ( ) ,
482
540
binding_owners : Default :: default ( ) ,
483
541
self_param : Default :: default ( ) ,
542
+ binding_hygiene : Default :: default ( ) ,
543
+ expr_hygiene : Default :: default ( ) ,
544
+ pat_hygiene : Default :: default ( ) ,
484
545
}
485
546
}
486
547
}
@@ -594,13 +655,11 @@ impl BodySourceMap {
594
655
pub fn implicit_format_args (
595
656
& self ,
596
657
node : InFile < & ast:: FormatArgsExpr > ,
597
- ) -> Option < & [ ( syntax:: TextRange , Name ) ] > {
658
+ ) -> Option < ( HygieneId , & [ ( syntax:: TextRange , Name ) ] ) > {
598
659
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) )
604
663
}
605
664
606
665
pub fn asm_template_args (
@@ -649,13 +708,4 @@ impl BodySourceMap {
649
708
diagnostics. shrink_to_fit ( ) ;
650
709
binding_definitions. shrink_to_fit ( ) ;
651
710
}
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
- }
661
711
}
0 commit comments