about summary refs log tree commit diff
path: root/tests/ui/errors
diff options
context:
space:
mode:
authorNathan Fenner <nfenneremail@gmail.com>2023-01-03 19:54:11 -0800
committerNathan Fenner <nfenneremail@gmail.com>2023-01-23 13:37:58 -0800
commit2a67e99d7d234f8f225d963114c85403fff8272c (patch)
treea873aa1ecc4bf9b511040a70eff90b633232a5bd /tests/ui/errors
parentc8e6a9e8b6251bbc8276cb78cabe1998deecbed7 (diff)
downloadrust-2a67e99d7d234f8f225d963114c85403fff8272c.tar.gz
rust-2a67e99d7d234f8f225d963114c85403fff8272c.zip
Point at specific field in struct literal when trait fulfillment fails
Diffstat (limited to 'tests/ui/errors')
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs28
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr35
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs131
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr380
4 files changed, 574 insertions, 0 deletions
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
new file mode 100644
index 00000000000..5134c672f5f
--- /dev/null
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
@@ -0,0 +1,28 @@
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl<B: T2> T1 for Wrapper<B> {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+impl<A: T3> T2 for Burrito<A> {}
+
+struct Wrapper<W> {
+    value: W,
+}
+
+struct Burrito<F> {
+    filling: F,
+}
+
+fn want<V: T1>(_x: V) {}
+
+fn example<Q>(q: Q) {
+    want(Wrapper { value: Burrito { filling: q } });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
new file mode 100644
index 00000000000..27b002db130
--- /dev/null
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:24:46
+   |
+LL |     want(Wrapper { value: Burrito { filling: q } });
+   |     ----                                     ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `Burrito<Q>` to implement `T2`
+  --> $DIR/blame-trait-error.rs:11:13
+   |
+LL | impl<A: T3> T2 for Burrito<A> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:6:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:21:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs
new file mode 100644
index 00000000000..2b75f432412
--- /dev/null
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs
@@ -0,0 +1,131 @@
+// This test examines the error spans reported when a generic `impl` fails.
+// For example, if a function wants an `Option<T>` where `T: Copy` but you pass `Some(vec![1, 2])`,
+// then we want to point at the `vec![1, 2]` and not the `Some( ... )` expression.
+
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+struct Wrapper<W> {
+    value: W,
+}
+impl<B: T2> T1 for Wrapper<B> {}
+
+struct Burrito<F> {
+    spicy: bool,
+    filling: F,
+}
+impl<A: T3> T2 for Burrito<A> {}
+
+struct BurritoTuple<F>(F);
+impl<C: T3> T2 for BurritoTuple<C> {}
+
+enum BurritoKinds<G> {
+    SmallBurrito { spicy: bool, small_filling: G },
+    LargeBurrito { spicy: bool, large_filling: G },
+    MultiBurrito { first_filling: G, second_filling: G },
+}
+impl<D: T3> T2 for BurritoKinds<D> {}
+
+struct Taco<H>(bool, H);
+impl<E: T3> T2 for Taco<E> {}
+
+enum TacoKinds<H> {
+    OneTaco(bool, H),
+    TwoTacos(bool, H, H),
+}
+impl<F: T3> T2 for TacoKinds<F> {}
+
+struct GenericBurrito<Spiciness, Filling> {
+    spiciness: Spiciness,
+    filling: Filling,
+}
+impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+struct NotSpicy;
+
+impl<A: T3, B: T3> T2 for (A, B) {}
+impl<A: T2, B: T2> T1 for (A, B) {}
+
+fn want<V: T1>(_x: V) {}
+
+// Some more-complex examples:
+type AliasBurrito<T> = GenericBurrito<T, T>;
+
+// The following example is fairly confusing. The idea is that we want to "misdirect" the location
+// of the error.
+
+struct Two<A, B> {
+    a: A,
+    b: B,
+}
+
+impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+
+struct DoubleWrapper<T> {
+    item: Wrapper<T>,
+}
+
+impl<T: T1> T1 for DoubleWrapper<T> {}
+
+fn example<Q>(q: Q) {
+    // In each of the following examples, we expect the error span to point at the 'q' variable,
+    // since the missing constraint is `Q: T3`.
+
+    // Verifies for struct:
+    want(Wrapper { value: Burrito { spicy: false, filling: q } });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for enum with named fields in variant:
+    want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for tuple struct:
+    want(Wrapper { value: Taco(false, q) });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for tuple enum variant:
+    want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for generic type with multiple parameters:
+    want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for tuple:
+    want((3, q));
+    //~^ ERROR the trait bound `Q: T2` is not satisfied [E0277]
+
+    // Verifies for nested tuple:
+    want(Wrapper { value: (3, q) });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    // Verifies for nested tuple:
+    want(((3, q), 5));
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    want(DoubleWrapper { item: Wrapper { value: q } });
+    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+    want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+    // Verifies for type alias to struct:
+    want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    want(Two { a: Two { a: (), b: q }, b: () });
+    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+    // We *should* blame the 'q'.
+    // FIXME: Right now, the wrong field is blamed.
+    want(
+        Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+        //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
new file mode 100644
index 00000000000..5f87c670d8a
--- /dev/null
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
@@ -0,0 +1,380 @@
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:79:60
+   |
+LL |     want(Wrapper { value: Burrito { spicy: false, filling: q } });
+   |     ---- required by a bound introduced by this call       ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `Burrito<Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13
+   |
+LL | impl<A: T3> T2 for Burrito<A> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:83:84
+   |
+LL |     want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+   |     ---- required by a bound introduced by this call                               ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `BurritoKinds<Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13
+   |
+LL | impl<D: T3> T2 for BurritoKinds<D> {}
+   |         --  ^^     ^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `Wrapper<BurritoKinds<Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:87:39
+   |
+LL |     want(Wrapper { value: Taco(false, q) });
+   |     ----                              ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `Taco<Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:35:13
+   |
+LL | impl<E: T3> T2 for Taco<E> {}
+   |         --  ^^     ^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `Wrapper<Taco<Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:91:27
+   |
+LL |     want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+   |     ----                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `TacoKinds<Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:41:13
+   |
+LL | impl<F: T3> T2 for TacoKinds<F> {}
+   |         --  ^^     ^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `Wrapper<TacoKinds<Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:95:74
+   |
+LL |     want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+   |     ---- required by a bound introduced by this call                     ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `GenericBurrito<NotSpicy, Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+   |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+   |            --  ^^     ^^^^^^^^^^^^^^^^^^^^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<NotSpicy, Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T2` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:99:14
+   |
+LL |     want((3, q));
+   |     ----     ^ the trait `T2` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `(i32, Q)` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+   |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+   |                --  ^^     ^^^^^^
+   |                |
+   |                unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T2>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:103:31
+   |
+LL |     want(Wrapper { value: (3, q) });
+   |     ----                      ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `(i32, Q)` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+   |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+   |                --  ^^     ^^^^^^
+   |                |
+   |                unsatisfied trait bound introduced here
+note: required for `Wrapper<(i32, Q)>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:107:15
+   |
+LL |     want(((3, q), 5));
+   |     ----      ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `(i32, Q)` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+   |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+   |                --  ^^     ^^^^^^
+   |                |
+   |                unsatisfied trait bound introduced here
+note: required for `((i32, Q), i32)` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+   |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+   |         --         ^^     ^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:110:49
+   |
+LL |     want(DoubleWrapper { item: Wrapper { value: q } });
+   |     ----                                        ^ the trait `T1` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+   |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+   |         --  ^^     ^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T1>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:113:88
+   |
+LL |     want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+   |     ---- required by a bound introduced by this call                                   ^ the trait `T1` is not implemented for `Q`
+   |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+   |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+   |         --  ^^     ^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `DoubleWrapper<DoubleWrapper<Q>>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T1>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:117:27
+   |
+LL |     want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+   |     ----                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `GenericBurrito<Q, Q>` to implement `T2`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+   |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+   |            --  ^^     ^^^^^^^^^^^^^^^^^^^^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<Q, Q>>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+   |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+   |         --  ^^     ^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:120:35
+   |
+LL |     want(Two { a: Two { a: (), b: q }, b: () });
+   |     ----                          ^ the trait `T1` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+   |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+   |            --     ^^     ^^^^^^^^^^^^^^^^^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T1>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:126:59
+   |
+LL |     want(
+   |     ---- required by a bound introduced by this call
+LL |         Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+   |                                                           ^ the trait `T1` is not implemented for `Q`
+   |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+   |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+   |            --     ^^     ^^^^^^^^^^^^^^^^^
+   |            |
+   |            unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `Two<Two<(), Two<Two<(), Q>, ()>>, ()>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T1>(q: Q) {
+   |             ++++
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.