Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fix suggestions for nested refs and muts
  • Loading branch information
JohnTitor committed Oct 11, 2025
commit dbc7327748d6dc190c594c8343dd53e8e60ca49c
24 changes: 23 additions & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2577,10 +2577,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& matches!(parent_pat.kind, hir::PatKind::Ref(..)) =>
Comment on lines +2576 to +2579
Copy link
Copy Markdown
Member

@fmease fmease Oct 11, 2025

Choose a reason for hiding this comment

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

Food for thought (I don't have time to investigate this): If the unsolved inference variable is not an integer/float one ({integer} / {float}) but a normal one, then need_type_info / InferSourceKind is able to figure out the type annotation for various kinds of patterns.

E.g.,

[].into_iter().filter(|&x| x.pow(0)); // suggests `: &T` on master
[].into_iter().filter(|(x,)| x.pow(0)); // suggests `: &(T,)` on master

So I guess ideally we would be modifying needs_type_info to properly deal with integer/float ty vars since that seems to have all the infrastructure in place already (unless they really follow a different code path in which case my suggestion would be nonsensical).

{
err.span_label(span, "you must specify a type for this binding");

let mut ref_muts = Vec::new();
let mut current_node = parent_node;

while let Node::Pat(parent_pat) = current_node {
if let hir::PatKind::Ref(_, mutability) = parent_pat.kind {
ref_muts.push(mutability);
current_node = self.tcx.parent_hir_node(parent_pat.hir_id);
} else {
break;
}
}

let mut type_annotation = String::new();
for mutability in ref_muts.iter().rev() {
match mutability {
hir::Mutability::Mut => type_annotation.push_str("&mut "),
hir::Mutability::Not => type_annotation.push('&'),
}
}
type_annotation.push_str(&concrete_type);

err.span_suggestion_verbose(
pat.span.shrink_to_hi(),
"specify the type in the closure argument list",
format!(": &{concrete_type}"),
format!(": {type_annotation}"),
Applicability::MaybeIncorrect,
);
}
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ fn main() {
let _ = (0..10).filter(|&v: &i32| v.pow(2) > 0);
//~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
//~| SUGGESTION &i32

let v = vec![0, 1, 2];
let _ = v.iter().filter(|&&v: &&i32| v.pow(2) > 0);
//~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
//~| SUGGESTION &&i32
}
5 changes: 5 additions & 0 deletions tests/ui/inference/ambiguous-numeric-in-closure-ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ fn main() {
let _ = (0..10).filter(|&v| v.pow(2) > 0);
//~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
//~| SUGGESTION &i32

let v = vec![0, 1, 2];
let _ = v.iter().filter(|&&v| v.pow(2) > 0);
//~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
//~| SUGGESTION &&i32
}
15 changes: 14 additions & 1 deletion tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ help: specify the type in the closure argument list
LL | let _ = (0..10).filter(|&v: &i32| v.pow(2) > 0);
| ++++++

error: aborting due to 1 previous error
error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
--> $DIR/ambiguous-numeric-in-closure-ref.rs:11:37
|
LL | let _ = v.iter().filter(|&&v| v.pow(2) > 0);
| - ^^^
| |
| you must specify a type for this binding
|
help: specify the type in the closure argument list
|
LL | let _ = v.iter().filter(|&&v: &&i32| v.pow(2) > 0);
| +++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0689`.