@@ -11,7 +11,7 @@ mod stmt;
11
11
mod generics;
12
12
13
13
use crate :: ast:: {
14
- self , DUMMY_NODE_ID , AttrStyle , Attribute , BindingMode , CrateSugar , FnDecl , Ident ,
14
+ self , DUMMY_NODE_ID , AttrStyle , Attribute , BindingMode , CrateSugar , Ident ,
15
15
IsAsync , MacDelimiter , Mutability , Param , StrStyle , SelfKind , TyKind , Visibility ,
16
16
VisibilityKind , Unsafety ,
17
17
} ;
@@ -56,6 +56,17 @@ crate enum BlockMode {
56
56
Ignore ,
57
57
}
58
58
59
+ /// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
60
+ struct ParamCfg {
61
+ /// Is `self` is allowed as the first parameter?
62
+ is_self_allowed : bool ,
63
+ /// Is `...` allowed as the tail of the parameter list?
64
+ allow_c_variadic : bool ,
65
+ /// `is_name_required` decides if, per-parameter,
66
+ /// the parameter must have a pattern or just a type.
67
+ is_name_required : fn ( & token:: Token ) -> bool ,
68
+ }
69
+
59
70
/// Like `maybe_whole_expr`, but for things other than expressions.
60
71
#[ macro_export]
61
72
macro_rules! maybe_whole {
@@ -1094,26 +1105,18 @@ impl<'a> Parser<'a> {
1094
1105
res
1095
1106
}
1096
1107
1097
- fn parse_fn_params (
1098
- & mut self ,
1099
- named_params : bool ,
1100
- allow_c_variadic : bool ,
1101
- ) -> PResult < ' a , Vec < Param > > {
1108
+ /// Parses the parameter list of a function, including the `(` and `)` delimiters.
1109
+ fn parse_fn_params ( & mut self , mut cfg : ParamCfg ) -> PResult < ' a , Vec < Param > > {
1102
1110
let sp = self . token . span ;
1103
- let do_not_enforce_named_params_for_c_variadic = |token : & token:: Token | {
1104
- match token. kind {
1105
- token:: DotDotDot => false ,
1106
- _ => named_params,
1107
- }
1108
- } ;
1111
+ let is_trait_item = cfg. is_self_allowed ;
1109
1112
let mut c_variadic = false ;
1113
+ // Parse the arguments, starting out with `self` being possibly allowed...
1110
1114
let ( params, _) = self . parse_paren_comma_seq ( |p| {
1111
- match p. parse_param_general (
1112
- false ,
1113
- false ,
1114
- allow_c_variadic,
1115
- do_not_enforce_named_params_for_c_variadic,
1116
- ) {
1115
+ let param = p. parse_param_general ( & cfg, is_trait_item) ;
1116
+ // ...now that we've parsed the first argument, `self` is no longer allowed.
1117
+ cfg. is_self_allowed = false ;
1118
+
1119
+ match param {
1117
1120
Ok ( param) => Ok (
1118
1121
if let TyKind :: CVarArgs = param. ty . kind {
1119
1122
c_variadic = true ;
@@ -1144,7 +1147,10 @@ impl<'a> Parser<'a> {
1144
1147
}
1145
1148
} ) ?;
1146
1149
1147
- let params: Vec < _ > = params. into_iter ( ) . filter_map ( |x| x) . collect ( ) ;
1150
+ let mut params: Vec < _ > = params. into_iter ( ) . filter_map ( |x| x) . collect ( ) ;
1151
+
1152
+ // Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
1153
+ self . deduplicate_recovered_params_names ( & mut params) ;
1148
1154
1149
1155
if c_variadic && params. len ( ) <= 1 {
1150
1156
self . span_err (
@@ -1156,79 +1162,53 @@ impl<'a> Parser<'a> {
1156
1162
Ok ( params)
1157
1163
}
1158
1164
1159
- /// Parses the parameter list and result type of a function that may have a `self` parameter.
1160
- fn parse_fn_decl_with_self (
1161
- & mut self ,
1162
- is_name_required : impl Copy + Fn ( & token:: Token ) -> bool ,
1163
- ) -> PResult < ' a , P < FnDecl > > {
1164
- // Parse the arguments, starting out with `self` being allowed...
1165
- let mut is_self_allowed = true ;
1166
- let ( mut inputs, _) : ( Vec < _ > , _ ) = self . parse_paren_comma_seq ( |p| {
1167
- let res = p. parse_param_general ( is_self_allowed, true , false , is_name_required) ;
1168
- // ...but now that we've parsed the first argument, `self` is no longer allowed.
1169
- is_self_allowed = false ;
1170
- res
1171
- } ) ?;
1172
-
1173
- // Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
1174
- self . deduplicate_recovered_params_names ( & mut inputs) ;
1175
-
1176
- Ok ( P ( FnDecl {
1177
- inputs,
1178
- output : self . parse_ret_ty ( true ) ?,
1179
- } ) )
1180
- }
1181
-
1182
1165
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
1183
1166
/// error.
1184
1167
/// This version of parse param doesn't necessarily require identifier names.
1185
- fn parse_param_general (
1186
- & mut self ,
1187
- is_self_allowed : bool ,
1188
- is_trait_item : bool ,
1189
- allow_c_variadic : bool ,
1190
- is_name_required : impl Fn ( & token:: Token ) -> bool ,
1191
- ) -> PResult < ' a , Param > {
1168
+ fn parse_param_general ( & mut self , cfg : & ParamCfg , is_trait_item : bool ) -> PResult < ' a , Param > {
1192
1169
let lo = self . token . span ;
1193
1170
let attrs = self . parse_outer_attributes ( ) ?;
1194
1171
1195
1172
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
1196
1173
if let Some ( mut param) = self . parse_self_param ( ) ? {
1197
1174
param. attrs = attrs. into ( ) ;
1198
- return if is_self_allowed {
1175
+ return if cfg . is_self_allowed {
1199
1176
Ok ( param)
1200
1177
} else {
1201
1178
self . recover_bad_self_param ( param, is_trait_item)
1202
1179
} ;
1203
1180
}
1204
1181
1205
- let is_name_required = is_name_required ( & self . token ) ;
1182
+ let is_name_required = match self . token . kind {
1183
+ token:: DotDotDot => false ,
1184
+ _ => ( cfg. is_name_required ) ( & self . token ) ,
1185
+ } ;
1206
1186
let ( pat, ty) = if is_name_required || self . is_named_param ( ) {
1207
1187
debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
1208
1188
1209
1189
let pat = self . parse_fn_param_pat ( ) ?;
1210
1190
if let Err ( mut err) = self . expect ( & token:: Colon ) {
1211
- if let Some ( ident) = self . parameter_without_type (
1191
+ return if let Some ( ident) = self . parameter_without_type (
1212
1192
& mut err,
1213
1193
pat,
1214
1194
is_name_required,
1215
- is_self_allowed,
1195
+ cfg . is_self_allowed ,
1216
1196
is_trait_item,
1217
1197
) {
1218
1198
err. emit ( ) ;
1219
- return Ok ( dummy_arg ( ident) ) ;
1199
+ Ok ( dummy_arg ( ident) )
1220
1200
} else {
1221
- return Err ( err) ;
1222
- }
1201
+ Err ( err)
1202
+ } ;
1223
1203
}
1224
1204
1225
1205
self . eat_incorrect_doc_comment_for_param_type ( ) ;
1226
- ( pat, self . parse_ty_common ( true , true , allow_c_variadic) ?)
1206
+ ( pat, self . parse_ty_common ( true , true , cfg . allow_c_variadic ) ?)
1227
1207
} else {
1228
1208
debug ! ( "parse_param_general ident_to_pat" ) ;
1229
1209
let parser_snapshot_before_ty = self . clone ( ) ;
1230
1210
self . eat_incorrect_doc_comment_for_param_type ( ) ;
1231
- let mut ty = self . parse_ty_common ( true , true , allow_c_variadic) ;
1211
+ let mut ty = self . parse_ty_common ( true , true , cfg . allow_c_variadic ) ;
1232
1212
if ty. is_ok ( ) && self . token != token:: Comma &&
1233
1213
self . token != token:: CloseDelim ( token:: Paren ) {
1234
1214
// This wasn't actually a type, but a pattern looking like a type,
0 commit comments