Skip to content

Commit c6732d4

Browse files
committed
Merge RFC 3722: Explicit ABIs in extern
The FCP for RFC 3722 completed on 2024-11-30 with a disposition to merge. Let's merge it.
2 parents aa49c76 + 958ba5b commit c6732d4

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

text/3722-explicit-extern-abis.md

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
- Feature Name: `explicit_extern_abis`
2+
- Start Date: 2024-10-30
3+
- RFC PR: [rust-lang/rfcs#3722](https://github.com/rust-lang/rfcs/pull/3722)
4+
- Tracking Issue: [rust-lang/rust#134986](https://github.com/rust-lang/rust/issues/134986)
5+
6+
# Summary
7+
8+
Disallow `extern` without an explicit ABI in a new edition. Write `extern "C"` (or another ABI) instead of just `extern`.
9+
10+
```diff
11+
- extern { … }
12+
+ extern "C" { … }
13+
14+
- extern fn foo() { … }
15+
+ extern "C" fn foo() { … }
16+
```
17+
18+
# Motivation
19+
20+
Originally, `"C"` was a very reasable default for `extern`.
21+
However, with work ongoing to add other ABIs to Rust, it is no longer obvious that `"C"` should forever stay the default.
22+
23+
By making the ABI explicit, it becomes much clearer that `"C"` is just one of the possible choices, rather than the "standard" way for external functions.
24+
Removing the default makes it easier to add a new ABI on equal footing as `"C"`.
25+
26+
Right now, "extern", "FFI" and "C" are somewhat used interchangeably in Rust. For example, this is the diagnostic when using a `String` in an `extern` function:
27+
28+
```
29+
warning: `extern` fn uses type `String`, which is not FFI-safe
30+
--> src/main.rs:1:16
31+
|
32+
1 | extern fn a(s: String) {}
33+
| ^^^^^^ not FFI-safe
34+
|
35+
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
36+
= note: this struct has unspecified layout
37+
= note: `#[warn(improper_ctypes_definitions)]` on by default
38+
```
39+
40+
If another future ABI will support `String`, this error should make it clearer that the problem is not that `String` doesn't support FFI, but rather that the `"C"` ABI doesn't support `String`.
41+
This would be easier if there was actually a `"C"` token to point at in the source code. E.g.:
42+
43+
```
44+
warning: `extern` fn uses type `String`, which is not supported by the "C" ABI
45+
--> src/main.rs:1:16
46+
|
47+
1 | extern "C" fn a(s: String) {}
48+
| --- ^^^^^^ String type not supported by this ABI
49+
| |
50+
| the "C" ABI does not support this type
51+
```
52+
53+
It would also make it clearer that swapping `"C"` for another ABI might be an option.
54+
55+
# Guilde-level explanation
56+
57+
Up to the previous edition, `extern` without an explicit ABI was equivalent to `extern "C"`.
58+
In the new edition, writing `extern` without an ABI is an error.
59+
Instead, you must write `extern "C"` explicitly.
60+
61+
# Automatic migration
62+
63+
Automatic migration (for `cargo fix --edition`) is trivial: Insert `"C"` after `extern` if there is no ABI.
64+
65+
# Drawbacks
66+
67+
- This is a breaking change and needs to be done in a new edition.
68+
69+
# Prior art
70+
71+
This was proposed before Rust 1.0 in 2015 in [RFC 697](https://github.com/rust-lang/rfcs/pull/697).
72+
It was not accepted at the time, because "C" seemed like the only resonable default.
73+
It was later closed because it'd be a backwards incompatible change, and editions were not yet invented.
74+
75+
# Unresolved questions
76+
77+
- ~~In which edition do we make this change?~~
78+
- It's too late for the 2024 edition: https://github.com/rust-lang/rfcs/pull/3722#issuecomment-2447333966
79+
- ~~Do we warn about `extern` without an explicit ABI in previous editions?~~
80+
- Yes, with separate FCP: https://github.com/rust-lang/rfcs/pull/3722#issuecomment-2447719047
81+
82+
# Future possibilities
83+
84+
In the future, we might want to add a new default ABI.
85+
For example, if `extern "stable-rust-abi"` becomes a thing and e.g. dynamically linking Rust from Rust becomes very popular, it might make sense to make that the default when writing `extern fn` without an ABI.
86+
That is, however, a separate discussion; it might also be reasonable to never have a default ABI again.

0 commit comments

Comments
 (0)