about summary refs log tree commit diff
path: root/compiler/rustc_attr
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2023-10-26 10:14:29 -0700
committerDavid Tolnay <dtolnay@gmail.com>2023-10-29 22:42:32 -0700
commit2fe7d17bd9aabe3948b8693c2a3d4841ce9fbd14 (patch)
treec8006b654e380b47fdea85fea88f84cb3e9b8d37 /compiler/rustc_attr
parent5c7cf837395db7221bd1061eee230fd27f81e6ad (diff)
downloadrust-2fe7d17bd9aabe3948b8693c2a3d4841ce9fbd14.tar.gz
rust-2fe7d17bd9aabe3948b8693c2a3d4841ce9fbd14.zip
Store version of `deprecated` attribute in structured form
Diffstat (limited to 'compiler/rustc_attr')
-rw-r--r--compiler/rustc_attr/src/builtin.rs61
1 files changed, 45 insertions, 16 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 592c9ff115b..62709ef4db9 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -13,6 +13,7 @@ use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::{RustcVersion, Session};
 use rustc_span::hygiene::Transparency;
 use rustc_span::{symbol::sym, symbol::Symbol, Span};
+use std::fmt::{self, Display};
 use std::num::NonZeroU32;
 
 use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
@@ -720,17 +721,37 @@ pub fn eval_condition(
 
 #[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
 pub struct Deprecation {
-    pub since: Option<Symbol>,
+    pub since: Option<DeprecatedSince>,
     /// The note to issue a reason.
     pub note: Option<Symbol>,
     /// A text snippet used to completely replace any use of the deprecated item in an expression.
     ///
     /// This is currently unstable.
     pub suggestion: Option<Symbol>,
+}
+
+/// Release in which an API is deprecated.
+#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
+pub enum DeprecatedSince {
+    RustcVersion(RustcVersion),
+    /// Deprecated in the future ("to be determined").
+    Future,
+    /// `feature(staged_api)` is off, or it's on but the deprecation version
+    /// cannot be parsed as a RustcVersion. In the latter case, an error has
+    /// already been emitted. In the former case, deprecation versions outside
+    /// the standard library are allowed to be arbitrary strings, for better or
+    /// worse.
+    Symbol(Symbol),
+}
 
-    /// Whether to treat the since attribute as being a Rust version identifier
-    /// (rather than an opaque string).
-    pub is_since_rustc_version: bool,
+impl Display for DeprecatedSince {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            DeprecatedSince::RustcVersion(since) => Display::fmt(since, formatter),
+            DeprecatedSince::Future => formatter.write_str("TBD"),
+            DeprecatedSince::Symbol(since) => Display::fmt(since, formatter),
+        }
+    }
 }
 
 /// Finds the deprecation attribute. `None` if none exists.
@@ -839,22 +860,30 @@ pub fn find_deprecation(
             }
         }
 
-        if is_rustc {
-            if since.is_none() {
-                sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
-                continue;
+        let since = if let Some(since) = since {
+            if since.as_str() == "TBD" {
+                Some(DeprecatedSince::Future)
+            } else if !is_rustc {
+                Some(DeprecatedSince::Symbol(since))
+            } else if let Some(version) = parse_version(since) {
+                Some(DeprecatedSince::RustcVersion(version))
+            } else {
+                sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
+                Some(DeprecatedSince::Symbol(since))
             }
+        } else if is_rustc {
+            sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
+            continue;
+        } else {
+            None
+        };
 
-            if note.is_none() {
-                sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
-                continue;
-            }
+        if is_rustc && note.is_none() {
+            sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
+            continue;
         }
 
-        depr = Some((
-            Deprecation { since, note, suggestion, is_since_rustc_version: is_rustc },
-            attr.span,
-        ));
+        depr = Some((Deprecation { since, note, suggestion }, attr.span));
     }
 
     depr