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:: { name, AsName , Name } ,
9
10
ExpandError , InFile ,
@@ -1432,14 +1433,12 @@ impl ExprCollector<'_> {
1432
1433
has_leading_comma : bool ,
1433
1434
binding_list : & mut BindingList ,
1434
1435
) -> ( Box < [ PatId ] > , Option < usize > ) {
1436
+ let args: Vec < _ > = args. map ( |p| self . collect_pat_possibly_rest ( p, binding_list) ) . collect ( ) ;
1435
1437
// Find the location of the `..`, if there is one. Note that we do not
1436
1438
// consider the possibility of there being multiple `..` here.
1437
- let ellipsis = args. clone ( ) . position ( |p| matches ! ( p , ast :: Pat :: RestPat ( _ ) ) ) ;
1439
+ let ellipsis = args. iter ( ) . position ( |p| p . is_right ( ) ) ;
1438
1440
// We want to skip the `..` pattern here, since we account for it above.
1439
- let mut args: Vec < _ > = args
1440
- . filter ( |p| !matches ! ( p, ast:: Pat :: RestPat ( _) ) )
1441
- . map ( |p| self . collect_pat ( p, binding_list) )
1442
- . collect ( ) ;
1441
+ let mut args: Vec < _ > = args. into_iter ( ) . filter_map ( Either :: left) . collect ( ) ;
1443
1442
// if there is a leading comma, the user is most likely to type out a leading pattern
1444
1443
// so we insert a missing pattern at the beginning for IDE features
1445
1444
if has_leading_comma {
@@ -1449,6 +1448,41 @@ impl ExprCollector<'_> {
1449
1448
( args. into_boxed_slice ( ) , ellipsis)
1450
1449
}
1451
1450
1451
+ // `collect_pat` rejects `ast::Pat::RestPat`, but it should be handled in some cases that
1452
+ // it is the macro expansion result of an arg sub-pattern in a slice or tuple pattern.
1453
+ fn collect_pat_possibly_rest (
1454
+ & mut self ,
1455
+ pat : ast:: Pat ,
1456
+ binding_list : & mut BindingList ,
1457
+ ) -> Either < PatId , ( ) > {
1458
+ match & pat {
1459
+ ast:: Pat :: RestPat ( _) => Either :: Right ( ( ) ) ,
1460
+ ast:: Pat :: MacroPat ( mac) => match mac. macro_call ( ) {
1461
+ Some ( call) => {
1462
+ let macro_ptr = AstPtr :: new ( & call) ;
1463
+ let src = self . expander . in_file ( AstPtr :: new ( & pat) ) ;
1464
+ let pat =
1465
+ self . collect_macro_call ( call, macro_ptr, true , |this, expanded_pat| {
1466
+ if let Some ( expanded_pat) = expanded_pat {
1467
+ this. collect_pat_possibly_rest ( expanded_pat, binding_list)
1468
+ } else {
1469
+ Either :: Left ( this. missing_pat ( ) )
1470
+ }
1471
+ } ) ;
1472
+ if let Some ( pat) = pat. left ( ) {
1473
+ self . source_map . pat_map . insert ( src, pat) ;
1474
+ }
1475
+ pat
1476
+ }
1477
+ None => {
1478
+ let ptr = AstPtr :: new ( & pat) ;
1479
+ Either :: Left ( self . alloc_pat ( Pat :: Missing , ptr) )
1480
+ }
1481
+ } ,
1482
+ _ => Either :: Left ( self . collect_pat ( pat, binding_list) ) ,
1483
+ }
1484
+ }
1485
+
1452
1486
// endregion: patterns
1453
1487
1454
1488
/// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
0 commit comments