Skip to content

Commit 458fdb3

Browse files
committed
Print type of every call in a method call chain
``` error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> 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<Item = &'a T>, | ^^^^^^^^^^^^ required by this bound in `cloned` ``` Partially address rust-lang#33941.
1 parent eead58e commit 458fdb3

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

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

+51
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,36 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
16211621
"type mismatch resolving `{}`",
16221622
predicate
16231623
);
1624+
let mut v = HirFinder { needle: obligation.cause.span, found: None };
1625+
let body = self.tcx.hir().get(obligation.cause.body_id);
1626+
if let hir::Node::Expr(expr) = body {
1627+
v.visit_expr(expr);
1628+
}
1629+
if let Some(expr) = v.found {
1630+
// FIXME(estebank): look for method calls that can be applied on the previous
1631+
// element of the chain, that would make the next call to typeck.
1632+
let mut receiver = expr;
1633+
if let (Some(typeck_results), hir::ExprKind::MethodCall(..)) =
1634+
(self.in_progress_typeck_results, &receiver.kind)
1635+
{
1636+
let typeck_results = typeck_results.borrow();
1637+
while let hir::ExprKind::MethodCall(method_segment, args, _) = receiver.kind {
1638+
if let Some(ty) = typeck_results.expr_ty_adjusted_opt(receiver) {
1639+
diag.span_label(
1640+
method_segment.ident.span,
1641+
&format!("this call is of type `{ty}`"),
1642+
);
1643+
}
1644+
receiver = &args[0];
1645+
}
1646+
while let hir::ExprKind::Call(path, _args) = receiver.kind {
1647+
if let Some(ty) = typeck_results.expr_ty_adjusted_opt(receiver) {
1648+
diag.span_label(path.span, &format!("this call is of type `{ty}`"));
1649+
}
1650+
receiver = &path;
1651+
}
1652+
}
1653+
}
16241654
let secondary_span = match predicate.kind().skip_binder() {
16251655
ty::PredicateKind::Projection(proj) => self
16261656
.tcx
@@ -2689,3 +2719,24 @@ impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
26892719
}
26902720
}
26912721
}
2722+
2723+
struct HirFinder<'tcx> {
2724+
needle: Span,
2725+
found: Option<&'tcx hir::Expr<'tcx>>,
2726+
}
2727+
2728+
impl<'v> Visitor<'v> for HirFinder<'v> {
2729+
fn visit_expr(&mut self, expr: &'v hir::Expr<'v>) {
2730+
if expr.span == self.needle {
2731+
self.found = Some(expr);
2732+
return;
2733+
}
2734+
if let hir::ExprKind::MethodCall(segment, _, _) = expr.kind {
2735+
if segment.ident.span == self.needle {
2736+
self.found = Some(expr);
2737+
return;
2738+
}
2739+
}
2740+
hir::intravisit::walk_expr(self, expr);
2741+
}
2742+
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item == &_`
22
--> $DIR/issue-31173.rs:10:10
33
|
4+
LL | let temp: Vec<u8> = it.take_while(|&x| {
5+
| ---------- this call is of type `TakeWhile<&mut std::vec::IntoIter<u8>, _>`
6+
...
47
LL | .cloned()
58
| ^^^^^^ expected reference, found `u8`
69
|

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _,
22
--> $DIR/issue-33941.rs:6:36
33
|
44
LL | for _ in HashMap::new().iter().cloned() {}
5-
| ^^^^^^ expected reference, found tuple
5+
| ------------ ---- ^^^^^^ expected reference, found tuple
6+
| | |
7+
| | this call is of type `std::collections::hash_map::Iter<'_, _, _>`
8+
| this call is of type `&HashMap<_, _>`
69
|
710
= note: expected reference `&_`
811
found tuple `(&_, &_)`

0 commit comments

Comments
 (0)