1mod anon_const;
2mod free_alias;
3mod inherent;
4mod opaque_types;
56use rustc_type_ir::solve::QueryResultOrRerunNonErased;
7use rustc_type_ir::{selfas ty, Interner, ProjectionPredicate};
8use tracing::{instrument, trace};
910use crate::delegate::SolverDelegate;
11use crate::solve::{
12Certainty, EvalCtxt, Goal, GoalEvaluation, GoalSource, NestedNormalizationGoals,
13};
1415impl<D, I> EvalCtxt<'_, D>
16where
17D: SolverDelegate<Interner = I>,
18 I: Interner,
19{
20x;#[instrument(level = "trace", skip(self), ret)]21pub(super) fn compute_projection_goal(
22&mut self,
23 goal: Goal<I, ProjectionPredicate<I>>,
24 ) -> QueryResultOrRerunNonErased<I> {
25match goal.predicate.projection_term.kind {
26 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => {
27self.normalize_associated_term(goal)
28 }
29 ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => {
30self.normalize_inherent_associated_term(goal)
31 }
32 ty::AliasTermKind::OpaqueTy { .. } => self.normalize_opaque_type(goal),
33 ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => {
34self.normalize_free_alias(goal).map_err(Into::into)
35 }
36 ty::AliasTermKind::AnonConst { .. } => {
37self.normalize_anon_const(goal).map_err(Into::into)
38 }
39 }
40 }
4142fn normalize_associated_term(
43&mut self,
44 goal: Goal<I, ProjectionPredicate<I>>,
45 ) -> QueryResultOrRerunNonErased<I> {
46let ty::ProjectionPredicate { projection_term: alias, term } = goal.predicate;
47let unconstrained_term = self.next_term_infer_of_kind(term);
48let normalizes_to =
49goal.with(self.cx(), ty::NormalizesTo { alias, term: unconstrained_term });
5051// We don't want candidate selection when normalizing associated terms to be impacted by
52 // the expected term. Normalization should behave like a function of just the alias being
53 // normalized. Because of this, we use an internal `NormalizesTo` goal for which the
54 // expected term is always fully unconstrained and then equate that to the actual expected
55 // term afterwards.
56 //
57 // But this results in weaker type inference if there's a nested where-clause when
58 // normalizing which we can actually make progress on based on the expected term. To avoid
59 // this, we return ambiguous nested goals for `NormalizesTo` to this context and register
60 // them as if they were this `Projection` goal's own nested goals. (See #122687)
61 //
62 // After registering those goals, we equate the original expected term to the normalization
63 // result. Although equating them can add inference constraint to the alias term, we don't
64 // reevaluate this special `NormalizesTo` goal. But that's fine because as those inference
65 // constraints should cause the caller to reevaluate the current `Projection `goal, which
66 // will then also reevaluate the `NormalizesTo` goal.
67let (
68NestedNormalizationGoals(nested_goals),
69GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ },
70 ) = self.evaluate_goal_raw(GoalSource::TypeRelating, normalizes_to, None)?;
7172{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs:72",
"rustc_next_trait_solver::solve::project_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs"),
::tracing_core::__macro_support::Option::Some(72u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::project_goals"),
::tracing_core::field::FieldSet::new(&["nested_goals"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&nested_goals)
as &dyn Value))])
});
} else { ; }
};trace!(?nested_goals);
7374// Add a `make_canonical_response` probe step so that we treat this as
75 // a candidate, even if `try_evaluate_added_goals` bails due to an error.
76 // It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
77 // since equating the normalized terms will lead to additional constraints.
78self.inspect.make_canonical_response(Certainty::AMBIGUOUS);
7980// FIXME: We shouldn't be doing this in the long term in favor of eager
81 // normalization.
82 // Normalize alias types in rhs. This is done in `EvalCtxt::add_goal` for nested
83 // goals, but we might be evaluating the root goal.
84let term = self.replace_alias_with_infer(term, GoalSource::TypeRelating, goal.param_env);
8586// Apply the constraints.
87self.try_evaluate_added_goals()?;
8889// Finally, equate the goal's RHS with the unconstrained var.
90 //
91 // SUBTLE:
92 // We structurally relate aliases here. This is necessary
93 // as we otherwise emit a nested `AliasRelate` goal in case the
94 // returned term is a rigid alias, resulting in overflow.
95 //
96 // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
97 // start out as an unconstrained inference variable so any aliases get
98 // fully normalized when instantiating it.
99 //
100 // FIXME: Strictly speaking this may be incomplete if the normalized-to
101 // type contains an ambiguous alias referencing bound regions. We should
102 // consider changing this to only use "shallow structural equality".
103self.eq_structurally_relating_aliases(goal.param_env, term, unconstrained_term)?;
104105// Add the nested goals from normalization to our own nested goals.
106for (s, g) in nested_goals {
107self.add_goal(s, g);
108 }
109110self.evaluate_added_goals_and_make_canonical_response(certainty)
111 }
112}