]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_attr/src/builtin.rs
Rollup merge of #99651 - compiler-errors:fn-and-raw-ptr-in-const-generics, r=oli-obk
[rust.git] / compiler / rustc_attr / src / builtin.rs
index dcfbecedfe8ffd5d9a77bb85d804956566a14383..10a9cfb626e63391ae7ae22a439f1d13d9f2a907 100644 (file)
@@ -135,9 +135,42 @@ pub fn is_const_stable(&self) -> bool {
 #[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub enum StabilityLevel {
-    // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
-    Stable { since: Symbol, allowed_through_unstable_modules: bool },
+    /// `#[unstable]`
+    Unstable {
+        /// Reason for the current stability level.
+        reason: UnstableReason,
+        /// Relevant `rust-lang/rust` issue.
+        issue: Option<NonZeroU32>,
+        is_soft: bool,
+        /// If part of a feature is stabilized and a new feature is added for the remaining parts,
+        /// then the `implied_by` attribute is used to indicate which now-stable feature previously
+        /// contained a item.
+        ///
+        /// ```pseudo-Rust
+        /// #[unstable(feature = "foo", issue = "...")]
+        /// fn foo() {}
+        /// #[unstable(feature = "foo", issue = "...")]
+        /// fn foobar() {}
+        /// ```
+        ///
+        /// ...becomes...
+        ///
+        /// ```pseudo-Rust
+        /// #[stable(feature = "foo", since = "1.XX.X")]
+        /// fn foo() {}
+        /// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
+        /// fn foobar() {}
+        /// ```
+        implied_by: Option<Symbol>,
+    },
+    /// `#[stable]`
+    Stable {
+        /// Rust release which stabilized this feature.
+        since: Symbol,
+        /// Is this item allowed to be referred to on stable, despite being contained in unstable
+        /// modules?
+        allowed_through_unstable_modules: bool,
+    },
 }
 
 impl StabilityLevel {
@@ -149,6 +182,32 @@ pub fn is_stable(&self) -> bool {
     }
 }
 
+#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
+#[derive(HashStable_Generic)]
+pub enum UnstableReason {
+    None,
+    Default,
+    Some(Symbol),
+}
+
+impl UnstableReason {
+    fn from_opt_reason(reason: Option<Symbol>) -> Self {
+        // UnstableReason::Default constructed manually
+        match reason {
+            Some(r) => Self::Some(r),
+            None => Self::None,
+        }
+    }
+
+    pub fn to_opt_reason(&self) -> Option<Symbol> {
+        match self {
+            Self::None => None,
+            Self::Default => Some(sym::unstable_location_reason_default),
+            Self::Some(r) => Some(*r),
+        }
+    }
+}
+
 /// Collects stability info from all stability attributes in `attrs`.
 /// Returns `None` if no stability attributes are found.
 pub fn find_stability(
@@ -243,6 +302,7 @@ fn find_stability_generic<'a, I>(
                     let mut issue = None;
                     let mut issue_num = None;
                     let mut is_soft = false;
+                    let mut implied_by = None;
                     for meta in metas {
                         let Some(mi) = meta.meta_item() else {
                             handle_errors(
@@ -308,6 +368,11 @@ fn find_stability_generic<'a, I>(
                                 }
                                 is_soft = true;
                             }
+                            sym::implied_by => {
+                                if !get(mi, &mut implied_by) {
+                                    continue 'outer;
+                                }
+                            }
                             _ => {
                                 handle_errors(
                                     &sess.parse_sess,
@@ -332,7 +397,12 @@ fn find_stability_generic<'a, I>(
                                 );
                                 continue;
                             }
-                            let level = Unstable { reason, issue: issue_num, is_soft };
+                            let level = Unstable {
+                                reason: UnstableReason::from_opt_reason(reason),
+                                issue: issue_num,
+                                is_soft,
+                                implied_by,
+                            };
                             if sym::unstable == meta_name {
                                 stab = Some((Stability { level, feature }, attr.span));
                             } else {
@@ -391,7 +461,7 @@ fn find_stability_generic<'a, I>(
                                         meta.span(),
                                         AttrError::UnknownMetaItem(
                                             pprust::path_to_string(&mi.path),
-                                            &["since", "note"],
+                                            &["feature", "since"],
                                         ),
                                     );
                                     continue 'outer;