@@ -10,6 +10,7 @@ use rustc_ast::{self as ast};
10
10
use rustc_ast_pretty:: pprust;
11
11
use rustc_errors:: codes:: * ;
12
12
use rustc_errors:: { Applicability , PResult , StashKey , struct_span_code_err} ;
13
+ use rustc_session:: lint:: builtin:: VARARGS_WITHOUT_PATTERN ;
13
14
use rustc_span:: edit_distance:: edit_distance;
14
15
use rustc_span:: edition:: Edition ;
15
16
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Ident , Span , Symbol , kw, source_map, sym} ;
@@ -117,7 +118,7 @@ impl<'a> Parser<'a> {
117
118
impl < ' a > Parser < ' a > {
118
119
pub fn parse_item ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < Box < Item > > > {
119
120
let fn_parse_mode =
120
- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
121
+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
121
122
self . parse_item_ ( fn_parse_mode, force_collect) . map ( |i| i. map ( Box :: new) )
122
123
}
123
124
@@ -977,7 +978,7 @@ impl<'a> Parser<'a> {
977
978
force_collect : ForceCollect ,
978
979
) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
979
980
let fn_parse_mode =
980
- FnParseMode { req_name : |_| true , context : FnContext :: Impl , req_body : true } ;
981
+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Impl , req_body : true } ;
981
982
self . parse_assoc_item ( fn_parse_mode, force_collect)
982
983
}
983
984
@@ -986,7 +987,7 @@ impl<'a> Parser<'a> {
986
987
force_collect : ForceCollect ,
987
988
) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
988
989
let fn_parse_mode = FnParseMode {
989
- req_name : |edition| edition >= Edition :: Edition2018 ,
990
+ req_name : |edition, _ | edition >= Edition :: Edition2018 ,
990
991
context : FnContext :: Trait ,
991
992
req_body : false ,
992
993
} ;
@@ -1266,8 +1267,11 @@ impl<'a> Parser<'a> {
1266
1267
& mut self ,
1267
1268
force_collect : ForceCollect ,
1268
1269
) -> PResult < ' a , Option < Option < Box < ForeignItem > > > > {
1269
- let fn_parse_mode =
1270
- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : false } ;
1270
+ let fn_parse_mode = FnParseMode {
1271
+ req_name : |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot :: No ,
1272
+ context : FnContext :: Free ,
1273
+ req_body : false ,
1274
+ } ;
1271
1275
Ok ( self . parse_item_ ( fn_parse_mode, force_collect) ?. map (
1272
1276
|Item { attrs, id, span, vis, kind, tokens } | {
1273
1277
let kind = match ForeignItemKind :: try_from ( kind) {
@@ -2142,7 +2146,7 @@ impl<'a> Parser<'a> {
2142
2146
Visibility { span : DUMMY_SP , kind : VisibilityKind :: Inherited , tokens : None } ;
2143
2147
// We use `parse_fn` to get a span for the function
2144
2148
let fn_parse_mode =
2145
- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
2149
+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
2146
2150
match self . parse_fn (
2147
2151
& mut AttrVec :: new ( ) ,
2148
2152
fn_parse_mode,
@@ -2375,8 +2379,16 @@ impl<'a> Parser<'a> {
2375
2379
/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
2376
2380
///
2377
2381
/// This function pointer accepts an edition, because in edition 2015, trait declarations
2378
- /// were allowed to omit parameter names. In 2018, they became required.
2379
- type ReqName = fn ( Edition ) -> bool ;
2382
+ /// were allowed to omit parameter names. In 2018, they became required. It also accepts an
2383
+ /// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are
2384
+ /// allowed to omit the name of the `...` but regular function items are not.
2385
+ type ReqName = fn ( Edition , IsDotDotDot ) -> bool ;
2386
+
2387
+ #[ derive( Copy , Clone , PartialEq ) ]
2388
+ pub ( crate ) enum IsDotDotDot {
2389
+ Yes ,
2390
+ No ,
2391
+ }
2380
2392
2381
2393
/// Parsing configuration for functions.
2382
2394
///
@@ -2409,6 +2421,9 @@ pub(crate) struct FnParseMode {
2409
2421
/// to true.
2410
2422
/// * The span is from Edition 2015. In particular, you can get a
2411
2423
/// 2015 span inside a 2021 crate using macros.
2424
+ ///
2425
+ /// Or if `IsDotDotDot::Yes`, this function will also return `false` if the item being parsed
2426
+ /// is inside an `extern` block.
2412
2427
pub ( super ) req_name : ReqName ,
2413
2428
/// The context in which this function is parsed, used for diagnostics.
2414
2429
/// This indicates the fn is a free function or method and so on.
@@ -3055,11 +3070,25 @@ impl<'a> Parser<'a> {
3055
3070
return Ok ( ( res?, Trailing :: No , UsePreAttrPos :: No ) ) ;
3056
3071
}
3057
3072
3058
- let is_name_required = match this. token . kind {
3059
- token:: DotDotDot => false ,
3060
- _ => ( fn_parse_mode. req_name ) (
3061
- this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3062
- ) ,
3073
+ let is_dot_dot_dot = if this. token . kind == token:: DotDotDot {
3074
+ IsDotDotDot :: Yes
3075
+ } else {
3076
+ IsDotDotDot :: No
3077
+ } ;
3078
+ let is_name_required = ( fn_parse_mode. req_name ) (
3079
+ this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3080
+ is_dot_dot_dot,
3081
+ ) ;
3082
+ let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot :: Yes {
3083
+ this. psess . buffer_lint (
3084
+ VARARGS_WITHOUT_PATTERN ,
3085
+ this. token . span ,
3086
+ ast:: CRATE_NODE_ID ,
3087
+ errors:: VarargsWithoutPattern { span : this. token . span } ,
3088
+ ) ;
3089
+ false
3090
+ } else {
3091
+ is_name_required
3063
3092
} ;
3064
3093
let ( pat, ty) = if is_name_required || this. is_named_param ( ) {
3065
3094
debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
0 commit comments