@@ -11,6 +11,8 @@ use rustc_ast::{self as ast};
1111use rustc_ast_pretty:: pprust;
1212use rustc_errors:: codes:: * ;
1313use rustc_errors:: { Applicability , PResult , StashKey , struct_span_code_err} ;
14+ use rustc_session:: lint:: BuiltinLintDiag ;
15+ use rustc_session:: lint:: builtin:: VARARGS_WITHOUT_PATTERN ;
1416use rustc_span:: edit_distance:: edit_distance;
1517use rustc_span:: edition:: Edition ;
1618use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Ident , Span , Symbol , kw, source_map, sym} ;
@@ -117,7 +119,7 @@ impl<'a> Parser<'a> {
117119
118120impl < ' a > Parser < ' a > {
119121 pub fn parse_item ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < P < Item > > > {
120- let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
122+ let fn_parse_mode = FnParseMode { req_name : |_, _ | true , req_body : true } ;
121123 self . parse_item_ ( fn_parse_mode, force_collect) . map ( |i| i. map ( P ) )
122124 }
123125
@@ -935,7 +937,7 @@ impl<'a> Parser<'a> {
935937 & mut self ,
936938 force_collect : ForceCollect ,
937939 ) -> PResult < ' a , Option < Option < P < AssocItem > > > > {
938- let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
940+ let fn_parse_mode = FnParseMode { req_name : |_, _ | true , req_body : true } ;
939941 self . parse_assoc_item ( fn_parse_mode, force_collect)
940942 }
941943
@@ -944,7 +946,7 @@ impl<'a> Parser<'a> {
944946 force_collect : ForceCollect ,
945947 ) -> PResult < ' a , Option < Option < P < AssocItem > > > > {
946948 let fn_parse_mode =
947- FnParseMode { req_name : |edition| edition >= Edition :: Edition2018 , req_body : false } ;
949+ FnParseMode { req_name : |edition, _ | edition >= Edition :: Edition2018 , req_body : false } ;
948950 self . parse_assoc_item ( fn_parse_mode, force_collect)
949951 }
950952
@@ -1221,7 +1223,10 @@ impl<'a> Parser<'a> {
12211223 & mut self ,
12221224 force_collect : ForceCollect ,
12231225 ) -> PResult < ' a , Option < Option < P < ForeignItem > > > > {
1224- let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : false } ;
1226+ let fn_parse_mode = FnParseMode {
1227+ req_name : |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot :: No ,
1228+ req_body : false ,
1229+ } ;
12251230 Ok ( self . parse_item_ ( fn_parse_mode, force_collect) ?. map (
12261231 |Item { attrs, id, span, vis, kind, tokens } | {
12271232 let kind = match ForeignItemKind :: try_from ( kind) {
@@ -2093,7 +2098,7 @@ impl<'a> Parser<'a> {
20932098 let inherited_vis =
20942099 Visibility { span : DUMMY_SP , kind : VisibilityKind :: Inherited , tokens : None } ;
20952100 // We use `parse_fn` to get a span for the function
2096- let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
2101+ let fn_parse_mode = FnParseMode { req_name : |_, _ | true , req_body : true } ;
20972102 match self . parse_fn (
20982103 & mut AttrVec :: new ( ) ,
20992104 fn_parse_mode,
@@ -2326,8 +2331,16 @@ impl<'a> Parser<'a> {
23262331/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
23272332///
23282333/// This function pointer accepts an edition, because in edition 2015, trait declarations
2329- /// were allowed to omit parameter names. In 2018, they became required.
2330- type ReqName = fn ( Edition ) -> bool ;
2334+ /// were allowed to omit parameter names. In 2018, they became required. It also accepts an
2335+ /// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are
2336+ /// allowed to omit the name of the `...` but regular function items are not.
2337+ type ReqName = fn ( Edition , IsDotDotDot ) -> bool ;
2338+
2339+ #[ derive( Copy , Clone , PartialEq ) ]
2340+ pub ( crate ) enum IsDotDotDot {
2341+ Yes ,
2342+ No ,
2343+ }
23312344
23322345/// Parsing configuration for functions.
23332346///
@@ -2360,6 +2373,8 @@ pub(crate) struct FnParseMode {
23602373 /// to true.
23612374 /// * The span is from Edition 2015. In particular, you can get a
23622375 /// 2015 span inside a 2021 crate using macros.
2376+ ///
2377+ /// Or if `IsDotDotDot::Yes`, this function will also return `false` with an `extern` block.
23632378 pub ( super ) req_name : ReqName ,
23642379 /// If this flag is set to `true`, then plain, semicolon-terminated function
23652380 /// prototypes are not allowed here.
@@ -2991,9 +3006,25 @@ impl<'a> Parser<'a> {
29913006 return Ok ( ( res?, Trailing :: No , UsePreAttrPos :: No ) ) ;
29923007 }
29933008
2994- let is_name_required = match this. token . kind {
2995- token:: DotDotDot => false ,
2996- _ => req_name ( this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ) ,
3009+ let is_dot_dot_dot = if this. token . kind == token:: DotDotDot {
3010+ IsDotDotDot :: Yes
3011+ } else {
3012+ IsDotDotDot :: No
3013+ } ;
3014+ let is_name_required = req_name (
3015+ this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3016+ is_dot_dot_dot,
3017+ ) ;
3018+ let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot :: Yes {
3019+ this. psess . buffer_lint (
3020+ VARARGS_WITHOUT_PATTERN ,
3021+ this. token . span ,
3022+ ast:: CRATE_NODE_ID ,
3023+ BuiltinLintDiag :: VarargsWithoutPattern { span : this. token . span } ,
3024+ ) ;
3025+ false
3026+ } else {
3027+ is_name_required
29973028 } ;
29983029 let ( pat, ty) = if is_name_required || this. is_named_param ( ) {
29993030 debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
0 commit comments