From 458fdb37f62fd3d6f9ae2ddf9f1bbdfcd0d126cd Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 10 May 2022 19:41:22 +0000 Subject: [PATCH] Print type of every call in a method call chain ``` error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` --> $DIR/issue-33941.rs:6:36 | LL | for _ in HashMap::new().iter().cloned() {} | ------------ ---- ^^^^^^ expected reference, found tuple | | | | | this call is of type `std::collections::hash_map::Iter<'_, _, _>` | this call is of type `&HashMap<_, _>` | = note: expected reference `&_` found tuple `(&_, &_)` note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | LL | Self: Sized + Iterator, | ^^^^^^^^^^^^ required by this bound in `cloned` ``` Partially address #33941. --- .../src/traits/error_reporting/mod.rs | 51 +++++++++++++++++++ src/test/ui/issues/issue-31173.stderr | 3 ++ src/test/ui/issues/issue-33941.stderr | 5 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 7a3579eb1cc85..0fa90dc7b9756 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1621,6 +1621,36 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { "type mismatch resolving `{}`", predicate ); + let mut v = HirFinder { needle: obligation.cause.span, found: None }; + let body = self.tcx.hir().get(obligation.cause.body_id); + if let hir::Node::Expr(expr) = body { + v.visit_expr(expr); + } + if let Some(expr) = v.found { + // FIXME(estebank): look for method calls that can be applied on the previous + // element of the chain, that would make the next call to typeck. + let mut receiver = expr; + if let (Some(typeck_results), hir::ExprKind::MethodCall(..)) = + (self.in_progress_typeck_results, &receiver.kind) + { + let typeck_results = typeck_results.borrow(); + while let hir::ExprKind::MethodCall(method_segment, args, _) = receiver.kind { + if let Some(ty) = typeck_results.expr_ty_adjusted_opt(receiver) { + diag.span_label( + method_segment.ident.span, + &format!("this call is of type `{ty}`"), + ); + } + receiver = &args[0]; + } + while let hir::ExprKind::Call(path, _args) = receiver.kind { + if let Some(ty) = typeck_results.expr_ty_adjusted_opt(receiver) { + diag.span_label(path.span, &format!("this call is of type `{ty}`")); + } + receiver = &path; + } + } + } let secondary_span = match predicate.kind().skip_binder() { ty::PredicateKind::Projection(proj) => self .tcx @@ -2689,3 +2719,24 @@ impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor { } } } + +struct HirFinder<'tcx> { + needle: Span, + found: Option<&'tcx hir::Expr<'tcx>>, +} + +impl<'v> Visitor<'v> for HirFinder<'v> { + fn visit_expr(&mut self, expr: &'v hir::Expr<'v>) { + if expr.span == self.needle { + self.found = Some(expr); + return; + } + if let hir::ExprKind::MethodCall(segment, _, _) = expr.kind { + if segment.ident.span == self.needle { + self.found = Some(expr); + return; + } + } + hir::intravisit::walk_expr(self, expr); + } +} diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 982b6118ce659..820696b03f1bf 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,6 +1,9 @@ error[E0271]: type mismatch resolving `, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item == &_` --> $DIR/issue-31173.rs:10:10 | +LL | let temp: Vec = it.take_while(|&x| { + | ---------- this call is of type `TakeWhile<&mut std::vec::IntoIter, _>` +... LL | .cloned() | ^^^^^^ expected reference, found `u8` | diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index e1ce6eed98efb..f32ec0831c5d8 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving ` $DIR/issue-33941.rs:6:36 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^ expected reference, found tuple + | ------------ ---- ^^^^^^ expected reference, found tuple + | | | + | | this call is of type `std::collections::hash_map::Iter<'_, _, _>` + | this call is of type `&HashMap<_, _>` | = note: expected reference `&_` found tuple `(&_, &_)`