@@ -30,7 +30,7 @@ use rustc_middle::query::Providers;
30
30
use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
31
31
use rustc_middle:: ty:: { self , AdtKind , Const , IsSuggestable , ToPredicate , Ty , TyCtxt } ;
32
32
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
33
- use rustc_span:: Span ;
33
+ use rustc_span:: { Span , DUMMY_SP } ;
34
34
use rustc_target:: abi:: FieldIdx ;
35
35
use rustc_target:: spec:: abi;
36
36
use rustc_trait_selection:: infer:: InferCtxtExt ;
@@ -1383,7 +1383,9 @@ fn infer_return_ty_for_fn_sig<'tcx>(
1383
1383
Applicability :: MachineApplicable ,
1384
1384
) ;
1385
1385
should_recover = true ;
1386
- } else if let Some ( sugg) = suggest_impl_trait ( tcx, ret_ty, ty. span , def_id) {
1386
+ } else if let Some ( sugg) =
1387
+ suggest_impl_trait ( & tcx. infer_ctxt ( ) . build ( ) , tcx. param_env ( def_id) , ret_ty)
1388
+ {
1387
1389
diag. span_suggestion (
1388
1390
ty. span ,
1389
1391
"replace with an appropriate return type" ,
@@ -1426,11 +1428,10 @@ fn infer_return_ty_for_fn_sig<'tcx>(
1426
1428
}
1427
1429
}
1428
1430
1429
- fn suggest_impl_trait < ' tcx > (
1430
- tcx : TyCtxt < ' tcx > ,
1431
+ pub fn suggest_impl_trait < ' tcx > (
1432
+ infcx : & InferCtxt < ' tcx > ,
1433
+ param_env : ty:: ParamEnv < ' tcx > ,
1431
1434
ret_ty : Ty < ' tcx > ,
1432
- span : Span ,
1433
- def_id : LocalDefId ,
1434
1435
) -> Option < String > {
1435
1436
let format_as_assoc: fn ( _, _, _, _, _) -> _ =
1436
1437
|tcx : TyCtxt < ' tcx > ,
@@ -1464,24 +1465,28 @@ fn suggest_impl_trait<'tcx>(
1464
1465
1465
1466
for ( trait_def_id, assoc_item_def_id, formatter) in [
1466
1467
(
1467
- tcx. get_diagnostic_item ( sym:: Iterator ) ,
1468
- tcx. get_diagnostic_item ( sym:: IteratorItem ) ,
1468
+ infcx . tcx . get_diagnostic_item ( sym:: Iterator ) ,
1469
+ infcx . tcx . get_diagnostic_item ( sym:: IteratorItem ) ,
1469
1470
format_as_assoc,
1470
1471
) ,
1471
1472
(
1472
- tcx. lang_items ( ) . future_trait ( ) ,
1473
- tcx. get_diagnostic_item ( sym:: FutureOutput ) ,
1473
+ infcx . tcx . lang_items ( ) . future_trait ( ) ,
1474
+ infcx . tcx . get_diagnostic_item ( sym:: FutureOutput ) ,
1474
1475
format_as_assoc,
1475
1476
) ,
1476
- ( tcx. lang_items ( ) . fn_trait ( ) , tcx. lang_items ( ) . fn_once_output ( ) , format_as_parenthesized) ,
1477
1477
(
1478
- tcx. lang_items ( ) . fn_mut_trait ( ) ,
1479
- tcx. lang_items ( ) . fn_once_output ( ) ,
1478
+ infcx. tcx . lang_items ( ) . fn_trait ( ) ,
1479
+ infcx. tcx . lang_items ( ) . fn_once_output ( ) ,
1480
+ format_as_parenthesized,
1481
+ ) ,
1482
+ (
1483
+ infcx. tcx . lang_items ( ) . fn_mut_trait ( ) ,
1484
+ infcx. tcx . lang_items ( ) . fn_once_output ( ) ,
1480
1485
format_as_parenthesized,
1481
1486
) ,
1482
1487
(
1483
- tcx. lang_items ( ) . fn_once_trait ( ) ,
1484
- tcx. lang_items ( ) . fn_once_output ( ) ,
1488
+ infcx . tcx . lang_items ( ) . fn_once_trait ( ) ,
1489
+ infcx . tcx . lang_items ( ) . fn_once_output ( ) ,
1485
1490
format_as_parenthesized,
1486
1491
) ,
1487
1492
] {
@@ -1491,36 +1496,45 @@ fn suggest_impl_trait<'tcx>(
1491
1496
let Some ( assoc_item_def_id) = assoc_item_def_id else {
1492
1497
continue ;
1493
1498
} ;
1494
- if tcx. def_kind ( assoc_item_def_id) != DefKind :: AssocTy {
1499
+ if infcx . tcx . def_kind ( assoc_item_def_id) != DefKind :: AssocTy {
1495
1500
continue ;
1496
1501
}
1497
- let param_env = tcx. param_env ( def_id) ;
1498
- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
1499
- let args = ty:: GenericArgs :: for_item ( tcx, trait_def_id, |param, _| {
1500
- if param. index == 0 { ret_ty. into ( ) } else { infcx. var_for_def ( span, param) }
1502
+ let sugg = infcx. probe ( |_| {
1503
+ let args = ty:: GenericArgs :: for_item ( infcx. tcx , trait_def_id, |param, _| {
1504
+ if param. index == 0 { ret_ty. into ( ) } else { infcx. var_for_def ( DUMMY_SP , param) }
1505
+ } ) ;
1506
+ if !infcx
1507
+ . type_implements_trait ( trait_def_id, args, param_env)
1508
+ . must_apply_modulo_regions ( )
1509
+ {
1510
+ return None ;
1511
+ }
1512
+ let ocx = ObligationCtxt :: new ( & infcx) ;
1513
+ let item_ty = ocx. normalize (
1514
+ & ObligationCause :: dummy ( ) ,
1515
+ param_env,
1516
+ Ty :: new_projection ( infcx. tcx , assoc_item_def_id, args) ,
1517
+ ) ;
1518
+ // FIXME(compiler-errors): We may benefit from resolving regions here.
1519
+ if ocx. select_where_possible ( ) . is_empty ( )
1520
+ && let item_ty = infcx. resolve_vars_if_possible ( item_ty)
1521
+ && let Some ( item_ty) = item_ty. make_suggestable ( infcx. tcx , false , None )
1522
+ && let Some ( sugg) = formatter (
1523
+ infcx. tcx ,
1524
+ infcx. resolve_vars_if_possible ( args) ,
1525
+ trait_def_id,
1526
+ assoc_item_def_id,
1527
+ item_ty,
1528
+ )
1529
+ {
1530
+ return Some ( sugg) ;
1531
+ }
1532
+
1533
+ None
1501
1534
} ) ;
1502
- if !infcx. type_implements_trait ( trait_def_id, args, param_env) . must_apply_modulo_regions ( ) {
1503
- continue ;
1504
- }
1505
- let ocx = ObligationCtxt :: new ( & infcx) ;
1506
- let item_ty = ocx. normalize (
1507
- & ObligationCause :: misc ( span, def_id) ,
1508
- param_env,
1509
- Ty :: new_projection ( tcx, assoc_item_def_id, args) ,
1510
- ) ;
1511
- // FIXME(compiler-errors): We may benefit from resolving regions here.
1512
- if ocx. select_where_possible ( ) . is_empty ( )
1513
- && let item_ty = infcx. resolve_vars_if_possible ( item_ty)
1514
- && let Some ( item_ty) = item_ty. make_suggestable ( tcx, false , None )
1515
- && let Some ( sugg) = formatter (
1516
- tcx,
1517
- infcx. resolve_vars_if_possible ( args) ,
1518
- trait_def_id,
1519
- assoc_item_def_id,
1520
- item_ty,
1521
- )
1522
- {
1523
- return Some ( sugg) ;
1535
+
1536
+ if sugg. is_some ( ) {
1537
+ return sugg;
1524
1538
}
1525
1539
}
1526
1540
None
0 commit comments