44use std:: mem;
55
66use base_db:: CrateId ;
7+ use either:: Either ;
78use hir_expand:: {
89 name:: { AsName , Name } ,
910 ExpandError , InFile ,
@@ -1437,14 +1438,12 @@ impl ExprCollector<'_> {
14371438 has_leading_comma : bool ,
14381439 binding_list : & mut BindingList ,
14391440 ) -> ( Box < [ PatId ] > , Option < usize > ) {
1441+ let args: Vec < _ > = args. map ( |p| self . collect_pat_possibly_rest ( p, binding_list) ) . collect ( ) ;
14401442 // Find the location of the `..`, if there is one. Note that we do not
14411443 // 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 ( ) ) ;
14431445 // 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 ( ) ;
14481447 // if there is a leading comma, the user is most likely to type out a leading pattern
14491448 // so we insert a missing pattern at the beginning for IDE features
14501449 if has_leading_comma {
@@ -1454,6 +1453,41 @@ impl ExprCollector<'_> {
14541453 ( args. into_boxed_slice ( ) , ellipsis)
14551454 }
14561455
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+
14571491 // endregion: patterns
14581492
14591493 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
0 commit comments