Skip to main content

hir_ty/next_solver/
structural_normalize.rs

1use rustc_type_ir::{AliasRelationDirection, inherent::Term as _};
2
3use crate::next_solver::{
4    Const, PredicateKind, Term, Ty,
5    fulfill::{FulfillmentCtxt, NextSolverError},
6    infer::{at::At, traits::Obligation},
7};
8
9impl<'db> At<'_, 'db> {
10    pub(crate) fn structurally_normalize_ty(
11        &self,
12        ty: Ty<'db>,
13        fulfill_cx: &mut FulfillmentCtxt<'db>,
14    ) -> Result<Ty<'db>, Vec<NextSolverError<'db>>> {
15        self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type())
16    }
17
18    pub(crate) fn structurally_normalize_const(
19        &self,
20        ct: Const<'db>,
21        fulfill_cx: &mut FulfillmentCtxt<'db>,
22    ) -> Result<Const<'db>, Vec<NextSolverError<'db>>> {
23        self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const())
24    }
25
26    pub(crate) fn structurally_normalize_term(
27        &self,
28        term: Term<'db>,
29        fulfill_cx: &mut FulfillmentCtxt<'db>,
30    ) -> Result<Term<'db>, Vec<NextSolverError<'db>>> {
31        assert!(!term.is_infer(), "should have resolved vars before calling");
32
33        if term.to_alias_term(self.infcx.interner).is_none() {
34            return Ok(term);
35        }
36
37        let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span());
38
39        // We simply emit an `alias-eq` goal here, since that will take care of
40        // normalizing the LHS of the projection until it is a rigid projection
41        // (or a not-yet-defined opaque in scope).
42        let obligation = Obligation::new(
43            self.infcx.interner,
44            *self.cause,
45            self.param_env,
46            PredicateKind::AliasRelate(term, new_infer, AliasRelationDirection::Equate),
47        );
48
49        fulfill_cx.register_predicate_obligation(self.infcx, obligation);
50        let errors = fulfill_cx.try_evaluate_obligations(self.infcx);
51        if !errors.is_empty() {
52            return Err(errors);
53        }
54
55        Ok(self.infcx.resolve_vars_if_possible(new_infer))
56    }
57}