@@ -1586,60 +1586,113 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1586
1586
}
1587
1587
1588
1588
self . probe ( |_| {
1589
- let ocx = ObligationCtxt :: new ( self ) ;
1590
-
1591
1589
// try to find the mismatched types to report the error with.
1592
1590
//
1593
1591
// this can fail if the problem was higher-ranked, in which
1594
1592
// cause I have no idea for a good error message.
1595
1593
let bound_predicate = predicate. kind ( ) ;
1596
- let ( values, err) = if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( data) ) =
1597
- bound_predicate. skip_binder ( )
1598
- {
1599
- let data = self . instantiate_binder_with_fresh_vars (
1600
- obligation. cause . span ,
1601
- infer:: BoundRegionConversionTime :: HigherRankedType ,
1602
- bound_predicate. rebind ( data) ,
1603
- ) ;
1604
- let unnormalized_term = data. projection_term . to_term ( self . tcx ) ;
1605
- // FIXME(-Znext-solver): For diagnostic purposes, it would be nice
1606
- // to deeply normalize this type.
1607
- let normalized_term =
1608
- ocx. normalize ( & obligation. cause , obligation. param_env , unnormalized_term) ;
1609
-
1610
- debug ! ( ?obligation. cause, ?obligation. param_env) ;
1611
-
1612
- debug ! ( ?normalized_term, data. ty = ?data. term) ;
1594
+ let ( values, err) = match bound_predicate. skip_binder ( ) {
1595
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( data) ) => {
1596
+ let ocx = ObligationCtxt :: new ( self ) ;
1597
+
1598
+ let data = self . instantiate_binder_with_fresh_vars (
1599
+ obligation. cause . span ,
1600
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1601
+ bound_predicate. rebind ( data) ,
1602
+ ) ;
1603
+ let unnormalized_term = data. projection_term . to_term ( self . tcx ) ;
1604
+ // FIXME(-Znext-solver): For diagnostic purposes, it would be nice
1605
+ // to deeply normalize this type.
1606
+ let normalized_term =
1607
+ ocx. normalize ( & obligation. cause , obligation. param_env , unnormalized_term) ;
1608
+
1609
+ let is_normalized_term_expected = !matches ! (
1610
+ obligation. cause. code( ) . peel_derives( ) ,
1611
+ ObligationCauseCode :: WhereClause ( ..)
1612
+ | ObligationCauseCode :: WhereClauseInExpr ( ..)
1613
+ | ObligationCauseCode :: Coercion { .. }
1614
+ ) ;
1613
1615
1614
- let is_normalized_term_expected = !matches ! (
1615
- obligation. cause. code( ) . peel_derives( ) ,
1616
- |ObligationCauseCode :: WhereClause ( ..) | ObligationCauseCode :: WhereClauseInExpr (
1617
- ..
1618
- ) | ObligationCauseCode :: Coercion { .. }
1619
- ) ;
1616
+ let ( expected, actual) = if is_normalized_term_expected {
1617
+ ( normalized_term, data. term )
1618
+ } else {
1619
+ ( data. term , normalized_term)
1620
+ } ;
1620
1621
1621
- let ( expected, actual) = if is_normalized_term_expected {
1622
- ( normalized_term, data. term )
1623
- } else {
1624
- ( data. term , normalized_term)
1625
- } ;
1622
+ // constrain inference variables a bit more to nested obligations from normalize so
1623
+ // we can have more helpful errors.
1624
+ //
1625
+ // we intentionally drop errors from normalization here,
1626
+ // since the normalization is just done to improve the error message.
1627
+ let _ = ocx. select_where_possible ( ) ;
1626
1628
1627
- // constrain inference variables a bit more to nested obligations from normalize so
1628
- // we can have more helpful errors.
1629
- //
1630
- // we intentionally drop errors from normalization here,
1631
- // since the normalization is just done to improve the error message.
1632
- let _ = ocx. select_where_possible ( ) ;
1629
+ if let Err ( new_err) =
1630
+ ocx. eq ( & obligation. cause , obligation. param_env , expected, actual)
1631
+ {
1632
+ (
1633
+ Some ( (
1634
+ data. projection_term ,
1635
+ is_normalized_term_expected,
1636
+ self . resolve_vars_if_possible ( normalized_term) ,
1637
+ data. term ,
1638
+ ) ) ,
1639
+ new_err,
1640
+ )
1641
+ } else {
1642
+ ( None , error. err )
1643
+ }
1644
+ }
1645
+ ty:: PredicateKind :: AliasRelate ( lhs, rhs, _) => {
1646
+ let derive_better_type_error =
1647
+ |alias_term : ty:: AliasTerm < ' tcx > , expected_term : ty:: Term < ' tcx > | {
1648
+ let ocx = ObligationCtxt :: new ( self ) ;
1649
+ let normalized_term = match expected_term. unpack ( ) {
1650
+ ty:: TermKind :: Ty ( _) => self . next_ty_var ( DUMMY_SP ) . into ( ) ,
1651
+ ty:: TermKind :: Const ( _) => self . next_const_var ( DUMMY_SP ) . into ( ) ,
1652
+ } ;
1653
+ ocx. register_obligation ( Obligation :: new (
1654
+ self . tcx ,
1655
+ ObligationCause :: dummy ( ) ,
1656
+ obligation. param_env ,
1657
+ ty:: PredicateKind :: NormalizesTo ( ty:: NormalizesTo {
1658
+ alias : alias_term,
1659
+ term : normalized_term,
1660
+ } ) ,
1661
+ ) ) ;
1662
+ let _ = ocx. select_where_possible ( ) ;
1663
+ if let Err ( terr) = ocx. eq (
1664
+ & ObligationCause :: dummy ( ) ,
1665
+ obligation. param_env ,
1666
+ expected_term,
1667
+ normalized_term,
1668
+ ) {
1669
+ Some ( ( terr, self . resolve_vars_if_possible ( normalized_term) ) )
1670
+ } else {
1671
+ None
1672
+ }
1673
+ } ;
1633
1674
1634
- if let Err ( new_err) =
1635
- ocx. eq ( & obligation. cause , obligation. param_env , expected, actual)
1636
- {
1637
- ( Some ( ( data, is_normalized_term_expected, normalized_term, data. term ) ) , new_err)
1638
- } else {
1639
- ( None , error. err )
1675
+ if let Some ( lhs) = lhs. to_alias_term ( )
1676
+ && let Some ( ( better_type_err, expected_term) ) =
1677
+ derive_better_type_error ( lhs, rhs)
1678
+ {
1679
+ (
1680
+ Some ( ( lhs, true , self . resolve_vars_if_possible ( expected_term) , rhs) ) ,
1681
+ better_type_err,
1682
+ )
1683
+ } else if let Some ( rhs) = rhs. to_alias_term ( )
1684
+ && let Some ( ( better_type_err, expected_term) ) =
1685
+ derive_better_type_error ( rhs, lhs)
1686
+ {
1687
+ (
1688
+ Some ( ( rhs, true , self . resolve_vars_if_possible ( expected_term) , lhs) ) ,
1689
+ better_type_err,
1690
+ )
1691
+ } else {
1692
+ ( None , error. err )
1693
+ }
1640
1694
}
1641
- } else {
1642
- ( None , error. err )
1695
+ _ => ( None , error. err ) ,
1643
1696
} ;
1644
1697
1645
1698
let msg = values
@@ -1737,15 +1790,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1737
1790
1738
1791
fn maybe_detailed_projection_msg (
1739
1792
& self ,
1740
- pred : ty:: ProjectionPredicate < ' tcx > ,
1793
+ projection_term : ty:: AliasTerm < ' tcx > ,
1741
1794
normalized_ty : ty:: Term < ' tcx > ,
1742
1795
expected_ty : ty:: Term < ' tcx > ,
1743
1796
) -> Option < String > {
1744
- let trait_def_id = pred . projection_term . trait_def_id ( self . tcx ) ;
1745
- let self_ty = pred . projection_term . self_ty ( ) ;
1797
+ let trait_def_id = projection_term. trait_def_id ( self . tcx ) ;
1798
+ let self_ty = projection_term. self_ty ( ) ;
1746
1799
1747
1800
with_forced_trimmed_paths ! {
1748
- if self . tcx. is_lang_item( pred . projection_term. def_id, LangItem :: FnOnceOutput ) {
1801
+ if self . tcx. is_lang_item( projection_term. def_id, LangItem :: FnOnceOutput ) {
1749
1802
let fn_kind = self_ty. prefix_string( self . tcx) ;
1750
1803
let item = match self_ty. kind( ) {
1751
1804
ty:: FnDef ( def, _) => self . tcx. item_name( * def) . to_string( ) ,
0 commit comments