about summary refs log tree commit diff
path: root/tests/ui/trait-bounds
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/trait-bounds')
-rw-r--r--tests/ui/trait-bounds/impl-bound-with-references-error.rs20
-rw-r--r--tests/ui/trait-bounds/impl-bound-with-references-error.stderr24
-rw-r--r--tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs33
-rw-r--r--tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr31
-rw-r--r--tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs36
-rw-r--r--tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr31
-rw-r--r--tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs38
-rw-r--r--tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr36
-rw-r--r--tests/ui/trait-bounds/issue-75961.rs7
-rw-r--r--tests/ui/trait-bounds/issue-93008.rs15
-rw-r--r--tests/ui/trait-bounds/issue-94680.rs14
-rw-r--r--tests/ui/trait-bounds/issue-94999.rs34
-rw-r--r--tests/ui/trait-bounds/issue-95640.rs31
-rw-r--r--tests/ui/trait-bounds/mismatch-fn-trait.rs28
-rw-r--r--tests/ui/trait-bounds/mismatch-fn-trait.stderr81
-rw-r--r--tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed16
-rw-r--r--tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs14
-rw-r--r--tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr19
-rw-r--r--tests/ui/trait-bounds/unsized-bound.rs32
-rw-r--r--tests/ui/trait-bounds/unsized-bound.stderr273
20 files changed, 813 insertions, 0 deletions
diff --git a/tests/ui/trait-bounds/impl-bound-with-references-error.rs b/tests/ui/trait-bounds/impl-bound-with-references-error.rs
new file mode 100644
index 00000000000..e5d0a1aaed0
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-bound-with-references-error.rs
@@ -0,0 +1,20 @@
+// Regression test for #105138.
+// This test ensures that the compiler does not add note
+// for implementation of trait whose inner type is erroneous.
+
+pub enum LabelText {
+    Plain,
+}
+
+impl<T> From<T> for LabelText
+//~^ ERROR conflicting implementations of trait `From<LabelText>` for type `LabelText` [E0119]
+where
+    T: Into<Cow<'static, str>>,
+    //~^ ERROR cannot find type `Cow` in this scope [E0412]
+{
+    fn from(text: T) -> Self {
+        LabelText::Plain(text.into())
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/impl-bound-with-references-error.stderr b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr
new file mode 100644
index 00000000000..95fd6bd504c
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr
@@ -0,0 +1,24 @@
+error[E0412]: cannot find type `Cow` in this scope
+  --> $DIR/impl-bound-with-references-error.rs:12:13
+   |
+LL |     T: Into<Cow<'static, str>>,
+   |             ^^^ not found in this scope
+   |
+help: consider importing this enum
+   |
+LL | use std::borrow::Cow;
+   |
+
+error[E0119]: conflicting implementations of trait `From<LabelText>` for type `LabelText`
+  --> $DIR/impl-bound-with-references-error.rs:9:1
+   |
+LL | impl<T> From<T> for LabelText
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> From<T> for T;
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0412.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs
new file mode 100644
index 00000000000..557d890882b
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs
@@ -0,0 +1,33 @@
+struct Victim<'a, T: Perpetrator + ?Sized> {
+  value: u8,
+  perp: &'a T,
+}
+
+trait VictimTrait {
+  type Ret;
+  fn get(self) -> Self::Ret;
+}
+
+// Actual fix is here
+impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+  type Ret = u8;
+  fn get(self) -> Self::Ret {
+    self.value
+  }
+}
+
+trait Perpetrator {
+  fn getter<'a>(&'a self) -> Victim<'a, Self> {
+    Victim {
+      value: 0,
+      perp: self,
+    }
+  }
+
+  fn trigger(&self) {
+    self.getter().get();
+    //~^ ERROR the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied
+  }
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr
new file mode 100644
index 00000000000..543ceac8e91
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr
@@ -0,0 +1,31 @@
+error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied
+  --> $DIR/impl-derived-implicit-sized-bound-2.rs:28:19
+   |
+LL | struct Victim<'a, T: Perpetrator + ?Sized> {
+   | ------------------------------------------
+   | |
+   | method `get` not found for this struct
+   | doesn't satisfy `Victim<'_, Self>: VictimTrait`
+...
+LL |     self.getter().get();
+   |                   ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds
+   |
+note: trait bound `Self: Sized` was not satisfied
+  --> $DIR/impl-derived-implicit-sized-bound-2.rs:12:10
+   |
+LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+   |          ^                            -----------     -------------
+   |          |
+   |          unsatisfied trait bound introduced here
+help: consider relaxing the type parameter's implicit `Sized` bound
+   |
+LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+   |             ++++++++
+help: consider restricting the type parameter to satisfy the trait bound
+   |
+LL | struct Victim<'a, T: Perpetrator + ?Sized> where Self: Sized {
+   |                                            +++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs
new file mode 100644
index 00000000000..28da41a0ca5
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs
@@ -0,0 +1,36 @@
+struct Victim<'a, T: Perpetrator + ?Sized>
+where
+  Self: Sized
+{
+  value: u8,
+  perp: &'a T,
+}
+
+trait VictimTrait {
+  type Ret;
+  fn get(self) -> Self::Ret;
+}
+
+// Actual fix is here
+impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+  type Ret = u8;
+  fn get(self) -> Self::Ret {
+    self.value
+  }
+}
+
+trait Perpetrator {
+  fn getter<'a>(&'a self) -> Victim<'a, Self> {
+    Victim {
+      value: 0,
+      perp: self,
+    }
+  }
+
+  fn trigger(&self) {
+    self.getter().get();
+    //~^ ERROR the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied
+  }
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr
new file mode 100644
index 00000000000..f08d685836e
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr
@@ -0,0 +1,31 @@
+error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied
+  --> $DIR/impl-derived-implicit-sized-bound.rs:31:19
+   |
+LL | struct Victim<'a, T: Perpetrator + ?Sized>
+   | ------------------------------------------
+   | |
+   | method `get` not found for this struct
+   | doesn't satisfy `Victim<'_, Self>: VictimTrait`
+...
+LL |     self.getter().get();
+   |                   ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds
+   |
+note: trait bound `Self: Sized` was not satisfied
+  --> $DIR/impl-derived-implicit-sized-bound.rs:15:10
+   |
+LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+   |          ^                            -----------     -------------
+   |          |
+   |          unsatisfied trait bound introduced here
+help: consider relaxing the type parameter's implicit `Sized` bound
+   |
+LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {
+   |             ++++++++
+help: consider restricting the type parameter to satisfy the trait bound
+   |
+LL |   Self: Sized, Self: Sized
+   |              +++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
new file mode 100644
index 00000000000..dcdbd022873
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
@@ -0,0 +1,38 @@
+trait Trait<T> {
+    fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+}
+
+impl Trait<()> for () {
+    fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195
+        todo!();
+    }
+}
+
+struct State;
+
+trait Foo<T> {
+    fn foo<'a>(&self, state: &'a State) -> &'a T
+    where
+        T: 'a;
+}
+
+impl<F, T> Foo<T> for F
+where
+    F: Fn(&State) -> &T,
+{
+    fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195
+        self(state)
+    }
+}
+
+trait Bar {
+    fn foo<'a>(&'a self) {}
+}
+
+impl Bar for () {
+    fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195
+}
+
+fn main() {
+    ().foo((), ());
+}
diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
new file mode 100644
index 00000000000..e26cb22163f
--- /dev/null
+++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
@@ -0,0 +1,36 @@
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11
+   |
+LL |     fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+   |           -------                            --     -- this bound might be missing in the impl
+   |           |                                  |
+   |           |                                  this bound might be missing in the impl
+   |           lifetimes in impl do not match this method in trait
+...
+LL |     fn foo<'a, K>(self, _: (), _: K) where {
+   |           ^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
+   |
+LL |     fn foo<'a>(&self, state: &'a State) -> &'a T
+   |           ---- lifetimes in impl do not match this method in trait
+LL |     where
+LL |         T: 'a;
+   |            -- this bound might be missing in the impl
+...
+LL |     fn foo<'a>(&self, state: &'a State) -> &'a T {
+   |           ^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
+   |
+LL |     fn foo<'a>(&'a self) {}
+   |           ---- lifetimes in impl do not match this method in trait
+...
+LL |     fn foo<'a: 'a>(&'a self) {}
+   |           ^^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/trait-bounds/issue-75961.rs b/tests/ui/trait-bounds/issue-75961.rs
new file mode 100644
index 00000000000..367eac7182a
--- /dev/null
+++ b/tests/ui/trait-bounds/issue-75961.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    <&mut () as Clone>::clone(&s);
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/issue-93008.rs b/tests/ui/trait-bounds/issue-93008.rs
new file mode 100644
index 00000000000..f4d21a160b6
--- /dev/null
+++ b/tests/ui/trait-bounds/issue-93008.rs
@@ -0,0 +1,15 @@
+// build-pass
+// compile-flags: -Zmir-opt-level=3 --crate-type=lib
+
+#![feature(trivial_bounds)]
+#![allow(trivial_bounds)]
+
+trait Foo {
+    fn test(self);
+}
+fn baz<T>()
+where
+    &'static str: Foo,
+{
+    "Foo".test()
+}
diff --git a/tests/ui/trait-bounds/issue-94680.rs b/tests/ui/trait-bounds/issue-94680.rs
new file mode 100644
index 00000000000..58e892079e6
--- /dev/null
+++ b/tests/ui/trait-bounds/issue-94680.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+fn main() {
+    println!("{:?}", {
+        type T = ();
+
+        pub fn cloneit(it: &'_ mut T) -> (&'_ mut T, &'_ mut T)
+        where
+            for<'any> &'any mut T: Clone,
+        {
+            (it.clone(), it)
+        }
+    });
+}
diff --git a/tests/ui/trait-bounds/issue-94999.rs b/tests/ui/trait-bounds/issue-94999.rs
new file mode 100644
index 00000000000..e131902346f
--- /dev/null
+++ b/tests/ui/trait-bounds/issue-94999.rs
@@ -0,0 +1,34 @@
+// check-pass
+
+trait Identity<Q> {
+    type T;
+}
+
+impl<Q, T> Identity<Q> for T {
+    type T = T;
+}
+
+trait Holds {
+    type Q;
+}
+
+struct S;
+struct X(S);
+
+struct XHelper;
+
+impl Holds for X {
+    type Q = XHelper;
+}
+
+impl<Q> Clone for X
+where
+    <S as Identity<Q>>::T: Clone,
+    X: Holds<Q = Q>,
+{
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/issue-95640.rs b/tests/ui/trait-bounds/issue-95640.rs
new file mode 100644
index 00000000000..e4e998b5d0b
--- /dev/null
+++ b/tests/ui/trait-bounds/issue-95640.rs
@@ -0,0 +1,31 @@
+// build-pass
+// compile-flags:-Zmir-opt-level=3
+
+struct D;
+
+trait Tr {
+    type It;
+    fn foo(self) -> Option<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+    type It = ();
+    fn foo(self) -> Option<()> {
+        None
+    }
+}
+
+fn run<F>(f: F)
+where
+    for<'a> &'a D: Tr,
+    F: Fn(<&D as Tr>::It),
+{
+    let d = &D;
+    while let Some(i) = d.foo() {
+        f(i);
+    }
+}
+
+fn main() {
+    run(|_| {});
+}
diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.rs b/tests/ui/trait-bounds/mismatch-fn-trait.rs
new file mode 100644
index 00000000000..0ed64043a9a
--- /dev/null
+++ b/tests/ui/trait-bounds/mismatch-fn-trait.rs
@@ -0,0 +1,28 @@
+fn take(_f: impl FnMut(i32)) {}
+
+fn test1(f: impl FnMut(u32)) {
+    take(f)
+    //~^ ERROR [E0277]
+}
+
+fn test2(f: impl FnMut(i32, i32)) {
+    take(f)
+    //~^ ERROR [E0277]
+}
+
+fn test3(f: impl FnMut()) {
+    take(f)
+    //~^ ERROR [E0277]
+}
+
+fn test4(f: impl FnOnce(i32)) {
+    take(f)
+    //~^ ERROR [E0277]
+}
+
+fn test5(f: impl FnOnce(u32)) {
+    take(f)
+    //~^ ERROR [E0277]
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
new file mode 100644
index 00000000000..961e6d88fbe
--- /dev/null
+++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
@@ -0,0 +1,81 @@
+error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(u32)`
+  --> $DIR/mismatch-fn-trait.rs:4:10
+   |
+LL |     take(f)
+   |     ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(u32)`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: expected a closure with arguments `(u32,)`
+              found a closure with arguments `(i32,)`
+note: required by a bound in `take`
+  --> $DIR/mismatch-fn-trait.rs:1:18
+   |
+LL | fn take(_f: impl FnMut(i32)) {}
+   |                  ^^^^^^^^^^ required by this bound in `take`
+
+error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)`
+  --> $DIR/mismatch-fn-trait.rs:9:10
+   |
+LL |     take(f)
+   |     ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: expected a closure taking 2 arguments, but one taking 1 argument was given
+note: required by a bound in `take`
+  --> $DIR/mismatch-fn-trait.rs:1:18
+   |
+LL | fn take(_f: impl FnMut(i32)) {}
+   |                  ^^^^^^^^^^ required by this bound in `take`
+
+error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut()`
+  --> $DIR/mismatch-fn-trait.rs:14:10
+   |
+LL |     take(f)
+   |     ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: expected a closure taking 0 arguments, but one taking 1 argument was given
+note: required by a bound in `take`
+  --> $DIR/mismatch-fn-trait.rs:1:18
+   |
+LL | fn take(_f: impl FnMut(i32)) {}
+   |                  ^^^^^^^^^^ required by this bound in `take`
+
+error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(i32)`
+  --> $DIR/mismatch-fn-trait.rs:19:10
+   |
+LL |     take(f)
+   |     ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(i32)`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: `impl FnOnce(i32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
+note: required by a bound in `take`
+  --> $DIR/mismatch-fn-trait.rs:1:18
+   |
+LL | fn take(_f: impl FnMut(i32)) {}
+   |                  ^^^^^^^^^^ required by this bound in `take`
+
+error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(u32)`
+  --> $DIR/mismatch-fn-trait.rs:24:10
+   |
+LL |     take(f)
+   |     ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(u32)`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
+   = note: expected a closure with arguments `(u32,)`
+              found a closure with arguments `(i32,)`
+note: required by a bound in `take`
+  --> $DIR/mismatch-fn-trait.rs:1:18
+   |
+LL | fn take(_f: impl FnMut(i32)) {}
+   |                  ^^^^^^^^^^ required by this bound in `take`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed
new file mode 100644
index 00000000000..39e90d7a3f7
--- /dev/null
+++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+#![allow(non_snake_case)]
+mod A {
+    pub trait Trait {}
+    impl Trait for i32 {}
+}
+
+mod B {
+    use A::Trait;
+
+pub struct A<H: Trait>(pub H); //~ ERROR cannot find trait
+}
+
+fn main() {
+    let _ = B::A(42);
+}
diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs
new file mode 100644
index 00000000000..ee6ed0cae67
--- /dev/null
+++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+#![allow(non_snake_case)]
+mod A {
+    pub trait Trait {}
+    impl Trait for i32 {}
+}
+
+mod B {
+    pub struct A<H: A::Trait>(pub H); //~ ERROR cannot find trait
+}
+
+fn main() {
+    let _ = B::A(42);
+}
diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr
new file mode 100644
index 00000000000..b297662955e
--- /dev/null
+++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr
@@ -0,0 +1,19 @@
+error[E0405]: cannot find trait `Trait` in `A`
+  --> $DIR/shadowed-path-in-trait-bound-suggestion.rs:9:24
+   |
+LL |     pub struct A<H: A::Trait>(pub H);
+   |                        ^^^^^ not found in `A`
+   |
+help: consider importing this trait
+   |
+LL |     use A::Trait;
+   |
+help: if you import `Trait`, refer to it directly
+   |
+LL -     pub struct A<H: A::Trait>(pub H);
+LL +     pub struct A<H: Trait>(pub H);
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/trait-bounds/unsized-bound.rs b/tests/ui/trait-bounds/unsized-bound.rs
new file mode 100644
index 00000000000..035b8ef1bde
--- /dev/null
+++ b/tests/ui/trait-bounds/unsized-bound.rs
@@ -0,0 +1,32 @@
+trait Trait<A> {}
+impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
+//~^ ERROR E0277
+//~| ERROR E0277
+impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+//~^ ERROR E0277
+//~| ERROR E0277
+//~| ERROR E0277
+trait Trait2<A> {}
+impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+//~^ ERROR E0277
+//~| ERROR E0277
+trait Trait3<A> {}
+impl<A> Trait3<A> for A where A: ?Sized {}
+//~^ ERROR E0277
+trait Trait4<A> {}
+impl<A: ?Sized> Trait4<A> for A {}
+//~^ ERROR E0277
+trait Trait5<A, B> {}
+impl<X, Y> Trait5<X, Y> for X where X: ?Sized {}
+//~^ ERROR E0277
+trait Trait6<A, B> {}
+impl<X: ?Sized, Y> Trait6<X, Y> for X {}
+//~^ ERROR E0277
+trait Trait7<A, B> {}
+impl<X, Y> Trait7<X, Y> for X where Y: ?Sized {}
+//~^ ERROR E0277
+trait Trait8<A, B> {}
+impl<X, Y: ?Sized> Trait8<X, Y> for X {}
+//~^ ERROR E0277
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr
new file mode 100644
index 00000000000..ec85ada7a8d
--- /dev/null
+++ b/tests/ui/trait-bounds/unsized-bound.stderr
@@ -0,0 +1,273 @@
+error[E0277]: the size for values of type `B` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:2:12
+   |
+LL | impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
+   |         -  ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         this type parameter needs to be `std::marker::Sized`
+   |
+   = note: required because it appears within the type `(A, B)`
+note: required by a bound in `Trait`
+  --> $DIR/unsized-bound.rs:1:13
+   |
+LL | trait Trait<A> {}
+   |             ^ required by this bound in `Trait`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
+LL + impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait<A: ?Sized> {}
+   |              ++++++++
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:2:30
+   |
+LL | impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
+   |      -                       ^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+   = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
+LL + impl<A, B> Trait<(A, B)> for (A, B) where B: ?Sized, {}
+   |
+
+error[E0277]: the size for values of type `C` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:5:31
+   |
+LL | impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+   |                    -          ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    |
+   |                    this type parameter needs to be `std::marker::Sized`
+   |
+   = note: required because it appears within the type `(A, B, C)`
+note: required by a bound in `Trait`
+  --> $DIR/unsized-bound.rs:1:13
+   |
+LL | trait Trait<A> {}
+   |             ^ required by this bound in `Trait`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+LL + impl<A, B: ?Sized, C> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait<A: ?Sized> {}
+   |              ++++++++
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:5:52
+   |
+LL | impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+   |      -                                             ^^^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+   = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+LL + impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C)  {}
+   |
+
+error[E0277]: the size for values of type `B` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:5:52
+   |
+LL | impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+   |         -                                          ^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         this type parameter needs to be `std::marker::Sized`
+   |
+   = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+LL + impl<A, B, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
+   |
+
+error[E0277]: the size for values of type `B` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:10:28
+   |
+LL | impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+   |                 -          ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                 |
+   |                 this type parameter needs to be `std::marker::Sized`
+   |
+   = note: required because it appears within the type `(A, B)`
+note: required by a bound in `Trait2`
+  --> $DIR/unsized-bound.rs:9:14
+   |
+LL | trait Trait2<A> {}
+   |              ^ required by this bound in `Trait2`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+LL + impl<A: ?Sized, B> Trait2<(A, B)> for (A, B) {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait2<A: ?Sized> {}
+   |               ++++++++
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:10:47
+   |
+LL | impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+   |      -                                        ^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+   = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+LL + impl<A, B: ?Sized> Trait2<(A, B)> for (A, B) {}
+   |
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:14:9
+   |
+LL | impl<A> Trait3<A> for A where A: ?Sized {}
+   |      -  ^^^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait3`
+  --> $DIR/unsized-bound.rs:13:14
+   |
+LL | trait Trait3<A> {}
+   |              ^ required by this bound in `Trait3`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A> Trait3<A> for A where A: ?Sized {}
+LL + impl<A> Trait3<A> for A  {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait3<A: ?Sized> {}
+   |               ++++++++
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:17:17
+   |
+LL | impl<A: ?Sized> Trait4<A> for A {}
+   |      -          ^^^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait4`
+  --> $DIR/unsized-bound.rs:16:14
+   |
+LL | trait Trait4<A> {}
+   |              ^ required by this bound in `Trait4`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<A: ?Sized> Trait4<A> for A {}
+LL + impl<A> Trait4<A> for A {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait4<A: ?Sized> {}
+   |               ++++++++
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:20:12
+   |
+LL | impl<X, Y> Trait5<X, Y> for X where X: ?Sized {}
+   |      -     ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait5`
+  --> $DIR/unsized-bound.rs:19:14
+   |
+LL | trait Trait5<A, B> {}
+   |              ^ required by this bound in `Trait5`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<X, Y> Trait5<X, Y> for X where X: ?Sized {}
+LL + impl<X, Y> Trait5<X, Y> for X  {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait5<A: ?Sized, B> {}
+   |               ++++++++
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:23:20
+   |
+LL | impl<X: ?Sized, Y> Trait6<X, Y> for X {}
+   |      -             ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait6`
+  --> $DIR/unsized-bound.rs:22:14
+   |
+LL | trait Trait6<A, B> {}
+   |              ^ required by this bound in `Trait6`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<X: ?Sized, Y> Trait6<X, Y> for X {}
+LL + impl<X, Y> Trait6<X, Y> for X {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait6<A: ?Sized, B> {}
+   |               ++++++++
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:26:12
+   |
+LL | impl<X, Y> Trait7<X, Y> for X where Y: ?Sized {}
+   |         -  ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait7`
+  --> $DIR/unsized-bound.rs:25:17
+   |
+LL | trait Trait7<A, B> {}
+   |                 ^ required by this bound in `Trait7`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<X, Y> Trait7<X, Y> for X where Y: ?Sized {}
+LL + impl<X, Y> Trait7<X, Y> for X  {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait7<A, B: ?Sized> {}
+   |                  ++++++++
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+  --> $DIR/unsized-bound.rs:29:20
+   |
+LL | impl<X, Y: ?Sized> Trait8<X, Y> for X {}
+   |         -          ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         this type parameter needs to be `std::marker::Sized`
+   |
+note: required by a bound in `Trait8`
+  --> $DIR/unsized-bound.rs:28:17
+   |
+LL | trait Trait8<A, B> {}
+   |                 ^ required by this bound in `Trait8`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - impl<X, Y: ?Sized> Trait8<X, Y> for X {}
+LL + impl<X, Y> Trait8<X, Y> for X {}
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Trait8<A, B: ?Sized> {}
+   |                  ++++++++
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.