Rollup merge of #119091 - compiler-errors:alias-eq-in-structural-normalize, r=lcnr
Use alias-eq in structural normalization We don't need to register repeated normalizes-to goals in a loop in structural normalize, but instead we can piggyback on the fact that alias-eq will already normalize aliases until they are rigid. This fixes rust-lang/trait-system-refactor-initiative#78. r? lcnr
This commit is contained in:
commit
9a72b7d04f
7 changed files with 49 additions and 49 deletions
|
@ -3,7 +3,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
|
|||
use rustc_infer::traits::{FulfillmentError, TraitEngine};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
|
||||
use crate::traits::{NormalizeExt, Obligation};
|
||||
|
||||
pub trait StructurallyNormalizeExt<'tcx> {
|
||||
fn structurally_normalize(
|
||||
|
@ -16,42 +16,43 @@ pub trait StructurallyNormalizeExt<'tcx> {
|
|||
impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||
fn structurally_normalize(
|
||||
&self,
|
||||
mut ty: Ty<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
// FIXME(-Znext-solver): correctly handle
|
||||
// overflow here.
|
||||
for _ in 0..256 {
|
||||
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, alias) = *ty.kind() else {
|
||||
break;
|
||||
};
|
||||
// FIXME(-Znext-solver): Should we resolve opaques here?
|
||||
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
|
||||
return Ok(ty);
|
||||
};
|
||||
|
||||
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||
span: self.cause.span,
|
||||
});
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::NormalizesTo { alias, term: new_infer_ty.into() },
|
||||
);
|
||||
if self.infcx.predicate_may_hold(&obligation) {
|
||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||
span: self.cause.span,
|
||||
});
|
||||
|
||||
// We simply emit an `alias-eq` goal here, since that will take care of
|
||||
// normalizing the LHS of the projection until it is a rigid projection
|
||||
// (or a not-yet-defined opaque in scope).
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
ty.into(),
|
||||
new_infer_ty.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
|
||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
|
||||
Ok(ty)
|
||||
Ok(self.infcx.resolve_vars_if_possible(new_infer_ty))
|
||||
} else {
|
||||
Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue