Skip to content

Commit 71db025

Browse files
committed
Account for method call chains split across multiple bindings
1 parent 64bc975 commit 71db025

File tree

5 files changed

+69
-11
lines changed

5 files changed

+69
-11
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,6 +2977,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29772977
prev_ty = self.resolve_vars_if_possible(
29782978
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
29792979
);
2980+
2981+
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
2982+
&& let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
2983+
&& let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
2984+
&& let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
2985+
&& let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
2986+
&& let Some(binding_expr) = local.init
2987+
{
2988+
// We've reached the root of the method call chain and it is a
2989+
// binding. Get the binding creation and try to continue the chain.
2990+
expr = binding_expr;
2991+
}
29802992
}
29812993

29822994
// We want the type before deref coercions, otherwise we talk about `&[_]`

src/test/ui/issues/issue-34334.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
2525
note: the method call chain might not have had the expected associated types
2626
--> $DIR/issue-34334.rs:5:36
2727
|
28+
LL | let sr: Vec<(u32, _, _) = vec![];
29+
| ------ this expression has type `Vec<(_, _, _)>`
30+
...
2831
LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
29-
| -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here
30-
| | |
31-
| | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here
32-
| this expression has type `Vec<(_, _, _)>`
32+
| ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here
33+
| |
34+
| associated type `std::iter::Iterator::Item` is `&(_, _, _)` here
3335
note: required by a bound in `collect`
3436
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
3537
|

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ LL | let x2: Vec<f64> = x1.into_iter().collect();
1111
note: the method call chain might not have had the expected associated types
1212
--> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
1313
|
14+
LL | let x1: &[f64] = &v;
15+
| -- this expression has type `&Vec<f64>`
1416
LL | let x2: Vec<f64> = x1.into_iter().collect();
15-
| -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here
16-
| |
17-
| this expression has type `&[f64]`
17+
| ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here
1818
note: required by a bound in `collect`
1919
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
2020
|
@@ -34,10 +34,11 @@ LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
3434
note: the method call chain might not have had the expected associated types
3535
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
3636
|
37+
LL | let x1: &[f64] = &v;
38+
| -- this expression has type `&Vec<f64>`
39+
...
3740
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
38-
| -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here
39-
| |
40-
| this expression has type `&[f64]`
41+
| ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here
4142
note: required by a bound in `collect`
4243
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
4344
|

src/test/ui/iterators/invalid-iterator-chain.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,13 @@ fn main() {
1919
);
2020
println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
2121
println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
22+
let a = vec![0];
23+
let b = a.into_iter();
24+
let c = b.map(|x| x + 1);
25+
let d = c.filter(|x| *x > 10 );
26+
let e = d.map(|x| {
27+
x + 1;
28+
});
29+
let f = e.filter(|_| false);
30+
let g: Vec<i32> = f.collect(); //~ ERROR E0277
2231
}

src/test/ui/iterators/invalid-iterator-chain.stderr

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,40 @@ note: required by a bound in `std::iter::Iterator::sum`
118118
LL | S: Sum<Self::Item>,
119119
| ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum`
120120

121-
error: aborting due to 4 previous errors
121+
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
122+
--> $DIR/invalid-iterator-chain.rs:30:23
123+
|
124+
LL | let g: Vec<i32> = f.collect();
125+
| ^ ------- required by a bound introduced by this call
126+
| |
127+
| value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
128+
|
129+
= help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
130+
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
131+
note: the method call chain might not have had the expected associated types
132+
--> $DIR/invalid-iterator-chain.rs:23:15
133+
|
134+
LL | let a = vec![0];
135+
| ------- this expression has type `Vec<{integer}>`
136+
LL | let b = a.into_iter();
137+
| ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `{integer}` here
138+
LL | let c = b.map(|x| x + 1);
139+
| --------------
140+
LL | let d = c.filter(|x| *x > 10 );
141+
| --------------------
142+
LL | let e = d.map(|x| {
143+
| _______________^
144+
LL | | x + 1;
145+
LL | | });
146+
| |______^ associated type `std::iter::Iterator::Item` changed to `()` here
147+
LL | let f = e.filter(|_| false);
148+
| -----------------
149+
note: required by a bound in `collect`
150+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
151+
|
152+
LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
153+
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
154+
155+
error: aborting due to 5 previous errors
122156

123157
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)