about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl3
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs10
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs8
-rw-r--r--tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.rs14
-rw-r--r--tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.stderr10
5 files changed, 45 insertions, 0 deletions
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 8d0ead63a8d..35ff48cb5f2 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -136,6 +136,9 @@ attr_parsing_unrecognized_repr_hint =
 attr_parsing_unstable_cfg_target_compact =
     compact `cfg(target(..))` is experimental and subject to change
 
+attr_parsing_unstable_feature_bound_incompatible_stability = Item annotated with `#[unstable_feature_bound]` should not be stable
+    .help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
+
 attr_parsing_unsupported_literal_cfg_boolean =
     literal in `cfg` predicate value must be a boolean
 attr_parsing_unsupported_literal_cfg_string =
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 6bccd0042a8..8f405e5aad9 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -98,6 +98,16 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
             }
         }
 
+        if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability {
+            for other_attr in cx.all_attrs {
+                if other_attr.word_is(sym::unstable_feature_bound) {
+                    cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability {
+                        span: cx.target_span,
+                    });
+                }
+            }
+        }
+
         let (stability, span) = self.stability?;
 
         Some(AttributeKind::Stability { stability, span })
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 97bf3d1c549..5b0bf0e6662 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -504,6 +504,14 @@ pub(crate) struct UnrecognizedReprHint {
 }
 
 #[derive(Diagnostic)]
+#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
+#[help]
+pub(crate) struct UnstableFeatureBoundIncompatibleStability {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
 pub(crate) struct NakedFunctionIncompatibleAttribute {
     #[primary_span]
diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.rs b/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.rs
new file mode 100644
index 00000000000..1a9652c1023
--- /dev/null
+++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.rs
@@ -0,0 +1,14 @@
+#![allow(internal_features)]
+#![feature(staged_api)]
+#![allow(dead_code)]
+#![stable(feature = "a", since = "1.1.1" )]
+
+// Lint against the usage of both #[unstable_feature_bound] and #[stable] on the
+// same item.
+
+#[stable(feature = "a", since = "1.1.1")]
+#[unstable_feature_bound(feat_bar)]
+fn bar() {}
+//~^ ERROR Item annotated with `#[unstable_feature_bound]` should not be stable
+
+fn main() {}
diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.stderr b/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.stderr
new file mode 100644
index 00000000000..9cb6a181bef
--- /dev/null
+++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_incompatible_stability.stderr
@@ -0,0 +1,10 @@
+error: Item annotated with `#[unstable_feature_bound]` should not be stable
+  --> $DIR/unstable_feature_bound_incompatible_stability.rs:11:1
+   |
+LL | fn bar() {}
+   | ^^^^^^^^^^^
+   |
+   = help: If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
+
+error: aborting due to 1 previous error
+