1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! Computes a normalizes-to (projection) goal for inherent associated types,
//! `#![feature(inherent_associated_type)]`. Since HIR ty lowering already determines
//! which impl the IAT is being projected from, we just:
//! 1. instantiate generic parameters,
//! 2. equate the self type, and
//! 3. instantiate and register where clauses.

use rustc_type_ir::{self as ty, Interner};

use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult};

impl<D, I> EvalCtxt<'_, D>
where
    D: SolverDelegate<Interner = I>,
    I: Interner,
{
    pub(super) fn normalize_inherent_associated_type(
        &mut self,
        goal: Goal<I, ty::NormalizesTo<I>>,
    ) -> QueryResult<I> {
        let cx = self.cx();
        let inherent = goal.predicate.alias.expect_ty(cx);

        let impl_def_id = cx.parent(inherent.def_id);
        let impl_args = self.fresh_args_for_item(impl_def_id);

        // Equate impl header and add impl where clauses
        self.eq(
            goal.param_env,
            inherent.self_ty(),
            cx.type_of(impl_def_id).instantiate(cx, impl_args),
        )?;

        // Equate IAT with the RHS of the project goal
        let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, cx);

        // Check both where clauses on the impl and IAT
        //
        // FIXME(-Znext-solver=coinductive): I think this should be split
        // and we tag the impl bounds with `GoalSource::ImplWhereBound`?
        // Right not this includes both the impl and the assoc item where bounds,
        // and I don't think the assoc item where-bounds are allowed to be coinductive.
        self.add_goals(
            GoalSource::Misc,
            cx.predicates_of(inherent.def_id)
                .iter_instantiated(cx, inherent_args)
                .map(|pred| goal.with(cx, pred)),
        );

        let normalized = cx.type_of(inherent.def_id).instantiate(cx, inherent_args);
        self.instantiate_normalizes_to_term(goal, normalized.into());
        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
    }
}