@@ -11,7 +11,7 @@ mod stmt;
1111mod generics;
1212
1313use crate :: ast:: {
14- self , DUMMY_NODE_ID , AttrStyle , Attribute , BindingMode , CrateSugar , FnDecl , Ident ,
14+ self , DUMMY_NODE_ID , AttrStyle , Attribute , BindingMode , CrateSugar , Ident ,
1515 IsAsync , MacDelimiter , Mutability , Param , StrStyle , SelfKind , TyKind , Visibility ,
1616 VisibilityKind , Unsafety ,
1717} ;
@@ -56,6 +56,17 @@ crate enum BlockMode {
5656 Ignore ,
5757}
5858
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+
5970/// Like `maybe_whole_expr`, but for things other than expressions.
6071#[ macro_export]
6172macro_rules! maybe_whole {
@@ -1094,26 +1105,18 @@ impl<'a> Parser<'a> {
10941105 res
10951106 }
10961107
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 > > {
11021110 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 ;
11091112 let mut c_variadic = false ;
1113+ // Parse the arguments, starting out with `self` being possibly allowed...
11101114 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 {
11171120 Ok ( param) => Ok (
11181121 if let TyKind :: CVarArgs = param. ty . kind {
11191122 c_variadic = true ;
@@ -1144,7 +1147,10 @@ impl<'a> Parser<'a> {
11441147 }
11451148 } ) ?;
11461149
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) ;
11481154
11491155 if c_variadic && params. len ( ) <= 1 {
11501156 self . span_err (
@@ -1156,79 +1162,53 @@ impl<'a> Parser<'a> {
11561162 Ok ( params)
11571163 }
11581164
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-
11821165 /// Skips unexpected attributes and doc comments in this position and emits an appropriate
11831166 /// error.
11841167 /// 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 > {
11921169 let lo = self . token . span ;
11931170 let attrs = self . parse_outer_attributes ( ) ?;
11941171
11951172 // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
11961173 if let Some ( mut param) = self . parse_self_param ( ) ? {
11971174 param. attrs = attrs. into ( ) ;
1198- return if is_self_allowed {
1175+ return if cfg . is_self_allowed {
11991176 Ok ( param)
12001177 } else {
12011178 self . recover_bad_self_param ( param, is_trait_item)
12021179 } ;
12031180 }
12041181
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+ } ;
12061186 let ( pat, ty) = if is_name_required || self . is_named_param ( ) {
12071187 debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
12081188
12091189 let pat = self . parse_fn_param_pat ( ) ?;
12101190 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 (
12121192 & mut err,
12131193 pat,
12141194 is_name_required,
1215- is_self_allowed,
1195+ cfg . is_self_allowed ,
12161196 is_trait_item,
12171197 ) {
12181198 err. emit ( ) ;
1219- return Ok ( dummy_arg ( ident) ) ;
1199+ Ok ( dummy_arg ( ident) )
12201200 } else {
1221- return Err ( err) ;
1222- }
1201+ Err ( err)
1202+ } ;
12231203 }
12241204
12251205 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 ) ?)
12271207 } else {
12281208 debug ! ( "parse_param_general ident_to_pat" ) ;
12291209 let parser_snapshot_before_ty = self . clone ( ) ;
12301210 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 ) ;
12321212 if ty. is_ok ( ) && self . token != token:: Comma &&
12331213 self . token != token:: CloseDelim ( token:: Paren ) {
12341214 // This wasn't actually a type, but a pattern looking like a type,
0 commit comments