diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-09-10 20:29:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 20:29:10 +0200 |
| commit | bb45ea3accf536e0915991c5d9120bab8a87541e (patch) | |
| tree | 301e5c15dcb2f6f64faf288a1fe2a1db1eaac790 | |
| parent | 86d39a06734cae9492d83498aac9bbdf3aa20508 (diff) | |
| parent | 9196844f0d86242ee3d6a446fe681b6b2d2d674c (diff) | |
| download | rust-bb45ea3accf536e0915991c5d9120bab8a87541e.tar.gz rust-bb45ea3accf536e0915991c5d9120bab8a87541e.zip | |
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
18 files changed, 357 insertions, 167 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 802a6fa3249..3e8fddd9954 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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 { diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index e5f1fcdc4b4..8dcf3e3aa38 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -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 diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 538918a890d..a6ef89b553d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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) { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 476ed27a10e..ae805042c54 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -319,13 +319,47 @@ 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> { #[primary_span] @@ -660,6 +694,18 @@ pub(crate) struct ConstAndCVariadic { } #[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`) pub(crate) struct PatternInForeign { diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index 537d0263adf..58dfee55cf8 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -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 } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index b58016b5a81..adbc04d3a65 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -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 diff --git a/tests/ui/c-variadic/not-async.rs b/tests/ui/c-variadic/not-async.rs new file mode 100644 index 00000000000..45a7e1f8972 --- /dev/null +++ b/tests/ui/c-variadic/not-async.rs @@ -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 diff --git a/tests/ui/c-variadic/not-async.stderr b/tests/ui/c-variadic/not-async.stderr new file mode 100644 index 00000000000..b8caf0d8bd8 --- /dev/null +++ b/tests/ui/c-variadic/not-async.stderr @@ -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`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs index ad4fca8252d..eb6f4a32365 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -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 } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr index 7aeb6969feb..8937def9428 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -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 diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs index 45c68842093..88d91dbd081 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.rs +++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs @@ -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 } diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr index e30a2f1ede3..808aa20948d 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr @@ -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 diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.rs b/tests/ui/inference/note-and-explain-ReVar-124973.rs index f1e24645636..aa4b909fa76 100644 --- a/tests/ui/inference/note-and-explain-ReVar-124973.rs +++ b/tests/ui/inference/note-and-explain-ReVar-124973.rs @@ -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() {} diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.stderr b/tests/ui/inference/note-and-explain-ReVar-124973.stderr index 574f6508e4c..964fbc4a4fb 100644 --- a/tests/ui/inference/note-and-explain-ReVar-124973.stderr +++ b/tests/ui/inference/note-and-explain-ReVar-124973.stderr @@ -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`. 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 9277994d9b3..dc0d14bf9d6 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,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 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 4a1aa49eb6e..31a393e7367 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -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`. diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index 243924e6c53..4db056f15a5 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -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); diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index 5c55cc38b56..0cd78318de6 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -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`. |
