diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fe7fe83ffda..8684c99a0beaa 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -1051,5 +1051,8 @@ lint_useless_ptr_null_checks_ref = references are not nullable, so checking them lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +lint_varargs_without_pattern = missing pattern for `...` argument + .suggestion = name the argument, or use `_` to continue ignoring it + lint_variant_size_differences = enum variant is more than three times larger ({$largest} bytes) than the next largest diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f0fbf5bc81e9b..f2f4513a2bad6 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -468,5 +468,8 @@ pub fn decorate_builtin_lint( BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } + BuiltinLintDiag::VarargsWithoutPattern { span } => { + lints::VarargsWithoutPattern { span }.decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd8d0f832aa47..bfb6373772826 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3215,6 +3215,13 @@ pub(crate) struct ReservedMultihash { pub suggestion: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_varargs_without_pattern)] +pub(crate) struct VarargsWithoutPattern { + #[suggestion(code = "_: ...", applicability = "machine-applicable")] + pub span: Span, +} + #[derive(Debug)] pub(crate) struct MismatchedLifetimeSyntaxes { pub inputs: LifetimeSyntaxCategories>, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b1edb5c304425..616eb7802fdc2 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -141,6 +141,7 @@ declare_lint_pass! { UNUSED_UNSAFE, UNUSED_VARIABLES, USELESS_DEPRECATED, + VARARGS_WITHOUT_PATTERN, WARNINGS, // tidy-alphabetical-end ] @@ -5099,3 +5100,50 @@ declare_lint! { report_in_deps: true, }; } + +declare_lint! { + /// The `varargs_without_pattern` lint detects when `...` is used as an argument to a + /// non-foreign function without any pattern being specified. + /// + /// ### Example + /// + /// ```rust + /// // Using `...` in non-foreign function definitions is unstable, however stability is + /// // currently only checked after attributes are expanded, so using `#[cfg(false)]` here will + /// // allow this to compile on stable Rust. + /// #[cfg(false)] + /// fn foo(...) { + /// + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Patterns are currently required for all non-`...` arguments in function definitions (with + /// some exceptions in the 2015 edition). Requiring `...` arguments to have patterns in + /// non-foreign function defitions makes the language more consistent, and removes a source of + /// confusion for the unstable C variadic feature. `...` arguments without a pattern are already + /// stable and widely used in foreign function definitions; this lint only affects non-foreign + /// function defitions. + /// + /// Using `...` (C varargs) in a non-foreign function definition is currently unstable. However, + /// stability checking for the `...` syntax in non-foreign function definitions is currently + /// implemented after attributes have been expanded, meaning that if the attribute removes the + /// use of the unstable syntax (e.g. `#[cfg(false)]`, or a procedural macro), the code will + /// compile on stable Rust; this is the only situtation where this lint affects code that + /// compiles on stable Rust. + /// + /// This is a [future-incompatible] lint to transition this to a hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub VARARGS_WITHOUT_PATTERN, + Warn, + "detects usage of `...` arguments without a pattern in non-foreign items", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseError, + reference: "issue #FIXME ", + report_in_deps: false, + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index fe068d96b7424..08ea1a01d1c7a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -807,6 +807,9 @@ pub enum BuiltinLintDiag { cfg_name: Symbol, controlled_by: &'static str, }, + VarargsWithoutPattern { + span: Span, + }, } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 41d3889c44838..0280c4c666566 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -200,7 +200,7 @@ impl<'a> Parser<'a> { AttrWrapper::empty(), true, false, - FnParseMode { req_name: |_| true, req_body: true }, + FnParseMode { req_name: |_, _| true, req_body: true }, ForceCollect::No, ) { Ok(Some(item)) => { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 65d84b3e3d9d5..9083724610c0a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -11,6 +11,8 @@ use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err}; +use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, source_map, sym}; @@ -117,7 +119,7 @@ impl<'a> Parser<'a> { impl<'a> Parser<'a> { pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + let fn_parse_mode = FnParseMode { req_name: |_, _| true, req_body: true }; self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P)) } @@ -949,7 +951,7 @@ impl<'a> Parser<'a> { &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + let fn_parse_mode = FnParseMode { req_name: |_, _| true, req_body: true }; self.parse_assoc_item(fn_parse_mode, force_collect) } @@ -958,7 +960,7 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, ) -> PResult<'a, Option>>> { let fn_parse_mode = - FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false }; + FnParseMode { req_name: |edition, _| edition >= Edition::Edition2018, req_body: false }; self.parse_assoc_item(fn_parse_mode, force_collect) } @@ -1235,7 +1237,10 @@ impl<'a> Parser<'a> { &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; + let fn_parse_mode = FnParseMode { + req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No, + req_body: false, + }; Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { @@ -2107,7 +2112,7 @@ impl<'a> Parser<'a> { let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None }; // We use `parse_fn` to get a span for the function - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + let fn_parse_mode = FnParseMode { req_name: |_, _| true, req_body: true }; match self.parse_fn( &mut AttrVec::new(), fn_parse_mode, @@ -2340,8 +2345,16 @@ impl<'a> Parser<'a> { /// The function decides if, per-parameter `p`, `p` must have a pattern or just a type. /// /// This function pointer accepts an edition, because in edition 2015, trait declarations -/// were allowed to omit parameter names. In 2018, they became required. -type ReqName = fn(Edition) -> bool; +/// were allowed to omit parameter names. In 2018, they became required. It also accepts an +/// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are +/// allowed to omit the name of the `...` but regular function items are not. +type ReqName = fn(Edition, IsDotDotDot) -> bool; + +#[derive(Copy, Clone, PartialEq)] +pub(crate) enum IsDotDotDot { + Yes, + No, +} /// Parsing configuration for functions. /// @@ -2374,6 +2387,8 @@ pub(crate) struct FnParseMode { /// to true. /// * The span is from Edition 2015. In particular, you can get a /// 2015 span inside a 2021 crate using macros. + /// + /// Or if `IsDotDotDot::Yes`, this function will also return `false` with an `extern` block. pub(super) req_name: ReqName, /// If this flag is set to `true`, then plain, semicolon-terminated function /// prototypes are not allowed here. @@ -3005,9 +3020,25 @@ impl<'a> Parser<'a> { return Ok((res?, Trailing::No, UsePreAttrPos::No)); } - let is_name_required = match this.token.kind { - token::DotDotDot => false, - _ => req_name(this.token.span.with_neighbor(this.prev_token.span).edition()), + let is_dot_dot_dot = if this.token.kind == token::DotDotDot { + IsDotDotDot::Yes + } else { + IsDotDotDot::No + }; + let is_name_required = req_name( + this.token.span.with_neighbor(this.prev_token.span).edition(), + is_dot_dot_dot, + ); + let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes { + this.psess.buffer_lint( + VARARGS_WITHOUT_PATTERN, + this.token.span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::VarargsWithoutPattern { span: this.token.span }, + ); + false + } else { + is_name_required }; let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 1f4049f197fa8..1755c83e0109e 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -400,7 +400,7 @@ impl<'a> Parser<'a> { let dcx = self.dcx(); let parse_params_result = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(|_| false, false, false); + let param = p.parse_param_general(|_, _| false, false, false); param.map(move |param| { if !matches!(param.pat.kind, PatKind::Missing) { dcx.emit_err(FnPathFoundNamedParams { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2fa6520f2a42a..5bb8186b25fd8 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -154,7 +154,7 @@ impl<'a> Parser<'a> { attrs.clone(), // FIXME: unwanted clone of attrs false, true, - FnParseMode { req_name: |_| true, req_body: true }, + FnParseMode { req_name: |_, _| true, req_body: true }, force_collect, )? { self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 740dd10ea8ba1..5dde015e5b01e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -750,7 +750,7 @@ impl<'a> Parser<'a> { if self.may_recover() && self.token == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; } - let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; + let decl = self.parse_fn_decl(|_, _| false, AllowPlus::No, recover_return_sign)?; let decl_span = span_start.to(self.prev_token.span); Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span }))) @@ -1289,7 +1289,7 @@ impl<'a> Parser<'a> { self.bump(); let args_lo = self.token.span; let snapshot = self.create_snapshot_for_diagnostic(); - match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { + match self.parse_fn_decl(|_, _| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { Ok(decl) => { self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span }); Some(ast::Path { @@ -1374,7 +1374,7 @@ impl<'a> Parser<'a> { // Parse `(T, U) -> R`. let inputs_lo = self.token.span; let inputs: ThinVec<_> = - self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect(); + self.parse_fn_params(|_, _| false)?.into_iter().map(|input| input.ty).collect(); let inputs_span = inputs_lo.to(self.prev_token.span); let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; let args = ast::ParenthesizedArgs { diff --git a/tests/crashes/132142.rs b/tests/crashes/132142.rs index 813bf0bf0a8e5..bfad88721aa8a 100644 --- a/tests/crashes/132142.rs +++ b/tests/crashes/132142.rs @@ -1,3 +1,3 @@ //@ known-bug: #132142 -async extern "cmse-nonsecure-entry" fn fun(...) {} +async extern "cmse-nonsecure-entry" fn fun(_: ...) {} diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index c0f5b7069a2d7..8cbd8f41b6469 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -16,12 +16,12 @@ fn main() { fn g1(_: extern "C" fn(_: u8, va: ...)) { } - fn g2(_: extern "C" fn(_: u8, ...)) { } + fn g2(_: extern "C" fn(_: u8, _: ...)) { } fn g3(_: extern "C" fn(u8, va: ...)) { } - fn g4(_: extern "C" fn(u8, ...)) { } + fn g4(_: extern "C" fn(u8, _: ...)) { } fn g5(_: extern "C" fn(va: ...)) { } - fn g6(_: extern "C" fn(...)) { } + fn g6(_: extern "C" fn(_: ...)) { } { let _ = diff --git a/tests/pretty/hir-fn-variadic.rs b/tests/pretty/hir-fn-variadic.rs index 99aa402c480b0..ce1b0f835ab27 100644 --- a/tests/pretty/hir-fn-variadic.rs +++ b/tests/pretty/hir-fn-variadic.rs @@ -14,16 +14,16 @@ pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { fn main() { fn g1(_: extern "C" fn(_: u8, va: ...)) {} - fn g2(_: extern "C" fn(_: u8, ...)) {} + fn g2(_: extern "C" fn(_: u8, _: ...)) {} fn g3(_: extern "C" fn(u8, va: ...)) {} - fn g4(_: extern "C" fn(u8, ...)) {} + fn g4(_: extern "C" fn(u8, _: ...)) {} fn g5(_: extern "C" fn(va: ...)) {} - fn g6(_: extern "C" fn(...)) {} + fn g6(_: extern "C" fn(_: ...)) {} _ = { unsafe extern "C" fn f1(_: u8, va: ...) {} }; - _ = { unsafe extern "C" fn f2(_: u8, ...) {} }; + _ = { unsafe extern "C" fn f2(_: u8, _: ...) {} }; _ = { unsafe extern "C" fn f5(va: ...) {} }; - _ = { unsafe extern "C" fn f6(...) {} }; + _ = { unsafe extern "C" fn f6(_: ...) {} }; } diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index 8eeb99a4cc19c..89c91e370077c 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -8,7 +8,7 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self , //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function - self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { //~^ ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index dc323f9a234d6..2796475f3a19c 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -25,46 +25,46 @@ LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , error: unexpected `self` parameter in function --> $DIR/issue-86053-1.rs:11:5 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:11:20 + --> $DIR/issue-86053-1.rs:11:23 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^^^^ must be the first parameter of an associated function +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:11:29 + --> $DIR/issue-86053-1.rs:11:32 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^^^^ must be the first parameter of an associated function +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function error: `...` must be the last argument of a C-variadic function --> $DIR/issue-86053-1.rs:11:12 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^^^ +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/issue-86053-1.rs:11:12 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^^^ ^^^ +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^^^ ^^^^^^ error[E0412]: cannot find type `F` in this scope - --> $DIR/issue-86053-1.rs:11:48 + --> $DIR/issue-86053-1.rs:11:54 | -LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^ +LL | self , _: ... , self , self , _: ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^ --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here | help: a trait with a similar name exists | -LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) { - | + +LL | self , _: ... , self , self , _: ... ) where Fn : FnOnce ( & 'a & 'b usize ) { + | + help: you might be missing a type parameter | LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self , diff --git a/tests/ui/c-variadic/issue-86053-2.rs b/tests/ui/c-variadic/issue-86053-2.rs index c545831f7171a..0914676a35f4f 100644 --- a/tests/ui/c-variadic/issue-86053-2.rs +++ b/tests/ui/c-variadic/issue-86053-2.rs @@ -5,7 +5,7 @@ trait H {} -unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} +unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), _: ...) {} //~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491] fn main() {} diff --git a/tests/ui/c-variadic/issue-86053-2.stderr b/tests/ui/c-variadic/issue-86053-2.stderr index 2c4be2522f614..823dadff6f895 100644 --- a/tests/ui/c-variadic/issue-86053-2.stderr +++ b/tests/ui/c-variadic/issue-86053-2.stderr @@ -1,14 +1,14 @@ error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references --> $DIR/issue-86053-2.rs:8:39 | -LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), _: ...) {} | ^^^^^^^^^^^^^^^^^^ | = note: the pointer is valid for the static lifetime note: but the referenced data is only valid for the lifetime `'a` as defined here --> $DIR/issue-86053-2.rs:8:32 | -LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), _: ...) {} | ^^ error: aborting due to 1 previous error diff --git a/tests/ui/c-variadic/parse-errors.e2015.stderr b/tests/ui/c-variadic/parse-errors.e2015.stderr new file mode 100644 index 0000000000000..097f6b4fe2f8f --- /dev/null +++ b/tests/ui/c-variadic/parse-errors.e2015.stderr @@ -0,0 +1,46 @@ +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:10:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +note: the lint level is defined here + --> $DIR/parse-errors.rs:6:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:13:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:19:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/c-variadic/parse-errors.e2018.stderr b/tests/ui/c-variadic/parse-errors.e2018.stderr new file mode 100644 index 0000000000000..7bec2c070888b --- /dev/null +++ b/tests/ui/c-variadic/parse-errors.e2018.stderr @@ -0,0 +1,59 @@ +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:10:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +note: the lint level is defined here + --> $DIR/parse-errors.rs:6:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:13:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:19:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:25:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #FIXME +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/c-variadic/parse-errors.rs b/tests/ui/c-variadic/parse-errors.rs new file mode 100644 index 0000000000000..d26c2ccf2bfe2 --- /dev/null +++ b/tests/ui/c-variadic/parse-errors.rs @@ -0,0 +1,35 @@ +//@ check-fail +//@ revisions: e2015 e2018 +//@[e2015] edition: 2015 +//@[e2018] edition: 2018 +#![crate_type = "lib"] +#![deny(varargs_without_pattern)] + +#[cfg(false)] +mod module { + unsafe extern "C" fn f(...) { + //~^ ERROR missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler + unsafe extern "C" fn f(...) {} + //~^ ERROR missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler + } + + impl A { + unsafe extern "C" fn f(...) {} + //~^ ERROR missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler + } + + trait A { + unsafe extern "C" fn f(...) {} + //[e2018]~^ ERROR missing pattern for `...` argument + //[e2018]~| WARN this was previously accepted by the compiler + } + + unsafe extern "C" { + fn f(...); // no error + } + + type A = unsafe extern "C" fn(...); // no error +} diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.rs b/tests/ui/inference/note-and-explain-ReVar-124973.rs index f1e2464563699..ad304969fcf04 100644 --- a/tests/ui/inference/note-and-explain-ReVar-124973.rs +++ b/tests/ui/inference/note-and-explain-ReVar-124973.rs @@ -2,7 +2,7 @@ #![feature(c_variadic)] -async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {} +async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, _: ...) {} //~^ ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.stderr b/tests/ui/inference/note-and-explain-ReVar-124973.stderr index 574f6508e4c78..29c4f3b57c7cc 100644 --- a/tests/ui/inference/note-and-explain-ReVar-124973.stderr +++ b/tests/ui/inference/note-and-explain-ReVar-124973.stderr @@ -1,8 +1,8 @@ error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds - --> $DIR/note-and-explain-ReVar-124973.rs:5:73 + --> $DIR/note-and-explain-ReVar-124973.rs:5:76 | -LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {} - | ----------------------------------------------------------------------- ^^ +LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, _: ...) {} + | -------------------------------------------------------------------------- ^^ | | | opaque type defined here | diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs index 78e5c96180285..90a758cb2647b 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -4,7 +4,7 @@ fn main() {} -fn foo(_: Bar, ...) -> impl {} +fn foo(_: Bar, _: ...) -> impl {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR cannot find type `Bar` in this scope //~| ERROR at least one trait must be specified diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr index 80a8a94aea400..839efbcbd5e60 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -1,19 +1,19 @@ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 | -LL | fn foo(_: Bar, ...) -> impl {} - | ^^^ +LL | fn foo(_: Bar, _: ...) -> impl {} + | ^^^^^^ error: at least one trait must be specified - --> $DIR/issue-83499-input-output-iteration-ice.rs:7:24 + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:27 | -LL | fn foo(_: Bar, ...) -> impl {} - | ^^^^ +LL | fn foo(_: Bar, _: ...) -> impl {} + | ^^^^ error[E0412]: cannot find type `Bar` in this scope --> $DIR/issue-83499-input-output-iteration-ice.rs:7:11 | -LL | fn foo(_: Bar, ...) -> impl {} +LL | fn foo(_: Bar, _: ...) -> impl {} | ^^^ not found in this scope error: aborting due to 3 previous errors diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index 1cd6d13d56b6b..c61e538959422 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -3,42 +3,42 @@ fn main() {} -fn f1_1(x: isize, ...) {} +fn f1_1(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -fn f1_2(...) {} +fn f1_2(_: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -extern "C" fn f2_1(x: isize, ...) {} +extern "C" fn f2_1(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -extern "C" fn f2_2(...) {} +extern "C" fn f2_2(_: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -extern "C" fn f2_3(..., x: isize) {} +extern "C" fn f2_3(_: ..., x: isize) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function -extern "C" fn f3_1(x: isize, ...) {} +extern "C" fn f3_1(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -extern "C" fn f3_2(...) {} +extern "C" fn f3_2(_: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -extern "C" fn f3_3(..., x: isize) {} +extern "C" fn f3_3(_: ..., x: isize) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function -const unsafe extern "C" fn f4_1(x: isize, ...) {} +const unsafe extern "C" fn f4_1(x: isize, _: ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time -const extern "C" fn f4_2(x: isize, ...) {} +const extern "C" fn f4_2(x: isize, _: ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time -const extern "C" fn f4_3(..., x: isize, ...) {} +const extern "C" fn f4_3(_: ..., x: isize, _: ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function @@ -51,35 +51,35 @@ extern "C" { struct X; impl X { - fn i_f1(x: isize, ...) {} + fn i_f1(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn i_f2(...) {} + fn i_f2(_: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn i_f3(..., x: isize, ...) {} + fn i_f3(_: ..., x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function - fn i_f4(..., x: isize, ...) {} + fn i_f4(_: ..., x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function - const fn i_f5(x: isize, ...) {} + const fn i_f5(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR functions cannot be both `const` and C-variadic //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { - fn t_f1(x: isize, ...) {} + fn t_f1(x: isize, _: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn t_f2(x: isize, ...); + fn t_f2(x: isize, _: ...); //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn t_f3(...) {} + fn t_f3(_: ...) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn t_f4(...); + fn t_f4(_: ...); //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - fn t_f5(..., x: isize) {} + fn t_f5(_: ..., x: isize) {} //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function - fn t_f6(..., x: isize); + fn t_f6(_: ..., x: isize); //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index b740cef020055..eb71d8a2de70b 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,92 +1,92 @@ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 | -LL | fn f1_1(x: isize, ...) {} - | ^^^ +LL | fn f1_1(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | -LL | fn f1_2(...) {} - | ^^^ +LL | fn f1_2(_: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 | -LL | extern "C" fn f2_1(x: isize, ...) {} - | ^^^ +LL | extern "C" fn f2_1(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 | -LL | extern "C" fn f2_2(...) {} - | ^^^ +LL | extern "C" fn f2_2(_: ...) {} + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:18:20 | -LL | extern "C" fn f2_3(..., x: isize) {} - | ^^^ +LL | extern "C" fn f2_3(_: ..., x: isize) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:18:20 | -LL | extern "C" fn f2_3(..., x: isize) {} - | ^^^ +LL | extern "C" fn f2_3(_: ..., x: isize) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:22:30 | -LL | extern "C" fn f3_1(x: isize, ...) {} - | ^^^ +LL | extern "C" fn f3_1(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:25:20 | -LL | extern "C" fn f3_2(...) {} - | ^^^ +LL | extern "C" fn f3_2(_: ...) {} + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:28:20 | -LL | extern "C" fn f3_3(..., x: isize) {} - | ^^^ +LL | extern "C" fn f3_3(_: ..., x: isize) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:28:20 | -LL | extern "C" fn f3_3(..., x: isize) {} - | ^^^ +LL | extern "C" fn f3_3(_: ..., x: isize) {} + | ^^^^^^ error: functions cannot be both `const` and C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:32:1 | -LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} - | ^^^^^ `const` because of this ^^^ C-variadic because of this +LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {} + | ^^^^^ `const` because of this ^^^^^^ C-variadic because of this error: functions cannot be both `const` and C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:36:1 | -LL | const extern "C" fn f4_2(x: isize, ...) {} - | ^^^^^ `const` because of this ^^^ C-variadic because of this +LL | const extern "C" fn f4_2(x: isize, _: ...) {} + | ^^^^^ `const` because of this ^^^^^^ C-variadic because of this error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:36:36 | -LL | const extern "C" fn f4_2(x: isize, ...) {} - | ^^^ +LL | const extern "C" fn f4_2(x: isize, _: ...) {} + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:41:26 | -LL | const extern "C" fn f4_3(..., x: isize, ...) {} - | ^^^ +LL | const extern "C" fn f4_3(_: ..., x: isize, _: ...) {} + | ^^^^^^ error: functions cannot be both `const` and C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:41:1 | -LL | const extern "C" fn f4_3(..., x: isize, ...) {} - | ^^^^^ ^^^ ^^^ C-variadic because of this +LL | const extern "C" fn f4_3(_: ..., x: isize, _: ...) {} + | ^^^^^ ^^^^^^ ^^^^^^ C-variadic because of this | | | | | C-variadic because of this | `const` because of this @@ -94,8 +94,8 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:41:26 | -LL | const extern "C" fn f4_3(..., x: isize, ...) {} - | ^^^ ^^^ +LL | const extern "C" fn f4_3(_: ..., x: isize, _: ...) {} + | ^^^^^^ ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 @@ -106,122 +106,122 @@ LL | fn e_f2(..., x: isize); error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:54:23 | -LL | fn i_f1(x: isize, ...) {} - | ^^^ +LL | fn i_f1(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:56:13 | -LL | fn i_f2(...) {} - | ^^^ +LL | fn i_f2(_: ...) {} + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:58:13 | -LL | fn i_f3(..., x: isize, ...) {} - | ^^^ +LL | fn i_f3(_: ..., x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:58:13 | -LL | fn i_f3(..., x: isize, ...) {} - | ^^^ ^^^ +LL | fn i_f3(_: ..., x: isize, _: ...) {} + | ^^^^^^ ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | -LL | fn i_f4(..., x: isize, ...) {} - | ^^^ +LL | fn i_f4(_: ..., x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | -LL | fn i_f4(..., x: isize, ...) {} - | ^^^ ^^^ +LL | fn i_f4(_: ..., x: isize, _: ...) {} + | ^^^^^^ ^^^^^^ error: functions cannot be both `const` and C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:64:5 | -LL | const fn i_f5(x: isize, ...) {} - | ^^^^^ ^^^ C-variadic because of this +LL | const fn i_f5(x: isize, _: ...) {} + | ^^^^^ ^^^^^^ C-variadic because of this | | | `const` because of this error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:64:29 | -LL | const fn i_f5(x: isize, ...) {} - | ^^^ +LL | const fn i_f5(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:71:23 | -LL | fn t_f1(x: isize, ...) {} - | ^^^ +LL | fn t_f1(x: isize, _: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:73:23 | -LL | fn t_f2(x: isize, ...); - | ^^^ +LL | fn t_f2(x: isize, _: ...); + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:75:13 | -LL | fn t_f3(...) {} - | ^^^ +LL | fn t_f3(_: ...) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:77:13 | -LL | fn t_f4(...); - | ^^^ +LL | fn t_f4(_: ...); + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:79:13 | -LL | fn t_f5(..., x: isize) {} - | ^^^ +LL | fn t_f5(_: ..., x: isize) {} + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:79:13 | -LL | fn t_f5(..., x: isize) {} - | ^^^ +LL | fn t_f5(_: ..., x: isize) {} + | ^^^^^^ error: `...` must be the last argument of a C-variadic function --> $DIR/variadic-ffi-semantic-restrictions.rs:82:13 | -LL | fn t_f6(..., x: isize); - | ^^^ +LL | fn t_f6(_: ..., x: isize); + | ^^^^^^ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg --> $DIR/variadic-ffi-semantic-restrictions.rs:82:13 | -LL | fn t_f6(..., x: isize); - | ^^^ +LL | fn t_f6(_: ..., x: isize); + | ^^^^^^ error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:32:43 | -LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} - | ^^^ - value is dropped here +LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {} + | ^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:36:36 | -LL | const extern "C" fn f4_2(x: isize, ...) {} - | ^^^ - value is dropped here +LL | const extern "C" fn f4_2(x: isize, _: ...) {} + | ^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time --> $DIR/variadic-ffi-semantic-restrictions.rs:64:29 | -LL | const fn i_f5(x: isize, ...) {} - | ^^^ - value is dropped here +LL | const fn i_f5(x: isize, _: ...) {} + | ^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/parser/variadic-ffi-syntactic-pass.rs b/tests/ui/parser/variadic-ffi-syntactic-pass.rs index ebe0b6c2dd258..6a6656044e174 100644 --- a/tests/ui/parser/variadic-ffi-syntactic-pass.rs +++ b/tests/ui/parser/variadic-ffi-syntactic-pass.rs @@ -3,28 +3,28 @@ fn main() {} #[cfg(false)] -fn f1_1(x: isize, ...) {} +fn f1_1(x: isize, _: ...) {} #[cfg(false)] -fn f1_2(...) {} +fn f1_2(_: ...) {} #[cfg(false)] -extern "C" fn f2_1(x: isize, ...) {} +extern "C" fn f2_1(x: isize, _: ...) {} #[cfg(false)] -extern "C" fn f2_2(...) {} +extern "C" fn f2_2(_: ...) {} #[cfg(false)] -extern "C" fn f2_3(..., x: isize) {} +extern "C" fn f2_3(_: ..., x: isize) {} #[cfg(false)] -extern fn f3_1(x: isize, ...) {} +extern fn f3_1(x: isize, _: ...) {} #[cfg(false)] -extern fn f3_2(...) {} +extern fn f3_2(_: ...) {} #[cfg(false)] -extern fn f3_3(..., x: isize) {} +extern fn f3_3(_: ..., x: isize) {} #[cfg(false)] extern { @@ -36,18 +36,18 @@ struct X; #[cfg(false)] impl X { - fn i_f1(x: isize, ...) {} - fn i_f2(...) {} - fn i_f3(..., x: isize, ...) {} - fn i_f4(..., x: isize, ...) {} + fn i_f1(x: isize, _: ...) {} + fn i_f2(_: ...) {} + fn i_f3(_: ..., x: isize, _: ...) {} + fn i_f4(_: ..., x: isize, _: ...) {} } #[cfg(false)] trait T { - fn t_f1(x: isize, ...) {} - fn t_f2(x: isize, ...); - fn t_f3(...) {} - fn t_f4(...); - fn t_f5(..., x: isize) {} - fn t_f6(..., x: isize); + fn t_f1(x: isize, _: ...) {} + fn t_f2(x: isize, _: ...); + fn t_f3(_: ...) {} + fn t_f4(_: ...); + fn t_f5(_: ..., x: isize) {} + fn t_f6(_: ..., x: isize); }