Rollup merge of #136948 - workingjubilee:split-off-extern-system-varargs, r=compiler-errors
Split out the `extern_system_varargs` feature After the stabilization PR was opened, `extern "system"` functions were added to `extended_varargs_abi_support`. This has a number of questions regarding it that were not discussed and were somewhat surprising. It deserves to be considered as its own feature, separate from `extended_varargs_abi_support`. Tracking issue: - https://github.com/rust-lang/rust/issues/136946
This commit is contained in:
commit
36d37966df
13 changed files with 63 additions and 53 deletions
|
@ -195,7 +195,6 @@ impl ExternAbi {
|
||||||
// * C and Cdecl obviously support varargs.
|
// * C and Cdecl obviously support varargs.
|
||||||
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
|
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
|
||||||
// * EfiApi is based on Win64 or C, so it also supports it.
|
// * EfiApi is based on Win64 or C, so it also supports it.
|
||||||
// * System falls back to C for functions with varargs.
|
|
||||||
//
|
//
|
||||||
// * Stdcall does not, because it would be impossible for the callee to clean
|
// * Stdcall does not, because it would be impossible for the callee to clean
|
||||||
// up the arguments. (callee doesn't know how many arguments are there)
|
// up the arguments. (callee doesn't know how many arguments are there)
|
||||||
|
@ -204,7 +203,6 @@ impl ExternAbi {
|
||||||
match self {
|
match self {
|
||||||
Self::C { .. }
|
Self::C { .. }
|
||||||
| Self::Cdecl { .. }
|
| Self::Cdecl { .. }
|
||||||
| Self::System { .. }
|
|
||||||
| Self::Aapcs { .. }
|
| Self::Aapcs { .. }
|
||||||
| Self::Win64 { .. }
|
| Self::Win64 { .. }
|
||||||
| Self::SysV64 { .. }
|
| Self::SysV64 { .. }
|
||||||
|
|
|
@ -487,9 +487,11 @@ declare_features! (
|
||||||
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
|
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
|
||||||
/// Allows explicit tail calls via `become` expression.
|
/// Allows explicit tail calls via `become` expression.
|
||||||
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
|
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
|
||||||
/// Allows using `efiapi`, `sysv64` and `win64` as calling convention
|
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
|
||||||
/// for functions with varargs.
|
/// for functions with varargs.
|
||||||
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
|
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
|
||||||
|
/// Allows using `system` as a calling convention with varargs.
|
||||||
|
(unstable, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
|
||||||
/// Allows defining `extern type`s.
|
/// Allows defining `extern type`s.
|
||||||
(unstable, extern_types, "1.23.0", Some(43467)),
|
(unstable, extern_types, "1.23.0", Some(43467)),
|
||||||
/// Allow using 128-bit (quad precision) floating point numbers.
|
/// Allow using 128-bit (quad precision) floating point numbers.
|
||||||
|
|
|
@ -122,28 +122,42 @@ fn require_c_abi_if_c_variadic(
|
||||||
const UNSTABLE_EXPLAIN: &str =
|
const UNSTABLE_EXPLAIN: &str =
|
||||||
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
|
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
|
||||||
|
|
||||||
|
// ABIs which can stably use varargs
|
||||||
if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
|
if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ABIs with feature-gated stability
|
||||||
let extended_abi_support = tcx.features().extended_varargs_abi_support();
|
let extended_abi_support = tcx.features().extended_varargs_abi_support();
|
||||||
let conventions = match (extended_abi_support, abi.supports_varargs()) {
|
let extern_system_varargs = tcx.features().extern_system_varargs();
|
||||||
// User enabled additional ABI support for varargs and function ABI matches those ones.
|
|
||||||
(true, true) => return,
|
|
||||||
|
|
||||||
// Using this ABI would be ok, if the feature for additional ABI support was enabled.
|
// If the feature gate has been enabled, we can stop here
|
||||||
// Return CONVENTIONS_STABLE, because we want the other error to look the same.
|
if extern_system_varargs && let ExternAbi::System { .. } = abi {
|
||||||
(false, true) => {
|
return;
|
||||||
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
|
};
|
||||||
.emit();
|
if extended_abi_support && abi.supports_varargs() {
|
||||||
CONVENTIONS_STABLE
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
(false, false) => CONVENTIONS_STABLE,
|
|
||||||
(true, false) => CONVENTIONS_UNSTABLE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
|
// Looks like we need to pick an error to emit.
|
||||||
|
// Is there any feature which we could have enabled to make this work?
|
||||||
|
match abi {
|
||||||
|
ExternAbi::System { .. } => {
|
||||||
|
feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
|
||||||
|
}
|
||||||
|
abi if abi.supports_varargs() => {
|
||||||
|
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
|
||||||
|
}
|
||||||
|
_ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
|
||||||
|
span,
|
||||||
|
conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
|
||||||
|
CONVENTIONS_UNSTABLE
|
||||||
|
} else {
|
||||||
|
CONVENTIONS_STABLE
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
|
|
|
@ -881,6 +881,7 @@ symbols! {
|
||||||
extern_crate_self,
|
extern_crate_self,
|
||||||
extern_in_paths,
|
extern_in_paths,
|
||||||
extern_prelude,
|
extern_prelude,
|
||||||
|
extern_system_varargs,
|
||||||
extern_types,
|
extern_types,
|
||||||
external,
|
external,
|
||||||
external_doc,
|
external_doc,
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
//@ only-x86_64
|
//@ only-x86_64
|
||||||
|
|
||||||
fn efiapi(f: extern "efiapi" fn(usize, ...)) {
|
fn efiapi(f: extern "efiapi" fn(usize, ...)) {
|
||||||
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
|
||||||
f(22, 44);
|
f(22, 44);
|
||||||
}
|
}
|
||||||
fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
||||||
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
|
||||||
f(22, 44);
|
f(22, 44);
|
||||||
}
|
}
|
||||||
fn win(f: extern "win64" fn(usize, ...)) {
|
fn win(f: extern "win64" fn(usize, ...)) {
|
||||||
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
|
||||||
f(22, 44);
|
f(22, 44);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,8 @@ LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
|
||||||
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
|
||||||
--> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14
|
|
||||||
|
|
|
||||||
LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
|
|
||||||
|
|
||||||
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
|
--> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12
|
||||||
|
|
|
|
||||||
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -24,14 +18,8 @@ LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
||||||
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
|
||||||
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
|
|
||||||
|
|
|
||||||
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
|
|
||||||
|
|
||||||
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
|
--> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11
|
||||||
|
|
|
|
||||||
LL | fn win(f: extern "win64" fn(usize, ...)) {
|
LL | fn win(f: extern "win64" fn(usize, ...)) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -40,13 +28,6 @@ LL | fn win(f: extern "win64" fn(usize, ...)) {
|
||||||
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
|
|
||||||
|
|
|
||||||
LL | fn win(f: extern "win64" fn(usize, ...)) {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0045, E0658.
|
|
||||||
For more information about an error, try `rustc --explain E0045`.
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
|
||||||
--> $DIR/variadic-ffi-1.rs:9:5
|
--> $DIR/variadic-ffi-1.rs:9:5
|
||||||
|
|
|
|
||||||
LL | fn printf(_: *const u8, ...);
|
LL | fn printf(_: *const u8, ...);
|
||||||
|
|
|
@ -8,9 +8,6 @@ fn baz(f: extern "stdcall" fn(usize, ...)) {
|
||||||
f(22, 44);
|
f(22, 44);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn system(f: extern "system" fn(usize, ...)) {
|
|
||||||
f(22, 44);
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
fn sysv(f: extern "sysv64" fn(usize, ...)) {
|
||||||
f(22, 44);
|
f(22, 44);
|
||||||
|
|
|
@ -39,4 +39,4 @@ type WithTransparentTraitObject =
|
||||||
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
|
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
|
||||||
|
|
||||||
type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
|
type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
|
||||||
//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]
|
//~^ ERROR C-variadic function must have a compatible calling convention, like `C`
|
||||||
|
|
|
@ -69,7 +69,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa
|
||||||
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
= note: functions with the `"C-cmse-nonsecure-call"` 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
|
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||||
|
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
|
||||||
--> $DIR/generics.rs:41:20
|
--> $DIR/generics.rs:41:20
|
||||||
|
|
|
|
||||||
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
|
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
|
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
|
||||||
--> $DIR/E0045.rs:1:17
|
--> $DIR/E0045.rs:1:17
|
||||||
|
|
|
|
||||||
LL | extern "Rust" { fn foo(x: u8, ...); }
|
LL | extern "Rust" { fn foo(x: u8, ...); }
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
fn system(f: extern "system" fn(usize, ...)) {
|
||||||
|
//~^ ERROR using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
|
|
||||||
|
f(22, 44);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,13 @@
|
||||||
|
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
|
||||||
|
--> $DIR/feature-gate-extern_system_varargs.rs:1:14
|
||||||
|
|
|
||||||
|
LL | fn system(f: extern "system" fn(usize, ...)) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #136946 <https://github.com/rust-lang/rust/issues/136946> for more information
|
||||||
|
= help: add `#![feature(extern_system_varargs)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Add table
Add a link
Reference in a new issue