1//! Computes a 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.
78use rustc_type_ir::solve::QueryResultOrRerunNonErased;
9use rustc_type_ir::{selfas ty, Interner, Unnormalized};
1011use crate::delegate::SolverDelegate;
12use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource};
1314impl<D, I> EvalCtxt<'_, D>
15where
16D: SolverDelegate<Interner = I>,
17 I: Interner,
18{
19pub(super) fn normalize_inherent_associated_term(
20&mut self,
21 goal: Goal<I, ty::ProjectionPredicate<I>>,
22 ) -> QueryResultOrRerunNonErased<I> {
23let cx = self.cx();
24let inherent = goal.predicate.projection_term;
25let def_id = inherent.expect_inherent_def_id();
26let impl_def_id = cx.inherent_alias_term_parent(def_id);
27let impl_args = self.fresh_args_for_item(impl_def_id.into());
2829// Equate impl header and add impl where clauses
30self.eq(
31 goal.param_env,
32 inherent.self_ty(),
33 cx.type_of(impl_def_id.into()).instantiate(cx, impl_args).skip_norm_wip(),
34 )?;
3536// Equate IAT with the RHS of the project goal
37let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, cx);
3839// Check both where clauses on the impl and IAT
40 //
41 // FIXME(-Znext-solver=coinductive): I think this should be split
42 // and we tag the impl bounds with `GoalSource::ImplWhereBound`?
43 // Right now this includes both the impl and the assoc item where bounds,
44 // and I don't think the assoc item where-bounds are allowed to be coinductive.
45 //
46 // Projecting to the IAT also "steps out the impl constructor", so we would have
47 // to be very careful when changing the impl where-clauses to be productive.
48self.add_goals(
49 GoalSource::Misc,
50 cx.predicates_of(def_id.into())
51 .iter_instantiated(cx, inherent_args)
52 .map(Unnormalized::skip_norm_wip)
53 .map(|pred| goal.with(cx, pred)),
54 )?;
5556let normalized: I::Term = match inherent.kind {
57 ty::AliasTermKind::InherentTy { def_id } => {
58let inherent = cx.type_of(def_id.into()).instantiate(cx, inherent_args);
59let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?;
60inherent.into()
61 }
62 ty::AliasTermKind::InherentConst { def_id } if cx.is_type_const(def_id.into()) => {
63let inherent = cx.const_of_item(def_id.into()).instantiate(cx, inherent_args);
64let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?;
65inherent.into()
66 }
67 ty::AliasTermKind::InherentConst { .. } => {
68// FIXME(gca): This is dead code at the moment. It should eventually call
69 // self.evaluate_const like projected consts do in consider_impl_candidate in
70 // normalizes_to/mod.rs. However, how generic args are represented for IACs is up in
71 // the air right now.
72 // Will self.evaluate_const eventually take the inherent_args or the impl_args form
73 // of args? It might be either.
74{
::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");
75 }
76 kind => {
::core::panicking::panic_fmt(format_args!("expected inherent alias, found {0:?}",
kind));
}panic!("expected inherent alias, found {kind:?}"),
77 };
7879self.push_const_arg_has_type_goal(
80 goal.param_env,
81 goal.predicate.projection_term,
82 normalized,
83 )?;
84self.eq(goal.param_env, goal.predicate.term, normalized)?;
85self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
86 }
87}