44use std:: mem;
55
66use base_db:: CrateId ;
7+ use either:: Either ;
78use hir_expand:: {
89 name:: { name, AsName , Name } ,
910 ExpandError , InFile ,
@@ -1432,14 +1433,12 @@ impl ExprCollector<'_> {
14321433 has_leading_comma : bool ,
14331434 binding_list : & mut BindingList ,
14341435 ) -> ( Box < [ PatId ] > , Option < usize > ) {
1436+ let args: Vec < _ > = args. map ( |p| self . collect_pat_possibly_rest ( p, binding_list) ) . collect ( ) ;
14351437 // Find the location of the `..`, if there is one. Note that we do not
14361438 // 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 ( ) ) ;
14381440 // 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 ( ) ;
14431442 // if there is a leading comma, the user is most likely to type out a leading pattern
14441443 // so we insert a missing pattern at the beginning for IDE features
14451444 if has_leading_comma {
@@ -1449,6 +1448,41 @@ impl ExprCollector<'_> {
14491448 ( args. into_boxed_slice ( ) , ellipsis)
14501449 }
14511450
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+
14521486 // endregion: patterns
14531487
14541488 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
0 commit comments