diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 2f9b8c21071..87ab863fa7b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2977,6 +2977,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()), ); + + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) + && let Some(binding_expr) = local.init + { + // We've reached the root of the method call chain and it is a + // binding. Get the binding creation and try to continue the chain. + expr = binding_expr; + } } // We want the type before deref coercions, otherwise we talk about `&[_]` diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index eca961633dc..89f5c45d7a9 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -25,11 +25,13 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece note: the method call chain might not have had the expected associated types --> $DIR/issue-34334.rs:5:36 | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ------ this expression has type `Vec<(_, _, _)>` +... LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); - | -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here - | | | - | | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here - | this expression has type `Vec<(_, _, _)>` + | ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` changed to `()` here + | | + | associated type `std::iter::Iterator::Item` is `&(_, _, _)` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 7f97b5bfcbe..7fe786dcfb5 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -11,10 +11,10 @@ LL | let x2: Vec = x1.into_iter().collect(); note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` LL | let x2: Vec = x1.into_iter().collect(); - | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here - | | - | this expression has type `&[f64]` + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -34,10 +34,11 @@ LL | let x3 = x1.into_iter().collect::>(); note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` +... LL | let x3 = x1.into_iter().collect::>(); - | -- ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here - | | - | this expression has type `&[f64]` + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `&f64` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index 3d4801b3732..e17b471b692 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -19,4 +19,13 @@ fn main() { ); println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 } diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 57be01a2442..8bf7eb93a72 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -118,6 +118,40 @@ note: required by a bound in `std::iter::Iterator::sum` LL | S: Sum, | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` -error: aborting due to 4 previous errors +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:30:23 + | +LL | let g: Vec = f.collect(); + | ^ ------- required by a bound introduced by this call + | | + | value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:23:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ associated type `std::iter::Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`.