1
- use crate :: ast;
2
1
use 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 ,
5
4
} ;
6
5
use crate :: parse:: { SeqSep , token, PResult , Parser } ;
7
6
use crate :: parse:: parser:: { BlockMode , PathStyle , SemiColonMode , TokenType , TokenExpectType } ;
@@ -12,9 +11,25 @@ use crate::symbol::{kw, sym};
12
11
use crate :: ThinVec ;
13
12
use crate :: util:: parser:: AssocOp ;
14
13
use errors:: { Applicability , DiagnosticBuilder , DiagnosticId } ;
14
+ use rustc_data_structures:: fx:: FxHashSet ;
15
15
use syntax_pos:: { Span , DUMMY_SP , MultiSpan } ;
16
16
use log:: { debug, trace} ;
17
17
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
+
18
33
pub enum Error {
19
34
FileNotFoundForModule {
20
35
mod_name : String ,
@@ -1092,12 +1107,12 @@ impl<'a> Parser<'a> {
1092
1107
pat : P < ast:: Pat > ,
1093
1108
require_name : bool ,
1094
1109
is_trait_item : bool ,
1095
- ) {
1110
+ ) -> Option < Ident > {
1096
1111
// If we find a pattern followed by an identifier, it could be an (incorrect)
1097
1112
// C-style parameter declaration.
1098
1113
if self . check_ident ( ) && self . look_ahead ( 1 , |t| {
1099
1114
* t == token:: Comma || * t == token:: CloseDelim ( token:: Paren )
1100
- } ) {
1115
+ } ) { // `fn foo(String s) {}`
1101
1116
let ident = self . parse_ident ( ) . unwrap ( ) ;
1102
1117
let span = pat. span . with_hi ( ident. span . hi ( ) ) ;
1103
1118
@@ -1107,18 +1122,30 @@ impl<'a> Parser<'a> {
1107
1122
String :: from ( "<identifier>: <type>" ) ,
1108
1123
Applicability :: HasPlaceholders ,
1109
1124
) ;
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) {}`
1112
1132
err. span_suggestion (
1113
1133
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" ,
1115
1141
format ! ( "_: {}" , ident) ,
1116
1142
Applicability :: MachineApplicable ,
1117
1143
) ;
1144
+ err. note ( "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ) ;
1145
+ return Some ( ident) ;
1118
1146
}
1119
-
1120
- err. note ( "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ) ;
1121
1147
}
1148
+ None
1122
1149
}
1123
1150
1124
1151
crate fn recover_arg_parse ( & mut self ) -> PResult < ' a , ( P < ast:: Pat > , P < ast:: Ty > ) > {
@@ -1205,4 +1232,31 @@ impl<'a> Parser<'a> {
1205
1232
err. span_label ( span, "expected expression" ) ;
1206
1233
err
1207
1234
}
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
+ }
1208
1262
}
0 commit comments