Rollup merge of #146342 - folkertdev:c-variadic-errors-take-3, r=workingjubilee

Improve C-variadic error messages: part 2

tracking issue: https://github.com/rust-lang/rust/issues/44930

a reimplementation of https://github.com/rust-lang/rust/pull/143546 that builds on https://github.com/rust-lang/rust/pull/146165.

This PR

- disallows coroutines (e.g. `async fn`) from having a `...` argument
- disallows associated functions (both in traits and standard impl blocks) from having a `...` argument
- splits up a generic "ill-formed C-variadic function" into specific errors about using an incorrect ABI, not specifying an ABI, or missing the unsafe keyword

C-variadic coroutines probably don't make sense? C-variadic functions are for FFI purposes, combining that with async functions seems weird.

For associated functions, we're just cutting scope. It's probably fine, but it's probably better to explicitly allow it. So for now, at least give a more targeted error message.

Made to be reviewed commit-by-commit.

cc `@workingjubilee`
r? compiler
This commit is contained in:
Matthias Krüger 2025-09-10 20:29:10 +02:00 committed by GitHub
commit bb45ea3acc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 357 additions and 167 deletions

View file

@ -2284,6 +2284,54 @@ pub struct FnSig {
pub span: Span,
}
impl FnSig {
/// Return a span encompassing the header, or where to insert it if empty.
pub fn header_span(&self) -> Span {
match self.header.ext {
Extern::Implicit(span) | Extern::Explicit(_, span) => {
return self.span.with_hi(span.hi());
}
Extern::None => {}
}
match self.header.safety {
Safety::Unsafe(span) | Safety::Safe(span) => return self.span.with_hi(span.hi()),
Safety::Default => {}
};
if let Some(coroutine_kind) = self.header.coroutine_kind {
return self.span.with_hi(coroutine_kind.span().hi());
}
if let Const::Yes(span) = self.header.constness {
return self.span.with_hi(span.hi());
}
self.span.shrink_to_lo()
}
/// The span of the header's safety, or where to insert it if empty.
pub fn safety_span(&self) -> Span {
match self.header.safety {
Safety::Unsafe(span) | Safety::Safe(span) => span,
Safety::Default => {
// Insert after the `coroutine_kind` if available.
if let Some(extern_span) = self.header.ext.span() {
return extern_span.shrink_to_lo();
}
// Insert right at the front of the signature.
self.header_span().shrink_to_hi()
}
}
}
/// The span of the header's extern, or where to insert it if empty.
pub fn extern_span(&self) -> Span {
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
}
}
/// A constraint on an associated item.
///
/// ### Examples
@ -3526,6 +3574,13 @@ impl Extern {
None => Extern::Implicit(span),
}
}
pub fn span(self) -> Option<Span> {
match self {
Extern::None => None,
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
}
}
}
/// A function header.
@ -3534,12 +3589,12 @@ impl Extern {
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub struct FnHeader {
/// Whether this is `unsafe`, or has a default safety.
pub safety: Safety,
/// Whether this is `async`, `gen`, or nothing.
pub coroutine_kind: Option<CoroutineKind>,
/// The `const` keyword, if any
pub constness: Const,
/// Whether this is `async`, `gen`, or nothing.
pub coroutine_kind: Option<CoroutineKind>,
/// Whether this is `unsafe`, or has a default safety.
pub safety: Safety,
/// The `extern` keyword and corresponding ABI string, if any.
pub ext: Extern,
}
@ -3553,38 +3608,6 @@ impl FnHeader {
|| matches!(constness, Const::Yes(_))
|| !matches!(ext, Extern::None)
}
/// Return a span encompassing the header, or none if all options are default.
pub fn span(&self) -> Option<Span> {
fn append(a: &mut Option<Span>, b: Span) {
*a = match a {
None => Some(b),
Some(x) => Some(x.to(b)),
}
}
let mut full_span = None;
match self.safety {
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
Safety::Default => {}
};
if let Some(coroutine_kind) = self.coroutine_kind {
append(&mut full_span, coroutine_kind.span());
}
if let Const::Yes(span) = self.constness {
append(&mut full_span, span);
}
match self.ext {
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
Extern::None => {}
}
full_span
}
}
impl Default for FnHeader {

View file

@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
.label = {ast_passes_auto_super_lifetime}
.suggestion = remove the super traits or lifetime bounds
ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
.cannot_have = cannot have a body
.invalid = the invalid body
@ -66,6 +64,19 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
.label = `extern "{$abi}"` because of this
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
ast_passes_c_variadic_must_be_unsafe =
functions with a C variable argument list must be unsafe
.suggestion = add the `unsafe` keyword to this definition
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
.const = `const` because of this
.variadic = C-variadic because of this
@ -84,6 +95,10 @@ ast_passes_const_without_body =
ast_passes_constraint_on_negative_bound =
associated type constraints not allowed on negative bounds
ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic
.const = `{$coroutine_kind}` because of this
.variadic = C-variadic because of this
ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
.label = not supported
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax

View file

@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> {
}
if !spans.is_empty() {
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo());
let header_span = sig.header_span();
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
let padding = if header_span.is_empty() { "" } else { " " };
@ -685,22 +685,53 @@ impl<'a> AstValidator<'a> {
});
}
if let Some(coroutine_kind) = sig.header.coroutine_kind {
self.dcx().emit_err(errors::CoroutineAndCVariadic {
spans: vec![coroutine_kind.span(), variadic_param.span],
coroutine_kind: coroutine_kind.as_str(),
coroutine_span: coroutine_kind.span(),
variadic_span: variadic_param.span,
});
}
match fn_ctxt {
FnCtxt::Foreign => return,
FnCtxt::Free => match sig.header.ext {
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
| Extern::Implicit(_)
if matches!(sig.header.safety, Safety::Unsafe(_)) =>
{
return;
Extern::Implicit(_) => {
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
}
}
_ => {}
},
FnCtxt::Assoc(_) => {}
};
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
self.dcx().emit_err(errors::CVariadicBadExtern {
span: variadic_param.span,
abi: symbol_unescaped,
extern_span: sig.extern_span(),
});
}
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
}
}
Extern::None => {
let err = errors::CVariadicNoExtern { span: variadic_param.span };
self.dcx().emit_err(err);
}
},
FnCtxt::Assoc(_) => {
// For now, C variable argument lists are unsupported in associated functions.
let err = errors::CVariadicAssociatedFunction { span: variadic_param.span };
self.dcx().emit_err(err);
}
}
}
fn check_item_named(&self, ident: Ident, kind: &str) {

View file

@ -319,12 +319,46 @@ pub(crate) struct ExternItemAscii {
}
#[derive(Diagnostic)]
#[diag(ast_passes_bad_c_variadic)]
pub(crate) struct BadCVariadic {
#[diag(ast_passes_c_variadic_associated_function)]
pub(crate) struct CVariadicAssociatedFunction {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_no_extern)]
#[help]
pub(crate) struct CVariadicNoExtern {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_must_be_unsafe)]
pub(crate) struct CVariadicMustBeUnsafe {
#[primary_span]
pub span: Span,
#[suggestion(
ast_passes_suggestion,
applicability = "maybe-incorrect",
code = "unsafe ",
style = "verbose"
)]
pub unsafe_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_bad_extern)]
#[help]
pub(crate) struct CVariadicBadExtern {
#[primary_span]
pub span: Span,
pub abi: Symbol,
#[label]
pub extern_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_item_underscore)]
pub(crate) struct ItemUnderscore<'a> {
@ -659,6 +693,18 @@ pub(crate) struct ConstAndCVariadic {
pub variadic_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_coroutine_and_c_variadic)]
pub(crate) struct CoroutineAndCVariadic {
#[primary_span]
pub spans: Vec<Span>,
pub coroutine_kind: &'static str,
#[label(ast_passes_const)]
pub coroutine_span: Span,
#[label(ast_passes_variadic)]
pub variadic_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)

View file

@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self ,
//~| ERROR unexpected `self` parameter in function
//~| ERROR unexpected `self` parameter in function
//~| ERROR `...` must be the last argument of a C-variadic function
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~| ERROR `...` is not supported for non-extern functions
//~| ERROR cannot find type `F` in this scope
}

View file

@ -46,11 +46,13 @@ error: `...` must be the last argument of a C-variadic function
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
error: `...` is not supported for non-extern functions
--> $DIR/issue-86053-1.rs:11:36
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error[E0412]: cannot find type `F` in this scope
--> $DIR/issue-86053-1.rs:11:48

View file

@ -0,0 +1,7 @@
//@ edition: 2021
#![feature(c_variadic)]
#![crate_type = "lib"]
async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
//~^ ERROR functions cannot be both `async` and C-variadic
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds

View file

@ -0,0 +1,19 @@
error: functions cannot be both `async` and C-variadic
--> $DIR/not-async.rs:5:1
|
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
| ^^^^^ `async` because of this ^^^ C-variadic because of this
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
--> $DIR/not-async.rs:5:59
|
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
| --------------------------------------------------------- ^^
| |
| opaque type defined here
|
= note: hidden type `{async fn body of cannot_be_async()}` captures lifetime `'_`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0700`.

View file

@ -53,9 +53,7 @@ extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait {
x
}
extern "cmse-nonsecure-entry" fn static_trait_object(
x: &'static dyn Trait,
) -> &'static dyn Trait {
extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x
}
@ -63,14 +61,12 @@ extern "cmse-nonsecure-entry" fn static_trait_object(
#[repr(transparent)]
struct WrapperTransparent<'a>(&'a dyn Trait);
extern "cmse-nonsecure-entry" fn wrapped_trait_object(
x: WrapperTransparent,
) -> WrapperTransparent {
extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x
}
extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
//~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions
//~| ERROR requires `va_list` lang_item
}

View file

@ -1,8 +1,12 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/generics.rs:73:53
error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions
--> $DIR/generics.rs:69:60
|
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^
LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ----------------------------- ^^^^^^
| |
| `extern "cmse-nonsecure-entry"` because of this
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:30:1
@ -50,28 +54,28 @@ LL | extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:58:6
--> $DIR/generics.rs:56:80
|
LL | ) -> &'static dyn Trait {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
LL | extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:68:6
--> $DIR/generics.rs:64:81
|
LL | ) -> WrapperTransparent {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
LL | extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error: requires `va_list` lang_item
--> $DIR/generics.rs:73:53
--> $DIR/generics.rs:69:60
|
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^
LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^
error: aborting due to 9 previous errors

View file

@ -1,10 +1,10 @@
#![crate_type="lib"]
#![crate_type = "lib"]
pub unsafe extern "C" fn test(_: i32, ap: ...) { }
pub unsafe extern "C" fn test(_: i32, ap: ...) {}
//~^ ERROR C-variadic functions are unstable
trait Trait {
unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
//~^ ERROR C-variadic functions are unstable
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~| ERROR associated functions cannot have a C variable argument list
}

View file

@ -1,14 +1,14 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
error: associated functions cannot have a C variable argument list
--> $DIR/feature-gate-c_variadic.rs:7:45
|
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
| ^^^^^^^
error[E0658]: C-variadic functions are unstable
--> $DIR/feature-gate-c_variadic.rs:3:1
|
LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
@ -17,8 +17,8 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
error[E0658]: C-variadic functions are unstable
--> $DIR/feature-gate-c_variadic.rs:7:5
|
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
= help: add `#![feature(c_variadic)]` to the crate attributes to enable

View file

@ -3,6 +3,7 @@
#![feature(c_variadic)]
async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
//~^ ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
//~^ ERROR functions cannot be both `async` and C-variadic
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
fn main() {}

View file

@ -1,3 +1,9 @@
error: functions cannot be both `async` and C-variadic
--> $DIR/note-and-explain-ReVar-124973.rs:5:1
|
LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
| ^^^^^ `async` because of this ^^^ C-variadic because of this
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
--> $DIR/note-and-explain-ReVar-124973.rs:5:73
|
@ -8,6 +14,6 @@ LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
|
= note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0700`.

View file

@ -4,7 +4,6 @@
fn main() {}
fn foo(_: Bar, ...) -> impl {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~| ERROR cannot find type `Bar` in this scope
unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
//~^ ERROR cannot find type `Bar` in this scope
//~| ERROR at least one trait must be specified

View file

@ -1,21 +1,15 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
|
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:42
|
LL | fn foo(_: Bar, ...) -> impl {}
| ^^^^
LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
| ^^^^
error[E0412]: cannot find type `Bar` in this scope
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:11
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:29
|
LL | fn foo(_: Bar, ...) -> impl {}
| ^^^ not found in this scope
LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
| ^^^ not found in this scope
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0412`.

View file

@ -4,25 +4,28 @@
fn main() {}
fn f1_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR `...` is not supported for non-extern functions
fn f1_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR `...` is not supported for non-extern functions
unsafe extern "Rust" fn f1_3(...) {}
//~^ ERROR `...` is not supported for `extern "Rust"` functions
extern "C" fn f2_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f2_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f2_3(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function
extern "C" fn f3_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f3_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f3_3(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function
@ -33,12 +36,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {}
const extern "C" fn f4_2(x: isize, ...) {}
//~^ ERROR functions cannot be both `const` and C-variadic
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~| ERROR functions with a C variable argument list must be unsafe
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
const extern "C" fn f4_3(..., x: isize, ...) {}
//~^ ERROR functions cannot be both `const` and C-variadic
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~| ERROR functions with a C variable argument list must be unsafe
//~| ERROR `...` must be the last argument of a C-variadic function
extern "C" {
@ -50,30 +53,30 @@ struct X;
impl X {
fn i_f1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn i_f2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn i_f3(..., x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
//~| ERROR `...` must be the last argument of a C-variadic function
fn i_f4(..., x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
//~| ERROR `...` must be the last argument of a C-variadic function
const fn i_f5(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
//~| 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, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn t_f2(x: isize, ...);
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn t_f3(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn t_f4(...);
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
//~^ ERROR associated functions cannot have a C variable argument list
fn t_f5(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function
fn t_f6(..., x: isize);

View file

@ -1,181 +1,225 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
error: `...` is not supported for non-extern functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
|
LL | fn f1_1(x: isize, ...) {}
| ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
error: `...` is not supported for non-extern functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
|
LL | fn f1_2(...) {}
| ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
error: `...` is not supported for `extern "Rust"` functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
LL | unsafe extern "Rust" fn f1_3(...) {}
| ------------- ^^^
| |
| `extern "Rust"` because of this
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:30
|
LL | extern "C" fn f2_1(x: isize, ...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f2_1(x: isize, ...) {}
| ++++++
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
LL | extern "C" fn f2_2(...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f2_2(...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:20
|
LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
|
LL | extern "C" fn f3_1(x: isize, ...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f3_1(x: isize, ...) {}
| ++++++
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
LL | extern "C" fn f3_2(...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f3_2(...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
|
LL | extern "C" fn f3_3(..., x: isize) {}
| ^^^
error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:1
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
|
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:34:1
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:1
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^^^ `const` because of this ^^^ C-variadic because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | const unsafe extern "C" fn f4_2(x: isize, ...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:26
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^
error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:1
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^^^ `const` because of this ^^^ C-variadic because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:41
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | const unsafe extern "C" fn f4_3(..., x: isize, ...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
|
LL | fn e_f2(..., x: isize);
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:52:23
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
|
LL | fn i_f1(x: isize, ...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
|
LL | fn i_f2(...) {}
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:13
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:28
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^
error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:5
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
|
LL | const fn i_f5(x: isize, ...) {}
| ^^^^^ ^^^ C-variadic because of this
| |
| `const` because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
LL | const fn i_f5(x: isize, ...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:23
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
|
LL | fn t_f1(x: isize, ...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:23
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
|
LL | fn t_f2(x: isize, ...);
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
|
LL | fn t_f3(...) {}
| ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/variadic-ffi-semantic-restrictions.rs:75:13
error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
|
LL | fn t_f4(...);
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:77:13
--> $DIR/variadic-ffi-semantic-restrictions.rs:80:13
|
LL | fn t_f5(..., x: isize) {}
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:79:13
--> $DIR/variadic-ffi-semantic-restrictions.rs:82:13
|
LL | fn t_f6(..., x: isize);
| ^^^
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:43
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:43
|
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
| ^^^ - value is dropped here
@ -183,7 +227,7 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
| 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:34:36
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^ - value is dropped here
@ -191,13 +235,13 @@ LL | const extern "C" fn f4_2(x: isize, ...) {}
| 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:62:29
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
LL | const fn i_f5(x: isize, ...) {}
| ^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 32 previous errors
error: aborting due to 33 previous errors
For more information about this error, try `rustc --explain E0493`.