Skip to content

Commit 964cb77

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 f6236f6 commit 964cb77

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -874,9 +874,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
874874
} else {
875875
// Only point to return type if the expected type is the return type, as if they
876876
// are not, the expectation must have been caused by something else.
877-
debug!("return type {:?}", hir_ty);
877+
debug!("return type (hir::Ty) {:?}", hir_ty);
878878
let ty = self.lowerer().lower_ty(hir_ty);
879-
debug!("return type {:?}", ty);
879+
debug!("return type (ty) {:?}", ty);
880880
debug!("expected type {:?}", expected);
881881
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
882882
let ty = Binder::bind_with_vars(ty, bound_vars);
@@ -888,7 +888,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
888888
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
889889
);
890890
self.try_suggest_return_impl_trait(err, expected, found, fn_id);
891-
self.note_caller_chooses_ty_for_ty_param(err, expected, found);
891+
self.try_note_caller_chooses_ty_for_ty_param(err, expected, found);
892892
return true;
893893
}
894894
}
@@ -898,21 +898,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
898898
false
899899
}
900900

901-
fn note_caller_chooses_ty_for_ty_param(
901+
fn try_note_caller_chooses_ty_for_ty_param(
902902
&self,
903903
diag: &mut Diag<'_>,
904904
expected: Ty<'tcx>,
905905
found: Ty<'tcx>,
906906
) {
907-
if let ty::Param(expected_ty_as_param) = expected.kind() {
908-
diag.subdiagnostic(
909-
self.dcx(),
910-
errors::NoteCallerChoosesTyForTyParam {
911-
ty_param_name: expected_ty_as_param.name,
912-
found_ty: found,
913-
},
914-
);
907+
// Only show the note if:
908+
// 1. `expected` ty is a type parameter;
909+
// 2. The `expected` type parameter does *not* occur in the return expression type. This can
910+
// happen for e.g. `fn foo<T>(t: &T) -> T { t }`, where `expected` is `T` but `found` is
911+
// `&T`. Saying "the caller chooses a type for `T` which can be different from `&T`" is
912+
// "well duh" and is only confusing and not helpful.
913+
914+
let ty::Param(expected_ty_as_param) = expected.kind() else {
915+
return;
916+
};
917+
918+
if found.contains(expected) {
919+
return;
915920
}
921+
922+
diag.subdiagnostic(
923+
self.dcx(),
924+
errors::NoteCallerChoosesTyForTyParam {
925+
ty_param_name: expected_ty_as_param.name,
926+
found_ty: found,
927+
},
928+
);
916929
}
917930

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

0 commit comments

Comments
 (0)