1mod anon_const;
2mod free_alias;
3mod inherent;
4mod opaque_types;
56use rustc_type_ir::search_graph::IncreaseDepthForNested;
7use rustc_type_ir::solve::QueryResultOrRerunNonErased;
8use rustc_type_ir::{selfas ty, Interner, ProjectionPredicate};
9use tracing::{instrument, trace};
1011use crate::delegate::SolverDelegate;
12use crate::solve::{
13Certainty, EvalCtxt, Goal, GoalEvaluation, GoalSource, NestedNormalizationGoals,
14};
1516impl<D, I> EvalCtxt<'_, D>
17where
18D: SolverDelegate<Interner = I>,
19 I: Interner,
20{
21x;#[instrument(level = "trace", skip(self), ret)]22pub(super) fn compute_projection_goal(
23&mut self,
24 goal: Goal<I, ProjectionPredicate<I>>,
25 ) -> QueryResultOrRerunNonErased<I> {
26match goal.predicate.projection_term.kind {
27 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => {
28self.normalize_associated_term(goal)
29 }
30 ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => {
31self.normalize_inherent_associated_term(goal)
32 }
33 ty::AliasTermKind::OpaqueTy { .. } => self.normalize_opaque_type(goal),
34 ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => {
35self.normalize_free_alias(goal).map_err(Into::into)
36 }
37 ty::AliasTermKind::AnonConst { .. } => {
38self.normalize_anon_const(goal).map_err(Into::into)
39 }
40 }
41 }
4243fn normalize_associated_term(
44&mut self,
45 goal: Goal<I, ProjectionPredicate<I>>,
46 ) -> QueryResultOrRerunNonErased<I> {
47let ty::ProjectionPredicate { projection_term: alias, term } = goal.predicate;
48let unconstrained_term = self.next_term_infer_of_alias_kind(alias);
49let normalizes_to =
50goal.with(self.cx(), ty::NormalizesTo { alias, term: unconstrained_term });
5152// We don't want candidate selection when normalizing associated terms to be impacted by
53 // the expected term. Normalization should behave like a function of just the alias being
54 // normalized. Because of this, we use an internal `NormalizesTo` goal for which the
55 // expected term is always fully unconstrained and then equate that to the actual expected
56 // term afterwards.
57 //
58 // But this results in weaker type inference if there's a nested where-clause when
59 // normalizing which we can actually make progress on based on the expected term. To avoid
60 // this, we return ambiguous nested goals for `NormalizesTo` to this context and register
61 // them as if they were this `Projection` goal's own nested goals. (See #122687)
62 //
63 // After registering those goals, we equate the original expected term to the normalization
64 // result. Although equating them can add inference constraint to the alias term, we don't
65 // reevaluate this special `NormalizesTo` goal. But that's fine because as those inference
66 // constraints should cause the caller to reevaluate the current `Projection `goal, which
67 // will then also reevaluate the `NormalizesTo` goal.
68let (
69NestedNormalizationGoals(nested_goals),
70GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ },
71 ) = self.evaluate_goal_raw(
72 GoalSource::TypeRelating,
73 normalizes_to,
74None,
75// We don't increase depth for nested goals for this `NormalizesTo` goal, as
76 // evaluating `NormalizesTo` is an extra step only exists in the new solver
77 // that behaves like a function call rather than an independent nested goal
78 // evaluation, so increasing the depth may end up regressions which hit the
79 // recursion limits for crates compiled well with the old solver. Furthermore,
80 // those nested goals from `NormalizesTo` will be evaluated again as the
81 // caller's nested goals with increased depths anyway.
82IncreaseDepthForNested::No,
83 )?;
8485{
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:85",
"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(85u32),
::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);
8687// Add a `make_canonical_response` probe step so that we treat this as
88 // a candidate, even if `try_evaluate_added_goals` bails due to an error.
89 // It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
90 // since equating the normalized terms will lead to additional constraints.
91self.inspect.make_canonical_response(Certainty::AMBIGUOUS);
9293self.eq(goal.param_env, term, unconstrained_term)?;
9495// Add the nested goals from normalization to our own nested goals.
96for (s, g) in nested_goals {
97self.add_goal(s, g)?;
98 }
99100self.evaluate_added_goals_and_make_canonical_response(certainty)
101 }
102}