Skip to content

Commit bfe6a26

Browse files
committed
hir_typeck: be more conservative in making "note caller chooses ty param" note
- Avoid "caller chooses ty for type param" note if the found type a.k.a. the return expression type *contains* the type parameter, because e.g. `&T` will always be different from `T` (i.e. "well duh"). - Rename `note_caller_chooses_ty_for_ty_param` to `try_note_caller_chooses_ty_for_ty_param` because the note is not always made. Issue: rust-lang#126547
1 parent dd104ef commit bfe6a26

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -859,10 +859,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
859859
} else {
860860
// Only point to return type if the expected type is the return type, as if they
861861
// are not, the expectation must have been caused by something else.
862-
debug!("return type {:?}", hir_ty);
862+
debug!(?hir_ty, "return type");
863863
let ty = self.lowerer().lower_ty(hir_ty);
864-
debug!("return type {:?}", ty);
865-
debug!("expected type {:?}", expected);
864+
debug!(?ty, "return type (lowered)");
865+
debug!(?expected, "expected type");
866866
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
867867
let ty = Binder::bind_with_vars(ty, bound_vars);
868868
let ty = self.normalize(hir_ty.span, ty);
@@ -873,7 +873,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
873873
expected,
874874
});
875875
self.try_suggest_return_impl_trait(err, expected, found, fn_id);
876-
self.note_caller_chooses_ty_for_ty_param(err, expected, found);
876+
self.try_note_caller_chooses_ty_for_ty_param(err, expected, found);
877877
return true;
878878
}
879879
}
@@ -883,18 +883,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
883883
false
884884
}
885885

886-
fn note_caller_chooses_ty_for_ty_param(
886+
fn try_note_caller_chooses_ty_for_ty_param(
887887
&self,
888888
diag: &mut Diag<'_>,
889889
expected: Ty<'tcx>,
890890
found: Ty<'tcx>,
891891
) {
892-
if let ty::Param(expected_ty_as_param) = expected.kind() {
893-
diag.subdiagnostic(errors::NoteCallerChoosesTyForTyParam {
894-
ty_param_name: expected_ty_as_param.name,
895-
found_ty: found,
896-
});
892+
// Only show the note if:
893+
// 1. `expected` ty is a type parameter;
894+
// 2. The `expected` type parameter does *not* occur in the return expression type. This can
895+
// happen for e.g. `fn foo<T>(t: &T) -> T { t }`, where `expected` is `T` but `found` is
896+
// `&T`. Saying "the caller chooses a type for `T` which can be different from `&T`" is
897+
// "well duh" and is only confusing and not helpful.
898+
let ty::Param(expected_ty_as_param) = expected.kind() else {
899+
return;
900+
};
901+
902+
if found.contains(expected) {
903+
return;
897904
}
905+
906+
diag.subdiagnostic(errors::NoteCallerChoosesTyForTyParam {
907+
ty_param_name: expected_ty_as_param.name,
908+
found_ty: found,
909+
});
898910
}
899911

900912
/// check whether the return type is a generic type with a trait bound

0 commit comments

Comments
 (0)