Skip to main content

rustc_next_trait_solver/solve/normalizes_to/
inherent.rs

1//! Computes a normalizes-to (projection) goal for inherent associated types,
2//! `#![feature(inherent_associated_type)]`. Since HIR ty lowering already determines
3//! which impl the IAT is being projected from, we just:
4//! 1. instantiate generic parameters,
5//! 2. equate the self type, and
6//! 3. instantiate and register where clauses.
7
8use rustc_type_ir::solve::QueryResultOrRerunNonErased;
9use rustc_type_ir::{self as ty, Interner, Unnormalized};
10
11use crate::delegate::SolverDelegate;
12use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource};
13
14impl<D, I> EvalCtxt<'_, D>
15where
16    D: SolverDelegate<Interner = I>,
17    I: Interner,
18{
19    pub(super) fn normalize_inherent_associated_term(
20        &mut self,
21        goal: Goal<I, ty::NormalizesTo<I>>,
22        def_id: I::InherentAssocTermId,
23    ) -> QueryResultOrRerunNonErased<I> {
24        let cx = self.cx();
25        let inherent = goal.predicate.alias;
26
27        let impl_def_id = cx.inherent_alias_term_parent(def_id);
28        let impl_args = self.fresh_args_for_item(impl_def_id.into());
29
30        // Equate impl header and add impl where clauses
31        self.eq(
32            goal.param_env,
33            inherent.self_ty(),
34            cx.type_of(impl_def_id.into()).instantiate(cx, impl_args).skip_norm_wip(),
35        )?;
36
37        // Equate IAT with the RHS of the project goal
38        let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, cx);
39
40        // Check both where clauses on the impl and IAT
41        //
42        // FIXME(-Znext-solver=coinductive): I think this should be split
43        // and we tag the impl bounds with `GoalSource::ImplWhereBound`?
44        // Right now this includes both the impl and the assoc item where bounds,
45        // and I don't think the assoc item where-bounds are allowed to be coinductive.
46        //
47        // Projecting to the IAT also "steps out the impl constructor", so we would have
48        // to be very careful when changing the impl where-clauses to be productive.
49        self.add_goals(
50            GoalSource::Misc,
51            cx.predicates_of(def_id.into())
52                .iter_instantiated(cx, inherent_args)
53                .map(Unnormalized::skip_norm_wip)
54                .map(|pred| goal.with(cx, pred)),
55        );
56
57        let normalized = match inherent.kind(cx) {
58            ty::AliasTermKind::InherentTy { def_id } => {
59                cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into()
60            }
61            ty::AliasTermKind::InherentConst { def_id } if cx.is_type_const(def_id.into()) => cx
62                .const_of_item(def_id.into())
63                .instantiate(cx, inherent_args)
64                .skip_norm_wip()
65                .into(),
66            ty::AliasTermKind::InherentConst { .. } => {
67                // FIXME(gca): This is dead code at the moment. It should eventually call
68                // self.evaluate_const like projected consts do in consider_impl_candidate in
69                // normalizes_to/mod.rs. However, how generic args are represented for IACs is up in
70                // the air right now.
71                // Will self.evaluate_const eventually take the inherent_args or the impl_args form
72                // of args? It might be either.
73                {
    ::core::panicking::panic_fmt(format_args!("References to inherent associated consts should have been blocked"));
};panic!("References to inherent associated consts should have been blocked");
74            }
75            kind => {
    ::core::panicking::panic_fmt(format_args!("expected inherent alias, found {0:?}",
            kind));
}panic!("expected inherent alias, found {kind:?}"),
76        };
77        self.instantiate_normalizes_to_term(goal, normalized);
78        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
79    }
80}