1- use  crate :: ast; 
21use  crate :: ast:: { 
3-     BlockCheckMode ,   BinOpKind ,   Expr ,   ExprKind ,   Item ,   ItemKind ,   Pat ,   PatKind ,   PathSegment ,   QSelf , 
4-     Ty ,  TyKind ,  VariantData , 
2+     self ,   Arg ,   BinOpKind ,   BindingMode ,   BlockCheckMode ,   Expr ,   ExprKind ,   Ident ,   Item ,   ItemKind , 
3+     Mutability ,   Pat ,   PatKind ,   PathSegment ,   QSelf ,   Ty ,  TyKind ,  VariantData , 
54} ; 
65use  crate :: parse:: { SeqSep ,  token,  PResult ,  Parser } ; 
76use  crate :: parse:: parser:: { BlockMode ,  PathStyle ,  SemiColonMode ,  TokenType ,  TokenExpectType } ; 
@@ -12,9 +11,25 @@ use crate::symbol::{kw, sym};
1211use  crate :: ThinVec ; 
1312use  crate :: util:: parser:: AssocOp ; 
1413use  errors:: { Applicability ,  DiagnosticBuilder ,  DiagnosticId } ; 
14+ use  rustc_data_structures:: fx:: FxHashSet ; 
1515use  syntax_pos:: { Span ,  DUMMY_SP ,  MultiSpan } ; 
1616use  log:: { debug,  trace} ; 
1717
18+ /// Creates a placeholder argument. 
19+ crate  fn  dummy_arg ( ident :  Ident )  -> Arg  { 
20+     let  pat = P ( Pat  { 
21+         id :  ast:: DUMMY_NODE_ID , 
22+         node :  PatKind :: Ident ( BindingMode :: ByValue ( Mutability :: Immutable ) ,  ident,  None ) , 
23+         span :  ident. span , 
24+     } ) ; 
25+     let  ty = Ty  { 
26+         node :  TyKind :: Err , 
27+         span :  ident. span , 
28+         id :  ast:: DUMMY_NODE_ID 
29+     } ; 
30+     Arg  {  ty :  P ( ty) ,  pat :  pat,  id :  ast:: DUMMY_NODE_ID ,  source :  ast:: ArgSource :: Normal  } 
31+ } 
32+ 
1833pub  enum  Error  { 
1934    FileNotFoundForModule  { 
2035        mod_name :  String , 
@@ -1092,12 +1107,12 @@ impl<'a> Parser<'a> {
10921107        pat :  P < ast:: Pat > , 
10931108        require_name :  bool , 
10941109        is_trait_item :  bool , 
1095-     )  { 
1110+     )  ->  Option < Ident >   { 
10961111        // If we find a pattern followed by an identifier, it could be an (incorrect) 
10971112        // C-style parameter declaration. 
10981113        if  self . check_ident ( )  && self . look_ahead ( 1 ,  |t| { 
10991114            * t == token:: Comma  || * t == token:: CloseDelim ( token:: Paren ) 
1100-         } )  { 
1115+         } )  {   // `fn foo(String s) {}` 
11011116            let  ident = self . parse_ident ( ) . unwrap ( ) ; 
11021117            let  span = pat. span . with_hi ( ident. span . hi ( ) ) ; 
11031118
@@ -1107,18 +1122,30 @@ impl<'a> Parser<'a> {
11071122                String :: from ( "<identifier>: <type>" ) , 
11081123                Applicability :: HasPlaceholders , 
11091124            ) ; 
1110-         }  else  if  require_name && is_trait_item { 
1111-             if  let  PatKind :: Ident ( _,  ident,  _)  = pat. node  { 
1125+             return  Some ( ident) ; 
1126+         }  else  if  let  PatKind :: Ident ( _,  ident,  _)  = pat. node  { 
1127+             if  require_name && ( 
1128+                 is_trait_item ||
1129+                 self . token  == token:: Comma  ||
1130+                 self . token  == token:: CloseDelim ( token:: Paren ) 
1131+             )  {  // `fn foo(a, b) {}` or `fn foo(usize, usize) {}` 
11121132                err. span_suggestion ( 
11131133                    pat. span , 
1114-                     "explicitly ignore parameter" , 
1134+                     "if this was a parameter name, give it a type" , 
1135+                     format ! ( "{}: TypeName" ,  ident) , 
1136+                     Applicability :: HasPlaceholders , 
1137+                 ) ; 
1138+                 err. span_suggestion ( 
1139+                     pat. span , 
1140+                     "if this is a type, explicitly ignore the parameter name" , 
11151141                    format ! ( "_: {}" ,  ident) , 
11161142                    Applicability :: MachineApplicable , 
11171143                ) ; 
1144+                 err. note ( "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ) ; 
1145+                 return  Some ( ident) ; 
11181146            } 
1119- 
1120-             err. note ( "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ) ; 
11211147        } 
1148+         None 
11221149    } 
11231150
11241151    crate  fn  recover_arg_parse ( & mut  self )  -> PResult < ' a ,  ( P < ast:: Pat > ,  P < ast:: Ty > ) >  { 
@@ -1205,4 +1232,31 @@ impl<'a> Parser<'a> {
12051232        err. span_label ( span,  "expected expression" ) ; 
12061233        err
12071234    } 
1235+ 
1236+     /// Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. 
1237+ /// 
1238+ /// This is necessary because at this point we don't know whether we parsed a function with 
1239+ /// anonymous arguments or a function with names but no types. In order to minimize 
1240+ /// unecessary errors, we assume the arguments are in the shape of `fn foo(a, b, c)` where 
1241+ /// the arguments are *names* (so we don't emit errors about not being able to find `b` in 
1242+ /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`, 
1243+ /// we deduplicate them to not complain about duplicated argument names. 
1244+ crate  fn  deduplicate_recovered_arg_names ( & self ,  fn_inputs :  & mut  Vec < Arg > )  { 
1245+         let  mut  seen_inputs = FxHashSet :: default ( ) ; 
1246+         for  input in  fn_inputs. iter_mut ( )  { 
1247+             let  opt_ident = if  let  ( PatKind :: Ident ( _,  ident,  _) ,  TyKind :: Err )  = ( 
1248+                 & input. pat . node ,  & input. ty . node , 
1249+             )  { 
1250+                 Some ( * ident) 
1251+             }  else  { 
1252+                 None 
1253+             } ; 
1254+             if  let  Some ( ident)  = opt_ident { 
1255+                 if  seen_inputs. contains ( & ident)  { 
1256+                     input. pat . node  = PatKind :: Wild ; 
1257+                 } 
1258+                 seen_inputs. insert ( ident) ; 
1259+             } 
1260+         } 
1261+     } 
12081262} 
0 commit comments