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