Improve presentation of closure signature mismatch from Fn trait goal

This commit is contained in:
Michael Goulet 2025-04-08 05:54:44 +00:00
parent c6c179662d
commit c5320454ed
5 changed files with 63 additions and 37 deletions

View file

@ -2,6 +2,7 @@ use core::ops::ControlFlow;
use std::borrow::Cow;
use std::path::PathBuf;
use rustc_abi::ExternAbi;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
@ -2799,34 +2800,59 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
// Note any argument mismatches
let given_ty = params.skip_binder();
let ty::Tuple(given) = *params.skip_binder().kind() else {
return;
};
let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
if let ty::Tuple(given) = given_ty.kind()
&& let ty::Tuple(expected) = expected_ty.kind()
{
let ty::Tuple(expected) = *expected_ty.kind() else {
return;
};
if expected.len() != given.len() {
// Note number of types that were expected and given
err.note(
format!(
err.note(format!(
"expected a closure taking {} argument{}, but one taking {} argument{} was given",
given.len(),
pluralize!(given.len()),
expected.len(),
pluralize!(expected.len()),
)
));
return;
}
let given_ty = Ty::new_fn_ptr(
self.tcx,
params.rebind(self.tcx.mk_fn_sig(
given,
self.tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
)),
);
} else if !self.same_type_modulo_infer(given_ty, expected_ty) {
let expected_ty = Ty::new_fn_ptr(
self.tcx,
trait_pred.rebind(self.tcx.mk_fn_sig(
expected,
self.tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
)),
);
if !self.same_type_modulo_infer(given_ty, expected_ty) {
// Print type mismatch
let (expected_args, given_args) = self.cmp(given_ty, expected_ty);
let (expected_args, given_args) = self.cmp(expected_ty, given_ty);
err.note_expected_found(
&"a closure with arguments",
&"a closure with signature",
expected_args,
&"a closure with arguments",
&"a closure with signature",
given_args,
);
}
}
}
fn maybe_add_note_for_unsatisfied_const(
&self,

View file

@ -6,8 +6,8 @@ LL | call(f, ());
| |
| required by a bound introduced by this call
|
= note: expected a closure with arguments `((),)`
found a closure with arguments `(<_ as ATC<'a>>::Type,)`
= note: expected a closure with signature `for<'a> fn(<_ as ATC<'a>>::Type)`
found a closure with signature `fn(())`
note: this is a known limitation of the trait solver that will be lifted in the future
--> $DIR/issue-62529-3.rs:25:14
|

View file

@ -6,8 +6,8 @@ LL | real_dispatch(f)
| |
| required by a bound introduced by this call
|
= note: expected a closure with arguments `(&mut UIView<'a, _>,)`
found a closure with arguments `(&mut UIView<'_, _>,)`
= note: expected a closure with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)`
found a closure with signature `fn(&mut UIView<'a, _>)`
note: required by a bound in `real_dispatch`
--> $DIR/issue-100690.rs:8:8
|

View file

@ -7,8 +7,8 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
| required by a bound introduced by this call
|
= help: the trait `for<'a> FnMut(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
= note: expected a closure with arguments `(i32,)`
found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
= note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
found a closure with signature `fn(i32)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
@ -27,8 +27,8 @@ LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
| required by a bound introduced by this call
|
= help: the trait `for<'a> FnMut(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
= note: expected a closure with arguments `(&&&i32,)`
found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
= note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
found a closure with signature `fn(&&&i32)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL

View file

@ -6,8 +6,8 @@ LL | take(f)
| |
| required by a bound introduced by this call
|
= note: expected a closure with arguments `(u32,)`
found a closure with arguments `(i32,)`
= note: expected a closure with signature `fn(i32)`
found a closure with signature `fn(u32)`
note: required by a bound in `take`
--> $DIR/mismatch-fn-trait.rs:1:18
|
@ -68,8 +68,8 @@ LL | take(f)
| required by a bound introduced by this call
|
= note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
= note: expected a closure with arguments `(u32,)`
found a closure with arguments `(i32,)`
= note: expected a closure with signature `fn(i32)`
found a closure with signature `fn(u32)`
note: required by a bound in `take`
--> $DIR/mismatch-fn-trait.rs:1:18
|