Skip to content

Commit 4bb0c3d

Browse files
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`.
1 parent ef148cd commit 4bb0c3d

File tree

13 files changed

+63
-53
lines changed

13 files changed

+63
-53
lines changed

Diff for: compiler/rustc_abi/src/extern_abi.rs

-2
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ impl ExternAbi {
195195
// * C and Cdecl obviously support varargs.
196196
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
197197
// * EfiApi is based on Win64 or C, so it also supports it.
198-
// * System falls back to C for functions with varargs.
199198
//
200199
// * Stdcall does not, because it would be impossible for the callee to clean
201200
// up the arguments. (callee doesn't know how many arguments are there)
@@ -204,7 +203,6 @@ impl ExternAbi {
204203
match self {
205204
Self::C { .. }
206205
| Self::Cdecl { .. }
207-
| Self::System { .. }
208206
| Self::Aapcs { .. }
209207
| Self::Win64 { .. }
210208
| Self::SysV64 { .. }

Diff for: compiler/rustc_feature/src/unstable.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,11 @@ declare_features! (
487487
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
488488
/// Allows explicit tail calls via `become` expression.
489489
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
490-
/// Allows using `efiapi`, `sysv64` and `win64` as calling convention
490+
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
491491
/// for functions with varargs.
492492
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
493+
/// Allows using `system` as a calling convention with varargs.
494+
(unstable, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
493495
/// Allows defining `extern type`s.
494496
(unstable, extern_types, "1.23.0", Some(43467)),
495497
/// Allow using 128-bit (quad precision) floating point numbers.

Diff for: compiler/rustc_hir_analysis/src/lib.rs

+28-14
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,42 @@ fn require_c_abi_if_c_variadic(
122122
const UNSTABLE_EXPLAIN: &str =
123123
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
124124

125+
// ABIs which can stably use varargs
125126
if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
126127
return;
127128
}
128129

130+
// ABIs with feature-gated stability
129131
let extended_abi_support = tcx.features().extended_varargs_abi_support();
130-
let conventions = match (extended_abi_support, abi.supports_varargs()) {
131-
// User enabled additional ABI support for varargs and function ABI matches those ones.
132-
(true, true) => return,
132+
let extern_system_varargs = tcx.features().extern_system_varargs();
133133

134-
// Using this ABI would be ok, if the feature for additional ABI support was enabled.
135-
// Return CONVENTIONS_STABLE, because we want the other error to look the same.
136-
(false, true) => {
137-
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
138-
.emit();
139-
CONVENTIONS_STABLE
140-
}
141-
142-
(false, false) => CONVENTIONS_STABLE,
143-
(true, false) => CONVENTIONS_UNSTABLE,
134+
// If the feature gate has been enabled, we can stop here
135+
if extern_system_varargs && let ExternAbi::System { .. } = abi {
136+
return;
137+
};
138+
if extended_abi_support && abi.supports_varargs() {
139+
return;
144140
};
145141

146-
tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
142+
// Looks like we need to pick an error to emit.
143+
// Is there any feature which we could have enabled to make this work?
144+
match abi {
145+
ExternAbi::System { .. } => {
146+
feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
147+
}
148+
abi if abi.supports_varargs() => {
149+
feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
150+
}
151+
_ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
152+
span,
153+
conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
154+
CONVENTIONS_UNSTABLE
155+
} else {
156+
CONVENTIONS_STABLE
157+
},
158+
}),
159+
}
160+
.emit();
147161
}
148162

149163
pub fn provide(providers: &mut Providers) {

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ symbols! {
879879
extern_crate_self,
880880
extern_in_paths,
881881
extern_prelude,
882+
extern_system_varargs,
882883
extern_types,
883884
external,
884885
external_doc,

Diff for: tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
//@ only-x86_64
22

33
fn efiapi(f: extern "efiapi" fn(usize, ...)) {
4-
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
5-
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
4+
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
65
f(22, 44);
76
}
87
fn sysv(f: extern "sysv64" fn(usize, ...)) {
9-
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
10-
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
8+
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
119
f(22, 44);
1210
}
1311
fn win(f: extern "win64" fn(usize, ...)) {
14-
//~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
15-
//~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
12+
//~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
1613
f(22, 44);
1714
}
1815

Diff for: tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr

+4-23
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,8 @@ LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
88
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

11-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
12-
--> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14
13-
|
14-
LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
15-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
16-
1711
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
18-
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
12+
--> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12
1913
|
2014
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
2115
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,14 +18,8 @@ LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
2418
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
2519
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2620

27-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
28-
--> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
29-
|
30-
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
32-
3321
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
34-
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
22+
--> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11
3523
|
3624
LL | fn win(f: extern "win64" fn(usize, ...)) {
3725
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,13 +28,6 @@ LL | fn win(f: extern "win64" fn(usize, ...)) {
4028
= help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
4129
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4230

43-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
44-
--> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
45-
|
46-
LL | fn win(f: extern "win64" fn(usize, ...)) {
47-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
48-
49-
error: aborting due to 6 previous errors
31+
error: aborting due to 3 previous errors
5032

51-
Some errors have detailed explanations: E0045, E0658.
52-
For more information about an error, try `rustc --explain E0045`.
33+
For more information about this error, try `rustc --explain E0658`.

Diff for: tests/ui/c-variadic/variadic-ffi-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
1+
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
22
--> $DIR/variadic-ffi-1.rs:9:5
33
|
44
LL | fn printf(_: *const u8, ...);

Diff for: tests/ui/c-variadic/variadic-ffi-2.rs

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ fn baz(f: extern "stdcall" fn(usize, ...)) {
88
f(22, 44);
99
}
1010

11-
fn system(f: extern "system" fn(usize, ...)) {
12-
f(22, 44);
13-
}
1411
#[cfg(target_arch = "x86_64")]
1512
fn sysv(f: extern "sysv64" fn(usize, ...)) {
1613
f(22, 44);

Diff for: tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ type WithTransparentTraitObject =
3939
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
4040

4141
type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
42-
//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]
42+
//~^ ERROR C-variadic function must have a compatible calling convention, like `C`

Diff for: tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa
6969
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
7070
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
7171

72-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
72+
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
7373
--> $DIR/generics.rs:41:20
7474
|
7575
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);

Diff for: tests/ui/error-codes/E0045.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
1+
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
22
--> $DIR/E0045.rs:1:17
33
|
44
LL | extern "Rust" { fn foo(x: u8, ...); }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn system(f: extern "system" fn(usize, ...)) {
2+
//~^ ERROR using calling conventions other than `C` or `cdecl` for varargs functions is unstable
3+
4+
f(22, 44);
5+
}
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable
2+
--> $DIR/feature-gate-extern_system_varargs.rs:1:14
3+
|
4+
LL | fn system(f: extern "system" fn(usize, ...)) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #136946 <https://github.com/rust-lang/rust/issues/136946> for more information
8+
= help: add `#![feature(extern_system_varargs)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)