@@ -1586,60 +1586,113 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
15861586 }
15871587
15881588 self . probe ( |_| {
1589- let ocx = ObligationCtxt :: new ( self ) ;
1590-
15911589 // try to find the mismatched types to report the error with.
15921590 //
15931591 // this can fail if the problem was higher-ranked, in which
15941592 // cause I have no idea for a good error message.
15951593 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+ ) ;
16131615
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+ } ;
16201621
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 ( ) ;
16261628
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+ } ;
16331674
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+ }
16401694 }
1641- } else {
1642- ( None , error. err )
1695+ _ => ( None , error. err ) ,
16431696 } ;
16441697
16451698 let msg = values
@@ -1737,15 +1790,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17371790
17381791 fn maybe_detailed_projection_msg (
17391792 & self ,
1740- pred : ty:: ProjectionPredicate < ' tcx > ,
1793+ projection_term : ty:: AliasTerm < ' tcx > ,
17411794 normalized_ty : ty:: Term < ' tcx > ,
17421795 expected_ty : ty:: Term < ' tcx > ,
17431796 ) -> 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 ( ) ;
17461799
17471800 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 ) {
17491802 let fn_kind = self_ty. prefix_string( self . tcx) ;
17501803 let item = match self_ty. kind( ) {
17511804 ty:: FnDef ( def, _) => self . tcx. item_name( * def) . to_string( ) ,
0 commit comments