@@ -51,6 +51,7 @@ use crate::parse::diagnostics::Error;
51
51
52
52
use errors:: { Applicability , DiagnosticBuilder , DiagnosticId , FatalError } ;
53
53
use rustc_target:: spec:: abi:: { self , Abi } ;
54
+ use rustc_data_structures:: fx:: FxHashSet ;
54
55
use syntax_pos:: { Span , BytePos , DUMMY_SP , FileName , hygiene:: CompilerDesugaringKind } ;
55
56
use log:: debug;
56
57
@@ -452,19 +453,18 @@ impl From<P<Expr>> for LhsExpr {
452
453
}
453
454
454
455
/// Creates a placeholder argument.
455
- fn dummy_arg ( span : Span ) -> Arg {
456
- let ident = Ident :: new ( kw:: Invalid , span) ;
456
+ fn dummy_arg ( ident : Ident ) -> Arg {
457
457
let pat = P ( Pat {
458
458
id : ast:: DUMMY_NODE_ID ,
459
459
node : PatKind :: Ident ( BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
460
- span,
460
+ span : ident . span ,
461
461
} ) ;
462
462
let ty = Ty {
463
463
node : TyKind :: Err ,
464
- span,
464
+ span : ident . span ,
465
465
id : ast:: DUMMY_NODE_ID
466
466
} ;
467
- Arg { ty : P ( ty) , pat : pat, id : ast:: DUMMY_NODE_ID , source : ast:: ArgSource :: Normal }
467
+ Arg { ty : P ( ty) , pat : pat, id : ast:: DUMMY_NODE_ID , source : ast:: ArgSource :: Recovery }
468
468
}
469
469
470
470
#[ derive( Copy , Clone , Debug ) ]
@@ -1528,8 +1528,17 @@ impl<'a> Parser<'a> {
1528
1528
let pat = self . parse_pat ( Some ( "argument name" ) ) ?;
1529
1529
1530
1530
if let Err ( mut err) = self . expect ( & token:: Colon ) {
1531
- self . argument_without_type ( & mut err, pat, require_name, is_trait_item) ;
1532
- return Err ( err) ;
1531
+ if let Some ( ident) = self . argument_without_type (
1532
+ & mut err,
1533
+ pat,
1534
+ require_name,
1535
+ is_trait_item,
1536
+ ) {
1537
+ err. emit ( ) ;
1538
+ return Ok ( dummy_arg ( ident) ) ;
1539
+ } else {
1540
+ return Err ( err) ;
1541
+ }
1533
1542
}
1534
1543
1535
1544
self . eat_incorrect_doc_comment ( "a method argument's type" ) ;
@@ -5431,7 +5440,7 @@ impl<'a> Parser<'a> {
5431
5440
p. eat_to_tokens ( & [ & token:: Comma , & token:: CloseDelim ( token:: Paren ) ] ) ;
5432
5441
// Create a placeholder argument for proper arg count (issue #34264).
5433
5442
let span = lo. to ( p. prev_span ) ;
5434
- Ok ( Some ( dummy_arg ( span) ) )
5443
+ Ok ( Some ( dummy_arg ( Ident :: new ( kw :: Invalid , span) ) ) )
5435
5444
}
5436
5445
}
5437
5446
}
@@ -5584,7 +5593,7 @@ impl<'a> Parser<'a> {
5584
5593
5585
5594
// Parse the rest of the function parameter list.
5586
5595
let sep = SeqSep :: trailing_allowed ( token:: Comma ) ;
5587
- let ( fn_inputs, recovered) = if let Some ( self_arg) = self_arg {
5596
+ let ( mut fn_inputs, recovered) = if let Some ( self_arg) = self_arg {
5588
5597
if self . check ( & token:: CloseDelim ( token:: Paren ) ) {
5589
5598
( vec ! [ self_arg] , false )
5590
5599
} else if self . eat ( & token:: Comma ) {
@@ -5607,6 +5616,24 @@ impl<'a> Parser<'a> {
5607
5616
// Parse closing paren and return type.
5608
5617
self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
5609
5618
}
5619
+ // Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors.
5620
+ let mut seen_inputs = FxHashSet :: default ( ) ;
5621
+ for input in fn_inputs. iter_mut ( ) {
5622
+ let opt_ident = if let ( PatKind :: Ident ( _, ident, _) , ast:: ArgSource :: Recovery ) = (
5623
+ & input. pat . node , & input. source ,
5624
+ ) {
5625
+ Some ( * ident)
5626
+ } else {
5627
+ None
5628
+ } ;
5629
+ if let Some ( ident) = opt_ident {
5630
+ if seen_inputs. contains ( & ident) {
5631
+ input. pat . node = PatKind :: Wild ;
5632
+ }
5633
+ seen_inputs. insert ( ident) ;
5634
+ }
5635
+ }
5636
+
5610
5637
Ok ( P ( FnDecl {
5611
5638
inputs : fn_inputs,
5612
5639
output : self . parse_ret_ty ( true ) ?,
0 commit comments