Rollup merge of #147577 - JohnTitor:issue-147312, r=davidtwco
Improve error message for ambiguous numeric types in closure parameters Closes https://github.com/rust-lang/rust/issues/147312
This commit is contained in:
@@ -2547,6 +2547,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"you must specify a type for this binding, like `{concrete_type}`",
|
||||
);
|
||||
|
||||
// FIXME: Maybe FileName::Anon should also be handled,
|
||||
// otherwise there would be no suggestion if the source is STDIN for example.
|
||||
match (filename, parent_node) {
|
||||
(
|
||||
FileName::Real(_),
|
||||
@@ -2568,6 +2570,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
// For closure parameters with reference patterns (e.g., |&v|), suggest the type annotation
|
||||
// on the pattern itself, e.g., |&v: &i32|
|
||||
(FileName::Real(_), Node::Pat(pat))
|
||||
if let Node::Pat(binding_pat) = self.tcx.hir_node(hir_id)
|
||||
&& let hir::PatKind::Binding(..) = binding_pat.kind
|
||||
&& let Node::Pat(parent_pat) = parent_node
|
||||
&& matches!(parent_pat.kind, hir::PatKind::Ref(..)) =>
|
||||
{
|
||||
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!(": {type_annotation}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
err.span_label(span, msg);
|
||||
}
|
||||
|
||||
14
tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed
Normal file
14
tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed
Normal file
@@ -0,0 +1,14 @@
|
||||
// Test for better error message when numeric type is ambiguous in closure parameter with reference
|
||||
|
||||
//@ run-rustfix
|
||||
|
||||
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
|
||||
}
|
||||
14
tests/ui/inference/ambiguous-numeric-in-closure-ref.rs
Normal file
14
tests/ui/inference/ambiguous-numeric-in-closure-ref.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
// Test for better error message when numeric type is ambiguous in closure parameter with reference
|
||||
|
||||
//@ run-rustfix
|
||||
|
||||
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
|
||||
}
|
||||
29
tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr
Normal file
29
tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr
Normal file
@@ -0,0 +1,29 @@
|
||||
error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
|
||||
--> $DIR/ambiguous-numeric-in-closure-ref.rs:6:35
|
||||
|
|
||||
LL | let _ = (0..10).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 _ = (0..10).filter(|&v: &i32| v.pow(2) > 0);
|
||||
| ++++++
|
||||
|
||||
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`.
|
||||
Reference in New Issue
Block a user