rustc_attr_data_structures/
stability.rs1use std::num::NonZero;
2
3use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
4use rustc_span::{ErrorGuaranteed, Symbol, sym};
5
6use crate::{PrintAttribute, RustcVersion};
7
8pub const VERSION_PLACEHOLDER: &str = concat!("CURRENT_RUSTC_VERSIO", "N");
13#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
24#[derive(HashStable_Generic, PrintAttribute)]
25pub struct Stability {
26    pub level: StabilityLevel,
27    pub feature: Symbol,
28}
29
30impl Stability {
31    pub fn is_unstable(&self) -> bool {
32        self.level.is_unstable()
33    }
34
35    pub fn is_stable(&self) -> bool {
36        self.level.is_stable()
37    }
38
39    pub fn stable_since(&self) -> Option<StableSince> {
40        self.level.stable_since()
41    }
42}
43
44#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
46#[derive(HashStable_Generic, PrintAttribute)]
47pub struct ConstStability {
48    pub level: StabilityLevel,
49    pub feature: Symbol,
50    pub promotable: bool,
52    pub const_stable_indirect: bool,
54}
55
56impl ConstStability {
57    pub fn from_partial(
58        PartialConstStability { level, feature, promotable }: PartialConstStability,
59        const_stable_indirect: bool,
60    ) -> Self {
61        Self { const_stable_indirect, level, feature, promotable }
62    }
63
64    pub fn unmarked(const_stable_indirect: bool, regular_stab: Stability) -> Self {
66        Self {
67            feature: regular_stab.feature,
68            promotable: false,
69            level: regular_stab.level,
70            const_stable_indirect,
71        }
72    }
73
74    pub fn is_const_unstable(&self) -> bool {
75        self.level.is_unstable()
76    }
77
78    pub fn is_const_stable(&self) -> bool {
79        self.level.is_stable()
80    }
81}
82
83#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
86#[derive(HashStable_Generic, PrintAttribute)]
87pub struct PartialConstStability {
88    pub level: StabilityLevel,
89    pub feature: Symbol,
90    pub promotable: bool,
92}
93
94impl PartialConstStability {
95    pub fn is_const_unstable(&self) -> bool {
96        self.level.is_unstable()
97    }
98
99    pub fn is_const_stable(&self) -> bool {
100        self.level.is_stable()
101    }
102}
103
104#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
106#[derive(HashStable_Generic, PrintAttribute)]
107pub enum StabilityLevel {
108    Unstable {
110        reason: UnstableReason,
112        issue: Option<NonZero<u32>>,
114        is_soft: bool,
115        implied_by: Option<Symbol>,
135        old_name: Option<Symbol>,
136    },
137    Stable {
139        since: StableSince,
141        allowed_through_unstable_modules: Option<Symbol>,
144    },
145}
146
147#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
149#[derive(HashStable_Generic, PrintAttribute)]
150pub enum StableSince {
151    Version(RustcVersion),
153    Current,
155    Err(ErrorGuaranteed),
157}
158
159impl StabilityLevel {
160    pub fn is_unstable(&self) -> bool {
161        matches!(self, StabilityLevel::Unstable { .. })
162    }
163    pub fn is_stable(&self) -> bool {
164        matches!(self, StabilityLevel::Stable { .. })
165    }
166    pub fn stable_since(&self) -> Option<StableSince> {
167        match *self {
168            StabilityLevel::Stable { since, .. } => Some(since),
169            StabilityLevel::Unstable { .. } => None,
170        }
171    }
172}
173
174#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
175#[derive(HashStable_Generic, PrintAttribute)]
176pub enum UnstableReason {
177    None,
178    Default,
179    Some(Symbol),
180}
181
182#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
184#[derive(HashStable_Generic, PrintAttribute)]
185pub struct DefaultBodyStability {
186    pub level: StabilityLevel,
187    pub feature: Symbol,
188}
189
190impl UnstableReason {
191    pub fn from_opt_reason(reason: Option<Symbol>) -> Self {
192        match reason {
194            Some(r) => Self::Some(r),
195            None => Self::None,
196        }
197    }
198
199    pub fn to_opt_reason(&self) -> Option<Symbol> {
200        match self {
201            Self::None => None,
202            Self::Default => Some(sym::unstable_location_reason_default),
203            Self::Some(r) => Some(*r),
204        }
205    }
206}