4
4
use std:: mem;
5
5
6
6
use base_db:: CrateId ;
7
+ use either:: Either ;
7
8
use hir_expand:: {
8
9
name:: { AsName , Name } ,
9
10
ExpandError , InFile ,
10
11
} ;
11
12
use intern:: { sym, Interned , Symbol } ;
12
13
use rustc_hash:: FxHashMap ;
13
- use smallvec:: SmallVec ;
14
14
use span:: AstIdMap ;
15
15
use stdx:: never;
16
16
use syntax:: {
@@ -1436,15 +1436,14 @@ impl ExprCollector<'_> {
1436
1436
args : AstChildren < ast:: Pat > ,
1437
1437
has_leading_comma : bool ,
1438
1438
binding_list : & mut BindingList ,
1439
- ) -> ( Box < [ PatId ] > , Option < usize > ) {
1439
+ ) -> ( Box < [ PatId ] > , Option < u32 > ) {
1440
+ let args: Vec < _ > = args. map ( |p| self . collect_pat_possibly_rest ( p, binding_list) ) . collect ( ) ;
1440
1441
// Find the location of the `..`, if there is one. Note that we do not
1441
1442
// consider the possibility of there being multiple `..` here.
1442
- let ellipsis = args. clone ( ) . position ( |p| matches ! ( p, ast:: Pat :: RestPat ( _) ) ) ;
1443
+ let ellipsis = args. iter ( ) . position ( |p| p. is_right ( ) ) . map ( |it| it as u32 ) ;
1444
+
1443
1445
// We want to skip the `..` pattern here, since we account for it above.
1444
- let mut args: Vec < _ > = args
1445
- . filter ( |p| !matches ! ( p, ast:: Pat :: RestPat ( _) ) )
1446
- . map ( |p| self . collect_pat ( p, binding_list) )
1447
- . collect ( ) ;
1446
+ let mut args: Vec < _ > = args. into_iter ( ) . filter_map ( Either :: left) . collect ( ) ;
1448
1447
// if there is a leading comma, the user is most likely to type out a leading pattern
1449
1448
// so we insert a missing pattern at the beginning for IDE features
1450
1449
if has_leading_comma {
@@ -1454,6 +1453,41 @@ impl ExprCollector<'_> {
1454
1453
( args. into_boxed_slice ( ) , ellipsis)
1455
1454
}
1456
1455
1456
+ // `collect_pat` rejects `ast::Pat::RestPat`, but it should be handled in some cases that
1457
+ // it is the macro expansion result of an arg sub-pattern in a slice or tuple pattern.
1458
+ fn collect_pat_possibly_rest (
1459
+ & mut self ,
1460
+ pat : ast:: Pat ,
1461
+ binding_list : & mut BindingList ,
1462
+ ) -> Either < PatId , ( ) > {
1463
+ match & pat {
1464
+ ast:: Pat :: RestPat ( _) => Either :: Right ( ( ) ) ,
1465
+ ast:: Pat :: MacroPat ( mac) => match mac. macro_call ( ) {
1466
+ Some ( call) => {
1467
+ let macro_ptr = AstPtr :: new ( & call) ;
1468
+ let src = self . expander . in_file ( AstPtr :: new ( & pat) ) ;
1469
+ let pat =
1470
+ self . collect_macro_call ( call, macro_ptr, true , |this, expanded_pat| {
1471
+ if let Some ( expanded_pat) = expanded_pat {
1472
+ this. collect_pat_possibly_rest ( expanded_pat, binding_list)
1473
+ } else {
1474
+ Either :: Left ( this. missing_pat ( ) )
1475
+ }
1476
+ } ) ;
1477
+ if let Some ( pat) = pat. left ( ) {
1478
+ self . source_map . pat_map . insert ( src, pat) ;
1479
+ }
1480
+ pat
1481
+ }
1482
+ None => {
1483
+ let ptr = AstPtr :: new ( & pat) ;
1484
+ Either :: Left ( self . alloc_pat ( Pat :: Missing , ptr) )
1485
+ }
1486
+ } ,
1487
+ _ => Either :: Left ( self . collect_pat ( pat, binding_list) ) ,
1488
+ }
1489
+ }
1490
+
1457
1491
// endregion: patterns
1458
1492
1459
1493
/// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
@@ -1478,7 +1512,7 @@ impl ExprCollector<'_> {
1478
1512
}
1479
1513
1480
1514
fn add_definition_to_binding ( & mut self , binding_id : BindingId , pat_id : PatId ) {
1481
- self . body . bindings [ binding_id] . definitions . push ( pat_id) ;
1515
+ self . source_map . binding_definitions . entry ( binding_id) . or_default ( ) . push ( pat_id) ;
1482
1516
}
1483
1517
1484
1518
// region: labels
@@ -2024,12 +2058,7 @@ impl ExprCollector<'_> {
2024
2058
}
2025
2059
2026
2060
fn alloc_binding ( & mut self , name : Name , mode : BindingAnnotation ) -> BindingId {
2027
- let binding = self . body . bindings . alloc ( Binding {
2028
- name,
2029
- mode,
2030
- definitions : SmallVec :: new ( ) ,
2031
- problems : None ,
2032
- } ) ;
2061
+ let binding = self . body . bindings . alloc ( Binding { name, mode, problems : None } ) ;
2033
2062
if let Some ( owner) = self . current_binding_owner {
2034
2063
self . body . binding_owners . insert ( binding, owner) ;
2035
2064
}
0 commit comments