Skip to content

Commit c778d76

Browse files
compiler: gate extern "{abi}"` in ast_lowering
1 parent 1a4f8c1 commit c778d76

File tree

12 files changed

+190
-155
lines changed

12 files changed

+190
-155
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3405,6 +3405,7 @@ dependencies = [
34053405
"rustc_ast_pretty",
34063406
"rustc_data_structures",
34073407
"rustc_errors",
3408+
"rustc_feature",
34083409
"rustc_fluent_macro",
34093410
"rustc_hir",
34103411
"rustc_index",

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#[cfg(feature = "nightly")]
2-
use crate::{BackendRepr, FieldsShape, TyAbiInterface, TyAndLayout};
3-
use crate::{Primitive, Size, Variants};
2+
use crate::{BackendRepr, FieldsShape, Primitive, Size, TyAbiInterface, TyAndLayout, Variants};
43

54
mod reg;
65

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

+3-102
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::fmt;
22

33
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
4-
use rustc_span::{Span, Symbol, sym};
54

65
#[cfg(test)]
76
mod tests;
@@ -95,14 +94,14 @@ impl Abi {
9594

9695
#[derive(Copy, Clone)]
9796
pub struct AbiData {
98-
abi: Abi,
97+
pub abi: Abi,
9998

10099
/// Name of this ABI as we like it called.
101-
name: &'static str,
100+
pub name: &'static str,
102101
}
103102

104103
#[allow(non_upper_case_globals)]
105-
const AbiDatas: &[AbiData] = &[
104+
pub const AbiDatas: &[AbiData] = &[
106105
AbiData { abi: Abi::Rust, name: "Rust" },
107106
AbiData { abi: Abi::C { unwind: false }, name: "C" },
108107
AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
@@ -169,104 +168,6 @@ pub fn all_names() -> Vec<&'static str> {
169168
AbiDatas.iter().map(|d| d.name).collect()
170169
}
171170

172-
pub fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
173-
AbiDatas
174-
.iter()
175-
.map(|d| d.name)
176-
.filter(|name| is_enabled(features, span, name).is_ok())
177-
.collect()
178-
}
179-
180-
pub enum AbiDisabled {
181-
Unstable { feature: Symbol, explain: &'static str },
182-
Unrecognized,
183-
}
184-
185-
pub fn is_enabled(
186-
features: &rustc_feature::Features,
187-
span: Span,
188-
name: &str,
189-
) -> Result<(), AbiDisabled> {
190-
let s = is_stable(name);
191-
if let Err(AbiDisabled::Unstable { feature, .. }) = s {
192-
if features.enabled(feature) || span.allows_unstable(feature) {
193-
return Ok(());
194-
}
195-
}
196-
s
197-
}
198-
199-
/// Returns whether the ABI is stable to use.
200-
///
201-
/// Note that there is a separate check determining whether the ABI is even supported
202-
/// on the current target; see `fn is_abi_supported` in `rustc_target::spec`.
203-
pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
204-
match name {
205-
// Stable
206-
"Rust" | "C" | "C-unwind" | "cdecl" | "cdecl-unwind" | "stdcall" | "stdcall-unwind"
207-
| "fastcall" | "fastcall-unwind" | "aapcs" | "aapcs-unwind" | "win64" | "win64-unwind"
208-
| "sysv64" | "sysv64-unwind" | "system" | "system-unwind" | "efiapi" | "thiscall"
209-
| "thiscall-unwind" => Ok(()),
210-
"rust-intrinsic" => Err(AbiDisabled::Unstable {
211-
feature: sym::intrinsics,
212-
explain: "intrinsics are subject to change",
213-
}),
214-
"vectorcall" => Err(AbiDisabled::Unstable {
215-
feature: sym::abi_vectorcall,
216-
explain: "vectorcall is experimental and subject to change",
217-
}),
218-
"vectorcall-unwind" => Err(AbiDisabled::Unstable {
219-
feature: sym::abi_vectorcall,
220-
explain: "vectorcall-unwind ABI is experimental and subject to change",
221-
}),
222-
"rust-call" => Err(AbiDisabled::Unstable {
223-
feature: sym::unboxed_closures,
224-
explain: "rust-call ABI is subject to change",
225-
}),
226-
"rust-cold" => Err(AbiDisabled::Unstable {
227-
feature: sym::rust_cold_cc,
228-
explain: "rust-cold is experimental and subject to change",
229-
}),
230-
"ptx-kernel" => Err(AbiDisabled::Unstable {
231-
feature: sym::abi_ptx,
232-
explain: "PTX ABIs are experimental and subject to change",
233-
}),
234-
"unadjusted" => Err(AbiDisabled::Unstable {
235-
feature: sym::abi_unadjusted,
236-
explain: "unadjusted ABI is an implementation detail and perma-unstable",
237-
}),
238-
"msp430-interrupt" => Err(AbiDisabled::Unstable {
239-
feature: sym::abi_msp430_interrupt,
240-
explain: "msp430-interrupt ABI is experimental and subject to change",
241-
}),
242-
"x86-interrupt" => Err(AbiDisabled::Unstable {
243-
feature: sym::abi_x86_interrupt,
244-
explain: "x86-interrupt ABI is experimental and subject to change",
245-
}),
246-
"gpu-kernel" => Err(AbiDisabled::Unstable {
247-
feature: sym::abi_gpu_kernel,
248-
explain: "gpu-kernel ABI is experimental and subject to change",
249-
}),
250-
"avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable {
251-
feature: sym::abi_avr_interrupt,
252-
explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
253-
}),
254-
"riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable {
255-
feature: sym::abi_riscv_interrupt,
256-
explain: "riscv-interrupt ABIs are experimental and subject to change",
257-
}),
258-
"C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
259-
feature: sym::abi_c_cmse_nonsecure_call,
260-
explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
261-
}),
262-
"C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable {
263-
feature: sym::cmse_nonsecure_entry,
264-
explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change",
265-
}),
266-
_ => Err(AbiDisabled::Unrecognized),
267-
}
268-
}
269-
270171
impl Abi {
271172
/// Default ABI chosen for `extern fn` declarations without an explicit ABI.
272173
pub const FALLBACK: Abi = Abi::C { unwind: false };

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ mod extern_abi;
6666

6767
pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
6868
#[cfg(feature = "nightly")]
69-
pub use extern_abi::{
70-
AbiDisabled, AbiUnsupported, ExternAbi, all_names, enabled_names, is_enabled, is_stable, lookup,
71-
};
69+
pub use extern_abi::{AbiDatas, AbiUnsupported, ExternAbi, all_names, lookup};
7270
#[cfg(feature = "nightly")]
7371
pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
7472
pub use layout::{LayoutCalculator, LayoutCalculatorError};

Diff for: compiler/rustc_ast_lowering/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rustc_ast = { path = "../rustc_ast" }
1313
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
1414
rustc_data_structures = { path = "../rustc_data_structures" }
1515
rustc_errors = { path = "../rustc_errors" }
16+
rustc_feature = { path = "../rustc_feature" }
1617
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
1718
rustc_hir = { path = "../rustc_hir" }
1819
rustc_index = { path = "../rustc_index" }

Diff for: compiler/rustc_ast_lowering/src/item.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use super::errors::{
2020
InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound,
2121
TupleStructWithDefault,
2222
};
23+
use super::stability::{enabled_names, gate_unstable_abi};
2324
use super::{
2425
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
2526
ResolverAstLoweringExt,
@@ -1385,11 +1386,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
13851386
}
13861387
}
13871388

1388-
pub(super) fn lower_abi(&mut self, abi: StrLit) -> ExternAbi {
1389-
rustc_abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|err| {
1390-
self.error_on_invalid_abi(abi, err);
1389+
pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {
1390+
let ast::StrLit { symbol_unescaped, span, .. } = abi_str;
1391+
let extern_abi = rustc_abi::lookup(symbol_unescaped.as_str()).unwrap_or_else(|err| {
1392+
self.error_on_invalid_abi(abi_str, err);
13911393
ExternAbi::Rust
1392-
})
1394+
});
1395+
let sess = self.tcx.sess;
1396+
let features = self.tcx.features();
1397+
gate_unstable_abi(sess, features, span, extern_abi);
1398+
extern_abi
13931399
}
13941400

13951401
pub(super) fn lower_extern(&mut self, ext: Extern) -> ExternAbi {
@@ -1401,7 +1407,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14011407
}
14021408

14031409
fn error_on_invalid_abi(&self, abi: StrLit, err: rustc_abi::AbiUnsupported) {
1404-
let abi_names = rustc_abi::enabled_names(self.tcx.features(), abi.span)
1410+
let abi_names = enabled_names(self.tcx.features(), abi.span)
14051411
.iter()
14061412
.map(|s| Symbol::intern(s))
14071413
.collect::<Vec<_>>();

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

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ mod index;
8383
mod item;
8484
mod pat;
8585
mod path;
86+
mod stability;
8687

8788
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
8889

Diff for: compiler/rustc_ast_lowering/src/stability.rs

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use std::fmt;
2+
3+
use rustc_abi::ExternAbi;
4+
use rustc_feature::Features;
5+
use rustc_session::Session;
6+
use rustc_session::parse::feature_err;
7+
use rustc_span::symbol::sym;
8+
use rustc_span::{Span, Symbol};
9+
10+
pub(crate) fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
11+
rustc_abi::AbiDatas
12+
.iter()
13+
.filter(|data| extern_abi_enabled(features, span, data.abi).is_ok())
14+
.map(|d| d.name)
15+
.collect()
16+
}
17+
18+
pub(crate) fn extern_abi_enabled(
19+
features: &rustc_feature::Features,
20+
span: Span,
21+
abi: ExternAbi,
22+
) -> Result<(), UnstableAbi> {
23+
extern_abi_stability(abi).or_else(|unstable @ UnstableAbi { feature, .. }| {
24+
if features.enabled(feature) || span.allows_unstable(feature) {
25+
Ok(())
26+
} else {
27+
Err(unstable)
28+
}
29+
})
30+
}
31+
32+
#[allow(rustc::untranslatable_diagnostic)]
33+
pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) {
34+
let result = extern_abi_stability(abi).or_else(|unstable @ UnstableAbi { feature, .. }| {
35+
if features.enabled(feature) || span.allows_unstable(feature) {
36+
Ok(())
37+
} else {
38+
Err(unstable)
39+
}
40+
});
41+
match result {
42+
Ok(_) => (),
43+
Err(unstable_abi) => {
44+
let explain = unstable_abi.to_string();
45+
feature_err(sess, unstable_abi.feature, span, explain).emit();
46+
}
47+
}
48+
}
49+
50+
pub(crate) struct UnstableAbi {
51+
abi: ExternAbi,
52+
feature: Symbol,
53+
explain: GateReason,
54+
}
55+
56+
enum GateReason {
57+
Experimental,
58+
ImplDetail,
59+
}
60+
61+
impl fmt::Display for UnstableAbi {
62+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63+
let Self { abi, .. } = self;
64+
let name = abi.to_string();
65+
let name = name.trim_matches('"');
66+
match self.explain {
67+
GateReason::Experimental => {
68+
write!(f, "{name} ABI is experimental and subject to change")
69+
}
70+
GateReason::ImplDetail => {
71+
write!(f, "{name} ABI is an implementation detail and perma-unstable")
72+
}
73+
}
74+
}
75+
}
76+
77+
pub(crate) fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
78+
match abi {
79+
// stable ABIs
80+
ExternAbi::Rust
81+
| ExternAbi::C { .. }
82+
| ExternAbi::Cdecl { .. }
83+
| ExternAbi::Stdcall { .. }
84+
| ExternAbi::Fastcall { .. }
85+
| ExternAbi::Thiscall { .. }
86+
| ExternAbi::Aapcs { .. }
87+
| ExternAbi::Win64 { .. }
88+
| ExternAbi::SysV64 { .. }
89+
| ExternAbi::System { .. }
90+
| ExternAbi::EfiApi => Ok(()),
91+
// implementation details
92+
ExternAbi::RustIntrinsic => {
93+
Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail })
94+
}
95+
ExternAbi::Unadjusted => {
96+
Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail })
97+
}
98+
// experimental
99+
ExternAbi::Vectorcall { .. } => Err(UnstableAbi {
100+
abi,
101+
feature: sym::abi_vectorcall,
102+
explain: GateReason::Experimental,
103+
}),
104+
ExternAbi::RustCall => Err(UnstableAbi {
105+
abi,
106+
feature: sym::unboxed_closures,
107+
explain: GateReason::Experimental,
108+
}),
109+
ExternAbi::RustCold => {
110+
Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental })
111+
}
112+
ExternAbi::GpuKernel => Err(UnstableAbi {
113+
abi,
114+
feature: sym::abi_gpu_kernel,
115+
explain: GateReason::Experimental,
116+
}),
117+
ExternAbi::PtxKernel => {
118+
Err(UnstableAbi { abi, feature: sym::abi_ptx, explain: GateReason::Experimental })
119+
}
120+
ExternAbi::Msp430Interrupt => Err(UnstableAbi {
121+
abi,
122+
feature: sym::abi_msp430_interrupt,
123+
explain: GateReason::Experimental,
124+
}),
125+
ExternAbi::X86Interrupt => Err(UnstableAbi {
126+
abi,
127+
feature: sym::abi_x86_interrupt,
128+
explain: GateReason::Experimental,
129+
}),
130+
ExternAbi::AvrInterrupt | ExternAbi::AvrNonBlockingInterrupt => Err(UnstableAbi {
131+
abi,
132+
feature: sym::abi_avr_interrupt,
133+
explain: GateReason::Experimental,
134+
}),
135+
ExternAbi::RiscvInterruptM | ExternAbi::RiscvInterruptS => Err(UnstableAbi {
136+
abi,
137+
feature: sym::abi_riscv_interrupt,
138+
explain: GateReason::Experimental,
139+
}),
140+
ExternAbi::CCmseNonSecureCall => Err(UnstableAbi {
141+
abi,
142+
feature: sym::abi_c_cmse_nonsecure_call,
143+
explain: GateReason::Experimental,
144+
}),
145+
ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi {
146+
abi,
147+
feature: sym::cmse_nonsecure_entry,
148+
explain: GateReason::Experimental,
149+
}),
150+
}
151+
}

0 commit comments

Comments
 (0)