Change:
The statement "the caller chooses a type for which can be different from " is confusing because and are always different. I think it would be best to supress that note when the types only differ in reference-ness. The message was introduced in . No response No response
label +D-confusing
Thanks, that note definitely doesn't make sense. CC (). I suggested to move out of in order to catch more cases but that was a bit too aggressive as can be witnessed here — that's on me. We should replicate some parts of , namely checking that the type param in question does not occur in the return expression type. That did cross my mind back then but I didn't really follow up on that thought for some reason.
Thanks for the cc I'll take a look ~today/tomorrow
Opened to avoid making the note if found return type contains the expected return type (type parameter).

Discussion:
} else { // Only point to return type if the expected type is the return type, as if they // are not, the expectation must have been caused by something else. <del> debug!("return type {:?}", hir_ty); </del> <ins> debug!(?hir_ty, "return type"); </ins> let ty = self.lowerer().lower_ty(hir_ty); <del> debug!("return type {:?}", ty); debug!("expected type {:?}", expected); </del> <ins> debug!(?ty, "return type (lowered)"); debug!(?expected, "expected type"); </ins> let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize(hir_ty.span, ty);

expected, }); self.try_suggest_return_impl_trait(err, expected, found, fn_id); <del> self.note_caller_chooses_ty_for_ty_param(err, expected, found); </del> <ins> self.try_note_caller_chooses_ty_for_ty_param(err, expected, found); </ins> return true; } }

false } <del> fn note_caller_chooses_ty_for_ty_param( </del> <ins> fn try_note_caller_chooses_ty_for_ty_param( </ins> &self, diag: &mut Diag<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, ) { <del> if let ty::Param(expected_ty_as_param) = expected.kind() { diag.subdiagnostic(errors::NoteCallerChoosesTyForTyParam { ty_param_name: expected_ty_as_param.name, found_ty: found, }); </del> <ins> // Only show the note if: // 1. `expected` ty is a type parameter; // 2. The `expected` type parameter does *not* occur in the return expression type. This can //    happen for e.g. `fn foo<T>(t: &T) -> T { t }`, where `expected` is `T` but `found` is //    `&T`. Saying "the caller chooses a type for `T` which can be different from `&T`" is //    "well duh" and is only confusing and not helpful. let ty::Param(expected_ty_as_param) = expected.kind() else { return; }; if found.contains(expected) { return; </ins> } <ins> diag.subdiagnostic(errors::NoteCallerChoosesTyForTyParam { ty_param_name: expected_ty_as_param.name, found_ty: found, }); </ins> } /// check whether the return type is a generic type with a trait bound

<del> // Checks existence of a note for "a caller chooses ty for ty param" upon return ty mismatch. </del> <ins> // Checks existence or absence of a note for "a caller chooses ty for ty param" upon return ty // mismatch. </ins> fn f<T>() -> (T,) { (0,) //~ ERROR mismatched types

0u8 } <ins> // This case was reported in <https://github.com/rust-lang/rust/issues/126547> where it doesn't // make sense to make the "note caller chooses ty for ty param" note if the found type contains // the ty param... fn k<T>(_t: &T) -> T { _t //~^ ERROR mismatched types } </ins> fn main() { f::<()>(); g::<(), ()>;

error[E0308]: mismatched types <del> --> $DIR/return-ty-mismatch-note.rs:4:6 </del> <ins> --> $DIR/return-ty-mismatch-note.rs:5:6 </ins> | LL | fn f<T>() -> (T,) { |      - expected this type parameter

found type `{integer}` error[E0308]: mismatched types <del> --> $DIR/return-ty-mismatch-note.rs:8:6 </del> <ins> --> $DIR/return-ty-mismatch-note.rs:9:6 </ins> | LL | fn g<U, V>() -> (U, V) { |      - expected this type parameter

found type `{integer}` error[E0308]: mismatched types <del> --> $DIR/return-ty-mismatch-note.rs:8:9 </del> <ins> --> $DIR/return-ty-mismatch-note.rs:9:9 </ins> | LL | fn g<U, V>() -> (U, V) { |         - expected this type parameter

= note: expected type parameter `V` found reference `&'static str` <del> error: aborting due to 3 previous errors </del> <ins> error[E0308]: mismatched types --> $DIR/return-ty-mismatch-note.rs:22:5 | LL | fn k<T>(_t: &T) -> T { |      -             - expected `T` because of return type |      | |      expected this type parameter LL |     _t |     ^^ expected type parameter `T`, found `&T` | = note: expected type parameter `_` found reference `&_` error: aborting due to 4 previous errors </ins> For more information about this error, try `rustc --explain E0308`.

| = note: expected type parameter `_` found reference `&_` <del> = note: the caller chooses a type for `T` which can be different from `&T` </del> note: `T` does not implement `Clone`, so `&T` was cloned instead --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5 |