@@ -1315,6 +1315,13 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
13151315 error : & MismatchedProjectionTypes < ' tcx > ,
13161316 ) ;
13171317
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+
13181325 fn fuzzy_match_tys (
13191326 & self ,
13201327 a : Ty < ' tcx > ,
@@ -1542,23 +1549,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15421549 normalized_ty,
15431550 data. term ,
15441551 ) {
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 ) ) ;
15501553 err_buf = error;
15511554 err = & err_buf;
15521555 }
15531556 }
15541557
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+
15621565 let secondary_span = match predicate. kind ( ) . skip_binder ( ) {
15631566 ty:: PredicateKind :: Projection ( proj) => self
15641567 . tcx
@@ -1596,7 +1599,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15961599 & mut diag,
15971600 & obligation. cause ,
15981601 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+ } ) ,
16001609 err,
16011610 true ,
16021611 false ,
@@ -1606,6 +1615,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
16061615 } ) ;
16071616 }
16081617
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+
16091645 fn fuzzy_match_tys (
16101646 & self ,
16111647 mut a : Ty < ' tcx > ,
0 commit comments