From 0f368e33195121db4fc543b270cd8220ca04e3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sat, 9 Mar 2024 20:32:36 +0000 Subject: [PATCH] Note that type param is chosen by caller when suggesting return impl Trait --- compiler/rustc_hir_typeck/src/expr.rs | 16 +++++++- .../src/fn_ctxt/suggestions.rs | 2 +- .../issues/issue-67945-1.full.stderr | 1 + tests/ui/typeck/return-ty-mismatch-note.rs | 21 ++++++++++ .../ui/typeck/return-ty-mismatch-note.stderr | 39 +++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/ui/typeck/return-ty-mismatch-note.rs create mode 100644 tests/ui/typeck/return-ty-mismatch-note.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ceaae9cf49f28..1d094ef2ef06e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -118,7 +118,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let ty = self.check_expr_with_hint(expr, expected); // checks don't need two phase - self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) + let (res_ty, diag) = + self.demand_coerce_diag(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No); + + if let Some(mut diag) = diag { + if let ty::Param(expected_ty_as_param) = expected.kind() { + diag.note(format!( + "the caller chooses a type for `{}` which can be different from `{}`", + expected_ty_as_param.name, ty + )); + } + + diag.emit(); + } + + res_ty } pub(super) fn check_expr_with_hint( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5a1c7b0561185..b3240285a5b7d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx(), errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected }, ); - self.try_suggest_return_impl_trait(err, expected, ty, fn_id); + self.try_suggest_return_impl_trait(err, expected, found, fn_id); return true; } } diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr index 2ecdc0366d558..75dbf55b0f7a0 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -11,6 +11,7 @@ LL | let x: S = MaybeUninit::uninit(); | = note: expected type parameter `S` found union `MaybeUninit<_>` + = note: the caller chooses a type for `S` which can be different from `MaybeUninit<_>` error: aborting due to 1 previous error diff --git a/tests/ui/typeck/return-ty-mismatch-note.rs b/tests/ui/typeck/return-ty-mismatch-note.rs new file mode 100644 index 0000000000000..352bc2a163763 --- /dev/null +++ b/tests/ui/typeck/return-ty-mismatch-note.rs @@ -0,0 +1,21 @@ +// Checks existence of a note for "a caller chooses ty for ty param" upon return ty mismatch. + +fn f() -> (T,) { + (0,) //~ ERROR mismatched types +} + +fn g() -> (U, V) { + (0, "foo") + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn h() -> u8 { + 0u8 +} + +fn main() { + f::<()>(); + g::<(), ()>; + let _ = h(); +} diff --git a/tests/ui/typeck/return-ty-mismatch-note.stderr b/tests/ui/typeck/return-ty-mismatch-note.stderr new file mode 100644 index 0000000000000..d922f44943a78 --- /dev/null +++ b/tests/ui/typeck/return-ty-mismatch-note.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/return-ty-mismatch-note.rs:4:6 + | +LL | fn f() -> (T,) { + | - expected this type parameter +LL | (0,) + | ^ expected type parameter `T`, found integer + | + = note: expected type parameter `T` + found type `{integer}` + = note: the caller chooses a type for `T` which can be different from `{integer}` + +error[E0308]: mismatched types + --> $DIR/return-ty-mismatch-note.rs:8:6 + | +LL | fn g() -> (U, V) { + | - expected this type parameter +LL | (0, "foo") + | ^ expected type parameter `U`, found integer + | + = note: expected type parameter `U` + found type `{integer}` + = note: the caller chooses a type for `U` which can be different from `{integer}` + +error[E0308]: mismatched types + --> $DIR/return-ty-mismatch-note.rs:8:9 + | +LL | fn g() -> (U, V) { + | - expected this type parameter +LL | (0, "foo") + | ^^^^^ expected type parameter `V`, found `&str` + | + = note: expected type parameter `V` + found reference `&'static str` + = note: the caller chooses a type for `V` which can be different from `&'static str` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.