about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGurinder Singh <frederick.the.fool@gmail.com>2024-02-10 16:05:39 +0530
committerGurinder Singh <frederick.the.fool@gmail.com>2024-02-10 16:05:39 +0530
commit0815067796a653ac9dbf95ff651d74074a4b3788 (patch)
tree2e5125b64d5aa6c417d9977064c8b917e8e7c8a3
parent98aa3624be70462d6a25ed5544333e3df62f4c66 (diff)
downloadrust-0815067796a653ac9dbf95ff651d74074a4b3788.tar.gz
rust-0815067796a653ac9dbf95ff651d74074a4b3788.zip
Take empty `where` into account when suggesting predicates
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs8
-rw-r--r--tests/ui/trait-impl-bound-suggestions.fixed9
-rw-r--r--tests/ui/trait-impl-bound-suggestions.rs9
-rw-r--r--tests/ui/trait-impl-bound-suggestions.stderr18
4 files changed, 42 insertions, 2 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 13cc5cbed44..7cb326ce696 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>(
         //      trait Foo<T=()> {... }
         //                     - insert: `where T: Zar`
         if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
+            // If we are here and the where clause span is of non-zero length
+            // it means we're dealing with an empty where clause like this:
+            //      fn foo<X>(x: X) where { ... }
+            // In that case we don't want to add another "where" (Fixes #120838)
+            let where_prefix = if generics.where_clause_span.is_empty() { " where" } else { "" };
+
             // Suggest a bound, but there is no existing `where` clause *and* the type param has a
             // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
-                format!(" where {param_name}: {constraint}"),
+                format!("{where_prefix} {param_name}: {constraint}"),
                 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
             ));
             continue;
diff --git a/tests/ui/trait-impl-bound-suggestions.fixed b/tests/ui/trait-impl-bound-suggestions.fixed
index 744e7bef04e..fb11286a175 100644
--- a/tests/ui/trait-impl-bound-suggestions.fixed
+++ b/tests/ui/trait-impl-bound-suggestions.fixed
@@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
     }
 }
 
+// Regression test for #120838
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
 pub fn main() { }
diff --git a/tests/ui/trait-impl-bound-suggestions.rs b/tests/ui/trait-impl-bound-suggestions.rs
index bf75175179e..46130a5e766 100644
--- a/tests/ui/trait-impl-bound-suggestions.rs
+++ b/tests/ui/trait-impl-bound-suggestions.rs
@@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> {
     }
 }
 
+// Regression test for #120838
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
 pub fn main() { }
diff --git a/tests/ui/trait-impl-bound-suggestions.stderr b/tests/ui/trait-impl-bound-suggestions.stderr
index c1f31e2b32e..9883c5bda01 100644
--- a/tests/ui/trait-impl-bound-suggestions.stderr
+++ b/tests/ui/trait-impl-bound-suggestions.stderr
@@ -14,6 +14,22 @@ help: consider further restricting type parameter `X`
 LL | trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
    |                                              ++++++++++++++++++++++++++
 
-error: aborting due to 1 previous error
+error[E0277]: the trait bound `X: Copy` is not satisfied
+  --> $DIR/trait-impl-bound-suggestions.rs:23:52
+   |
+LL |     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
+   |
+note: required by a bound in `ConstrainedStruct`
+  --> $DIR/trait-impl-bound-suggestions.rs:8:29
+   |
+LL | struct ConstrainedStruct<X: Copy> {
+   |                             ^^^^ required by this bound in `ConstrainedStruct`
+help: consider further restricting type parameter `X`
+   |
+LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
+   |                                                                  ++++++++++++++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.