about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs32
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr10
-rw-r--r--tests/ui/mir/validate/validate-unsize-cast.stderr2
-rw-r--r--tests/ui/trait-bounds/unstable-trait-suggestion.rs15
-rw-r--r--tests/ui/trait-bounds/unstable-trait-suggestion.stderr21
-rw-r--r--tests/ui/tuple/builtin-fail.stderr2
6 files changed, 67 insertions, 15 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index fd807882e0f..b08e1632f65 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,6 +1,5 @@
 //! Diagnostics related methods for `Ty`.
 
-use std::borrow::Cow;
 use std::fmt::Write;
 use std::ops::ControlFlow;
 
@@ -278,8 +277,21 @@ pub fn suggest_constraining_type_params<'a>(
     span_to_replace: Option<Span>,
 ) -> bool {
     let mut grouped = FxHashMap::default();
+    let mut unstable_suggestion = false;
     param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
-        grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id))
+        let stable = match def_id {
+            Some(def_id) => match tcx.lookup_stability(def_id) {
+                Some(s) => s.level.is_stable(),
+                None => true,
+            },
+            None => true,
+        };
+        if stable || tcx.sess.is_nightly_build() {
+            grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id));
+            if !stable {
+                unstable_suggestion = true;
+            }
+        }
     });
 
     let mut applicability = Applicability::MachineApplicable;
@@ -464,28 +476,32 @@ pub fn suggest_constraining_type_params<'a>(
 
     if suggestions.len() == 1 {
         let (span, suggestion, msg) = suggestions.pop().unwrap();
+        let post = if unstable_suggestion { " but it is an `unstable` trait" } else { "" };
         let msg = match msg {
             SuggestChangingConstraintsMessage::RestrictBoundFurther => {
-                Cow::from("consider further restricting this bound")
+                format!("consider further restricting this bound{post}")
             }
             SuggestChangingConstraintsMessage::RestrictType { ty } => {
-                Cow::from(format!("consider restricting type parameter `{ty}`"))
+                format!("consider restricting type parameter `{ty}`{post}")
             }
             SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
-                Cow::from(format!("consider further restricting type parameter `{ty}`"))
+                format!("consider further restricting type parameter `{ty}`{post}")
             }
             SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
-                Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
+                format!(
+                    "consider removing the `?Sized` bound to make the type parameter `Sized`{post}"
+                )
             }
             SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
-                Cow::from("consider replacing `?Sized` with `Sized`")
+                format!("consider replacing `?Sized` with `Sized`{post}")
             }
         };
 
         err.span_suggestion_verbose(span, msg, suggestion, applicability);
     } else if suggestions.len() > 1 {
+        let post = if unstable_suggestion { " but some of them are `unstable` traits" } else { "" };
         err.multipart_suggestion_verbose(
-            "consider restricting type parameters",
+            format!("consider restricting type parameters{post}"),
             suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
             applicability,
         );
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
index 206a6801065..17506dadb9f 100644
--- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -6,7 +6,7 @@ LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
    |
 note: required by a bound in `FnOnce`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -19,7 +19,7 @@ LL | impl<A, B> FnMut<A> for CachedFun<A, B>
    |
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -30,7 +30,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
 LL |     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
    |
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -41,7 +41,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
 LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
    |
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
@@ -56,7 +56,7 @@ LL |         self.call_mut(a)
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
diff --git a/tests/ui/mir/validate/validate-unsize-cast.stderr b/tests/ui/mir/validate/validate-unsize-cast.stderr
index cfb47b34e98..513e1e597bf 100644
--- a/tests/ui/mir/validate/validate-unsize-cast.stderr
+++ b/tests/ui/mir/validate/validate-unsize-cast.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `CastTo`
    |
 LL | pub trait CastTo<U: ?Sized>: Unsize<U> {}
    |                              ^^^^^^^^^ required by this bound in `CastTo`
-help: consider further restricting this bound
+help: consider further restricting this bound but it is an `unstable` trait
    |
 LL | impl<T: ?Sized + std::marker::Unsize<U>, U: ?Sized> CastTo<U> for T {}
    |                ++++++++++++++++++++++++
diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.rs b/tests/ui/trait-bounds/unstable-trait-suggestion.rs
new file mode 100644
index 00000000000..fff61e4a6f5
--- /dev/null
+++ b/tests/ui/trait-bounds/unstable-trait-suggestion.rs
@@ -0,0 +1,15 @@
+#![feature(staged_api)]
+#![allow(internal_features)]
+#![stable(feature = "unit_test", since = "1.0.0")]
+
+#[unstable(feature = "step_trait", issue = "42168")]
+pub trait Unstable {}
+
+#[stable(feature = "unit_test", since = "1.0.0")]
+fn foo<T: Unstable>(_: T) {}
+
+#[stable(feature = "unit_test", since = "1.0.0")]
+pub fn demo<T>(t: T) { //~ HELP consider restricting type parameter `T` but it is an `unstable` trait
+    foo(t) //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr
new file mode 100644
index 00000000000..7b5e9f8d124
--- /dev/null
+++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: Unstable` is not satisfied
+  --> $DIR/unstable-trait-suggestion.rs:13:9
+   |
+LL |     foo(t)
+   |     --- ^ the trait `Unstable` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/unstable-trait-suggestion.rs:9:11
+   |
+LL | fn foo<T: Unstable>(_: T) {}
+   |           ^^^^^^^^ required by this bound in `foo`
+help: consider restricting type parameter `T` but it is an `unstable` trait
+   |
+LL | pub fn demo<T: Unstable>(t: T) {
+   |              ++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr
index e3e29a73fdc..cc295dabb17 100644
--- a/tests/ui/tuple/builtin-fail.stderr
+++ b/tests/ui/tuple/builtin-fail.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `assert_is_tuple`
    |
 LL | fn assert_is_tuple<T: std::marker::Tuple + ?Sized>() {}
    |                       ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple`
-help: consider restricting type parameter `T`
+help: consider restricting type parameter `T` but it is an `unstable` trait
    |
 LL | fn from_param_env<T: std::marker::Tuple>() {
    |                    ++++++++++++++++++++