@@ -1315,6 +1315,13 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
1315
1315
error : & MismatchedProjectionTypes < ' tcx > ,
1316
1316
) ;
1317
1317
1318
+ fn maybe_detailed_projection_msg (
1319
+ & self ,
1320
+ pred : ty:: ProjectionPredicate < ' tcx > ,
1321
+ normalized_ty : ty:: Term < ' tcx > ,
1322
+ expected_ty : ty:: Term < ' tcx > ,
1323
+ ) -> Option < String > ;
1324
+
1318
1325
fn fuzzy_match_tys (
1319
1326
& self ,
1320
1327
a : Ty < ' tcx > ,
@@ -1542,23 +1549,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1542
1549
normalized_ty,
1543
1550
data. term ,
1544
1551
) {
1545
- values = Some ( infer:: ValuePairs :: Terms ( ExpectedFound :: new (
1546
- is_normalized_ty_expected,
1547
- normalized_ty,
1548
- data. term ,
1549
- ) ) ) ;
1552
+ values = Some ( ( data, is_normalized_ty_expected, normalized_ty, data. term ) ) ;
1550
1553
err_buf = error;
1551
1554
err = & err_buf;
1552
1555
}
1553
1556
}
1554
1557
1555
- let mut diag = struct_span_err ! (
1556
- self . tcx . sess ,
1557
- obligation . cause . span ,
1558
- E0271 ,
1559
- "type mismatch resolving `{}`" ,
1560
- predicate
1561
- ) ;
1558
+ let msg = values
1559
+ . and_then ( | ( predicate , _ , normalized_ty , expected_ty ) | {
1560
+ self . maybe_detailed_projection_msg ( predicate , normalized_ty , expected_ty )
1561
+ } )
1562
+ . unwrap_or_else ( || format ! ( "type mismatch resolving `{}`" , predicate ) ) ;
1563
+ let mut diag = struct_span_err ! ( self . tcx . sess , obligation . cause . span , E0271 , "{msg}" ) ;
1564
+
1562
1565
let secondary_span = match predicate. kind ( ) . skip_binder ( ) {
1563
1566
ty:: PredicateKind :: Projection ( proj) => self
1564
1567
. tcx
@@ -1596,7 +1599,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1596
1599
& mut diag,
1597
1600
& obligation. cause ,
1598
1601
secondary_span,
1599
- values,
1602
+ values. map ( |( _, is_normalized_ty_expected, normalized_ty, term) | {
1603
+ infer:: ValuePairs :: Terms ( ExpectedFound :: new (
1604
+ is_normalized_ty_expected,
1605
+ normalized_ty,
1606
+ term,
1607
+ ) )
1608
+ } ) ,
1600
1609
err,
1601
1610
true ,
1602
1611
false ,
@@ -1606,6 +1615,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
1606
1615
} ) ;
1607
1616
}
1608
1617
1618
+ fn maybe_detailed_projection_msg (
1619
+ & self ,
1620
+ pred : ty:: ProjectionPredicate < ' tcx > ,
1621
+ normalized_ty : ty:: Term < ' tcx > ,
1622
+ expected_ty : ty:: Term < ' tcx > ,
1623
+ ) -> Option < String > {
1624
+ let trait_def_id = pred. projection_ty . trait_def_id ( self . tcx ) ;
1625
+ let self_ty = pred. projection_ty . self_ty ( ) ;
1626
+
1627
+ if Some ( pred. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( ) {
1628
+ Some ( format ! (
1629
+ "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`" ,
1630
+ fn_kind = self_ty. prefix_string( self . tcx)
1631
+ ) )
1632
+ } else if Some ( trait_def_id) == self . tcx . lang_items ( ) . future_trait ( ) {
1633
+ Some ( format ! (
1634
+ "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
1635
+ ) )
1636
+ } else if Some ( trait_def_id) == self . tcx . get_diagnostic_item ( sym:: Iterator ) {
1637
+ Some ( format ! (
1638
+ "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
1639
+ ) )
1640
+ } else {
1641
+ None
1642
+ }
1643
+ }
1644
+
1609
1645
fn fuzzy_match_tys (
1610
1646
& self ,
1611
1647
mut a : Ty < ' tcx > ,
0 commit comments