1
Fork 0

Clean up infer_return_ty_for_fn_sig

This commit is contained in:
Michael Goulet 2024-12-13 15:10:58 +00:00
parent 4847d6a9d0
commit d82c520f14

View file

@ -1330,7 +1330,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
.. ..
}) })
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => { | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx) lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
} }
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
@ -1347,7 +1347,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
None, None,
) )
} else { } else {
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx) lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
} }
} }
@ -1397,18 +1397,37 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
ty::EarlyBinder::bind(output) ty::EarlyBinder::bind(output)
} }
fn infer_return_ty_for_fn_sig<'tcx>( fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
sig: &hir::FnSig<'tcx>,
generics: &hir::Generics<'_>,
def_id: LocalDefId,
icx: &ItemCtxt<'tcx>, icx: &ItemCtxt<'tcx>,
sig: &'tcx hir::FnSig<'tcx>,
generics: &'tcx hir::Generics<'tcx>,
def_id: LocalDefId,
) -> ty::PolyFnSig<'tcx> {
if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
}
icx.lowerer().lower_fn_ty(
icx.tcx().local_def_id_to_hir_id(def_id),
sig.header.safety,
sig.header.abi,
sig.decl,
Some(generics),
None,
)
}
fn recover_infer_ret_ty<'tcx>(
icx: &ItemCtxt<'tcx>,
infer_ret_ty: &'tcx hir::Ty<'tcx>,
generics: &'tcx hir::Generics<'tcx>,
def_id: LocalDefId,
) -> ty::PolyFnSig<'tcx> { ) -> ty::PolyFnSig<'tcx> {
let tcx = icx.tcx; let tcx = icx.tcx;
let hir_id = tcx.local_def_id_to_hir_id(def_id); let hir_id = tcx.local_def_id_to_hir_id(def_id);
match sig.decl.output.get_infer_ret_ty() {
Some(ty) => {
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
// Typeck doesn't expect erased regions to be returned from `type_of`. // Typeck doesn't expect erased regions to be returned from `type_of`.
// This is a heuristic approach. If the scope has region parameters, // This is a heuristic approach. If the scope has region parameters,
// we should change fn_sig's lifetime from `ReErased` to `ReError`, // we should change fn_sig's lifetime from `ReErased` to `ReError`,
@ -1433,18 +1452,18 @@ fn infer_return_ty_for_fn_sig<'tcx>(
}); });
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(ty); visitor.visit_ty(infer_ret_ty);
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type"); let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
let ret_ty = fn_sig.output(); let ret_ty = fn_sig.output();
// Don't leak types into signatures unless they're nameable! // Don't leak types into signatures unless they're nameable!
// For example, if a function returns itself, we don't want that // For example, if a function returns itself, we don't want that
// recursive function definition to leak out into the fn sig. // recursive function definition to leak out into the fn sig.
let mut recovered_ret_ty = None; let mut recovered_ret_ty = None;
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) { if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
diag.span_suggestion( diag.span_suggestion(
ty.span, infer_ret_ty.span,
"replace with the correct return type", "replace with the correct return type",
suggestable_ret_ty, suggestable_ret_ty,
Applicability::MachineApplicable, Applicability::MachineApplicable,
@ -1456,7 +1475,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
ret_ty, ret_ty,
) { ) {
diag.span_suggestion( diag.span_suggestion(
ty.span, infer_ret_ty.span,
"replace with an appropriate return type", "replace with an appropriate return type",
sugg, sugg,
Applicability::MachineApplicable, Applicability::MachineApplicable,
@ -1464,6 +1483,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
} else if ret_ty.is_closure() { } else if ret_ty.is_closure() {
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
} }
// Also note how `Fn` traits work just in case! // Also note how `Fn` traits work just in case!
if ret_ty.is_closure() { if ret_ty.is_closure() {
diag.note( diag.note(
@ -1471,7 +1491,6 @@ fn infer_return_ty_for_fn_sig<'tcx>(
https://doc.rust-lang.org/book/ch13-01-closures.html", https://doc.rust-lang.org/book/ch13-01-closures.html",
); );
} }
let guar = diag.emit(); let guar = diag.emit();
ty::Binder::dummy(tcx.mk_fn_sig( ty::Binder::dummy(tcx.mk_fn_sig(
fn_sig.inputs().iter().copied(), fn_sig.inputs().iter().copied(),
@ -1480,16 +1499,6 @@ fn infer_return_ty_for_fn_sig<'tcx>(
fn_sig.safety, fn_sig.safety,
fn_sig.abi, fn_sig.abi,
)) ))
}
None => icx.lowerer().lower_fn_ty(
hir_id,
sig.header.safety,
sig.header.abi,
sig.decl,
Some(generics),
None,
),
}
} }
pub fn suggest_impl_trait<'tcx>( pub fn suggest_impl_trait<'tcx>(