about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2023-10-16 12:30:32 -0700
committerDavid Tolnay <dtolnay@gmail.com>2023-10-23 13:04:35 -0700
commit82ed3f5e8b65291d4861f62f8c9c5bc8630e42b2 (patch)
treeff1f408dce11f1e9e8f8386b9c544273d1b87929
parent01b909174bf44b72b927b524626b06738e5872a4 (diff)
downloadrust-82ed3f5e8b65291d4861f62f8c9c5bc8630e42b2.tar.gz
rust-82ed3f5e8b65291d4861f62f8c9c5bc8630e42b2.zip
Validate `since` value in stable attribute
-rw-r--r--compiler/rustc_attr/messages.ftl3
-rw-r--r--compiler/rustc_attr/src/builtin.rs19
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs7
3 files changed, 21 insertions, 8 deletions
diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl
index e6cbbaf3704..7281282fec3 100644
--- a/compiler/rustc_attr/messages.ftl
+++ b/compiler/rustc_attr/messages.ftl
@@ -58,6 +58,9 @@ attr_invalid_repr_hint_no_paren =
 attr_invalid_repr_hint_no_value =
     invalid representation hint: `{$name}` does not take a value
 
+attr_invalid_since =
+    'since' must be a Rust version number, such as "1.31.0"
+
 attr_missing_feature =
     missing 'feature'
 
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 50045cb1f0f..44ba495721d 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -362,12 +362,6 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
         }
     }
 
-    if let Some(s) = since
-        && s.as_str() == VERSION_PLACEHOLDER
-    {
-        since = Some(rust_version_symbol());
-    }
-
     let feature = match feature {
         Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
         Some(_bad_feature) => {
@@ -376,8 +370,17 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
         None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })),
     };
 
-    let since =
-        since.ok_or_else(|| sess.emit_err(session_diagnostics::MissingSince { span: attr.span }));
+    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)
+        } else {
+            Err(sess.emit_err(session_diagnostics::InvalidSince { span: attr.span }))
+        }
+    } else {
+        Err(sess.emit_err(session_diagnostics::MissingSince { span: attr.span }))
+    };
 
     match (feature, since) {
         (Ok(feature), Ok(since)) => {
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 86f27254db2..ca9bbd28b95 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -371,6 +371,13 @@ pub(crate) struct ExpectsFeatures {
 }
 
 #[derive(Diagnostic)]
+#[diag(attr_invalid_since)]
+pub(crate) struct InvalidSince {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(attr_soft_no_args)]
 pub(crate) struct SoftNoArgs {
     #[primary_span]