about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-04-08 21:25:59 +0200
committerGitHub <noreply@github.com>2025-04-08 21:25:59 +0200
commitb41e2bd807884180cb06bb971d7add2a5ed93b03 (patch)
tree6d0f5658456db58313645cca62b835a4ac1e0934
parentdf9796f20dd9a6cd983cbef739ec612c0582509a (diff)
parentd940038636c3694c896988c5cb035da4456a2cb0 (diff)
downloadrust-b41e2bd807884180cb06bb971d7add2a5ed93b03.tar.gz
rust-b41e2bd807884180cb06bb971d7add2a5ed93b03.zip
Rollup merge of #139515 - compiler-errors:sig-mismatch, r=lcnr
Improve presentation of closure signature mismatch from `Fn` trait goal

Flip the order of "expected" and "found" since that wasn't correct.

Don't present the arguments as a tuple, since it leaves a trailing comma. Instead, just use `fn(arg, arg)`.

Finally, be better with binders since we were just skipping binders.

r? oli-obk or reassign
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs8
-rw-r--r--compiler/rustc_lint/src/lints.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs76
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr4
-rw-r--r--tests/ui/implied-bounds/issue-100690.stderr4
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr8
-rw-r--r--tests/ui/trait-bounds/mismatch-fn-trait.stderr8
9 files changed, 70 insertions, 44 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 794502d7aae..bd13c413a4d 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -647,9 +647,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     #[rustc_lint_diagnostics]
     pub fn note_expected_found(
         &mut self,
-        expected_label: &dyn fmt::Display,
+        expected_label: &str,
         expected: DiagStyledString,
-        found_label: &dyn fmt::Display,
+        found_label: &str,
         found: DiagStyledString,
     ) -> &mut Self {
         self.note_expected_found_extra(
@@ -665,9 +665,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     #[rustc_lint_diagnostics]
     pub fn note_expected_found_extra(
         &mut self,
-        expected_label: &dyn fmt::Display,
+        expected_label: &str,
         expected: DiagStyledString,
-        found_label: &dyn fmt::Display,
+        found_label: &str,
         found: DiagStyledString,
         expected_extra: DiagStyledString,
         found_extra: DiagStyledString,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 55d010e6d34..51214c8e8a4 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -513,7 +513,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> {
         expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
         let mut found_str = DiagStyledString::new();
         found_str.push(self.found.fn_sig(self.tcx).to_string(), true);
-        diag.note_expected_found(&"", expected_str, &"", found_str);
+        diag.note_expected_found("", expected_str, "", found_str);
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index c7f0a88f951..fcb98f740b0 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -967,7 +967,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 format!("...so that the {}", sup_trace.cause.as_requirement_str()),
             );
 
-            err.note_expected_found(&"", sup_expected, &"", sup_found);
+            err.note_expected_found("", sup_expected, "", sup_found);
             return if sub_region.is_error() | sup_region.is_error() {
                 err.delay_as_bug()
             } else {
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..5648021f613 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,
+            );
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 9f7bfe5101a..bb4aba9d29e 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -415,7 +415,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
                 label_or_note(span, fluent::trait_selection_subtype);
                 diag.arg("requirement", requirement);
 
-                diag.note_expected_found(&"", expected, &"", found);
+                diag.note_expected_found("", expected, "", found);
             }
             RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
                 // FIXME: this really should be handled at some earlier stage. Our
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
index 64707642eeb..36264b0d997 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
@@ -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
    |
diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr
index 4964dccd551..d00895d8fc9 100644
--- a/tests/ui/implied-bounds/issue-100690.stderr
+++ b/tests/ui/implied-bounds/issue-100690.stderr
@@ -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
    |
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index b7161310619..7912ed4d707 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -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
 
diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
index 519aa9ea3f3..051e660c2d1 100644
--- a/tests/ui/trait-bounds/mismatch-fn-trait.stderr
+++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
@@ -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
    |