@@ -10,6 +10,7 @@ use std::ops::{Deref, Index};
10
10
11
11
use base_db:: CrateId ;
12
12
use cfg:: { CfgExpr , CfgOptions } ;
13
+ use either:: Either ;
13
14
use hir_expand:: { name:: Name , ExpandError , InFile } ;
14
15
use la_arena:: { Arena , ArenaMap , Idx , RawIdx } ;
15
16
use rustc_hash:: FxHashMap ;
@@ -22,8 +23,8 @@ use crate::{
22
23
db:: DefDatabase ,
23
24
expander:: Expander ,
24
25
hir:: {
25
- dummy_expr_id, Array , AsmOperand , Binding , BindingId , Expr , ExprId , Label , LabelId , Pat ,
26
- PatId , RecordFieldPat , Statement ,
26
+ dummy_expr_id, Array , AsmOperand , Binding , BindingId , Expr , ExprId , ExprOrPatId , Label ,
27
+ LabelId , Pat , PatId , RecordFieldPat , Statement ,
27
28
} ,
28
29
item_tree:: AttrOwner ,
29
30
nameres:: DefMap ,
@@ -68,9 +69,12 @@ pub type LabelSource = InFile<LabelPtr>;
68
69
pub type FieldPtr = AstPtr < ast:: RecordExprField > ;
69
70
pub type FieldSource = InFile < FieldPtr > ;
70
71
71
- pub type PatFieldPtr = AstPtr < ast:: RecordPatField > ;
72
+ pub type PatFieldPtr = AstPtr < Either < ast:: RecordExprField , ast :: RecordPatField > > ;
72
73
pub type PatFieldSource = InFile < PatFieldPtr > ;
73
74
75
+ pub type ExprOrPatPtr = AstPtr < Either < ast:: Expr , ast:: Pat > > ;
76
+ pub type ExprOrPatSource = InFile < ExprOrPatPtr > ;
77
+
74
78
/// An item body together with the mapping from syntax nodes to HIR expression
75
79
/// IDs. This is needed to go from e.g. a position in a file to the HIR
76
80
/// expression containing it; but for type inference etc., we want to operate on
@@ -84,11 +88,13 @@ pub type PatFieldSource = InFile<PatFieldPtr>;
84
88
/// this properly for macros.
85
89
#[ derive( Default , Debug , Eq , PartialEq ) ]
86
90
pub struct BodySourceMap {
87
- expr_map : FxHashMap < ExprSource , ExprId > ,
91
+ // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map
92
+ // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected).
93
+ expr_map : FxHashMap < ExprSource , ExprOrPatId > ,
88
94
expr_map_back : ArenaMap < ExprId , ExprSource > ,
89
95
90
96
pat_map : FxHashMap < PatSource , PatId > ,
91
- pat_map_back : ArenaMap < PatId , PatSource > ,
97
+ pat_map_back : ArenaMap < PatId , ExprOrPatSource > ,
92
98
93
99
label_map : FxHashMap < LabelSource , LabelId > ,
94
100
label_map_back : ArenaMap < LabelId , LabelSource > ,
@@ -372,7 +378,7 @@ impl Body {
372
378
if let & Some ( expr) = else_branch {
373
379
f ( expr) ;
374
380
}
375
- walk_exprs_in_pat ( self , * pat, & mut f) ;
381
+ self . walk_exprs_in_pat ( * pat, & mut f) ;
376
382
}
377
383
Statement :: Expr { expr : expression, .. } => f ( * expression) ,
378
384
Statement :: Item => ( ) ,
@@ -448,18 +454,18 @@ impl Body {
448
454
}
449
455
} ,
450
456
& Expr :: Assignment { target, value } => {
451
- walk_exprs_in_pat ( self , target, & mut f) ;
457
+ self . walk_exprs_in_pat ( target, & mut f) ;
452
458
f ( value) ;
453
459
}
454
460
}
461
+ }
455
462
456
- fn walk_exprs_in_pat ( this : & Body , pat_id : PatId , f : & mut impl FnMut ( ExprId ) ) {
457
- this. walk_pats ( pat_id, & mut |pat| {
458
- if let Pat :: Expr ( expr) | Pat :: ConstBlock ( expr) = this[ pat] {
459
- f ( expr) ;
460
- }
461
- } ) ;
462
- }
463
+ pub fn walk_exprs_in_pat ( & self , pat_id : PatId , f : & mut impl FnMut ( ExprId ) ) {
464
+ self . walk_pats ( pat_id, & mut |pat| {
465
+ if let Pat :: Expr ( expr) | Pat :: ConstBlock ( expr) = self [ pat] {
466
+ f ( expr) ;
467
+ }
468
+ } ) ;
463
469
}
464
470
}
465
471
@@ -514,11 +520,18 @@ impl Index<BindingId> for Body {
514
520
// FIXME: Change `node_` prefix to something more reasonable.
515
521
// Perhaps `expr_syntax` and `expr_id`?
516
522
impl BodySourceMap {
523
+ pub fn expr_or_pat_syntax ( & self , id : ExprOrPatId ) -> Result < ExprOrPatSource , SyntheticSyntax > {
524
+ match id {
525
+ ExprOrPatId :: ExprId ( id) => self . expr_syntax ( id) . map ( |it| it. map ( AstPtr :: wrap_left) ) ,
526
+ ExprOrPatId :: PatId ( id) => self . pat_syntax ( id) ,
527
+ }
528
+ }
529
+
517
530
pub fn expr_syntax ( & self , expr : ExprId ) -> Result < ExprSource , SyntheticSyntax > {
518
531
self . expr_map_back . get ( expr) . cloned ( ) . ok_or ( SyntheticSyntax )
519
532
}
520
533
521
- pub fn node_expr ( & self , node : InFile < & ast:: Expr > ) -> Option < ExprId > {
534
+ pub fn node_expr ( & self , node : InFile < & ast:: Expr > ) -> Option < ExprOrPatId > {
522
535
let src = node. map ( AstPtr :: new) ;
523
536
self . expr_map . get ( & src) . cloned ( )
524
537
}
@@ -534,7 +547,7 @@ impl BodySourceMap {
534
547
self . expansions . iter ( ) . map ( |( & a, & b) | ( a, b) )
535
548
}
536
549
537
- pub fn pat_syntax ( & self , pat : PatId ) -> Result < PatSource , SyntheticSyntax > {
550
+ pub fn pat_syntax ( & self , pat : PatId ) -> Result < ExprOrPatSource , SyntheticSyntax > {
538
551
self . pat_map_back . get ( pat) . cloned ( ) . ok_or ( SyntheticSyntax )
539
552
}
540
553
@@ -567,7 +580,7 @@ impl BodySourceMap {
567
580
self . pat_field_map_back [ & pat]
568
581
}
569
582
570
- pub fn macro_expansion_expr ( & self , node : InFile < & ast:: MacroExpr > ) -> Option < ExprId > {
583
+ pub fn macro_expansion_expr ( & self , node : InFile < & ast:: MacroExpr > ) -> Option < ExprOrPatId > {
571
584
let src = node. map ( AstPtr :: new) . map ( AstPtr :: upcast :: < ast:: MacroExpr > ) . map ( AstPtr :: upcast) ;
572
585
self . expr_map . get ( & src) . copied ( )
573
586
}
@@ -583,16 +596,20 @@ impl BodySourceMap {
583
596
node : InFile < & ast:: FormatArgsExpr > ,
584
597
) -> Option < & [ ( syntax:: TextRange , Name ) ] > {
585
598
let src = node. map ( AstPtr :: new) . map ( AstPtr :: upcast :: < ast:: Expr > ) ;
586
- self . template_map . as_ref ( ) ?. 0 . get ( self . expr_map . get ( & src) ?) . map ( std:: ops:: Deref :: deref)
599
+ self . template_map
600
+ . as_ref ( ) ?
601
+ . 0
602
+ . get ( & self . expr_map . get ( & src) ?. as_expr ( ) ?)
603
+ . map ( std:: ops:: Deref :: deref)
587
604
}
588
605
589
606
pub fn asm_template_args (
590
607
& self ,
591
608
node : InFile < & ast:: AsmExpr > ,
592
609
) -> Option < ( ExprId , & [ Vec < ( syntax:: TextRange , usize ) > ] ) > {
593
610
let src = node. map ( AstPtr :: new) . map ( AstPtr :: upcast :: < ast:: Expr > ) ;
594
- let expr = self . expr_map . get ( & src) ?;
595
- Some ( * expr) . zip ( self . template_map . as_ref ( ) ?. 1 . get ( expr) . map ( std:: ops:: Deref :: deref) )
611
+ let expr = self . expr_map . get ( & src) ?. as_expr ( ) ? ;
612
+ Some ( expr) . zip ( self . template_map . as_ref ( ) ?. 1 . get ( & expr) . map ( std:: ops:: Deref :: deref) )
596
613
}
597
614
598
615
/// Get a reference to the body source map's diagnostics.
0 commit comments