@@ -51,6 +51,7 @@ use crate::parse::diagnostics::Error;
5151
5252use errors:: { Applicability , DiagnosticBuilder , DiagnosticId , FatalError } ;
5353use rustc_target:: spec:: abi:: { self , Abi } ;
54+ use rustc_data_structures:: fx:: FxHashSet ;
5455use syntax_pos:: { Span , BytePos , DUMMY_SP , FileName , hygiene:: CompilerDesugaringKind } ;
5556use log:: debug;
5657
@@ -452,19 +453,18 @@ impl From<P<Expr>> for LhsExpr {
452453}
453454
454455/// 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 {
457457 let pat = P ( Pat {
458458 id : ast:: DUMMY_NODE_ID ,
459459 node : PatKind :: Ident ( BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
460- span,
460+ span : ident . span ,
461461 } ) ;
462462 let ty = Ty {
463463 node : TyKind :: Err ,
464- span,
464+ span : ident . span ,
465465 id : ast:: DUMMY_NODE_ID
466466 } ;
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 }
468468}
469469
470470#[ derive( Copy , Clone , Debug ) ]
@@ -1528,8 +1528,17 @@ impl<'a> Parser<'a> {
15281528 let pat = self . parse_pat ( Some ( "argument name" ) ) ?;
15291529
15301530 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+ }
15331542 }
15341543
15351544 self . eat_incorrect_doc_comment ( "a method argument's type" ) ;
@@ -5431,7 +5440,7 @@ impl<'a> Parser<'a> {
54315440 p. eat_to_tokens ( & [ & token:: Comma , & token:: CloseDelim ( token:: Paren ) ] ) ;
54325441 // Create a placeholder argument for proper arg count (issue #34264).
54335442 let span = lo. to ( p. prev_span ) ;
5434- Ok ( Some ( dummy_arg ( span) ) )
5443+ Ok ( Some ( dummy_arg ( Ident :: new ( kw :: Invalid , span) ) ) )
54355444 }
54365445 }
54375446 }
@@ -5584,7 +5593,7 @@ impl<'a> Parser<'a> {
55845593
55855594 // Parse the rest of the function parameter list.
55865595 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 {
55885597 if self . check ( & token:: CloseDelim ( token:: Paren ) ) {
55895598 ( vec ! [ self_arg] , false )
55905599 } else if self . eat ( & token:: Comma ) {
@@ -5607,6 +5616,24 @@ impl<'a> Parser<'a> {
56075616 // Parse closing paren and return type.
56085617 self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
56095618 }
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+
56105637 Ok ( P ( FnDecl {
56115638 inputs : fn_inputs,
56125639 output : self . parse_ret_ty ( true ) ?,
0 commit comments