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 ,
@@ -1437,14 +1438,12 @@ impl ExprCollector<'_> {
1437
1438
has_leading_comma : bool ,
1438
1439
binding_list : & mut BindingList ,
1439
1440
) -> ( Box < [ PatId ] > , Option < usize > ) {
1441
+ let args: Vec < _ > = args. map ( |p| self . collect_pat_possibly_rest ( p, binding_list) ) . collect ( ) ;
1440
1442
// Find the location of the `..`, if there is one. Note that we do not
1441
1443
// consider the possibility of there being multiple `..` here.
1442
- let ellipsis = args. clone ( ) . position ( |p| matches ! ( p , ast :: Pat :: RestPat ( _ ) ) ) ;
1444
+ let ellipsis = args. iter ( ) . position ( |p| p . is_right ( ) ) ;
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
0 commit comments