about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_passes/src/check_attr.rs43
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_passes/src/stability.rs27
-rw-r--r--tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr22
4 files changed, 51 insertions, 45 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 44b7afc88ec..7df008133de 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -11,11 +11,17 @@ use std::slice;
 
 use rustc_abi::{Align, ExternAbi, Size};
 use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms};
-use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr};
+use rustc_attr_data_structures::{
+    AttributeKind, InlineAttr, PartialConstStability, ReprAttr, Stability, StabilityLevel,
+    find_attr,
+};
 use rustc_attr_parsing::{AttributeParser, Late};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
-use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
+use rustc_feature::{
+    ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
+    BuiltinAttribute,
+};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
@@ -165,9 +171,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         Target::Impl { of_trait: true },
                     ),
                 Attribute::Parsed(
-                    AttributeKind::Stability { span, .. }
-                    | AttributeKind::ConstStability { span, .. },
-                ) => self.check_stability_promotable(*span, target),
+                    AttributeKind::Stability {
+                        span: attr_span,
+                        stability: Stability { level, feature },
+                    }
+                    | AttributeKind::ConstStability {
+                        span: attr_span,
+                        stability: PartialConstStability { level, feature, .. },
+                    },
+                ) => self.check_stability(*attr_span, span, level, *feature, target),
                 Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
                 Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
                     self.check_inline(hir_id, *attr_span, span, kind, target)
@@ -2319,13 +2331,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_stability_promotable(&self, span: Span, target: Target) {
+    fn check_stability(
+        &self,
+        attr_span: Span,
+        item_span: Span,
+        level: &StabilityLevel,
+        feature: Symbol,
+        target: Target,
+    ) {
         match target {
             Target::Expression => {
-                self.dcx().emit_err(errors::StabilityPromotable { attr_span: span });
+                self.dcx().emit_err(errors::StabilityPromotable { attr_span });
             }
             _ => {}
         }
+
+        // Stable *language* features shouldn't be used as unstable library features.
+        // (Not doing this for stable library features is checked by tidy.)
+        if level.is_unstable()
+            && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
+        {
+            self.tcx
+                .dcx()
+                .emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span });
+        }
     }
 
     fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 37330c0ed6e..c6ab6b0d601 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1373,9 +1373,9 @@ pub(crate) struct UnstableAttrForAlreadyStableFeature {
     #[primary_span]
     #[label]
     #[help]
-    pub span: Span,
+    pub attr_span: Span,
     #[label(passes_item)]
-    pub item_sp: Span,
+    pub item_span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index cd29800cce5..6fa1c81e569 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -11,7 +11,7 @@ use rustc_attr_data_structures::{
 };
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
-use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature};
+use rustc_feature::{EnabledLangFeature, EnabledLibFeature};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
 use rustc_hir::hir_id::CRATE_HIR_ID;
@@ -478,6 +478,7 @@ struct MissingStabilityAnnotations<'tcx> {
 }
 
 impl<'tcx> MissingStabilityAnnotations<'tcx> {
+    /// Verify that deprecation and stability attributes make sense with one another.
     #[instrument(level = "trace", skip(self))]
     fn check_compatible_stability(&self, def_id: LocalDefId, item_sp: Span) {
         if !self.tcx.features().staged_api() {
@@ -539,17 +540,6 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
                     }
                 }
             }
-
-            // Stable *language* features shouldn't be used as unstable library features.
-            // (Not doing this for stable library features is checked by tidy.)
-            if let Stability { level: StabilityLevel::Unstable { .. }, feature } = stab
-                && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
-                && let Some(span) = find_attr_span!(Stability)
-            {
-                self.tcx
-                    .dcx()
-                    .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp });
-            }
         }
 
         // If the current node is a function with const stability attributes (directly given or
@@ -575,19 +565,6 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
                 .emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
         }
 
-        // Stable *language* features shouldn't be used as unstable library features.
-        // (Not doing this for stable library features is checked by tidy.)
-        if let Some(ConstStability { level: StabilityLevel::Unstable { .. }, feature, .. }) =
-            const_stab
-            && let Some(const_span) = find_attr_span!(ConstStability)
-            && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
-        {
-            self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
-                span: const_span,
-                item_sp,
-            });
-        }
-
         if let Some(stab) = &const_stab
             && stab.is_const_stable()
             && stab.const_stable_indirect
diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
index 319056a9c88..d599523c727 100644
--- a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
+++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
@@ -1,31 +1,31 @@
 error: can't mark as unstable using an already stable feature
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
    |
-LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | const fn my_fun() {}
    | -------------------- the stability attribute annotates this item
    |
 help: consider removing the attribute
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
    |
-LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: can't mark as unstable using an already stable feature
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
    |
+LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | const fn my_fun() {}
    | -------------------- the stability attribute annotates this item
    |
 help: consider removing the attribute
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
    |
-LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors