rustc_ast_lowering/
stability.rs1use std::fmt;
2
3use rustc_abi::ExternAbi;
4use rustc_feature::Features;
5use rustc_session::Session;
6use rustc_session::errors::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
32pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) {
33 match extern_abi_enabled(features, span, abi) {
34 Ok(_) => (),
35 Err(unstable_abi) => {
36 let explain = unstable_abi.to_string();
37 feature_err(sess, unstable_abi.feature, span, explain).emit();
38 }
39 }
40}
41
42pub struct UnstableAbi {
43 abi: ExternAbi,
44 feature: Symbol,
45 explain: GateReason,
46}
47
48enum GateReason {
49 Experimental,
50 ImplDetail,
51}
52
53impl fmt::Display for UnstableAbi {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 let Self { abi, .. } = self;
56 match self.explain {
57 GateReason::Experimental => {
58 f.write_fmt(format_args!("the extern {0} ABI is experimental and subject to change",
abi))write!(f, "the extern {abi} ABI is experimental and subject to change")
59 }
60 GateReason::ImplDetail => {
61 f.write_fmt(format_args!("the extern {0} ABI is an implementation detail and perma-unstable",
abi))write!(f, "the extern {abi} ABI is an implementation detail and perma-unstable")
62 }
63 }
64 }
65}
66
67pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
68 match abi {
69 ExternAbi::Rust
71 | ExternAbi::C { .. }
72 | ExternAbi::Cdecl { .. }
73 | ExternAbi::Stdcall { .. }
74 | ExternAbi::Fastcall { .. }
75 | ExternAbi::Thiscall { .. }
76 | ExternAbi::Aapcs { .. }
77 | ExternAbi::Win64 { .. }
78 | ExternAbi::SysV64 { .. }
79 | ExternAbi::System { .. }
80 | ExternAbi::EfiApi => Ok(()),
81 ExternAbi::Unadjusted => {
82 Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail })
83 }
84 ExternAbi::Vectorcall { .. } => Err(UnstableAbi {
86 abi,
87 feature: sym::abi_vectorcall,
88 explain: GateReason::Experimental,
89 }),
90 ExternAbi::RustCall => Err(UnstableAbi {
91 abi,
92 feature: sym::unboxed_closures,
93 explain: GateReason::Experimental,
94 }),
95 ExternAbi::RustCold => {
96 Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental })
97 }
98 ExternAbi::RustPreserveNone => Err(UnstableAbi {
99 abi,
100 feature: sym::rust_preserve_none_cc,
101 explain: GateReason::Experimental,
102 }),
103 ExternAbi::RustTail => {
104 Err(UnstableAbi { abi, feature: sym::rust_tail_cc, explain: GateReason::Experimental })
105 }
106 ExternAbi::RustInvalid => {
107 Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail })
108 }
109 ExternAbi::GpuKernel => Err(UnstableAbi {
110 abi,
111 feature: sym::abi_gpu_kernel,
112 explain: GateReason::Experimental,
113 }),
114 ExternAbi::PtxKernel => {
115 Err(UnstableAbi { abi, feature: sym::abi_ptx, explain: GateReason::Experimental })
116 }
117 ExternAbi::Msp430Interrupt => Err(UnstableAbi {
118 abi,
119 feature: sym::abi_msp430_interrupt,
120 explain: GateReason::Experimental,
121 }),
122 ExternAbi::X86Interrupt => Err(UnstableAbi {
123 abi,
124 feature: sym::abi_x86_interrupt,
125 explain: GateReason::Experimental,
126 }),
127 ExternAbi::AvrInterrupt | ExternAbi::AvrNonBlockingInterrupt => Err(UnstableAbi {
128 abi,
129 feature: sym::abi_avr_interrupt,
130 explain: GateReason::Experimental,
131 }),
132 ExternAbi::RiscvInterruptM | ExternAbi::RiscvInterruptS => Err(UnstableAbi {
133 abi,
134 feature: sym::abi_riscv_interrupt,
135 explain: GateReason::Experimental,
136 }),
137 ExternAbi::CmseNonSecureCall => Err(UnstableAbi {
138 abi,
139 feature: sym::abi_cmse_nonsecure_call,
140 explain: GateReason::Experimental,
141 }),
142 ExternAbi::CmseNonSecureEntry => Err(UnstableAbi {
143 abi,
144 feature: sym::cmse_nonsecure_entry,
145 explain: GateReason::Experimental,
146 }),
147 ExternAbi::Custom => {
148 Err(UnstableAbi { abi, feature: sym::abi_custom, explain: GateReason::Experimental })
149 }
150 ExternAbi::Swift => {
151 Err(UnstableAbi { abi, feature: sym::abi_swift, explain: GateReason::Experimental })
152 }
153 }
154}