diff options
| author | Michael Goulet <michael@errs.io> | 2025-04-08 05:54:44 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-04-08 05:54:57 +0000 |
| commit | c5320454ed47736d17d1e07438e27345f08782bc (patch) | |
| tree | 4fede2245bdb729b3c38ba822648a9d6b58c3838 /compiler/rustc_trait_selection/src | |
| parent | c6c179662d5a6fc0520e05b5c0682dcfc7333f77 (diff) | |
| download | rust-c5320454ed47736d17d1e07438e27345f08782bc.tar.gz rust-c5320454ed47736d17d1e07438e27345f08782bc.zip | |
Improve presentation of closure signature mismatch from Fn trait goal
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index bc45fc11e9b..a01574f2826 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -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,32 +2800,57 @@ 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() - { - if expected.len() != given.len() { - // Note number of types that were expected and given - err.note( - format!( - "expected a closure taking {} argument{}, but one taking {} argument{} was given", - given.len(), - pluralize!(given.len()), - expected.len(), - pluralize!(expected.len()), - ) - ); - } else if !self.same_type_modulo_infer(given_ty, expected_ty) { - // Print type mismatch - let (expected_args, given_args) = self.cmp(given_ty, expected_ty); - err.note_expected_found( - &"a closure with arguments", - expected_args, - &"a closure with arguments", - given_args, - ); - } + 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!( + "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, + )), + ); + 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(expected_ty, given_ty); + err.note_expected_found( + &"a closure with signature", + expected_args, + &"a closure with signature", + given_args, + ); } } |
