Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print type of every call in a method call chain #96918

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines +1630 to +1631
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@compiler-errors I think that this is the part that would be useful from this PR, that this PR didn't handle: enabling rustc to look for method calls that could be added to make the code compile would be the biggest benefit of this change, but this PR on its own might not be as useful as I envisioned.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least in the case of #33941, suggesting other methods that are compatible with the real Item type doesn't seem like the right direction for a suggestion to go imo.

I think the compiler should be trying to stress that that (&K, &V) is not &T instead. I'm not sure how to make the connection more clear that if they want (&K, &V) -> (K, V) they've gotta do the map themselves... now I don't think this needs special-casing per se, but conversely, I think suggesting other methods is probably going to lead them further astray?

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) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if resolving ty here would give us the Item type instead of _, which would be useful then.

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
Expand Down Expand Up @@ -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);
}
}
3 changes: 3 additions & 0 deletions src/test/ui/issues/issue-31173.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item == &_`
--> $DIR/issue-31173.rs:10:10
|
LL | let temp: Vec<u8> = it.take_while(|&x| {
| ---------- this call is of type `TakeWhile<&mut std::vec::IntoIter<u8>, _>`
...
LL | .cloned()
| ^^^^^^ expected reference, found `u8`
|
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-33941.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _,
--> $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 `(&_, &_)`
Expand Down