about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr/src/builtin.rs56
-rw-r--r--compiler/rustc_passes/messages.ftl5
-rw-r--r--compiler/rustc_passes/src/errors.rs10
-rw-r--r--compiler/rustc_passes/src/stability.rs64
4 files changed, 74 insertions, 61 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 44ba495721d..bd85483885e 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::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};
@@ -23,9 +24,10 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
 /// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
 pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
 
+pub const CURRENT_RUSTC_VERSION: &str = env!("CFG_RELEASE");
+
 pub fn rust_version_symbol() -> Symbol {
-    let version = option_env!("CFG_RELEASE").unwrap_or("<current>");
-    Symbol::intern(&version)
+    Symbol::intern(CURRENT_RUSTC_VERSION)
 }
 
 pub fn is_builtin_attr(attr: &Attribute) -> bool {
@@ -144,13 +146,24 @@ pub enum StabilityLevel {
     /// `#[stable]`
     Stable {
         /// Rust release which stabilized this feature.
-        since: Symbol,
+        since: Since,
         /// Is this item allowed to be referred to on stable, despite being contained in unstable
         /// modules?
         allowed_through_unstable_modules: bool,
     },
 }
 
+/// Rust release in which a feature is stabilized.
+#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
+#[derive(HashStable_Generic)]
+pub enum Since {
+    Version(Version),
+    /// Stabilized in the upcoming version, whatever number that is.
+    Current,
+    /// Failed to parse a stabilization version.
+    Err,
+}
+
 impl StabilityLevel {
     pub fn is_unstable(&self) -> bool {
         matches!(self, StabilityLevel::Unstable { .. })
@@ -372,22 +385,24 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
 
     let since = if let Some(since) = since {
         if since.as_str() == VERSION_PLACEHOLDER {
-            Ok(rust_version_symbol())
-        } else if parse_version(since.as_str(), false).is_some() {
-            Ok(since)
+            Since::Current
+        } else if let Some(version) = parse_version(since.as_str(), false) {
+            Since::Version(version)
         } else {
-            Err(sess.emit_err(session_diagnostics::InvalidSince { span: attr.span }))
+            sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
+            Since::Err
         }
     } else {
-        Err(sess.emit_err(session_diagnostics::MissingSince { span: attr.span }))
+        sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
+        Since::Err
     };
 
-    match (feature, since) {
-        (Ok(feature), Ok(since)) => {
+    match feature {
+        Ok(feature) => {
             let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
             Some((feature, level))
         }
-        (Err(ErrorGuaranteed { .. }), _) | (_, Err(ErrorGuaranteed { .. })) => None,
+        Err(ErrorGuaranteed { .. }) => None,
     }
 }
 
@@ -556,11 +571,12 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-struct Version {
-    major: u16,
-    minor: u16,
-    patch: u16,
+#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(HashStable_Generic)]
+pub struct Version {
+    pub major: u16,
+    pub minor: u16,
+    pub patch: u16,
 }
 
 fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
@@ -576,6 +592,12 @@ fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
     Some(Version { major, minor, patch })
 }
 
+impl Display for Version {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
+    }
+}
+
 /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
 /// evaluate individual items.
 pub fn eval_condition(
@@ -609,7 +631,7 @@ pub fn eval_condition(
                 sess.emit_warning(session_diagnostics::UnknownVersionLiteral { span: *span });
                 return false;
             };
-            let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
+            let rustc_version = parse_version(CURRENT_RUSTC_VERSION, true).unwrap();
 
             // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
             if sess.assume_incomplete_release {
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 25ef5245cf1..84d3b84e13f 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -402,11 +402,6 @@ passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]
 
 passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
 
-passes_invalid_stability =
-    invalid stability version found
-    .label = invalid stability version
-    .item = the stability attribute annotates this item
-
 passes_lang_item_fn_with_target_feature =
     `{$name}` language item function is not allowed to have `#[target_feature]`
     .label = `{$name}` language item function is not allowed to have `#[target_feature]`
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 6f87b56c636..6e840f24c69 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1505,16 +1505,6 @@ pub struct UselessStability {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_invalid_stability)]
-pub struct InvalidStability {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    #[label(passes_item)]
-    pub item_sp: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_cannot_stabilize_deprecated)]
 pub struct CannotStabilizeDeprecated {
     #[primary_span]
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index bb23dc257d7..41a240fa880 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -3,7 +3,7 @@
 
 use crate::errors;
 use rustc_attr::{
-    self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
+    self as attr, rust_version_symbol, ConstStability, Since, Stability, StabilityLevel, Unstable,
     UnstableReason, VERSION_PLACEHOLDER,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
@@ -226,37 +226,43 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
             if let (&Some(dep_since), &attr::Stable { since: stab_since, .. }) =
                 (&depr.as_ref().and_then(|(d, _)| d.since), &stab.level)
             {
-                // Explicit version of iter::order::lt to handle parse errors properly
-                for (dep_v, stab_v) in
-                    iter::zip(dep_since.as_str().split('.'), stab_since.as_str().split('.'))
-                {
-                    match stab_v.parse::<u64>() {
-                        Err(_) => {
-                            self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp });
-                            break;
-                        }
-                        Ok(stab_vp) => match dep_v.parse::<u64>() {
-                            Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
-                                Ordering::Less => {
-                                    self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
-                                        span,
-                                        item_sp,
-                                    });
+                match stab_since {
+                    Since::Current => {
+                        self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
+                    }
+                    Since::Version(stab_since) => {
+                        // Explicit version of iter::order::lt to handle parse errors properly
+                        for (dep_v, stab_v) in iter::zip(
+                            dep_since.as_str().split('.'),
+                            [stab_since.major, stab_since.minor, stab_since.patch],
+                        ) {
+                            match dep_v.parse::<u64>() {
+                                Ok(dep_vp) => match dep_vp.cmp(&u64::from(stab_v)) {
+                                    Ordering::Less => {
+                                        self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
+                                            span,
+                                            item_sp,
+                                        });
+                                        break;
+                                    }
+                                    Ordering::Equal => continue,
+                                    Ordering::Greater => break,
+                                },
+                                Err(_) => {
+                                    if dep_v != "TBD" {
+                                        self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
+                                            span,
+                                            item_sp,
+                                        });
+                                    }
                                     break;
                                 }
-                                Ordering::Equal => continue,
-                                Ordering::Greater => break,
-                            },
-                            Err(_) => {
-                                if dep_v != "TBD" {
-                                    self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
-                                        span,
-                                        item_sp,
-                                    });
-                                }
-                                break;
                             }
-                        },
+                        }
+                    }
+                    Since::Err => {
+                        // An error already reported. Assume the unparseable stabilization
+                        // version is older than the deprecation version.
                     }
                 }
             }