@@ -12,6 +12,7 @@ use rustc_ast::{
1212use rustc_ast_pretty:: pprust;
1313use rustc_errors:: codes:: * ;
1414use rustc_errors:: { Applicability , PResult , StashKey , struct_span_code_err} ;
15+ use rustc_session:: lint:: builtin:: VARARGS_WITHOUT_PATTERN ;
1516use rustc_span:: edit_distance:: edit_distance;
1617use rustc_span:: edition:: Edition ;
1718use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Ident , Span , Symbol , kw, source_map, sym} ;
@@ -119,7 +120,7 @@ impl<'a> Parser<'a> {
119120impl < ' a > Parser < ' a > {
120121 pub fn parse_item ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < Box < Item > > > {
121122 let fn_parse_mode =
122- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
123+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
123124 self . parse_item_ ( fn_parse_mode, force_collect) . map ( |i| i. map ( Box :: new) )
124125 }
125126
@@ -976,7 +977,7 @@ impl<'a> Parser<'a> {
976977 force_collect : ForceCollect ,
977978 ) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
978979 let fn_parse_mode =
979- FnParseMode { req_name : |_| true , context : FnContext :: Impl , req_body : true } ;
980+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Impl , req_body : true } ;
980981 self . parse_assoc_item ( fn_parse_mode, force_collect)
981982 }
982983
@@ -985,7 +986,7 @@ impl<'a> Parser<'a> {
985986 force_collect : ForceCollect ,
986987 ) -> PResult < ' a , Option < Option < Box < AssocItem > > > > {
987988 let fn_parse_mode = FnParseMode {
988- req_name : |edition| edition >= Edition :: Edition2018 ,
989+ req_name : |edition, _ | edition >= Edition :: Edition2018 ,
989990 context : FnContext :: Trait ,
990991 req_body : false ,
991992 } ;
@@ -1245,8 +1246,11 @@ impl<'a> Parser<'a> {
12451246 & mut self ,
12461247 force_collect : ForceCollect ,
12471248 ) -> PResult < ' a , Option < Option < Box < ForeignItem > > > > {
1248- let fn_parse_mode =
1249- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : false } ;
1249+ let fn_parse_mode = FnParseMode {
1250+ req_name : |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot :: No ,
1251+ context : FnContext :: Free ,
1252+ req_body : false ,
1253+ } ;
12501254 Ok ( self . parse_item_ ( fn_parse_mode, force_collect) ?. map (
12511255 |Item { attrs, id, span, vis, kind, tokens } | {
12521256 let kind = match ForeignItemKind :: try_from ( kind) {
@@ -2133,7 +2137,7 @@ impl<'a> Parser<'a> {
21332137 Visibility { span : DUMMY_SP , kind : VisibilityKind :: Inherited , tokens : None } ;
21342138 // We use `parse_fn` to get a span for the function
21352139 let fn_parse_mode =
2136- FnParseMode { req_name : |_| true , context : FnContext :: Free , req_body : true } ;
2140+ FnParseMode { req_name : |_, _ | true , context : FnContext :: Free , req_body : true } ;
21372141 match self . parse_fn (
21382142 & mut AttrVec :: new ( ) ,
21392143 fn_parse_mode,
@@ -2366,8 +2370,16 @@ impl<'a> Parser<'a> {
23662370/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
23672371///
23682372/// This function pointer accepts an edition, because in edition 2015, trait declarations
2369- /// were allowed to omit parameter names. In 2018, they became required.
2370- type ReqName = fn ( Edition ) -> bool ;
2373+ /// were allowed to omit parameter names. In 2018, they became required. It also accepts an
2374+ /// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are
2375+ /// allowed to omit the name of the `...` but regular function items are not.
2376+ type ReqName = fn ( Edition , IsDotDotDot ) -> bool ;
2377+
2378+ #[ derive( Copy , Clone , PartialEq ) ]
2379+ pub ( crate ) enum IsDotDotDot {
2380+ Yes ,
2381+ No ,
2382+ }
23712383
23722384/// Parsing configuration for functions.
23732385///
@@ -2400,6 +2412,9 @@ pub(crate) struct FnParseMode {
24002412 /// to true.
24012413 /// * The span is from Edition 2015. In particular, you can get a
24022414 /// 2015 span inside a 2021 crate using macros.
2415+ ///
2416+ /// Or if `IsDotDotDot::Yes`, this function will also return `false` if the item being parsed
2417+ /// is inside an `extern` block.
24032418 pub ( super ) req_name : ReqName ,
24042419 /// The context in which this function is parsed, used for diagnostics.
24052420 /// This indicates the fn is a free function or method and so on.
@@ -3049,11 +3064,25 @@ impl<'a> Parser<'a> {
30493064 return Ok ( ( res?, Trailing :: No , UsePreAttrPos :: No ) ) ;
30503065 }
30513066
3052- let is_name_required = match this. token . kind {
3053- token:: DotDotDot => false ,
3054- _ => ( fn_parse_mode. req_name ) (
3055- this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3056- ) ,
3067+ let is_dot_dot_dot = if this. token . kind == token:: DotDotDot {
3068+ IsDotDotDot :: Yes
3069+ } else {
3070+ IsDotDotDot :: No
3071+ } ;
3072+ let is_name_required = ( fn_parse_mode. req_name ) (
3073+ this. token . span . with_neighbor ( this. prev_token . span ) . edition ( ) ,
3074+ is_dot_dot_dot,
3075+ ) ;
3076+ let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot :: Yes {
3077+ this. psess . buffer_lint (
3078+ VARARGS_WITHOUT_PATTERN ,
3079+ this. token . span ,
3080+ ast:: CRATE_NODE_ID ,
3081+ errors:: VarargsWithoutPattern { span : this. token . span } ,
3082+ ) ;
3083+ false
3084+ } else {
3085+ is_name_required
30573086 } ;
30583087 let ( pat, ty) = if is_name_required || this. is_named_param ( ) {
30593088 debug ! ( "parse_param_general parse_pat (is_name_required:{})" , is_name_required) ;
0 commit comments