@@ -10,6 +10,8 @@ use rustc_ast::{self as ast};
1010use rustc_ast_pretty:: pprust;
1111use rustc_errors:: codes:: * ;
1212use rustc_errors:: { Applicability , PResult , StashKey , struct_span_code_err} ;
13+ use rustc_session:: lint:: BuiltinLintDiag ;
14+ use rustc_session:: lint:: builtin:: VARARGS_WITHOUT_PATTERN ;
1315use rustc_span:: edit_distance:: edit_distance;
1416use rustc_span:: edition:: Edition ;
1517use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Ident , Span , Symbol , kw, source_map, sym} ;
@@ -117,7 +119,7 @@ impl<'a> Parser<'a> {
117119impl < ' a > Parser < ' a > {
118120 pub fn parse_item ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < Box < Item > > > {
119121 let fn_parse_mode =
120- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
122+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
121123 self . parse_item_ ( fn_parse_mode, force_collect) . map ( |i| i. map ( Box :: new) )
122124 }
123125
@@ -977,7 +979,7 @@ impl<'a> Parser<'a> {
977979 force_collect : ForceCollect ,
978980 ) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
979981 let fn_parse_mode =
980- FnParseMode { req_name : |_| true , context : FnContext :: Impl , req_body : true } ;
982+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Impl , req_body : true } ;
981983 self . parse_assoc_item ( fn_parse_mode, force_collect)
982984 }
983985
@@ -986,7 +988,7 @@ impl<'a> Parser<'a> {
986988 force_collect : ForceCollect ,
987989 ) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
988990 let fn_parse_mode = FnParseMode {
989- req_name : |edition| edition >= Edition :: Edition2018 ,
991+ req_name : |edition, _ | edition >= Edition :: Edition2018 ,
990992 context : FnContext :: Trait ,
991993 req_body : false ,
992994 } ;
@@ -1266,8 +1268,11 @@ impl<'a> Parser<'a> {
12661268 & mut self ,
12671269 force_collect : ForceCollect ,
12681270 ) -> PResult < ' a , Option < Option < Box < ForeignItem > > > > {
1269- let fn_parse_mode =
1270- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : false } ;
1271+ let fn_parse_mode = FnParseMode {
1272+ req_name : |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot :: No ,
1273+ context : FnContext :: Free ,
1274+ req_body : false ,
1275+ } ;
12711276 Ok ( self . parse_item_ ( fn_parse_mode, force_collect) ?. map (
12721277 |Item { attrs, id, span, vis, kind, tokens } | {
12731278 let kind = match ForeignItemKind :: try_from ( kind) {
@@ -2142,7 +2147,7 @@ impl<'a> Parser<'a> {
21422147 Visibility { span : DUMMY_SP , kind : VisibilityKind :: Inherited , tokens : None } ;
21432148 // We use `parse_fn` to get a span for the function
21442149 let fn_parse_mode =
2145- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
2150+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
21462151 match self . parse_fn (
21472152 & mut AttrVec :: new ( ) ,
21482153 fn_parse_mode,
@@ -2375,8 +2380,16 @@ impl<'a> Parser<'a> {
23752380/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
23762381///
23772382/// 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 ;
2383+ /// were allowed to omit parameter names. In 2018, they became required. It also accepts an
2384+ /// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are
2385+ /// allowed to omit the name of the `...` but regular function items are not.
2386+ type ReqName = fn ( Edition , IsDotDotDot ) -> bool ;
2387+
2388+ #[ derive( Copy , Clone , PartialEq ) ]
2389+ pub ( crate ) enum IsDotDotDot {
2390+ Yes ,
2391+ No ,
2392+ }
23802393
23812394/// Parsing configuration for functions.
23822395///
@@ -2409,6 +2422,9 @@ pub(crate) struct FnParseMode {
24092422 /// to true.
24102423 /// * The span is from Edition 2015. In particular, you can get a
24112424 /// 2015 span inside a 2021 crate using macros.
2425+ ///
2426+ /// Or if `IsDotDotDot::Yes`, this function will also return `false` if the item being parsed
2427+ /// is inside an `extern` block.
24122428 pub ( super ) req_name : ReqName ,
24132429 /// The context in which this function is parsed, used for diagnostics.
24142430 /// This indicates the fn is a free function or method and so on.
@@ -3055,11 +3071,25 @@ impl<'a> Parser<'a> {
30553071 return Ok ( ( res?, Trailing :: No , UsePreAttrPos :: No ) ) ;
30563072 }
30573073
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- ) ,
3074+ let is_dot_dot_dot = if this. token . kind == token:: DotDotDot {
3075+ IsDotDotDot :: Yes
3076+ } else {
3077+ IsDotDotDot :: No
3078+ } ;
3079+ let is_name_required = ( fn_parse_mode. req_name ) (
3080+ this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3081+ is_dot_dot_dot,
3082+ ) ;
3083+ let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot :: Yes {
3084+ this. psess . buffer_lint (
3085+ VARARGS_WITHOUT_PATTERN ,
3086+ this. token . span ,
3087+ ast:: CRATE_NODE_ID ,
3088+ BuiltinLintDiag :: VarargsWithoutPattern { span : this. token . span } ,
3089+ ) ;
3090+ false
3091+ } else {
3092+ is_name_required
30633093 } ;
30643094 let ( pat, ty) = if is_name_required || this. is_named_param ( ) {
30653095 debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
0 commit comments