Skip to main content

rustc_ast_lowering/
stability.rs

1use 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        // stable ABIs
70        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        // experimental
85        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}