@@ -1340,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1340
1340
..
1341
1341
} )
1342
1342
| 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)
1344
1344
}
1345
1345
1346
1346
ImplItem ( hir:: ImplItem { kind : ImplItemKind :: Fn ( sig, _) , generics, .. } ) => {
@@ -1357,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1357
1357
None ,
1358
1358
)
1359
1359
} 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)
1361
1361
}
1362
1362
}
1363
1363
@@ -1407,99 +1407,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
1407
1407
ty:: EarlyBinder :: bind ( output)
1408
1408
}
1409
1409
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 > ,
1413
1414
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 > (
1414
1431
icx : & ItemCtxt < ' tcx > ,
1432
+ infer_ret_ty : & ' tcx hir:: Ty < ' tcx > ,
1433
+ generics : & ' tcx hir:: Generics < ' tcx > ,
1434
+ def_id : LocalDefId ,
1415
1435
) -> ty:: PolyFnSig < ' tcx > {
1416
1436
let tcx = icx. tcx ;
1417
1437
let hir_id = tcx. local_def_id_to_hir_id ( def_id) ;
1418
1438
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] ;
1444
1440
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
1483
1459
}
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
- ) )
1493
1460
}
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
+ ) ;
1502
1503
}
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
+ ) )
1503
1512
}
1504
1513
1505
1514
pub fn suggest_impl_trait < ' tcx > (
0 commit comments