@@ -10,6 +10,7 @@ use std::ops::{Deref, Index};
1010
1111use base_db:: CrateId ;
1212use cfg:: { CfgExpr , CfgOptions } ;
13+ use either:: Either ;
1314use hir_expand:: { name:: Name , ExpandError , InFile } ;
1415use la_arena:: { Arena , ArenaMap , Idx , RawIdx } ;
1516use rustc_hash:: FxHashMap ;
@@ -22,8 +23,8 @@ use crate::{
2223 db:: DefDatabase ,
2324 expander:: Expander ,
2425 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 ,
2728 } ,
2829 item_tree:: AttrOwner ,
2930 nameres:: DefMap ,
@@ -68,9 +69,12 @@ pub type LabelSource = InFile<LabelPtr>;
6869pub type FieldPtr = AstPtr < ast:: RecordExprField > ;
6970pub type FieldSource = InFile < FieldPtr > ;
7071
71- pub type PatFieldPtr = AstPtr < ast:: RecordPatField > ;
72+ pub type PatFieldPtr = AstPtr < Either < ast:: RecordExprField , ast :: RecordPatField > > ;
7273pub type PatFieldSource = InFile < PatFieldPtr > ;
7374
75+ pub type ExprOrPatPtr = AstPtr < Either < ast:: Expr , ast:: Pat > > ;
76+ pub type ExprOrPatSource = InFile < ExprOrPatPtr > ;
77+
7478/// An item body together with the mapping from syntax nodes to HIR expression
7579/// IDs. This is needed to go from e.g. a position in a file to the HIR
7680/// expression containing it; but for type inference etc., we want to operate on
@@ -84,11 +88,13 @@ pub type PatFieldSource = InFile<PatFieldPtr>;
8488/// this properly for macros.
8589#[ derive( Default , Debug , Eq , PartialEq ) ]
8690pub 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 > ,
8894 expr_map_back : ArenaMap < ExprId , ExprSource > ,
8995
9096 pat_map : FxHashMap < PatSource , PatId > ,
91- pat_map_back : ArenaMap < PatId , PatSource > ,
97+ pat_map_back : ArenaMap < PatId , ExprOrPatSource > ,
9298
9399 label_map : FxHashMap < LabelSource , LabelId > ,
94100 label_map_back : ArenaMap < LabelId , LabelSource > ,
@@ -372,7 +378,7 @@ impl Body {
372378 if let & Some ( expr) = else_branch {
373379 f ( expr) ;
374380 }
375- walk_exprs_in_pat ( self , * pat, & mut f) ;
381+ self . walk_exprs_in_pat ( * pat, & mut f) ;
376382 }
377383 Statement :: Expr { expr : expression, .. } => f ( * expression) ,
378384 Statement :: Item => ( ) ,
@@ -448,18 +454,18 @@ impl Body {
448454 }
449455 } ,
450456 & Expr :: Assignment { target, value } => {
451- walk_exprs_in_pat ( self , target, & mut f) ;
457+ self . walk_exprs_in_pat ( target, & mut f) ;
452458 f ( value) ;
453459 }
454460 }
461+ }
455462
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+ } ) ;
463469 }
464470}
465471
@@ -514,11 +520,18 @@ impl Index<BindingId> for Body {
514520// FIXME: Change `node_` prefix to something more reasonable.
515521// Perhaps `expr_syntax` and `expr_id`?
516522impl 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+
517530 pub fn expr_syntax ( & self , expr : ExprId ) -> Result < ExprSource , SyntheticSyntax > {
518531 self . expr_map_back . get ( expr) . cloned ( ) . ok_or ( SyntheticSyntax )
519532 }
520533
521- pub fn node_expr ( & self , node : InFile < & ast:: Expr > ) -> Option < ExprId > {
534+ pub fn node_expr ( & self , node : InFile < & ast:: Expr > ) -> Option < ExprOrPatId > {
522535 let src = node. map ( AstPtr :: new) ;
523536 self . expr_map . get ( & src) . cloned ( )
524537 }
@@ -534,7 +547,7 @@ impl BodySourceMap {
534547 self . expansions . iter ( ) . map ( |( & a, & b) | ( a, b) )
535548 }
536549
537- pub fn pat_syntax ( & self , pat : PatId ) -> Result < PatSource , SyntheticSyntax > {
550+ pub fn pat_syntax ( & self , pat : PatId ) -> Result < ExprOrPatSource , SyntheticSyntax > {
538551 self . pat_map_back . get ( pat) . cloned ( ) . ok_or ( SyntheticSyntax )
539552 }
540553
@@ -567,7 +580,7 @@ impl BodySourceMap {
567580 self . pat_field_map_back [ & pat]
568581 }
569582
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 > {
571584 let src = node. map ( AstPtr :: new) . map ( AstPtr :: upcast :: < ast:: MacroExpr > ) . map ( AstPtr :: upcast) ;
572585 self . expr_map . get ( & src) . copied ( )
573586 }
@@ -583,16 +596,20 @@ impl BodySourceMap {
583596 node : InFile < & ast:: FormatArgsExpr > ,
584597 ) -> Option < & [ ( syntax:: TextRange , Name ) ] > {
585598 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)
587604 }
588605
589606 pub fn asm_template_args (
590607 & self ,
591608 node : InFile < & ast:: AsmExpr > ,
592609 ) -> Option < ( ExprId , & [ Vec < ( syntax:: TextRange , usize ) > ] ) > {
593610 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) )
596613 }
597614
598615 /// Get a reference to the body source map's diagnostics.
0 commit comments