rustc_ast_lowering/
stability.rs
1use std::fmt;
2
3use rustc_abi::ExternAbi;
4use rustc_feature::Features;
5use rustc_session::Session;
6use rustc_session::parse::feature_err;
7use rustc_span::symbol::sym;
8use rustc_span::{Span, Symbol};
9
10pub(crate) fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
11 ExternAbi::ALL_VARIANTS
12 .into_iter()
13 .filter(|abi| extern_abi_enabled(features, span, **abi).is_ok())
14 .map(|abi| abi.as_str())
15 .collect()
16}
17
18pub(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)]
33pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) {
34 match extern_abi_enabled(features, span, abi) {
35 Ok(_) => (),
36 Err(unstable_abi) => {
37 let explain = unstable_abi.to_string();
38 feature_err(sess, unstable_abi.feature, span, explain).emit();
39 }
40 }
41}
42
43pub struct UnstableAbi {
44 abi: ExternAbi,
45 feature: Symbol,
46 explain: GateReason,
47}
48
49enum GateReason {
50 Experimental,
51 ImplDetail,
52}
53
54impl fmt::Display for UnstableAbi {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 let Self { abi, .. } = self;
57 match self.explain {
58 GateReason::Experimental => {
59 write!(f, "the extern {abi} ABI is experimental and subject to change")
60 }
61 GateReason::ImplDetail => {
62 write!(f, "the extern {abi} ABI is an implementation detail and perma-unstable")
63 }
64 }
65 }
66}
67
68pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
69 match abi {
70 ExternAbi::Rust
72 | ExternAbi::C { .. }
73 | ExternAbi::Cdecl { .. }
74 | ExternAbi::Stdcall { .. }
75 | ExternAbi::Fastcall { .. }
76 | ExternAbi::Thiscall { .. }
77 | ExternAbi::Aapcs { .. }
78 | ExternAbi::Win64 { .. }
79 | ExternAbi::SysV64 { .. }
80 | ExternAbi::System { .. }
81 | ExternAbi::EfiApi => Ok(()),
82 ExternAbi::RustIntrinsic => {
84 Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail })
85 }
86 ExternAbi::Unadjusted => {
87 Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail })
88 }
89 ExternAbi::Vectorcall { .. } => Err(UnstableAbi {
91 abi,
92 feature: sym::abi_vectorcall,
93 explain: GateReason::Experimental,
94 }),
95 ExternAbi::RustCall => Err(UnstableAbi {
96 abi,
97 feature: sym::unboxed_closures,
98 explain: GateReason::Experimental,
99 }),
100 ExternAbi::RustCold => {
101 Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental })
102 }
103 ExternAbi::GpuKernel => Err(UnstableAbi {
104 abi,
105 feature: sym::abi_gpu_kernel,
106 explain: GateReason::Experimental,
107 }),
108 ExternAbi::PtxKernel => {
109 Err(UnstableAbi { abi, feature: sym::abi_ptx, explain: GateReason::Experimental })
110 }
111 ExternAbi::Msp430Interrupt => Err(UnstableAbi {
112 abi,
113 feature: sym::abi_msp430_interrupt,
114 explain: GateReason::Experimental,
115 }),
116 ExternAbi::X86Interrupt => Err(UnstableAbi {
117 abi,
118 feature: sym::abi_x86_interrupt,
119 explain: GateReason::Experimental,
120 }),
121 ExternAbi::AvrInterrupt | ExternAbi::AvrNonBlockingInterrupt => Err(UnstableAbi {
122 abi,
123 feature: sym::abi_avr_interrupt,
124 explain: GateReason::Experimental,
125 }),
126 ExternAbi::RiscvInterruptM | ExternAbi::RiscvInterruptS => Err(UnstableAbi {
127 abi,
128 feature: sym::abi_riscv_interrupt,
129 explain: GateReason::Experimental,
130 }),
131 ExternAbi::CCmseNonSecureCall => Err(UnstableAbi {
132 abi,
133 feature: sym::abi_c_cmse_nonsecure_call,
134 explain: GateReason::Experimental,
135 }),
136 ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi {
137 abi,
138 feature: sym::cmse_nonsecure_entry,
139 explain: GateReason::Experimental,
140 }),
141 }
142}