@@ -1340,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13401340 ..
13411341 } )
13421342 | Item ( hir:: Item { kind : ItemKind :: Fn ( sig, generics, _) , .. } ) => {
1343- infer_return_ty_for_fn_sig ( sig, generics, def_id, & icx )
1343+ lower_fn_sig_recovering_infer_ret_ty ( & icx , sig, generics, def_id)
13441344 }
13451345
13461346 ImplItem ( hir:: ImplItem { kind : ImplItemKind :: Fn ( sig, _) , generics, .. } ) => {
@@ -1357,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13571357 None ,
13581358 )
13591359 } else {
1360- infer_return_ty_for_fn_sig ( sig, generics, def_id, & icx )
1360+ lower_fn_sig_recovering_infer_ret_ty ( & icx , sig, generics, def_id)
13611361 }
13621362 }
13631363
@@ -1407,99 +1407,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
14071407 ty:: EarlyBinder :: bind ( output)
14081408}
14091409
1410- fn infer_return_ty_for_fn_sig < ' tcx > (
1411- sig : & hir:: FnSig < ' tcx > ,
1412- generics : & hir:: Generics < ' _ > ,
1410+ fn lower_fn_sig_recovering_infer_ret_ty < ' tcx > (
1411+ icx : & ItemCtxt < ' tcx > ,
1412+ sig : & ' tcx hir:: FnSig < ' tcx > ,
1413+ generics : & ' tcx hir:: Generics < ' tcx > ,
14131414 def_id : LocalDefId ,
1415+ ) -> ty:: PolyFnSig < ' tcx > {
1416+ if let Some ( infer_ret_ty) = sig. decl . output . get_infer_ret_ty ( ) {
1417+ return recover_infer_ret_ty ( icx, infer_ret_ty, generics, def_id) ;
1418+ }
1419+
1420+ icx. lowerer ( ) . lower_fn_ty (
1421+ icx. tcx ( ) . local_def_id_to_hir_id ( def_id) ,
1422+ sig. header . safety ,
1423+ sig. header . abi ,
1424+ sig. decl ,
1425+ Some ( generics) ,
1426+ None ,
1427+ )
1428+ }
1429+
1430+ fn recover_infer_ret_ty < ' tcx > (
14141431 icx : & ItemCtxt < ' tcx > ,
1432+ infer_ret_ty : & ' tcx hir:: Ty < ' tcx > ,
1433+ generics : & ' tcx hir:: Generics < ' tcx > ,
1434+ def_id : LocalDefId ,
14151435) -> ty:: PolyFnSig < ' tcx > {
14161436 let tcx = icx. tcx ;
14171437 let hir_id = tcx. local_def_id_to_hir_id ( def_id) ;
14181438
1419- match sig. decl . output . get_infer_ret_ty ( ) {
1420- Some ( ty) => {
1421- let fn_sig = tcx. typeck ( def_id) . liberated_fn_sigs ( ) [ hir_id] ;
1422- // Typeck doesn't expect erased regions to be returned from `type_of`.
1423- // This is a heuristic approach. If the scope has region parameters,
1424- // we should change fn_sig's lifetime from `ReErased` to `ReError`,
1425- // otherwise to `ReStatic`.
1426- let has_region_params = generics. params . iter ( ) . any ( |param| match param. kind {
1427- GenericParamKind :: Lifetime { .. } => true ,
1428- _ => false ,
1429- } ) ;
1430- let fn_sig = fold_regions ( tcx, fn_sig, |r, _| match * r {
1431- ty:: ReErased => {
1432- if has_region_params {
1433- ty:: Region :: new_error_with_message (
1434- tcx,
1435- DUMMY_SP ,
1436- "erased region is not allowed here in return type" ,
1437- )
1438- } else {
1439- tcx. lifetimes . re_static
1440- }
1441- }
1442- _ => r,
1443- } ) ;
1439+ let fn_sig = tcx. typeck ( def_id) . liberated_fn_sigs ( ) [ hir_id] ;
14441440
1445- let mut visitor = HirPlaceholderCollector :: default ( ) ;
1446- visitor. visit_ty ( ty) ;
1447-
1448- let mut diag = bad_placeholder ( icx. lowerer ( ) , visitor. 0 , "return type" ) ;
1449- let ret_ty = fn_sig. output ( ) ;
1450- // Don't leak types into signatures unless they're nameable!
1451- // For example, if a function returns itself, we don't want that
1452- // recursive function definition to leak out into the fn sig.
1453- let mut recovered_ret_ty = None ;
1454-
1455- if let Some ( suggestable_ret_ty) = ret_ty. make_suggestable ( tcx, false , None ) {
1456- diag. span_suggestion (
1457- ty. span ,
1458- "replace with the correct return type" ,
1459- suggestable_ret_ty,
1460- Applicability :: MachineApplicable ,
1461- ) ;
1462- recovered_ret_ty = Some ( suggestable_ret_ty) ;
1463- } else if let Some ( sugg) = suggest_impl_trait (
1464- & tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ,
1465- tcx. param_env ( def_id) ,
1466- ret_ty,
1467- ) {
1468- diag. span_suggestion (
1469- ty. span ,
1470- "replace with an appropriate return type" ,
1471- sugg,
1472- Applicability :: MachineApplicable ,
1473- ) ;
1474- } else if ret_ty. is_closure ( ) {
1475- diag. help ( "consider using an `Fn`, `FnMut`, or `FnOnce` trait bound" ) ;
1476- }
1477- // Also note how `Fn` traits work just in case!
1478- if ret_ty. is_closure ( ) {
1479- diag. note (
1480- "for more information on `Fn` traits and closure types, see \
1481- https://doc.rust-lang.org/book/ch13-01-closures.html",
1482- ) ;
1441+ // Typeck doesn't expect erased regions to be returned from `type_of`.
1442+ // This is a heuristic approach. If the scope has region parameters,
1443+ // we should change fn_sig's lifetime from `ReErased` to `ReError`,
1444+ // otherwise to `ReStatic`.
1445+ let has_region_params = generics. params . iter ( ) . any ( |param| match param. kind {
1446+ GenericParamKind :: Lifetime { .. } => true ,
1447+ _ => false ,
1448+ } ) ;
1449+ let fn_sig = fold_regions ( tcx, fn_sig, |r, _| match * r {
1450+ ty:: ReErased => {
1451+ if has_region_params {
1452+ ty:: Region :: new_error_with_message (
1453+ tcx,
1454+ DUMMY_SP ,
1455+ "erased region is not allowed here in return type" ,
1456+ )
1457+ } else {
1458+ tcx. lifetimes . re_static
14831459 }
1484-
1485- let guar = diag. emit ( ) ;
1486- ty:: Binder :: dummy ( tcx. mk_fn_sig (
1487- fn_sig. inputs ( ) . iter ( ) . copied ( ) ,
1488- recovered_ret_ty. unwrap_or_else ( || Ty :: new_error ( tcx, guar) ) ,
1489- fn_sig. c_variadic ,
1490- fn_sig. safety ,
1491- fn_sig. abi ,
1492- ) )
14931460 }
1494- None => icx. lowerer ( ) . lower_fn_ty (
1495- hir_id,
1496- sig. header . safety ,
1497- sig. header . abi ,
1498- sig. decl ,
1499- Some ( generics) ,
1500- None ,
1501- ) ,
1461+ _ => r,
1462+ } ) ;
1463+
1464+ let mut visitor = HirPlaceholderCollector :: default ( ) ;
1465+ visitor. visit_ty ( infer_ret_ty) ;
1466+
1467+ let mut diag = bad_placeholder ( icx. lowerer ( ) , visitor. 0 , "return type" ) ;
1468+ let ret_ty = fn_sig. output ( ) ;
1469+
1470+ // Don't leak types into signatures unless they're nameable!
1471+ // For example, if a function returns itself, we don't want that
1472+ // recursive function definition to leak out into the fn sig.
1473+ let mut recovered_ret_ty = None ;
1474+ if let Some ( suggestable_ret_ty) = ret_ty. make_suggestable ( tcx, false , None ) {
1475+ diag. span_suggestion (
1476+ infer_ret_ty. span ,
1477+ "replace with the correct return type" ,
1478+ suggestable_ret_ty,
1479+ Applicability :: MachineApplicable ,
1480+ ) ;
1481+ recovered_ret_ty = Some ( suggestable_ret_ty) ;
1482+ } else if let Some ( sugg) = suggest_impl_trait (
1483+ & tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ,
1484+ tcx. param_env ( def_id) ,
1485+ ret_ty,
1486+ ) {
1487+ diag. span_suggestion (
1488+ infer_ret_ty. span ,
1489+ "replace with an appropriate return type" ,
1490+ sugg,
1491+ Applicability :: MachineApplicable ,
1492+ ) ;
1493+ } else if ret_ty. is_closure ( ) {
1494+ diag. help ( "consider using an `Fn`, `FnMut`, or `FnOnce` trait bound" ) ;
1495+ }
1496+
1497+ // Also note how `Fn` traits work just in case!
1498+ if ret_ty. is_closure ( ) {
1499+ diag. note (
1500+ "for more information on `Fn` traits and closure types, see \
1501+ https://doc.rust-lang.org/book/ch13-01-closures.html",
1502+ ) ;
15021503 }
1504+ let guar = diag. emit ( ) ;
1505+ ty:: Binder :: dummy ( tcx. mk_fn_sig (
1506+ fn_sig. inputs ( ) . iter ( ) . copied ( ) ,
1507+ recovered_ret_ty. unwrap_or_else ( || Ty :: new_error ( tcx, guar) ) ,
1508+ fn_sig. c_variadic ,
1509+ fn_sig. safety ,
1510+ fn_sig. abi ,
1511+ ) )
15031512}
15041513
15051514pub fn suggest_impl_trait < ' tcx > (
0 commit comments