@@ -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
14951504pub fn suggest_impl_trait < ' tcx > (
0 commit comments