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.rs57
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))
+ }
+}