Skip to content

Commit b6494a7

Browse files
committed
More accurately point at arguments
1 parent bac0e55 commit b6494a7

24 files changed

+125
-137
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+34-44
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4343
_ => return false,
4444
};
4545

46+
let direct_param = if let ty::ClauseKind::Trait(pred) = unsubstituted_pred.kind().skip_binder()
47+
&& let ty = pred.trait_ref.self_ty()
48+
&& let ty::Param(_param) = ty.kind()
49+
&& let Some(arg) = predicate_args.get(0)
50+
&& let ty::GenericArgKind::Type(arg_ty) = arg.unpack()
51+
&& arg_ty == ty
52+
{
53+
Some(*arg)
54+
} else {
55+
None
56+
};
4657
let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
4758
predicate_args.iter().find_map(|arg| {
4859
arg.walk().find_map(|arg| {
@@ -63,32 +74,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6374
})
6475
};
6576

66-
// Account for enum variant constructors, where the type param corresponds to the enum
67-
// itself.
68-
let enum_def_id =
69-
if let DefKind::Ctor(hir::def::CtorOf::Variant, _) = self.tcx.def_kind(def_id) {
70-
// `def_id` corresponds to a constructor, and its parent is the variant, and we want
71-
// the enum.
72-
Some(self.tcx.parent(self.tcx.parent(def_id)))
73-
} else {
74-
None
75-
};
76-
let variant_param_to_point_at = find_param_matching(&|param_term| {
77-
// FIXME: It would be nice to make this not use string manipulation,
78-
// but it's pretty hard to do this, since `ty::ParamTy` is missing
79-
// sufficient info to determine if it is synthetic, and we don't
80-
// always have a convenient way of getting `ty::Generics` at the call
81-
// sites we invoke `IsSuggestable::is_suggestable`.
82-
let include = match param_term {
83-
ty::ParamTerm::Ty(param_ty) => !param_ty.name.as_str().starts_with("impl "),
84-
_ => true,
85-
};
86-
// Account for enum variant constructors, where the type param corresponds to the enum
87-
// itself.
88-
let def_id = if let Some(def_id) = enum_def_id { def_id } else { def_id };
89-
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) == def_id
90-
&& include
91-
});
9277
// Prefer generics that are local to the fn item, since these are likely
9378
// to be the cause of the unsatisfied predicate.
9479
let mut param_to_point_at = find_param_matching(&|param_term| {
@@ -134,20 +119,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134119
};
135120

136121
if let Some(qpath) = qpath {
137-
let def_id = if let Some(def_id) = enum_def_id { def_id } else { def_id };
138-
if let hir::QPath::Resolved(None, path) = qpath {
139-
for segment in path.segments {
140-
if let Some(param) = variant_param_to_point_at
141-
&& self.point_at_generic_if_possible(error, def_id, param, segment)
142-
{
143-
return true;
144-
}
145-
}
146-
}
147-
if let hir::QPath::TypeRelative(_ty, segment) = qpath {
148-
if let Some(param) = variant_param_to_point_at
149-
&& self.point_at_generic_if_possible(error, def_id, param, segment)
150-
{
122+
if let Some(param) = direct_param {
123+
if self.point_at_path_if_possible(error, def_id, param, &qpath) {
151124
return true;
152125
}
153126
}
@@ -195,6 +168,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
195168

196169
match expr.map(|e| e.kind) {
197170
Some(hir::ExprKind::MethodCall(segment, receiver, args, ..)) => {
171+
if let Some(param) = direct_param
172+
&& self.point_at_generic_if_possible(error, def_id, param, segment)
173+
{
174+
error.obligation.cause.map_code(|parent_code| {
175+
ObligationCauseCode::FunctionArgumentObligation {
176+
arg_hir_id: receiver.hir_id,
177+
call_hir_id: hir_id,
178+
parent_code,
179+
}
180+
});
181+
return true;
182+
}
198183
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
199184
.into_iter()
200185
.flatten()
@@ -251,9 +236,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
251236
}
252237
}
253238

254-
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
255-
.into_iter()
256-
.flatten()
239+
for param in [
240+
direct_param,
241+
param_to_point_at,
242+
fallback_param_to_point_at,
243+
self_param_to_point_at,
244+
]
245+
.into_iter()
246+
.flatten()
257247
{
258248
if self.point_at_path_if_possible(error, def_id, param, qpath) {
259249
return true;
@@ -485,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
485475
}
486476

487477
/**
488-
* Recursively searches for the most-specific blamable expression.
478+
* Recursively searches for the most-specific blameable expression.
489479
* For example, if you have a chain of constraints like:
490480
* - want `Vec<i32>: Copy`
491481
* - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`

tests/ui/argument-suggestions/issue-100154.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ LL | fn foo(i: impl std::fmt::Display) {}
1414
= note: `impl Trait` cannot be explicitly specified as a generic argument
1515

1616
error[E0277]: `()` doesn't implement `std::fmt::Display`
17-
--> $DIR/issue-100154.rs:4:15
17+
--> $DIR/issue-100154.rs:4:11
1818
|
1919
LL | foo::<()>(());
20-
| --------- ^^ `()` cannot be formatted with the default formatter
21-
| |
22-
| required by a bound introduced by this call
20+
| ^^ `()` cannot be formatted with the default formatter
2321
|
2422
= help: the trait `std::fmt::Display` is not implemented for `()`
2523
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
2-
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:22
2+
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:13
33
|
44
LL | let u: <T as Foo<usize>>::Bar = t.get_bar();
5-
| ^^^^^ the trait `Foo<usize>` is not implemented for `T`
5+
| ^ the trait `Foo<usize>` is not implemented for `T`
66
|
77
help: consider further restricting this bound
88
|

tests/ui/associated-types/associated-types-issue-20346.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0271]: type mismatch resolving `<Adapter<I> as Iterator>::Item == Option<T>`
2-
--> $DIR/associated-types-issue-20346.rs:34:33
2+
--> $DIR/associated-types-issue-20346.rs:34:36
33
|
44
LL | fn test_adapter<T, I: Iterator<Item=Option<T>>>(it: I) {
55
| - this type parameter
66
...
77
LL | is_iterator_of::<Option<T>, _>(&adapter);
8-
| ^ type mismatch resolving `<Adapter<I> as Iterator>::Item == Option<T>`
8+
| ------------------------------ ^^^^^^^^ type mismatch resolving `<Adapter<I> as Iterator>::Item == Option<T>`
9+
| |
10+
| required by a bound introduced by this call
911
|
1012
note: expected this to be `Option<T>`
1113
--> $DIR/associated-types-issue-20346.rs:23:17

tests/ui/const-generics/exhaustive-value.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the trait bound `(): Foo<N>` is not satisfied
2-
--> $DIR/exhaustive-value.rs:262:16
2+
--> $DIR/exhaustive-value.rs:262:6
33
|
44
LL | <() as Foo<N>>::test()
5-
| ^ the trait `Foo<N>` is not implemented for `()`
5+
| ^^ the trait `Foo<N>` is not implemented for `()`
66
|
77
= help: the following other types implement trait `Foo<N>`:
88
<() as Foo<0>>

tests/ui/inference/issue-72690.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0283]: type annotations needed
22
--> $DIR/issue-72690.rs:7:5
33
|
44
LL | String::from("x".as_ref());
5-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
5+
| ^^^^^^ cannot infer type for reference `&_`
66
|
77
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
88
- impl<> From<&String> for String;
@@ -71,7 +71,7 @@ error[E0283]: type annotations needed
7171
--> $DIR/issue-72690.rs:21:5
7272
|
7373
LL | String::from("x".as_ref());
74-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
74+
| ^^^^^^ cannot infer type for reference `&_`
7575
|
7676
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
7777
- impl<> From<&String> for String;
@@ -97,7 +97,7 @@ error[E0283]: type annotations needed
9797
--> $DIR/issue-72690.rs:28:5
9898
|
9999
LL | String::from("x".as_ref());
100-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
100+
| ^^^^^^ cannot infer type for reference `&_`
101101
|
102102
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
103103
- impl<> From<&String> for String;
@@ -123,7 +123,7 @@ error[E0283]: type annotations needed
123123
--> $DIR/issue-72690.rs:37:5
124124
|
125125
LL | String::from("x".as_ref());
126-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
126+
| ^^^^^^ cannot infer type for reference `&_`
127127
|
128128
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
129129
- impl<> From<&String> for String;
@@ -149,7 +149,7 @@ error[E0283]: type annotations needed
149149
--> $DIR/issue-72690.rs:46:5
150150
|
151151
LL | String::from("x".as_ref());
152-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
152+
| ^^^^^^ cannot infer type for reference `&_`
153153
|
154154
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
155155
- impl<> From<&String> for String;
@@ -175,7 +175,7 @@ error[E0283]: type annotations needed
175175
--> $DIR/issue-72690.rs:53:5
176176
|
177177
LL | String::from("x".as_ref());
178-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
178+
| ^^^^^^ cannot infer type for reference `&_`
179179
|
180180
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
181181
- impl<> From<&String> for String;
@@ -201,7 +201,7 @@ error[E0283]: type annotations needed
201201
--> $DIR/issue-72690.rs:62:5
202202
|
203203
LL | String::from("x".as_ref());
204-
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
204+
| ^^^^^^ cannot infer type for reference `&_`
205205
|
206206
= note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
207207
- impl<> From<&String> for String;

tests/ui/issues/issue-29147.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0283]: type annotations needed
2-
--> $DIR/issue-29147.rs:22:13
2+
--> $DIR/issue-29147.rs:22:14
33
|
44
LL | let _ = <S5<_>>::xxx;
5-
| ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
5+
| ^^^^^ cannot infer type for struct `S5<_>`
66
|
77
note: multiple `impl`s satisfying `S5<_>: Foo` found
88
--> $DIR/issue-29147.rs:18:1

tests/ui/issues/issue-66923-show-error-for-correct-call.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ note: required by a bound in `collect`
1717
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
1818

1919
error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
20-
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
20+
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:39
2121
|
2222
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
23-
| ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
23+
| ------- ^^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
24+
| |
25+
| required by a bound introduced by this call
2426
|
2527
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
2628
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`

tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
error[E0277]: a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}`
2-
--> $DIR/invalid-iterator-chain-with-int-infer.rs:2:41
2+
--> $DIR/invalid-iterator-chain-with-int-infer.rs:2:47
33
|
44
LL | let x = Some(()).iter().map(|()| 1).sum::<f32>();
5-
| ^^^ value of type `f32` cannot be made by summing a `std::iter::Iterator<Item={integer}>`
5+
| --- ^^^ value of type `f32` cannot be made by summing a `std::iter::Iterator<Item={integer}>`
6+
| |
7+
| required by a bound introduced by this call
68
|
79
= help: the trait `Sum<{integer}>` is not implemented for `f32`
810
= help: the following other types implement trait `Sum<A>`:

tests/ui/iterators/invalid-iterator-chain.stderr

+20-10
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ note: required by a bound in `collect`
1717
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
1818

1919
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
20-
--> $DIR/invalid-iterator-chain.rs:15:27
20+
--> $DIR/invalid-iterator-chain.rs:15:33
2121
|
2222
LL | println!("{}", scores.sum::<i32>());
23-
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
23+
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
24+
| |
25+
| required by a bound introduced by this call
2426
|
2527
= help: the trait `Sum<()>` is not implemented for `i32`
2628
= help: the following other types implement trait `Sum<A>`:
@@ -42,10 +44,12 @@ note: required by a bound in `std::iter::Iterator::sum`
4244
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
4345

4446
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
45-
--> $DIR/invalid-iterator-chain.rs:26:14
47+
--> $DIR/invalid-iterator-chain.rs:26:20
4648
|
4749
LL | .sum::<i32>(),
48-
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
50+
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
51+
| |
52+
| required by a bound introduced by this call
4953
|
5054
= help: the trait `Sum<()>` is not implemented for `i32`
5155
= help: the following other types implement trait `Sum<A>`:
@@ -74,10 +78,12 @@ note: required by a bound in `std::iter::Iterator::sum`
7478
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
7579

7680
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
77-
--> $DIR/invalid-iterator-chain.rs:36:14
81+
--> $DIR/invalid-iterator-chain.rs:36:20
7882
|
7983
LL | .sum::<i32>(),
80-
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
84+
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
85+
| |
86+
| required by a bound introduced by this call
8187
|
8288
= help: the trait `Sum<f64>` is not implemented for `i32`
8389
= help: the following other types implement trait `Sum<A>`:
@@ -102,10 +108,12 @@ note: required by a bound in `std::iter::Iterator::sum`
102108
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
103109

104110
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
105-
--> $DIR/invalid-iterator-chain.rs:38:54
111+
--> $DIR/invalid-iterator-chain.rs:38:60
106112
|
107113
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
108-
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
114+
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
115+
| |
116+
| required by a bound introduced by this call
109117
|
110118
= help: the trait `Sum<()>` is not implemented for `i32`
111119
= help: the following other types implement trait `Sum<A>`:
@@ -123,10 +131,12 @@ note: required by a bound in `std::iter::Iterator::sum`
123131
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
124132

125133
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
126-
--> $DIR/invalid-iterator-chain.rs:39:40
134+
--> $DIR/invalid-iterator-chain.rs:39:46
127135
|
128136
LL | println!("{}", vec![(), ()].iter().sum::<i32>());
129-
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
137+
| --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
138+
| |
139+
| required by a bound introduced by this call
130140
|
131141
= help: the trait `Sum<&()>` is not implemented for `i32`
132142
= help: the following other types implement trait `Sum<A>`:

tests/ui/methods/issues/issue-61525.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time
2-
--> $DIR/issue-61525.rs:14:33
2+
--> $DIR/issue-61525.rs:14:19
33
|
44
LL | 1.query::<dyn ToString>("")
5-
| ----- ^^ doesn't have a size known at compile-time
5+
| ----- ^^^^^^^^^^^^ doesn't have a size known at compile-time
66
| |
77
| required by a bound introduced by this call
88
|

tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
error[E0277]: the trait bound `E: From<()>` is not satisfied
2-
--> $DIR/never-value-fallback-issue-66757.rs:28:26
2+
--> $DIR/never-value-fallback-issue-66757.rs:28:6
33
|
44
LL | <E as From<_>>::from(never);
5-
| -------------------- ^^^^^ the trait `From<()>` is not implemented for `E`
6-
| |
7-
| required by a bound introduced by this call
5+
| ^ the trait `From<()>` is not implemented for `E`
86
|
97
= help: the trait `From<!>` is implemented for `E`
108

0 commit comments

Comments
 (0)