Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/structural_normalize.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/structural_normalize.rs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/crates/hir-ty/src/next_solver/structural_normalize.rs b/crates/hir-ty/src/next_solver/structural_normalize.rs new file mode 100644 index 0000000000..00c3708358 --- /dev/null +++ b/crates/hir-ty/src/next_solver/structural_normalize.rs @@ -0,0 +1,57 @@ +use rustc_type_ir::{AliasRelationDirection, inherent::Term as _}; + +use crate::next_solver::{ + Const, PredicateKind, Term, Ty, + fulfill::{FulfillmentCtxt, NextSolverError}, + infer::{at::At, traits::Obligation}, +}; + +impl<'db> At<'_, 'db> { + pub(crate) fn structurally_normalize_ty( + &self, + ty: Ty<'db>, + fulfill_cx: &mut FulfillmentCtxt<'db>, + ) -> Result<Ty<'db>, Vec<NextSolverError<'db>>> { + self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type()) + } + + pub(crate) fn structurally_normalize_const( + &self, + ct: Const<'db>, + fulfill_cx: &mut FulfillmentCtxt<'db>, + ) -> Result<Const<'db>, Vec<NextSolverError<'db>>> { + self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const()) + } + + pub(crate) fn structurally_normalize_term( + &self, + term: Term<'db>, + fulfill_cx: &mut FulfillmentCtxt<'db>, + ) -> Result<Term<'db>, Vec<NextSolverError<'db>>> { + assert!(!term.is_infer(), "should have resolved vars before calling"); + + if term.to_alias_term().is_none() { + return Ok(term); + } + + let new_infer = self.infcx.next_term_var_of_kind(term); + + // 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.interner, + self.cause.clone(), + self.param_env, + PredicateKind::AliasRelate(term, new_infer, AliasRelationDirection::Equate), + ); + + fulfill_cx.register_predicate_obligation(self.infcx, obligation); + let errors = fulfill_cx.try_evaluate_obligations(self.infcx); + if !errors.is_empty() { + return Err(errors); + } + + Ok(self.infcx.resolve_vars_if_possible(new_infer)) + } +} |