Skip to content

Commit bb3e156

Browse files
authored
Rollup merge of rust-lang#135340 - obeis:explicit-extern-abis, r=traviscross,nadrieril
Add `explicit_extern_abis` Feature and Enforce Explicit ABIs The unstable `explicit_extern_abis` feature is introduced, requiring explicit ABIs in `extern` blocks. Hard errors will be enforced with this feature enabled in a future edition. RFC rust-lang/rfcs#3722 Update rust-lang#134986
2 parents 78f2104 + d17c04e commit bb3e156

27 files changed

+334
-21
lines changed

Diff for: compiler/rustc_ast_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$de
7979
.suggestion = remove the {$remove_descr}
8080
.label = `extern` block begins here
8181
82+
ast_passes_extern_without_abi = `extern` declarations without an explicit ABI are disallowed
83+
.suggestion = specify an ABI
84+
.help = prior to Rust 2024, a default ABI was inferred
85+
8286
ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
8387
.suggestion = remove the attribute
8488
.stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ impl<'a> AstValidator<'a> {
684684
self.dcx().emit_err(errors::PatternFnPointer { span });
685685
});
686686
if let Extern::Implicit(extern_span) = bfty.ext {
687-
self.maybe_lint_missing_abi(extern_span, ty.id);
687+
self.handle_missing_abi(extern_span, ty.id);
688688
}
689689
}
690690
TyKind::TraitObject(bounds, ..) => {
@@ -717,10 +717,12 @@ impl<'a> AstValidator<'a> {
717717
}
718718
}
719719

720-
fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) {
720+
fn handle_missing_abi(&mut self, span: Span, id: NodeId) {
721721
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
722722
// call site which do not have a macro backtrace. See #61963.
723-
if self
723+
if span.edition().at_least_edition_future() && self.features.explicit_extern_abis() {
724+
self.dcx().emit_err(errors::MissingAbi { span });
725+
} else if self
724726
.sess
725727
.source_map()
726728
.span_to_snippet(span)
@@ -996,7 +998,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
996998
}
997999

9981000
if abi.is_none() {
999-
self.maybe_lint_missing_abi(*extern_span, item.id);
1001+
self.handle_missing_abi(*extern_span, item.id);
10001002
}
10011003
self.with_in_extern_mod(*safety, |this| {
10021004
visit::walk_item(this, item);
@@ -1370,7 +1372,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13701372
},
13711373
) = fk
13721374
{
1373-
self.maybe_lint_missing_abi(*extern_span, id);
1375+
self.handle_missing_abi(*extern_span, id);
13741376
}
13751377

13761378
// Functions without bodies cannot have patterns.

Diff for: compiler/rustc_ast_passes/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -823,3 +823,12 @@ pub(crate) struct DuplicatePreciseCapturing {
823823
#[label]
824824
pub bound2: Span,
825825
}
826+
827+
#[derive(Diagnostic)]
828+
#[diag(ast_passes_extern_without_abi)]
829+
#[help]
830+
pub(crate) struct MissingAbi {
831+
#[primary_span]
832+
#[suggestion(code = "extern \"<abi>\"", applicability = "has-placeholders")]
833+
pub span: Span,
834+
}

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

+2
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ declare_features! (
477477
(incomplete, ergonomic_clones, "1.87.0", Some(132290)),
478478
/// Allows exhaustive pattern matching on types that contain uninhabited types.
479479
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
480+
/// Disallows `extern` without an explicit ABI.
481+
(unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)),
480482
/// Allows explicit tail calls via `become` expression.
481483
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
482484
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions

Diff for: compiler/rustc_lint/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ lint_expectation = this lint expectation is unfulfilled
271271
lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition
272272
.suggestion = convert it to a `use`
273273
274-
lint_extern_without_abi = extern declarations without an explicit ABI are deprecated
274+
lint_extern_without_abi = `extern` declarations without an explicit ABI are deprecated
275275
.label = ABI should be specified here
276276
.suggestion = explicitly specify the {$default_abi} ABI
277277

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

+1
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,7 @@ symbols! {
916916
expf16,
917917
expf32,
918918
expf64,
919+
explicit_extern_abis,
919920
explicit_generic_args_with_impl_trait,
920921
explicit_tail_calls,
921922
export_name,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# `explicit_extern_abis`
2+
3+
The tracking issue for this feature is: #134986
4+
5+
------
6+
7+
Disallow `extern` without an explicit ABI. We should write `extern "C"`
8+
(or another ABI) instead of just `extern`.
9+
10+
By making the ABI explicit, it becomes much clearer that "C" is just one of the
11+
possible choices, rather than the "standard" way for external functions.
12+
Removing the default makes it easier to add a new ABI on equal footing as "C".
13+
14+
```rust,editionfuture,compile_fail
15+
#![feature(explicit_extern_abis)]
16+
17+
extern fn function1() {} // ERROR `extern` declarations without an explicit ABI
18+
// are disallowed
19+
20+
extern "C" fn function2() {} // compiles
21+
22+
extern "aapcs" fn function3() {} // compiles
23+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// The purpose of this feature gate is to make something into a hard error in a
2+
// future edition. Consequently, this test differs from most other feature gate
3+
// tests. Instead of verifying that an error occurs when the feature gate is
4+
// missing, it ensures that the hard error is only produced with the feature
5+
// gate is present in the `future` edition -- and otherwise that only a warning
6+
// is emitted.
7+
8+
//@ revisions: current current_feature future future_feature
9+
10+
//@ [current] run-rustfix
11+
//@ [current] check-pass
12+
13+
//@ [current_feature] run-rustfix
14+
//@ [current_feature] check-pass
15+
16+
//@ [future] edition: future
17+
//@ [future] compile-flags: -Z unstable-options
18+
//@ [future] run-rustfix
19+
//@ [future] check-pass
20+
21+
//@ [future_feature] edition: future
22+
//@ [future_feature] compile-flags: -Z unstable-options
23+
24+
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25+
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
26+
27+
extern "C" fn _foo() {}
28+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
29+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
30+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
31+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
32+
33+
unsafe extern "C" fn _bar() {}
34+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
35+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
36+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
37+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
38+
39+
unsafe extern "C" {}
40+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
41+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
42+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
43+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
44+
45+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
warning: `extern` declarations without an explicit ABI are deprecated
2+
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
3+
|
4+
LL | extern fn _foo() {}
5+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
6+
|
7+
= note: `#[warn(missing_abi)]` on by default
8+
9+
warning: `extern` declarations without an explicit ABI are deprecated
10+
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
11+
|
12+
LL | unsafe extern fn _bar() {}
13+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
14+
15+
warning: `extern` declarations without an explicit ABI are deprecated
16+
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
17+
|
18+
LL | unsafe extern {}
19+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
20+
21+
warning: 3 warnings emitted
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// The purpose of this feature gate is to make something into a hard error in a
2+
// future edition. Consequently, this test differs from most other feature gate
3+
// tests. Instead of verifying that an error occurs when the feature gate is
4+
// missing, it ensures that the hard error is only produced with the feature
5+
// gate is present in the `future` edition -- and otherwise that only a warning
6+
// is emitted.
7+
8+
//@ revisions: current current_feature future future_feature
9+
10+
//@ [current] run-rustfix
11+
//@ [current] check-pass
12+
13+
//@ [current_feature] run-rustfix
14+
//@ [current_feature] check-pass
15+
16+
//@ [future] edition: future
17+
//@ [future] compile-flags: -Z unstable-options
18+
//@ [future] run-rustfix
19+
//@ [future] check-pass
20+
21+
//@ [future_feature] edition: future
22+
//@ [future_feature] compile-flags: -Z unstable-options
23+
24+
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25+
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
26+
27+
extern "C" fn _foo() {}
28+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
29+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
30+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
31+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
32+
33+
unsafe extern "C" fn _bar() {}
34+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
35+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
36+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
37+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
38+
39+
unsafe extern "C" {}
40+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
41+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
42+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
43+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
44+
45+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
warning: `extern` declarations without an explicit ABI are deprecated
2+
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
3+
|
4+
LL | extern fn _foo() {}
5+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
6+
|
7+
= note: `#[warn(missing_abi)]` on by default
8+
9+
warning: `extern` declarations without an explicit ABI are deprecated
10+
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
11+
|
12+
LL | unsafe extern fn _bar() {}
13+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
14+
15+
warning: `extern` declarations without an explicit ABI are deprecated
16+
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
17+
|
18+
LL | unsafe extern {}
19+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
20+
21+
warning: 3 warnings emitted
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// The purpose of this feature gate is to make something into a hard error in a
2+
// future edition. Consequently, this test differs from most other feature gate
3+
// tests. Instead of verifying that an error occurs when the feature gate is
4+
// missing, it ensures that the hard error is only produced with the feature
5+
// gate is present in the `future` edition -- and otherwise that only a warning
6+
// is emitted.
7+
8+
//@ revisions: current current_feature future future_feature
9+
10+
//@ [current] run-rustfix
11+
//@ [current] check-pass
12+
13+
//@ [current_feature] run-rustfix
14+
//@ [current_feature] check-pass
15+
16+
//@ [future] edition: future
17+
//@ [future] compile-flags: -Z unstable-options
18+
//@ [future] run-rustfix
19+
//@ [future] check-pass
20+
21+
//@ [future_feature] edition: future
22+
//@ [future_feature] compile-flags: -Z unstable-options
23+
24+
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25+
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
26+
27+
extern "C" fn _foo() {}
28+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
29+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
30+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
31+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
32+
33+
unsafe extern "C" fn _bar() {}
34+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
35+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
36+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
37+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
38+
39+
unsafe extern "C" {}
40+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
41+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
42+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
43+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
44+
45+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
warning: `extern` declarations without an explicit ABI are deprecated
2+
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
3+
|
4+
LL | extern fn _foo() {}
5+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
6+
|
7+
= note: `#[warn(missing_abi)]` on by default
8+
9+
warning: `extern` declarations without an explicit ABI are deprecated
10+
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
11+
|
12+
LL | unsafe extern fn _bar() {}
13+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
14+
15+
warning: `extern` declarations without an explicit ABI are deprecated
16+
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
17+
|
18+
LL | unsafe extern {}
19+
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
20+
21+
warning: 3 warnings emitted
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `extern` declarations without an explicit ABI are disallowed
2+
--> $DIR/feature-gate-explicit-extern-abis.rs:27:1
3+
|
4+
LL | extern fn _foo() {}
5+
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
6+
|
7+
= help: prior to Rust 2024, a default ABI was inferred
8+
9+
error: `extern` declarations without an explicit ABI are disallowed
10+
--> $DIR/feature-gate-explicit-extern-abis.rs:33:8
11+
|
12+
LL | unsafe extern fn _bar() {}
13+
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
14+
|
15+
= help: prior to Rust 2024, a default ABI was inferred
16+
17+
error: `extern` declarations without an explicit ABI are disallowed
18+
--> $DIR/feature-gate-explicit-extern-abis.rs:39:8
19+
|
20+
LL | unsafe extern {}
21+
| ^^^^^^ help: specify an ABI: `extern "<abi>"`
22+
|
23+
= help: prior to Rust 2024, a default ABI was inferred
24+
25+
error: aborting due to 3 previous errors
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// The purpose of this feature gate is to make something into a hard error in a
2+
// future edition. Consequently, this test differs from most other feature gate
3+
// tests. Instead of verifying that an error occurs when the feature gate is
4+
// missing, it ensures that the hard error is only produced with the feature
5+
// gate is present in the `future` edition -- and otherwise that only a warning
6+
// is emitted.
7+
8+
//@ revisions: current current_feature future future_feature
9+
10+
//@ [current] run-rustfix
11+
//@ [current] check-pass
12+
13+
//@ [current_feature] run-rustfix
14+
//@ [current_feature] check-pass
15+
16+
//@ [future] edition: future
17+
//@ [future] compile-flags: -Z unstable-options
18+
//@ [future] run-rustfix
19+
//@ [future] check-pass
20+
21+
//@ [future_feature] edition: future
22+
//@ [future_feature] compile-flags: -Z unstable-options
23+
24+
#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25+
#![cfg_attr(current_feature, feature(explicit_extern_abis))]
26+
27+
extern fn _foo() {}
28+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
29+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
30+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
31+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
32+
33+
unsafe extern fn _bar() {}
34+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
35+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
36+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
37+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
38+
39+
unsafe extern {}
40+
//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
41+
//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
42+
//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
43+
//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
44+
45+
fn main() {}

0 commit comments

Comments
 (0)