@@ -1330,7 +1330,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1330
1330
..
1331
1331
} )
1332
1332
| 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)
1334
1334
}
1335
1335
1336
1336
ImplItem ( hir:: ImplItem { kind : ImplItemKind :: Fn ( sig, _) , generics, .. } ) => {
@@ -1347,7 +1347,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1347
1347
None ,
1348
1348
)
1349
1349
} 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)
1351
1351
}
1352
1352
}
1353
1353
@@ -1397,99 +1397,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1397
1397
ty:: EarlyBinder :: bind ( output)
1398
1398
}
1399
1399
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 > ,
1403
1404
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 > (
1404
1421
icx : & ItemCtxt < ' tcx > ,
1422
+ infer_ret_ty : & ' tcx hir:: Ty < ' tcx > ,
1423
+ generics : & ' tcx hir:: Generics < ' tcx > ,
1424
+ def_id : LocalDefId ,
1405
1425
) -> ty:: PolyFnSig < ' tcx > {
1406
1426
let tcx = icx. tcx ;
1407
1427
let hir_id = tcx. local_def_id_to_hir_id ( def_id) ;
1408
1428
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] ;
1434
1430
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
1473
1449
}
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
- ) )
1483
1450
}
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
+ ) ;
1492
1493
}
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
+ ) )
1493
1502
}
1494
1503
1495
1504
pub fn suggest_impl_trait < ' tcx > (
0 commit comments