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