compiler/rustc_attr_ir/src/stability.rs RUST 207 lines View on github.com → Search inside
1use std::num::NonZero;23use rustc_ast::attr::version::RustcVersion;4use rustc_macros::{BlobDecodable, Decodable, Encodable, PrintAttribute, StableHash};5use rustc_span::{ErrorGuaranteed, Symbol, sym};67use crate::PrintAttribute;89/// The version placeholder that recently stabilized features contain inside the10/// `since` field of the `#[stable]` attribute.11///12/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).13pub const VERSION_PLACEHOLDER: &str = concat!("CURRENT_RUSTC_VERSIO", "N");14// Note that the `concat!` macro above prevents `src/tools/replace-version-placeholder` from15// replacing the constant with the current version. Hardcoding the tool to skip this file doesn't16// work as the file can (and at some point will) be moved around.17//18// Turning the `concat!` macro into a string literal will make Pietro cry. That'd be sad :(1920/// Represents the following attributes:21///22/// - `#[stable]`23/// - `#[unstable]`24#[derive(Encodable, BlobDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]25#[derive(StableHash, PrintAttribute)]26pub struct Stability {27    pub level: StabilityLevel,28    pub feature: Symbol,29}3031impl Stability {32    pub fn is_unstable(&self) -> bool {33        self.level.is_unstable()34    }3536    pub fn is_stable(&self) -> bool {37        self.level.is_stable()38    }3940    pub fn stable_since(&self) -> Option<StableSince> {41        self.level.stable_since()42    }43}4445/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.46#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]47#[derive(StableHash, PrintAttribute)]48pub struct ConstStability {49    pub level: StabilityLevel,50    pub feature: Symbol,51    /// whether the function has a `#[rustc_promotable]` attribute52    pub promotable: bool,53    /// This is true iff the `const_stable_indirect` attribute is present.54    pub const_stable_indirect: bool,55}5657impl ConstStability {58    pub fn from_partial(59        PartialConstStability { level, feature, promotable }: PartialConstStability,60        const_stable_indirect: bool,61    ) -> Self {62        Self { const_stable_indirect, level, feature, promotable }63    }6465    /// The stability assigned to unmarked items when -Zforce-unstable-if-unmarked is set.66    pub fn unmarked(const_stable_indirect: bool, regular_stab: Stability) -> Self {67        Self {68            feature: regular_stab.feature,69            promotable: false,70            level: regular_stab.level,71            const_stable_indirect,72        }73    }7475    pub fn is_const_unstable(&self) -> bool {76        self.level.is_unstable()77    }7879    pub fn is_const_stable(&self) -> bool {80        self.level.is_stable()81    }82}8384/// Excludes `const_stable_indirect`. This is necessary because when `-Zforce-unstable-if-unmarked`85/// is set, we need to encode standalone `#[rustc_const_stable_indirect]` attributes86#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]87#[derive(StableHash, PrintAttribute)]88pub struct PartialConstStability {89    pub level: StabilityLevel,90    pub feature: Symbol,91    /// whether the function has a `#[rustc_promotable]` attribute92    pub promotable: bool,93}9495impl PartialConstStability {96    pub fn is_const_unstable(&self) -> bool {97        self.level.is_unstable()98    }99100    pub fn is_const_stable(&self) -> bool {101        self.level.is_stable()102    }103}104105/// The available stability levels.106#[derive(Encodable, BlobDecodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]107#[derive(StableHash, PrintAttribute)]108pub enum StabilityLevel {109    /// `#[unstable]`110    Unstable {111        /// Reason for the current stability level.112        reason: UnstableReason,113        /// Relevant `rust-lang/rust` issue.114        issue: Option<NonZero<u32>>,115        /// If part of a feature is stabilized and a new feature is added for the remaining parts,116        /// then the `implied_by` attribute is used to indicate which now-stable feature previously117        /// contained an item.118        ///119        /// ```pseudo-Rust120        /// #[unstable(feature = "foo", issue = "...")]121        /// fn foo() {}122        /// #[unstable(feature = "foo", issue = "...")]123        /// fn foobar() {}124        /// ```125        ///126        /// ...becomes...127        ///128        /// ```pseudo-Rust129        /// #[stable(feature = "foo", since = "1.XX.X")]130        /// fn foo() {}131        /// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]132        /// fn foobar() {}133        /// ```134        implied_by: Option<Symbol>,135        old_name: Option<Symbol>,136    },137    /// `#[stable]`138    Stable {139        /// Rust release which stabilized this feature.140        since: StableSince,141        /// This is `Some` if this item allowed to be referred to on stable via unstable modules;142        /// the `Symbol` is the deprecation message printed in that case.143        allowed_through_unstable_modules: Option<Symbol>,144    },145}146147/// Rust release in which a feature is stabilized.148#[derive(Encodable, BlobDecodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]149#[derive(StableHash, PrintAttribute)]150pub enum StableSince {151    /// also stores the original symbol for printing152    Version(RustcVersion),153    /// Stabilized in the upcoming version, whatever number that is.154    Current,155    /// Failed to parse a stabilization version.156    Err(ErrorGuaranteed),157}158159impl 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}173174#[derive(Encodable, BlobDecodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]175#[derive(StableHash, PrintAttribute)]176pub enum UnstableReason {177    None,178    Default,179    Some(Symbol),180}181182/// Represents the `#[rustc_default_body_unstable]` attribute.183#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]184#[derive(StableHash, PrintAttribute)]185pub struct DefaultBodyStability {186    pub level: StabilityLevel,187    pub feature: Symbol,188}189190impl UnstableReason {191    pub fn from_opt_reason(reason: Option<Symbol>) -> Self {192        // UnstableReason::Default constructed manually193        match reason {194            Some(r) => Self::Some(r),195            None => Self::None,196        }197    }198199    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}

Code quality findings 1

Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.