@@ -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