Structurally normalize in the new solver
This commit is contained in:
parent
eaf10dcb70
commit
4cfafb275e
6 changed files with 181 additions and 29 deletions
|
@ -17,6 +17,7 @@ pub mod query;
|
|||
mod select;
|
||||
mod specialize;
|
||||
mod structural_match;
|
||||
mod structural_normalize;
|
||||
mod util;
|
||||
mod vtable;
|
||||
pub mod wf;
|
||||
|
@ -62,6 +63,7 @@ pub use self::specialize::{
|
|||
pub use self::structural_match::{
|
||||
search_for_adt_const_param_violation, search_for_structural_match_violation,
|
||||
};
|
||||
pub use self::structural_normalize::StructurallyNormalizeExt;
|
||||
pub use self::util::elaborate;
|
||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
use rustc_infer::infer::at::At;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::traits::{FulfillmentError, TraitEngine};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
|
||||
|
||||
pub trait StructurallyNormalizeExt<'tcx> {
|
||||
fn structurally_normalize(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
|
||||
}
|
||||
|
||||
impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||
fn structurally_normalize(
|
||||
&self,
|
||||
mut 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.tcx.trait_solver_next() {
|
||||
while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
|
||||
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::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
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;
|
||||
}
|
||||
}
|
||||
Ok(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