Skip to content

Commit c532045

Browse files
Improve presentation of closure signature mismatch from Fn trait goal
1 parent c6c1796 commit c532045

File tree

5 files changed

+63
-37
lines changed

5 files changed

+63
-37
lines changed

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

+51-25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use core::ops::ControlFlow;
22
use std::borrow::Cow;
33
use std::path::PathBuf;
44

5+
use rustc_abi::ExternAbi;
56
use rustc_ast::TraitObjectSyntax;
67
use rustc_data_structures::fx::FxHashMap;
78
use rustc_data_structures::unord::UnordSet;
@@ -2799,32 +2800,57 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27992800
}
28002801

28012802
// Note any argument mismatches
2802-
let given_ty = params.skip_binder();
2803+
let ty::Tuple(given) = *params.skip_binder().kind() else {
2804+
return;
2805+
};
2806+
28032807
let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
2804-
if let ty::Tuple(given) = given_ty.kind()
2805-
&& let ty::Tuple(expected) = expected_ty.kind()
2806-
{
2807-
if expected.len() != given.len() {
2808-
// Note number of types that were expected and given
2809-
err.note(
2810-
format!(
2811-
"expected a closure taking {} argument{}, but one taking {} argument{} was given",
2812-
given.len(),
2813-
pluralize!(given.len()),
2814-
expected.len(),
2815-
pluralize!(expected.len()),
2816-
)
2817-
);
2818-
} else if !self.same_type_modulo_infer(given_ty, expected_ty) {
2819-
// Print type mismatch
2820-
let (expected_args, given_args) = self.cmp(given_ty, expected_ty);
2821-
err.note_expected_found(
2822-
&"a closure with arguments",
2823-
expected_args,
2824-
&"a closure with arguments",
2825-
given_args,
2826-
);
2827-
}
2808+
let ty::Tuple(expected) = *expected_ty.kind() else {
2809+
return;
2810+
};
2811+
2812+
if expected.len() != given.len() {
2813+
// Note number of types that were expected and given
2814+
err.note(format!(
2815+
"expected a closure taking {} argument{}, but one taking {} argument{} was given",
2816+
given.len(),
2817+
pluralize!(given.len()),
2818+
expected.len(),
2819+
pluralize!(expected.len()),
2820+
));
2821+
return;
2822+
}
2823+
2824+
let given_ty = Ty::new_fn_ptr(
2825+
self.tcx,
2826+
params.rebind(self.tcx.mk_fn_sig(
2827+
given,
2828+
self.tcx.types.unit,
2829+
false,
2830+
hir::Safety::Safe,
2831+
ExternAbi::Rust,
2832+
)),
2833+
);
2834+
let expected_ty = Ty::new_fn_ptr(
2835+
self.tcx,
2836+
trait_pred.rebind(self.tcx.mk_fn_sig(
2837+
expected,
2838+
self.tcx.types.unit,
2839+
false,
2840+
hir::Safety::Safe,
2841+
ExternAbi::Rust,
2842+
)),
2843+
);
2844+
2845+
if !self.same_type_modulo_infer(given_ty, expected_ty) {
2846+
// Print type mismatch
2847+
let (expected_args, given_args) = self.cmp(expected_ty, given_ty);
2848+
err.note_expected_found(
2849+
&"a closure with signature",
2850+
expected_args,
2851+
&"a closure with signature",
2852+
given_args,
2853+
);
28282854
}
28292855
}
28302856

tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr

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

tests/ui/implied-bounds/issue-100690.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ LL | real_dispatch(f)
66
| |
77
| required by a bound introduced by this call
88
|
9-
= note: expected a closure with arguments `(&mut UIView<'a, _>,)`
10-
found a closure with arguments `(&mut UIView<'_, _>,)`
9+
= note: expected a closure with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)`
10+
found a closure with signature `fn(&mut UIView<'a, _>)`
1111
note: required by a bound in `real_dispatch`
1212
--> $DIR/issue-100690.rs:8:8
1313
|

tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
77
| required by a bound introduced by this call
88
|
99
= 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}`
10-
= note: expected a closure with arguments `(i32,)`
11-
found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
10+
= note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
11+
found a closure with signature `fn(i32)`
1212
note: required by a bound in `find`
1313
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
1414

@@ -27,8 +27,8 @@ LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
2727
| required by a bound introduced by this call
2828
|
2929
= 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}`
30-
= note: expected a closure with arguments `(&&&i32,)`
31-
found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
30+
= note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
31+
found a closure with signature `fn(&&&i32)`
3232
note: required by a bound in `find`
3333
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
3434

tests/ui/trait-bounds/mismatch-fn-trait.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ LL | take(f)
66
| |
77
| required by a bound introduced by this call
88
|
9-
= note: expected a closure with arguments `(u32,)`
10-
found a closure with arguments `(i32,)`
9+
= note: expected a closure with signature `fn(i32)`
10+
found a closure with signature `fn(u32)`
1111
note: required by a bound in `take`
1212
--> $DIR/mismatch-fn-trait.rs:1:18
1313
|
@@ -68,8 +68,8 @@ LL | take(f)
6868
| required by a bound introduced by this call
6969
|
7070
= note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
71-
= note: expected a closure with arguments `(u32,)`
72-
found a closure with arguments `(i32,)`
71+
= note: expected a closure with signature `fn(i32)`
72+
found a closure with signature `fn(u32)`
7373
note: required by a bound in `take`
7474
--> $DIR/mismatch-fn-trait.rs:1:18
7575
|

0 commit comments

Comments
 (0)