about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-12-07 11:11:06 -0800
committerEsteban Küber <esteban@kuber.com.ar>2022-12-11 09:46:02 -0800
commit71db025cfa85ea3c1e7d628f4c596ca498c7acf0 (patch)
tree17572e8ecd0cd5aa7394ecd315d950f20f92d103
parent64bc975d27f86aaa1d3d94921c9c042477b4e88b (diff)
downloadrust-71db025cfa85ea3c1e7d628f4c596ca498c7acf0.tar.gz
rust-71db025cfa85ea3c1e7d628f4c596ca498c7acf0.zip
Account for method call chains split across multiple bindings
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs12
-rw-r--r--src/test/ui/issues/issue-34334.stderr10
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr13
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.rs9
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.stderr36
5 files changed, 69 insertions, 11 deletions
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<f64> = 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<f64>`
 LL |     let x2: Vec<f64> = 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::<Vec<f64>>();
 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<f64>`
+...
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |              -- ^^^^^^^^^^^ 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::<i32>()); //~ ERROR E0277
     println!("{}", vec![(), ()].iter().sum::<i32>()); //~ 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<i32> = 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<Self::Item>,
    |            ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum`
 
-error: aborting due to 4 previous errors
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:30:23
+   |
+LL |     let g: Vec<i32> = f.collect();
+   |                       ^ ------- required by a bound introduced by this call
+   |                       |
+   |                       value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+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<B: FromIterator<Self::Item>>(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`.