about summary refs log tree commit diff
path: root/tests/ui/on-unimplemented
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/on-unimplemented')
-rw-r--r--tests/ui/on-unimplemented/auxiliary/no_debug.rs3
-rw-r--r--tests/ui/on-unimplemented/bad-annotation.rs64
-rw-r--r--tests/ui/on-unimplemented/bad-annotation.stderr83
-rw-r--r--tests/ui/on-unimplemented/expected-comma-found-token.rs13
-rw-r--r--tests/ui/on-unimplemented/expected-comma-found-token.stderr10
-rw-r--r--tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs8
-rw-r--r--tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr11
-rw-r--r--tests/ui/on-unimplemented/impl-substs.rs15
-rw-r--r--tests/ui/on-unimplemented/impl-substs.stderr14
-rw-r--r--tests/ui/on-unimplemented/issue-104140.rs8
-rw-r--r--tests/ui/on-unimplemented/issue-104140.stderr15
-rw-r--r--tests/ui/on-unimplemented/multiple-impls.rs45
-rw-r--r--tests/ui/on-unimplemented/multiple-impls.stderr108
-rw-r--r--tests/ui/on-unimplemented/no-debug.rs16
-rw-r--r--tests/ui/on-unimplemented/no-debug.stderr46
-rw-r--r--tests/ui/on-unimplemented/on-impl.rs26
-rw-r--r--tests/ui/on-unimplemented/on-impl.stderr32
-rw-r--r--tests/ui/on-unimplemented/on-trait.rs32
-rw-r--r--tests/ui/on-unimplemented/on-trait.stderr29
-rw-r--r--tests/ui/on-unimplemented/parent-label.rs27
-rw-r--r--tests/ui/on-unimplemented/parent-label.stderr69
-rw-r--r--tests/ui/on-unimplemented/slice-index.rs10
-rw-r--r--tests/ui/on-unimplemented/slice-index.stderr25
-rw-r--r--tests/ui/on-unimplemented/sum.rs9
-rw-r--r--tests/ui/on-unimplemented/sum.stderr43
25 files changed, 761 insertions, 0 deletions
diff --git a/tests/ui/on-unimplemented/auxiliary/no_debug.rs b/tests/ui/on-unimplemented/auxiliary/no_debug.rs
new file mode 100644
index 00000000000..fd3dc0abdc8
--- /dev/null
+++ b/tests/ui/on-unimplemented/auxiliary/no_debug.rs
@@ -0,0 +1,3 @@
+#![crate_type = "lib"]
+
+pub struct Bar;
diff --git a/tests/ui/on-unimplemented/bad-annotation.rs b/tests/ui/on-unimplemented/bad-annotation.rs
new file mode 100644
index 00000000000..f05436b8c04
--- /dev/null
+++ b/tests/ui/on-unimplemented/bad-annotation.rs
@@ -0,0 +1,64 @@
+// ignore-tidy-linelength
+
+#![feature(rustc_attrs)]
+
+#![allow(unused)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>
+{}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Builds a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+#[rustc_on_unimplemented]
+//~^ ERROR malformed `rustc_on_unimplemented` attribute
+trait BadAnnotation1
+{}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+//~^ ERROR there is no parameter `C` on trait `BadAnnotation2`
+trait BadAnnotation2<A,B>
+{}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+//~^ only named substitution parameters are allowed
+trait BadAnnotation3<A,B>
+{}
+
+#[rustc_on_unimplemented(lorem="")]
+//~^ this attribute must have a valid
+trait BadAnnotation4 {}
+
+#[rustc_on_unimplemented(lorem(ipsum(dolor)))]
+//~^ this attribute must have a valid
+trait BadAnnotation5 {}
+
+#[rustc_on_unimplemented(message="x", message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation6 {}
+
+#[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
+//~^ this attribute must have a valid
+trait BadAnnotation7 {}
+
+#[rustc_on_unimplemented(on(), message="y")]
+//~^ empty `on`-clause
+trait BadAnnotation8 {}
+
+#[rustc_on_unimplemented(on="x", message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation9 {}
+
+#[rustc_on_unimplemented(on(x="y"), message="y")]
+trait BadAnnotation10 {}
+
+#[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation11 {}
+
+pub fn main() {
+}
diff --git a/tests/ui/on-unimplemented/bad-annotation.stderr b/tests/ui/on-unimplemented/bad-annotation.stderr
new file mode 100644
index 00000000000..a8d3c8680fa
--- /dev/null
+++ b/tests/ui/on-unimplemented/bad-annotation.stderr
@@ -0,0 +1,83 @@
+error: malformed `rustc_on_unimplemented` attribute input
+  --> $DIR/bad-annotation.rs:17:1
+   |
+LL | #[rustc_on_unimplemented]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: the following are the possible correct uses
+   |
+LL | #[rustc_on_unimplemented = "message"]
+   |
+LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]
+   |
+
+error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
+  --> $DIR/bad-annotation.rs:22:1
+   |
+LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0231]: only named substitution parameters are allowed
+  --> $DIR/bad-annotation.rs:27:1
+   |
+LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:32:26
+   |
+LL | #[rustc_on_unimplemented(lorem="")]
+   |                          ^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:36:26
+   |
+LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
+   |                          ^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:40:39
+   |
+LL | #[rustc_on_unimplemented(message="x", message="y")]
+   |                                       ^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:44:39
+   |
+LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
+  --> $DIR/bad-annotation.rs:48:26
+   |
+LL | #[rustc_on_unimplemented(on(), message="y")]
+   |                          ^^^^ empty on-clause here
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:52:26
+   |
+LL | #[rustc_on_unimplemented(on="x", message="y")]
+   |                          ^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:59:40
+   |
+LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0230, E0231, E0232.
+For more information about an error, try `rustc --explain E0230`.
diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.rs b/tests/ui/on-unimplemented/expected-comma-found-token.rs
new file mode 100644
index 00000000000..8fb34f21152
--- /dev/null
+++ b/tests/ui/on-unimplemented/expected-comma-found-token.rs
@@ -0,0 +1,13 @@
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(
+    message="the message"
+    label="the label" //~ ERROR expected `,`, found `label`
+)]
+trait T {}
+
+fn main() {  }
diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.stderr b/tests/ui/on-unimplemented/expected-comma-found-token.stderr
new file mode 100644
index 00000000000..048b72ee3bc
--- /dev/null
+++ b/tests/ui/on-unimplemented/expected-comma-found-token.stderr
@@ -0,0 +1,10 @@
+error: expected `,`, found `label`
+  --> $DIR/expected-comma-found-token.rs:9:5
+   |
+LL |     message="the message"
+   |                          - expected `,`
+LL |     label="the label"
+   |     ^^^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs
new file mode 100644
index 00000000000..3cc50e3499a
--- /dev/null
+++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs
@@ -0,0 +1,8 @@
+// Test that `#[rustc_on_unimplemented]` is gated by `rustc_attrs` feature gate.
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
+//~^ ERROR this is an internal attribute that will never be stable
+trait Foo<Bar>
+{}
+
+fn main() {}
diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr
new file mode 100644
index 00000000000..a4b33963fb0
--- /dev/null
+++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr
@@ -0,0 +1,11 @@
+error[E0658]: this is an internal attribute that will never be stable
+  --> $DIR/feature-gate-on-unimplemented.rs:3:1
+   |
+LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/on-unimplemented/impl-substs.rs b/tests/ui/on-unimplemented/impl-substs.rs
new file mode 100644
index 00000000000..fe9c50ec3d4
--- /dev/null
+++ b/tests/ui/on-unimplemented/impl-substs.rs
@@ -0,0 +1,15 @@
+#![feature(rustc_attrs)]
+
+trait Foo<A> {
+    fn foo(self);
+}
+
+#[rustc_on_unimplemented = "an impl did not match: {A} {B} {C}"]
+impl<A, B, C> Foo<A> for (A, B, C) {
+    fn foo(self) {}
+}
+
+fn main() {
+    Foo::<usize>::foo((1i32, 1i32, 1i32));
+    //~^ ERROR the trait bound `(i32, i32, i32): Foo<usize>` is not satisfied
+}
diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr
new file mode 100644
index 00000000000..a0fad0acd0b
--- /dev/null
+++ b/tests/ui/on-unimplemented/impl-substs.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `(i32, i32, i32): Foo<usize>` is not satisfied
+  --> $DIR/impl-substs.rs:13:23
+   |
+LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
+   |     ----------------- ^^^^^^^^^^^^^^^^^^ an impl did not match: usize _ _
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
+   = help: the trait `Foo<A>` is implemented for `(A, B, C)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/issue-104140.rs b/tests/ui/on-unimplemented/issue-104140.rs
new file mode 100644
index 00000000000..ade3f727004
--- /dev/null
+++ b/tests/ui/on-unimplemented/issue-104140.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+trait Foo {}
+
+#[rustc_on_unimplemented] //~ ERROR malformed `rustc_on_unimplemented` attribute input
+impl Foo for u32 {}
+
+fn main() {}
diff --git a/tests/ui/on-unimplemented/issue-104140.stderr b/tests/ui/on-unimplemented/issue-104140.stderr
new file mode 100644
index 00000000000..ddb1f50f0bb
--- /dev/null
+++ b/tests/ui/on-unimplemented/issue-104140.stderr
@@ -0,0 +1,15 @@
+error: malformed `rustc_on_unimplemented` attribute input
+  --> $DIR/issue-104140.rs:5:1
+   |
+LL | #[rustc_on_unimplemented]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: the following are the possible correct uses
+   |
+LL | #[rustc_on_unimplemented = "message"]
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/on-unimplemented/multiple-impls.rs b/tests/ui/on-unimplemented/multiple-impls.rs
new file mode 100644
index 00000000000..a32fd456623
--- /dev/null
+++ b/tests/ui/on-unimplemented/multiple-impls.rs
@@ -0,0 +1,45 @@
+// Test if the on_unimplemented message override works
+
+#![feature(rustc_attrs)]
+
+
+struct Foo<T>(T);
+struct Bar<T>(T);
+
+#[rustc_on_unimplemented = "trait message"]
+trait Index<Idx: ?Sized> {
+    type Output: ?Sized;
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+#[rustc_on_unimplemented = "on impl for Foo"]
+impl Index<Foo<usize>> for [i32] {
+    type Output = i32;
+    fn index(&self, _index: Foo<usize>) -> &i32 {
+        loop {}
+    }
+}
+
+#[rustc_on_unimplemented = "on impl for Bar"]
+impl Index<Bar<usize>> for [i32] {
+    type Output = i32;
+    fn index(&self, _index: Bar<usize>) -> &i32 {
+        loop {}
+    }
+}
+
+
+fn main() {
+    Index::index(&[] as &[i32], 2u32);
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
+    Index::index(&[] as &[i32], Foo(2u32));
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
+    Index::index(&[] as &[i32], Bar(2u32));
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr
new file mode 100644
index 00000000000..d628b159a66
--- /dev/null
+++ b/tests/ui/on-unimplemented/multiple-impls.stderr
@@ -0,0 +1,108 @@
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:33
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ------------                ^^^^ trait message
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:37:33
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ------------                ^^^^^^^^^ on impl for Foo
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:37:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:41:33
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ------------                ^^^^^^^^^ on impl for Bar
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:41:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:37:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:41:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/no-debug.rs b/tests/ui/on-unimplemented/no-debug.rs
new file mode 100644
index 00000000000..bdc80c5b357
--- /dev/null
+++ b/tests/ui/on-unimplemented/no-debug.rs
@@ -0,0 +1,16 @@
+// aux-build:no_debug.rs
+
+extern crate no_debug;
+
+use no_debug::Bar;
+
+struct Foo;
+
+fn main() {
+    println!("{:?} {:?}", Foo, Bar);
+    println!("{} {}", Foo, Bar);
+}
+//~^^^ ERROR `Foo` doesn't implement `Debug`
+//~| ERROR `Bar` doesn't implement `Debug`
+//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display`
+//~| ERROR `Bar` doesn't implement `std::fmt::Display`
diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr
new file mode 100644
index 00000000000..1035da54d8a
--- /dev/null
+++ b/tests/ui/on-unimplemented/no-debug.stderr
@@ -0,0 +1,46 @@
+error[E0277]: `Foo` doesn't implement `Debug`
+  --> $DIR/no-debug.rs:10:27
+   |
+LL |     println!("{:?} {:?}", Foo, Bar);
+   |                           ^^^ `Foo` cannot be formatted using `{:?}`
+   |
+   = help: the trait `Debug` is not implemented for `Foo`
+   = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `Foo` with `#[derive(Debug)]`
+   |
+LL | #[derive(Debug)]
+   |
+
+error[E0277]: `Bar` doesn't implement `Debug`
+  --> $DIR/no-debug.rs:10:32
+   |
+LL |     println!("{:?} {:?}", Foo, Bar);
+   |                                ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `Bar`
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `Foo` doesn't implement `std::fmt::Display`
+  --> $DIR/no-debug.rs:11:23
+   |
+LL |     println!("{} {}", Foo, Bar);
+   |                       ^^^ `Foo` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Foo`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `Bar` doesn't implement `std::fmt::Display`
+  --> $DIR/no-debug.rs:11:28
+   |
+LL |     println!("{} {}", Foo, Bar);
+   |                            ^^^ `Bar` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Bar`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/on-impl.rs b/tests/ui/on-unimplemented/on-impl.rs
new file mode 100644
index 00000000000..d0537810ce1
--- /dev/null
+++ b/tests/ui/on-unimplemented/on-impl.rs
@@ -0,0 +1,26 @@
+// Test if the on_unimplemented message override works
+
+#![feature(rustc_attrs)]
+
+
+#[rustc_on_unimplemented = "invalid"]
+trait Index<Idx: ?Sized> {
+    type Output: ?Sized;
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+#[rustc_on_unimplemented = "a usize is required to index into a slice"]
+impl Index<usize> for [i32] {
+    type Output = i32;
+    fn index(&self, index: usize) -> &i32 {
+        &self[index]
+    }
+}
+
+
+fn main() {
+    Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr
new file mode 100644
index 00000000000..2253c5992a6
--- /dev/null
+++ b/tests/ui/on-unimplemented/on-impl.stderr
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:47
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     -------------------                       ^^^^ a usize is required to index into a slice
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/on-trait.rs b/tests/ui/on-unimplemented/on-trait.rs
new file mode 100644
index 00000000000..556813cd479
--- /dev/null
+++ b/tests/ui/on-unimplemented/on-trait.rs
@@ -0,0 +1,32 @@
+// ignore-tidy-linelength
+
+#![feature(rustc_attrs)]
+
+pub mod Bar {
+  #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"]
+  pub trait Foo<Bar, Baz, Quux> {}
+}
+
+use Bar::Foo;
+
+fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+    panic!()
+}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Builds a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+    MyFromIterator::my_from_iter(it)
+}
+
+pub fn main() {
+    let x = vec![1u8, 2, 3, 4];
+    let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+    //~^ ERROR
+
+    let x: String = foobar(); //~ ERROR
+}
diff --git a/tests/ui/on-unimplemented/on-trait.stderr b/tests/ui/on-unimplemented/on-trait.stderr
new file mode 100644
index 00000000000..4b040f1ac5a
--- /dev/null
+++ b/tests/ui/on-unimplemented/on-trait.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `Option<Vec<u8>>: MyFromIterator<&u8>` is not satisfied
+  --> $DIR/on-trait.rs:28:30
+   |
+LL |     let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+   |                              ^^^^^^^ a collection of type `Option<Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
+   |
+   = help: the trait `MyFromIterator<&u8>` is not implemented for `Option<Vec<u8>>`
+note: required by a bound in `collect`
+  --> $DIR/on-trait.rs:22:39
+   |
+LL | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+   |                                       ^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error[E0277]: the trait bound `String: Foo<u8, _, u32>` is not satisfied
+  --> $DIR/on-trait.rs:31:21
+   |
+LL |     let x: String = foobar();
+   |                     ^^^^^^ test error `String` with `u8` `_` `u32` in `Foo`
+   |
+   = help: the trait `Foo<u8, _, u32>` is not implemented for `String`
+note: required by a bound in `foobar`
+  --> $DIR/on-trait.rs:12:24
+   |
+LL | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+   |                        ^^^^^^^^^^^^^^^ required by this bound in `foobar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/parent-label.rs b/tests/ui/on-unimplemented/parent-label.rs
new file mode 100644
index 00000000000..b65f6496831
--- /dev/null
+++ b/tests/ui/on-unimplemented/parent-label.rs
@@ -0,0 +1,27 @@
+// Test scope annotations from `parent_label` parameter
+
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(parent_label = "in this scope")]
+trait Trait {}
+
+struct Foo;
+
+fn f<T: Trait>(x: T) {}
+
+fn main() {
+    let x = || {
+        f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        let y = || {
+            f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        };
+    };
+
+    {
+        {
+            f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        }
+    }
+
+    f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+}
diff --git a/tests/ui/on-unimplemented/parent-label.stderr b/tests/ui/on-unimplemented/parent-label.stderr
new file mode 100644
index 00000000000..8cd7412fd9d
--- /dev/null
+++ b/tests/ui/on-unimplemented/parent-label.stderr
@@ -0,0 +1,69 @@
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:14:11
+   |
+LL |     let x = || {
+   |             -- in this scope
+LL |         f(Foo {});
+   |         - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |         |
+   |         required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:16:15
+   |
+LL |         let y = || {
+   |                 -- in this scope
+LL |             f(Foo {});
+   |             - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |             |
+   |             required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:22:15
+   |
+LL | fn main() {
+   | --------- in this scope
+...
+LL |             f(Foo {});
+   |             - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |             |
+   |             required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:26:7
+   |
+LL | fn main() {
+   | --------- in this scope
+...
+LL |     f(Foo {});
+   |     - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/slice-index.rs b/tests/ui/on-unimplemented/slice-index.rs
new file mode 100644
index 00000000000..758220d3c4e
--- /dev/null
+++ b/tests/ui/on-unimplemented/slice-index.rs
@@ -0,0 +1,10 @@
+// Test new Index error message for slices
+
+use std::ops::Index;
+
+
+fn main() {
+    let x = &[1, 2, 3] as &[i32];
+    x[1i32]; //~ ERROR E0277
+    x[..1i32]; //~ ERROR E0277
+}
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
new file mode 100644
index 00000000000..a7ec3bda85e
--- /dev/null
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the type `[i32]` cannot be indexed by `i32`
+  --> $DIR/slice-index.rs:8:7
+   |
+LL |     x[1i32];
+   |       ^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
+   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = note: required for `[i32]` to implement `Index<i32>`
+
+error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
+  --> $DIR/slice-index.rs:9:7
+   |
+LL |     x[..1i32];
+   |       ^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             <RangeTo<usize> as SliceIndex<[T]>>
+             <RangeTo<usize> as SliceIndex<str>>
+   = note: required for `[i32]` to implement `Index<RangeTo<i32>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/sum.rs b/tests/ui/on-unimplemented/sum.rs
new file mode 100644
index 00000000000..4f1c521d9fe
--- /dev/null
+++ b/tests/ui/on-unimplemented/sum.rs
@@ -0,0 +1,9 @@
+// <https://github.com/rust-lang/rust/issues/105184>
+
+fn main() {
+    vec![(), ()].iter().sum::<i32>();
+    //~^ ERROR
+
+    vec![(), ()].iter().product::<i32>();
+    //~^ ERROR
+}
diff --git a/tests/ui/on-unimplemented/sum.stderr b/tests/ui/on-unimplemented/sum.stderr
new file mode 100644
index 00000000000..2a316dba778
--- /dev/null
+++ b/tests/ui/on-unimplemented/sum.stderr
@@ -0,0 +1,43 @@
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/sum.rs:4:25
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |                         ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:4:18
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
+  --> $DIR/sum.rs:7:25
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |                         ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Product<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Product<A>`:
+             <i32 as Product<&'a i32>>
+             <i32 as Product>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:7:18
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::product`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.