Rollup merge of #108254 - Nathan-Fenner:nathanf/error-span-ref-trait-refine, r=WaffleLapkin
Refine error span for trait error into borrowed expression Extends the error span refinement in #106477 to drill into borrowed expressions just like tuples/struct/enum literals. For example, ```rs trait Fancy {} trait Good {} impl <'a, T> Fancy for &'a T where T: Good {} impl <S> Good for Option<S> where S: Iterator {} fn want_fancy<F>(f: F) where F: Fancy {} fn example() { want_fancy(&Some(5)); // (BEFORE) ^^^^^^^^ `{integer}` is not an iterator // (AFTER) ^ `{integer}` is not an iterator } ``` Existing heuristics try to find the right part of the expression to "point at"; current heuristics look at e.g. struct constructors and tuples. This PR adds a new check for borrowed expressions when looking into a borrowed type.
This commit is contained in:
commit
194d52cc18
@ -549,6 +549,19 @@ fn blame_specific_part_of_expr_corresponding_to_generic_param(
|
||||
return Err(expr);
|
||||
};
|
||||
|
||||
if let (
|
||||
hir::ExprKind::AddrOf(_borrow_kind, _borrow_mutability, borrowed_expr),
|
||||
ty::Ref(_ty_region, ty_ref_type, _ty_mutability),
|
||||
) = (&expr.kind, in_ty.kind())
|
||||
{
|
||||
// We can "drill into" the borrowed expression.
|
||||
return self.blame_specific_part_of_expr_corresponding_to_generic_param(
|
||||
param,
|
||||
borrowed_expr,
|
||||
(*ty_ref_type).into(),
|
||||
);
|
||||
}
|
||||
|
||||
if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
|
||||
(&expr.kind, in_ty.kind())
|
||||
{
|
||||
|
@ -71,6 +71,8 @@ struct DoubleWrapper<T> {
|
||||
|
||||
impl<T: T1> T1 for DoubleWrapper<T> {}
|
||||
|
||||
impl<'a, T: T2> T1 for &'a 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`.
|
||||
@ -126,6 +128,10 @@ fn example<Q>(q: Q) {
|
||||
Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
|
||||
//~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
|
||||
);
|
||||
|
||||
// Verifies for reference:
|
||||
want(&Burrito { spicy: false, filling: q });
|
||||
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:79:60
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:81: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`
|
||||
@ -29,7 +29,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:85: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`
|
||||
@ -59,7 +59,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:89:39
|
||||
|
|
||||
LL | want(Wrapper { value: Taco(false, q) });
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
@ -91,7 +91,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:93:27
|
||||
|
|
||||
LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
|
||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
|
||||
@ -123,7 +123,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:97: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`
|
||||
@ -153,7 +153,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:101:14
|
||||
|
|
||||
LL | want((3, q));
|
||||
| ---- ^ the trait `T2` is not implemented for `Q`
|
||||
@ -178,7 +178,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:105:31
|
||||
|
|
||||
LL | want(Wrapper { value: (3, q) });
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
@ -210,7 +210,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:109:15
|
||||
|
|
||||
LL | want(((3, q), 5));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
@ -242,7 +242,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:112:49
|
||||
|
|
||||
LL | want(DoubleWrapper { item: Wrapper { value: q } });
|
||||
| ---- ^ the trait `T1` is not implemented for `Q`
|
||||
@ -267,7 +267,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:115: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`
|
||||
@ -292,7 +292,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:119:27
|
||||
|
|
||||
LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
|
||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
|
||||
@ -324,7 +324,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:122:35
|
||||
|
|
||||
LL | want(Two { a: Two { a: (), b: q }, b: () });
|
||||
| ---- ^ the trait `T1` is not implemented for `Q`
|
||||
@ -349,7 +349,7 @@ 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
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:128:59
|
||||
|
|
||||
LL | want(
|
||||
| ---- required by a bound introduced by this call
|
||||
@ -375,6 +375,38 @@ help: consider restricting type parameter `Q`
|
||||
LL | fn example<Q: T1>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:133:44
|
||||
|
|
||||
LL | want(&Burrito { spicy: false, 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-spans-on-exprs.rs:22:13
|
||||
|
|
||||
LL | impl<A: T3> T2 for Burrito<A> {}
|
||||
| -- ^^ ^^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required for `&Burrito<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:74:17
|
||||
|
|
||||
LL | impl<'a, T: T2> T1 for &'a 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: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
|
||||
--> $DIR/issue-39029.rs:16:37
|
||||
--> $DIR/issue-39029.rs:16:38
|
||||
|
|
||||
LL | let _errors = TcpListener::bind(&bad);
|
||||
| ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
|
||||
| ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
Loading…
Reference in New Issue
Block a user