Skip to content

Commit d82c520

Browse files
Clean up infer_return_ty_for_fn_sig
1 parent 4847d6a commit d82c520

File tree

1 file changed

+94
-85
lines changed

1 file changed

+94
-85
lines changed

Diff for: compiler/rustc_hir_analysis/src/collect.rs

+94-85
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13301330
..
13311331
})
13321332
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
1333-
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
1333+
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
13341334
}
13351335

13361336
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
@@ -1347,7 +1347,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13471347
None,
13481348
)
13491349
} else {
1350-
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
1350+
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
13511351
}
13521352
}
13531353

@@ -1397,99 +1397,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13971397
ty::EarlyBinder::bind(output)
13981398
}
13991399

1400-
fn infer_return_ty_for_fn_sig<'tcx>(
1401-
sig: &hir::FnSig<'tcx>,
1402-
generics: &hir::Generics<'_>,
1400+
fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1401+
icx: &ItemCtxt<'tcx>,
1402+
sig: &'tcx hir::FnSig<'tcx>,
1403+
generics: &'tcx hir::Generics<'tcx>,
14031404
def_id: LocalDefId,
1405+
) -> ty::PolyFnSig<'tcx> {
1406+
if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
1407+
return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1408+
}
1409+
1410+
icx.lowerer().lower_fn_ty(
1411+
icx.tcx().local_def_id_to_hir_id(def_id),
1412+
sig.header.safety,
1413+
sig.header.abi,
1414+
sig.decl,
1415+
Some(generics),
1416+
None,
1417+
)
1418+
}
1419+
1420+
fn recover_infer_ret_ty<'tcx>(
14041421
icx: &ItemCtxt<'tcx>,
1422+
infer_ret_ty: &'tcx hir::Ty<'tcx>,
1423+
generics: &'tcx hir::Generics<'tcx>,
1424+
def_id: LocalDefId,
14051425
) -> ty::PolyFnSig<'tcx> {
14061426
let tcx = icx.tcx;
14071427
let hir_id = tcx.local_def_id_to_hir_id(def_id);
14081428

1409-
match sig.decl.output.get_infer_ret_ty() {
1410-
Some(ty) => {
1411-
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1412-
// Typeck doesn't expect erased regions to be returned from `type_of`.
1413-
// This is a heuristic approach. If the scope has region parameters,
1414-
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
1415-
// otherwise to `ReStatic`.
1416-
let has_region_params = generics.params.iter().any(|param| match param.kind {
1417-
GenericParamKind::Lifetime { .. } => true,
1418-
_ => false,
1419-
});
1420-
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
1421-
ty::ReErased => {
1422-
if has_region_params {
1423-
ty::Region::new_error_with_message(
1424-
tcx,
1425-
DUMMY_SP,
1426-
"erased region is not allowed here in return type",
1427-
)
1428-
} else {
1429-
tcx.lifetimes.re_static
1430-
}
1431-
}
1432-
_ => r,
1433-
});
1429+
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
14341430

1435-
let mut visitor = HirPlaceholderCollector::default();
1436-
visitor.visit_ty(ty);
1437-
1438-
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
1439-
let ret_ty = fn_sig.output();
1440-
// Don't leak types into signatures unless they're nameable!
1441-
// For example, if a function returns itself, we don't want that
1442-
// recursive function definition to leak out into the fn sig.
1443-
let mut recovered_ret_ty = None;
1444-
1445-
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1446-
diag.span_suggestion(
1447-
ty.span,
1448-
"replace with the correct return type",
1449-
suggestable_ret_ty,
1450-
Applicability::MachineApplicable,
1451-
);
1452-
recovered_ret_ty = Some(suggestable_ret_ty);
1453-
} else if let Some(sugg) = suggest_impl_trait(
1454-
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1455-
tcx.param_env(def_id),
1456-
ret_ty,
1457-
) {
1458-
diag.span_suggestion(
1459-
ty.span,
1460-
"replace with an appropriate return type",
1461-
sugg,
1462-
Applicability::MachineApplicable,
1463-
);
1464-
} else if ret_ty.is_closure() {
1465-
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1466-
}
1467-
// Also note how `Fn` traits work just in case!
1468-
if ret_ty.is_closure() {
1469-
diag.note(
1470-
"for more information on `Fn` traits and closure types, see \
1471-
https://doc.rust-lang.org/book/ch13-01-closures.html",
1472-
);
1431+
// Typeck doesn't expect erased regions to be returned from `type_of`.
1432+
// This is a heuristic approach. If the scope has region parameters,
1433+
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
1434+
// otherwise to `ReStatic`.
1435+
let has_region_params = generics.params.iter().any(|param| match param.kind {
1436+
GenericParamKind::Lifetime { .. } => true,
1437+
_ => false,
1438+
});
1439+
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
1440+
ty::ReErased => {
1441+
if has_region_params {
1442+
ty::Region::new_error_with_message(
1443+
tcx,
1444+
DUMMY_SP,
1445+
"erased region is not allowed here in return type",
1446+
)
1447+
} else {
1448+
tcx.lifetimes.re_static
14731449
}
1474-
1475-
let guar = diag.emit();
1476-
ty::Binder::dummy(tcx.mk_fn_sig(
1477-
fn_sig.inputs().iter().copied(),
1478-
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1479-
fn_sig.c_variadic,
1480-
fn_sig.safety,
1481-
fn_sig.abi,
1482-
))
14831450
}
1484-
None => icx.lowerer().lower_fn_ty(
1485-
hir_id,
1486-
sig.header.safety,
1487-
sig.header.abi,
1488-
sig.decl,
1489-
Some(generics),
1490-
None,
1491-
),
1451+
_ => r,
1452+
});
1453+
1454+
let mut visitor = HirPlaceholderCollector::default();
1455+
visitor.visit_ty(infer_ret_ty);
1456+
1457+
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
1458+
let ret_ty = fn_sig.output();
1459+
1460+
// Don't leak types into signatures unless they're nameable!
1461+
// For example, if a function returns itself, we don't want that
1462+
// recursive function definition to leak out into the fn sig.
1463+
let mut recovered_ret_ty = None;
1464+
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1465+
diag.span_suggestion(
1466+
infer_ret_ty.span,
1467+
"replace with the correct return type",
1468+
suggestable_ret_ty,
1469+
Applicability::MachineApplicable,
1470+
);
1471+
recovered_ret_ty = Some(suggestable_ret_ty);
1472+
} else if let Some(sugg) = suggest_impl_trait(
1473+
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1474+
tcx.param_env(def_id),
1475+
ret_ty,
1476+
) {
1477+
diag.span_suggestion(
1478+
infer_ret_ty.span,
1479+
"replace with an appropriate return type",
1480+
sugg,
1481+
Applicability::MachineApplicable,
1482+
);
1483+
} else if ret_ty.is_closure() {
1484+
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1485+
}
1486+
1487+
// Also note how `Fn` traits work just in case!
1488+
if ret_ty.is_closure() {
1489+
diag.note(
1490+
"for more information on `Fn` traits and closure types, see \
1491+
https://doc.rust-lang.org/book/ch13-01-closures.html",
1492+
);
14921493
}
1494+
let guar = diag.emit();
1495+
ty::Binder::dummy(tcx.mk_fn_sig(
1496+
fn_sig.inputs().iter().copied(),
1497+
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1498+
fn_sig.c_variadic,
1499+
fn_sig.safety,
1500+
fn_sig.abi,
1501+
))
14931502
}
14941503

14951504
pub fn suggest_impl_trait<'tcx>(

0 commit comments

Comments
 (0)