about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-05-06 22:36:43 +0200
committerGitHub <noreply@github.com>2020-05-06 22:36:43 +0200
commitce14d6db5a7a7896d2fc7713a482cc3b810b9102 (patch)
tree447323cd2ce31fd4fbbfd24c372d9ffa5931fe1a /src/test
parent1836e3b42a5b2f37fd79104eedbe8f48a5afdee6 (diff)
parentb17b20cafc87193dace2beb1cdb0e126d944f8e3 (diff)
downloadrust-ce14d6db5a7a7896d2fc7713a482cc3b810b9102.tar.gz
rust-ce14d6db5a7a7896d2fc7713a482cc3b810b9102.zip
Rollup merge of #70908 - estebank:suggest-add, r=nikomatsakis
Provide suggestions for type parameters missing bounds for associated types

When implementing the binary operator traits it is easy to forget to restrict the `Output` associated type. `rustc` now accounts for different cases to lead users in the right direction to add the necessary restrictions. The structured suggestions in the following output are new:

```
error: equality constraints are not yet supported in `where` clauses
  --> $DIR/missing-bounds.rs:37:33
   |
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
   |                                 ^^^^^^^^^^^^^^^^^^^^^^ not supported
   |
   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
   |
LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
   |                                 ^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> $DIR/missing-bounds.rs:11:11
   |
7  | impl<B> Add for A<B> where B: Add {
   |      - this type parameter
...
11 |         A(self.0 + rhs.0)
   |           ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
   |
   = note: expected type parameter `B`
             found associated type `<B as std::ops::Add>::Output`
help: consider further restricting this bound
   |
7  | impl<B> Add for A<B> where B: Add + std::ops::Add<Output = B> {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0369]: cannot add `B` to `B`
  --> $DIR/missing-bounds.rs:31:21
   |
31 |         Self(self.0 + rhs.0)
   |              ------ ^ ----- B
   |              |
   |              B
   |
help: consider restricting type parameter `B`
   |
27 | impl<B: std::ops::Add<Output = B>> Add for D<B> {
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

That output is given for the following cases:

```rust
struct A<B>(B);
impl<B> Add for A<B> where B: Add {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        A(self.0 + rhs.0) //~ ERROR mismatched types
    }
}

struct D<B>(B);
impl<B> Add for D<B> {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B`
    }
}

struct E<B>(B);
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Self(self.0 + rhs.0)
    }
}
```
Diffstat (limited to 'src/test')
-rw-r--r--src/test/ui/generic-associated-types/construct_with_other_type.stderr9
-rw-r--r--src/test/ui/generic-associated-types/missing-bounds.fixed46
-rw-r--r--src/test/ui/generic-associated-types/missing-bounds.rs46
-rw-r--r--src/test/ui/generic-associated-types/missing-bounds.stderr77
-rw-r--r--src/test/ui/issues/issue-20005.stderr12
-rw-r--r--src/test/ui/issues/issue-24204.stderr4
-rw-r--r--src/test/ui/issues/issue-6738.stderr5
-rw-r--r--src/test/ui/type/type-check/missing_trait_impl.stderr10
8 files changed, 200 insertions, 9 deletions
diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.stderr b/src/test/ui/generic-associated-types/construct_with_other_type.stderr
index bad746f7ef1..b9468b3330b 100644
--- a/src/test/ui/generic-associated-types/construct_with_other_type.stderr
+++ b/src/test/ui/generic-associated-types/construct_with_other_type.stderr
@@ -2,11 +2,16 @@ error[E0271]: type mismatch resolving `for<'a> <<T as Baz>::Baa<'a> as std::ops:
   --> $DIR/construct_with_other_type.rs:19:9
    |
 LL | impl<T> Baz for T where T: Foo {
-   |         ^^^ expected type parameter `T`, found associated type
+   |      -  ^^^ expected type parameter `T`, found associated type
+   |      |
+   |      this type parameter
    |
    = note: expected associated type `<T as Foo>::Bar<'_, 'static>`
               found associated type `<<T as Baz>::Quux<'_> as Foo>::Bar<'_, 'static>`
-   = note: you might be missing a type parameter or trait bound
+help: consider further restricting this bound
+   |
+LL | impl<T> Baz for T where T: Foo + Baz<Quux = T> {
+   |                                ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed
new file mode 100644
index 00000000000..364d2388741
--- /dev/null
+++ b/src/test/ui/generic-associated-types/missing-bounds.fixed
@@ -0,0 +1,46 @@
+// run-rustfix
+
+use std::ops::Add;
+
+struct A<B>(B);
+
+impl<B> Add for A<B> where B: Add + std::ops::Add<Output = B> {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        A(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+struct C<B>(B);
+
+impl<B: Add + std::ops::Add<Output = B>> Add for C<B> {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+struct D<B>(B);
+
+impl<B: std::ops::Add<Output = B>> Add for D<B> {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B`
+    }
+}
+
+struct E<B>(B);
+
+impl<B: Add> Add for E<B> where B: Add<Output = B>, B: std::ops::Add<Output = B> {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/missing-bounds.rs b/src/test/ui/generic-associated-types/missing-bounds.rs
new file mode 100644
index 00000000000..ffafff5e9f5
--- /dev/null
+++ b/src/test/ui/generic-associated-types/missing-bounds.rs
@@ -0,0 +1,46 @@
+// run-rustfix
+
+use std::ops::Add;
+
+struct A<B>(B);
+
+impl<B> Add for A<B> where B: Add {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        A(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+struct C<B>(B);
+
+impl<B: Add> Add for C<B> {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+struct D<B>(B);
+
+impl<B> Add for D<B> {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B`
+    }
+}
+
+struct E<B>(B);
+
+impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr
new file mode 100644
index 00000000000..50536fdaca9
--- /dev/null
+++ b/src/test/ui/generic-associated-types/missing-bounds.stderr
@@ -0,0 +1,77 @@
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/missing-bounds.rs:37:33
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
+   |                                 ^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/missing-bounds.rs:11:11
+   |
+LL | impl<B> Add for A<B> where B: Add {
+   |      - this type parameter
+...
+LL |         A(self.0 + rhs.0)
+   |           ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |
+   = note: expected type parameter `B`
+             found associated type `<B as std::ops::Add>::Output`
+help: consider further restricting this bound
+   |
+LL | impl<B> Add for A<B> where B: Add + std::ops::Add<Output = B> {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/missing-bounds.rs:21:14
+   |
+LL | impl<B: Add> Add for C<B> {
+   |      - this type parameter
+...
+LL |         Self(self.0 + rhs.0)
+   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |
+   = note: expected type parameter `B`
+             found associated type `<B as std::ops::Add>::Output`
+help: consider further restricting this bound
+   |
+LL | impl<B: Add + std::ops::Add<Output = B>> Add for C<B> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0369]: cannot add `B` to `B`
+  --> $DIR/missing-bounds.rs:31:21
+   |
+LL |         Self(self.0 + rhs.0)
+   |              ------ ^ ----- B
+   |              |
+   |              B
+   |
+help: consider restricting type parameter `B`
+   |
+LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/missing-bounds.rs:42:14
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |      - this type parameter
+...
+LL |         Self(self.0 + rhs.0)
+   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |
+   = note: expected type parameter `B`
+             found associated type `<B as std::ops::Add>::Output`
+help: consider further restricting type parameter `B`
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: std::ops::Add<Output = B> {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr
index 19ccf707619..f53489a99f3 100644
--- a/src/test/ui/issues/issue-20005.stderr
+++ b/src/test/ui/issues/issue-20005.stderr
@@ -5,12 +5,18 @@ LL | trait From<Src> {
    |            --- required by this bound in `From`
 ...
 LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
-   |                                                 ^^^^^^^^^^- help: consider further restricting `Self`: `, Self: std::marker::Sized`
-   |                                                 |
-   |                                                 doesn't have a size known at compile-time
+   |                                                 ^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `Self`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+help: consider further restricting `Self`
+   |
+LL |     ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: std::marker::Sized  {
+   |                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait From<Src: ?Sized> {
+   |               ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr
index d69efc86005..d5cbcf786bf 100644
--- a/src/test/ui/issues/issue-24204.stderr
+++ b/src/test/ui/issues/issue-24204.stderr
@@ -7,7 +7,9 @@ LL |     type A: MultiDispatch<Self::B, O = Self>;
    |                                    -------- required by this bound in `Trait`
 ...
 LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
-   |            ^^^^^^^^^^^^ expected type parameter `T`, found associated type
+   |         -  ^^^^^^^^^^^^ expected type parameter `T`, found associated type
+   |         |
+   |         this type parameter
    |
    = note: expected type parameter `T`
              found associated type `<<T as Trait>::A as MultiDispatch<i32>>::O`
diff --git a/src/test/ui/issues/issue-6738.stderr b/src/test/ui/issues/issue-6738.stderr
index 82b670bd03b..a428ff7e91f 100644
--- a/src/test/ui/issues/issue-6738.stderr
+++ b/src/test/ui/issues/issue-6738.stderr
@@ -6,7 +6,10 @@ LL |         self.x += v.x;
    |         |
    |         cannot use `+=` on type `T`
    |
-   = note: `T` might need a bound for `std::ops::AddAssign`
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::ops::AddAssign> Foo<T> {
+   |       ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check/missing_trait_impl.stderr b/src/test/ui/type/type-check/missing_trait_impl.stderr
index 7186d6a542d..30df1261cef 100644
--- a/src/test/ui/type/type-check/missing_trait_impl.stderr
+++ b/src/test/ui/type/type-check/missing_trait_impl.stderr
@@ -6,7 +6,10 @@ LL |     let z = x + y;
    |             |
    |             T
    |
-   = note: `T` might need a bound for `std::ops::Add`
+help: consider restricting type parameter `T`
+   |
+LL | fn foo<T: std::ops::Add<Output = T>>(x: T, y: T) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
   --> $DIR/missing_trait_impl.rs:9:5
@@ -16,7 +19,10 @@ LL |     x += x;
    |     |
    |     cannot use `+=` on type `T`
    |
-   = note: `T` might need a bound for `std::ops::AddAssign`
+help: consider restricting type parameter `T`
+   |
+LL | fn bar<T: std::ops::AddAssign>(x: T) {
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors