rustc_next_trait_solver/solve/eval_ctxt/
mod.rs

1use std::mem;
2use std::ops::ControlFlow;
3
4#[cfg(feature = "nightly")]
5use rustc_macros::HashStable_NoContext;
6use rustc_type_ir::data_structures::{HashMap, HashSet};
7use rustc_type_ir::inherent::*;
8use rustc_type_ir::relate::Relate;
9use rustc_type_ir::relate::solver_relating::RelateExt;
10use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind};
11use rustc_type_ir::solve::OpaqueTypesJank;
12use rustc_type_ir::{
13    self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder,
14    TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
15    TypingMode,
16};
17use tracing::{debug, instrument, trace};
18
19use super::has_only_region_constraints;
20use crate::canonical::{
21    canonicalize_goal, canonicalize_response, instantiate_and_apply_query_response,
22    response_no_constraints_raw,
23};
24use crate::coherence;
25use crate::delegate::SolverDelegate;
26use crate::placeholder::BoundVarReplacer;
27use crate::resolve::eager_resolve_vars;
28use crate::solve::search_graph::SearchGraph;
29use crate::solve::ty::may_use_unstable_feature;
30use crate::solve::{
31    CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, FIXPOINT_STEP_LIMIT,
32    Goal, GoalEvaluation, GoalSource, GoalStalledOn, HasChanged, MaybeCause,
33    NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, Response, inspect,
34};
35
36mod probe;
37
38/// The kind of goal we're currently proving.
39///
40/// This has effects on cycle handling handling and on how we compute
41/// query responses, see the variant descriptions for more info.
42#[derive(Debug, Copy, Clone)]
43enum CurrentGoalKind {
44    Misc,
45    /// We're proving an trait goal for a coinductive trait, either an auto trait or `Sized`.
46    ///
47    /// These are currently the only goals whose impl where-clauses are considered to be
48    /// productive steps.
49    CoinductiveTrait,
50    /// Unlike other goals, `NormalizesTo` goals act like functions with the expected term
51    /// always being fully unconstrained. This would weaken inference however, as the nested
52    /// goals never get the inference constraints from the actual normalized-to type.
53    ///
54    /// Because of this we return any ambiguous nested goals from `NormalizesTo` to the
55    /// caller when then adds these to its own context. The caller is always an `AliasRelate`
56    /// goal so this never leaks out of the solver.
57    NormalizesTo,
58}
59
60impl CurrentGoalKind {
61    fn from_query_input<I: Interner>(cx: I, input: QueryInput<I, I::Predicate>) -> CurrentGoalKind {
62        match input.goal.predicate.kind().skip_binder() {
63            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
64                if cx.trait_is_coinductive(pred.trait_ref.def_id) {
65                    CurrentGoalKind::CoinductiveTrait
66                } else {
67                    CurrentGoalKind::Misc
68                }
69            }
70            ty::PredicateKind::NormalizesTo(_) => CurrentGoalKind::NormalizesTo,
71            _ => CurrentGoalKind::Misc,
72        }
73    }
74}
75
76pub struct EvalCtxt<'a, D, I = <D as SolverDelegate>::Interner>
77where
78    D: SolverDelegate<Interner = I>,
79    I: Interner,
80{
81    /// The inference context that backs (mostly) inference and placeholder terms
82    /// instantiated while solving goals.
83    ///
84    /// NOTE: The `InferCtxt` that backs the `EvalCtxt` is intentionally private,
85    /// because the `InferCtxt` is much more general than `EvalCtxt`. Methods such
86    /// as  `take_registered_region_obligations` can mess up query responses,
87    /// using `At::normalize` is totally wrong, calling `evaluate_root_goal` can
88    /// cause coinductive unsoundness, etc.
89    ///
90    /// Methods that are generally of use for trait solving are *intentionally*
91    /// re-declared through the `EvalCtxt` below, often with cleaner signatures
92    /// since we don't care about things like `ObligationCause`s and `Span`s here.
93    /// If some `InferCtxt` method is missing, please first think defensively about
94    /// the method's compatibility with this solver, or if an existing one does
95    /// the job already.
96    delegate: &'a D,
97
98    /// The variable info for the `var_values`, only used to make an ambiguous response
99    /// with no constraints.
100    variables: I::CanonicalVarKinds,
101
102    /// What kind of goal we're currently computing, see the enum definition
103    /// for more info.
104    current_goal_kind: CurrentGoalKind,
105    pub(super) var_values: CanonicalVarValues<I>,
106
107    /// The highest universe index nameable by the caller.
108    ///
109    /// When we enter a new binder inside of the query we create new universes
110    /// which the caller cannot name. We have to be careful with variables from
111    /// these new universes when creating the query response.
112    ///
113    /// Both because these new universes can prevent us from reaching a fixpoint
114    /// if we have a coinductive cycle and because that's the only way we can return
115    /// new placeholders to the caller.
116    pub(super) max_input_universe: ty::UniverseIndex,
117    /// The opaque types from the canonical input. We only need to return opaque types
118    /// which have been added to the storage while evaluating this goal.
119    pub(super) initial_opaque_types_storage_num_entries:
120        <D::Infcx as InferCtxtLike>::OpaqueTypeStorageEntries,
121
122    pub(super) search_graph: &'a mut SearchGraph<D>,
123
124    nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<GoalStalledOn<I>>)>,
125
126    pub(super) origin_span: I::Span,
127
128    // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
129    //
130    // If so, then it can no longer be used to make a canonical query response,
131    // since subsequent calls to `try_evaluate_added_goals` have possibly dropped
132    // ambiguous goals. Instead, a probe needs to be introduced somewhere in the
133    // evaluation code.
134    tainted: Result<(), NoSolution>,
135
136    pub(super) inspect: inspect::EvaluationStepBuilder<D>,
137}
138
139#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
140#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
141pub enum GenerateProofTree {
142    Yes,
143    No,
144}
145
146pub trait SolverDelegateEvalExt: SolverDelegate {
147    /// Evaluates a goal from **outside** of the trait solver.
148    ///
149    /// Using this while inside of the solver is wrong as it uses a new
150    /// search graph which would break cycle detection.
151    fn evaluate_root_goal(
152        &self,
153        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
154        span: <Self::Interner as Interner>::Span,
155        stalled_on: Option<GoalStalledOn<Self::Interner>>,
156    ) -> Result<GoalEvaluation<Self::Interner>, NoSolution>;
157
158    /// Checks whether evaluating `goal` may hold while treating not-yet-defined
159    /// opaque types as being kind of rigid.
160    ///
161    /// See the comment on [OpaqueTypesJank] for more details.
162    fn root_goal_may_hold_opaque_types_jank(
163        &self,
164        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
165    ) -> bool;
166
167    /// Check whether evaluating `goal` with a depth of `root_depth` may
168    /// succeed. This only returns `false` if the goal is guaranteed to
169    /// not hold. In case evaluation overflows and fails with ambiguity this
170    /// returns `true`.
171    ///
172    /// This is only intended to be used as a performance optimization
173    /// in coherence checking.
174    fn root_goal_may_hold_with_depth(
175        &self,
176        root_depth: usize,
177        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
178    ) -> bool;
179
180    // FIXME: This is only exposed because we need to use it in `analyse.rs`
181    // which is not yet uplifted. Once that's done, we should remove this.
182    fn evaluate_root_goal_for_proof_tree(
183        &self,
184        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
185        span: <Self::Interner as Interner>::Span,
186    ) -> (
187        Result<NestedNormalizationGoals<Self::Interner>, NoSolution>,
188        inspect::GoalEvaluation<Self::Interner>,
189    );
190}
191
192impl<D, I> SolverDelegateEvalExt for D
193where
194    D: SolverDelegate<Interner = I>,
195    I: Interner,
196{
197    #[instrument(level = "debug", skip(self), ret)]
198    fn evaluate_root_goal(
199        &self,
200        goal: Goal<I, I::Predicate>,
201        span: I::Span,
202        stalled_on: Option<GoalStalledOn<I>>,
203    ) -> Result<GoalEvaluation<I>, NoSolution> {
204        EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| {
205            ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on)
206        })
207    }
208
209    #[instrument(level = "debug", skip(self), ret)]
210    fn root_goal_may_hold_opaque_types_jank(
211        &self,
212        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
213    ) -> bool {
214        self.probe(|| {
215            EvalCtxt::enter_root(self, self.cx().recursion_limit(), I::Span::dummy(), |ecx| {
216                ecx.evaluate_goal(GoalSource::Misc, goal, None)
217            })
218            .is_ok_and(|r| match r.certainty {
219                Certainty::Yes => true,
220                Certainty::Maybe { cause: _, opaque_types_jank } => match opaque_types_jank {
221                    OpaqueTypesJank::AllGood => true,
222                    OpaqueTypesJank::ErrorIfRigidSelfTy => false,
223                },
224            })
225        })
226    }
227
228    fn root_goal_may_hold_with_depth(
229        &self,
230        root_depth: usize,
231        goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
232    ) -> bool {
233        self.probe(|| {
234            EvalCtxt::enter_root(self, root_depth, I::Span::dummy(), |ecx| {
235                ecx.evaluate_goal(GoalSource::Misc, goal, None)
236            })
237        })
238        .is_ok()
239    }
240
241    #[instrument(level = "debug", skip(self))]
242    fn evaluate_root_goal_for_proof_tree(
243        &self,
244        goal: Goal<I, I::Predicate>,
245        span: I::Span,
246    ) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
247        evaluate_root_goal_for_proof_tree(self, goal, span)
248    }
249}
250
251impl<'a, D, I> EvalCtxt<'a, D>
252where
253    D: SolverDelegate<Interner = I>,
254    I: Interner,
255{
256    pub(super) fn typing_mode(&self) -> TypingMode<I> {
257        self.delegate.typing_mode()
258    }
259
260    /// Computes the `PathKind` for the step from the current goal to the
261    /// nested goal required due to `source`.
262    ///
263    /// See #136824 for a more detailed reasoning for this behavior. We
264    /// consider cycles to be coinductive if they 'step into' a where-clause
265    /// of a coinductive trait. We will likely extend this function in the future
266    /// and will need to clearly document it in the rustc-dev-guide before
267    /// stabilization.
268    pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
269        match source {
270            // We treat these goals as unknown for now. It is likely that most miscellaneous
271            // nested goals will be converted to an inductive variant in the future.
272            //
273            // Having unknown cycles is always the safer option, as changing that to either
274            // succeed or hard error is backwards compatible. If we incorrectly treat a cycle
275            // as inductive even though it should not be, it may be unsound during coherence and
276            // fixing it may cause inference breakage or introduce ambiguity.
277            GoalSource::Misc => PathKind::Unknown,
278            GoalSource::NormalizeGoal(path_kind) => path_kind,
279            GoalSource::ImplWhereBound => match self.current_goal_kind {
280                // We currently only consider a cycle coinductive if it steps
281                // into a where-clause of a coinductive trait.
282                CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive,
283                // While normalizing via an impl does step into a where-clause of
284                // an impl, accessing the associated item immediately steps out of
285                // it again. This means cycles/recursive calls are not guarded
286                // by impls used for normalization.
287                //
288                // See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
289                // for how this can go wrong.
290                CurrentGoalKind::NormalizesTo => PathKind::Inductive,
291                // We probably want to make all traits coinductive in the future,
292                // so we treat cycles involving where-clauses of not-yet coinductive
293                // traits as ambiguous for now.
294                CurrentGoalKind::Misc => PathKind::Unknown,
295            },
296            // Relating types is always unproductive. If we were to map proof trees to
297            // corecursive functions as explained in #136824, relating types never
298            // introduces a constructor which could cause the recursion to be guarded.
299            GoalSource::TypeRelating => PathKind::Inductive,
300            // Instantiating a higher ranked goal can never cause the recursion to be
301            // guarded and is therefore unproductive.
302            GoalSource::InstantiateHigherRanked => PathKind::Inductive,
303            // These goal sources are likely unproductive and can be changed to
304            // `PathKind::Inductive`. Keeping them as unknown until we're confident
305            // about this and have an example where it is necessary.
306            GoalSource::AliasBoundConstCondition | GoalSource::AliasWellFormed => PathKind::Unknown,
307        }
308    }
309
310    /// Creates a root evaluation context and search graph. This should only be
311    /// used from outside of any evaluation, and other methods should be preferred
312    /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]).
313    pub(super) fn enter_root<R>(
314        delegate: &D,
315        root_depth: usize,
316        origin_span: I::Span,
317        f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
318    ) -> R {
319        let mut search_graph = SearchGraph::new(root_depth);
320
321        let mut ecx = EvalCtxt {
322            delegate,
323            search_graph: &mut search_graph,
324            nested_goals: Default::default(),
325            inspect: inspect::EvaluationStepBuilder::new_noop(),
326
327            // Only relevant when canonicalizing the response,
328            // which we don't do within this evaluation context.
329            max_input_universe: ty::UniverseIndex::ROOT,
330            initial_opaque_types_storage_num_entries: Default::default(),
331            variables: Default::default(),
332            var_values: CanonicalVarValues::dummy(),
333            current_goal_kind: CurrentGoalKind::Misc,
334            origin_span,
335            tainted: Ok(()),
336        };
337        let result = f(&mut ecx);
338        assert!(
339            ecx.nested_goals.is_empty(),
340            "root `EvalCtxt` should not have any goals added to it"
341        );
342        assert!(search_graph.is_empty());
343        result
344    }
345
346    /// Creates a nested evaluation context that shares the same search graph as the
347    /// one passed in. This is suitable for evaluation, granted that the search graph
348    /// has had the nested goal recorded on its stack. This method only be used by
349    /// `search_graph::Delegate::compute_goal`.
350    ///
351    /// This function takes care of setting up the inference context, setting the anchor,
352    /// and registering opaques from the canonicalized input.
353    pub(super) fn enter_canonical<R>(
354        cx: I,
355        search_graph: &'a mut SearchGraph<D>,
356        canonical_input: CanonicalInput<I>,
357        proof_tree_builder: &mut inspect::ProofTreeBuilder<D>,
358        f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
359    ) -> R {
360        let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input);
361        for (key, ty) in input.predefined_opaques_in_body.iter() {
362            let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy());
363            // It may be possible that two entries in the opaque type storage end up
364            // with the same key after resolving contained inference variables.
365            //
366            // We could put them in the duplicate list but don't have to. The opaques we
367            // encounter here are already tracked in the caller, so there's no need to
368            // also store them here. We'd take them out when computing the query response
369            // and then discard them, as they're already present in the input.
370            //
371            // Ideally we'd drop duplicate opaque type definitions when computing
372            // the canonical input. This is more annoying to implement and may cause a
373            // perf regression, so we do it inside of the query for now.
374            if let Some(prev) = prev {
375                debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
376            }
377        }
378
379        let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries();
380        let mut ecx = EvalCtxt {
381            delegate,
382            variables: canonical_input.canonical.variables,
383            var_values,
384            current_goal_kind: CurrentGoalKind::from_query_input(cx, input),
385            max_input_universe: canonical_input.canonical.max_universe,
386            initial_opaque_types_storage_num_entries,
387            search_graph,
388            nested_goals: Default::default(),
389            origin_span: I::Span::dummy(),
390            tainted: Ok(()),
391            inspect: proof_tree_builder.new_evaluation_step(var_values),
392        };
393
394        let result = f(&mut ecx, input.goal);
395        ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe);
396        proof_tree_builder.finish_evaluation_step(ecx.inspect);
397
398        // When creating a query response we clone the opaque type constraints
399        // instead of taking them. This would cause an ICE here, since we have
400        // assertions against dropping an `InferCtxt` without taking opaques.
401        // FIXME: Once we remove support for the old impl we can remove this.
402        // FIXME: Could we make `build_with_canonical` into `enter_with_canonical` and call this at the end?
403        delegate.reset_opaque_types();
404
405        result
406    }
407
408    pub(super) fn ignore_candidate_head_usages(&mut self, usages: CandidateHeadUsages) {
409        self.search_graph.ignore_candidate_head_usages(usages);
410    }
411
412    /// Recursively evaluates `goal`, returning whether any inference vars have
413    /// been constrained and the certainty of the result.
414    fn evaluate_goal(
415        &mut self,
416        source: GoalSource,
417        goal: Goal<I, I::Predicate>,
418        stalled_on: Option<GoalStalledOn<I>>,
419    ) -> Result<GoalEvaluation<I>, NoSolution> {
420        let (normalization_nested_goals, goal_evaluation) =
421            self.evaluate_goal_raw(source, goal, stalled_on)?;
422        assert!(normalization_nested_goals.is_empty());
423        Ok(goal_evaluation)
424    }
425
426    /// Recursively evaluates `goal`, returning the nested goals in case
427    /// the nested goal is a `NormalizesTo` goal.
428    ///
429    /// As all other goal kinds do not return any nested goals and
430    /// `NormalizesTo` is only used by `AliasRelate`, all other callsites
431    /// should use [`EvalCtxt::evaluate_goal`] which discards that empty
432    /// storage.
433    pub(super) fn evaluate_goal_raw(
434        &mut self,
435        source: GoalSource,
436        goal: Goal<I, I::Predicate>,
437        stalled_on: Option<GoalStalledOn<I>>,
438    ) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
439        // If we have run this goal before, and it was stalled, check that any of the goal's
440        // args have changed. Otherwise, we don't need to re-run the goal because it'll remain
441        // stalled, since it'll canonicalize the same way and evaluation is pure.
442        if let Some(GoalStalledOn {
443            num_opaques,
444            ref stalled_vars,
445            ref sub_roots,
446            stalled_certainty,
447        }) = stalled_on
448            && !stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
449            && !sub_roots
450                .iter()
451                .any(|&vid| self.delegate.sub_unification_table_root_var(vid) != vid)
452            && !self.delegate.opaque_types_storage_num_entries().needs_reevaluation(num_opaques)
453        {
454            return Ok((
455                NestedNormalizationGoals::empty(),
456                GoalEvaluation {
457                    goal,
458                    certainty: stalled_certainty,
459                    has_changed: HasChanged::No,
460                    stalled_on,
461                },
462            ));
463        }
464
465        // We only care about one entry per `OpaqueTypeKey` here,
466        // so we only canonicalize the lookup table and ignore
467        // duplicate entries.
468        let opaque_types = self.delegate.clone_opaque_types_lookup_table();
469        let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
470
471        let (orig_values, canonical_goal) = canonicalize_goal(self.delegate, goal, &opaque_types);
472        let canonical_result = self.search_graph.evaluate_goal(
473            self.cx(),
474            canonical_goal,
475            self.step_kind_for_source(source),
476            &mut inspect::ProofTreeBuilder::new_noop(),
477        );
478        let response = match canonical_result {
479            Err(e) => return Err(e),
480            Ok(response) => response,
481        };
482
483        let has_changed =
484            if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
485
486        let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response(
487            self.delegate,
488            goal.param_env,
489            &orig_values,
490            response,
491            self.origin_span,
492        );
493
494        // FIXME: We previously had an assert here that checked that recomputing
495        // a goal after applying its constraints did not change its response.
496        //
497        // This assert was removed as it did not hold for goals constraining
498        // an inference variable to a recursive alias, e.g. in
499        // tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs.
500        //
501        // Once we have decided on how to handle trait-system-refactor-initiative#75,
502        // we should re-add an assert here.
503
504        let stalled_on = match certainty {
505            Certainty::Yes => None,
506            Certainty::Maybe { .. } => match has_changed {
507                // FIXME: We could recompute a *new* set of stalled variables by walking
508                // through the orig values, resolving, and computing the root vars of anything
509                // that is not resolved. Only when *these* have changed is it meaningful
510                // to recompute this goal.
511                HasChanged::Yes => None,
512                HasChanged::No => {
513                    let mut stalled_vars = orig_values;
514
515                    // Remove the unconstrained RHS arg, which is expected to have changed.
516                    if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
517                        let normalizes_to = normalizes_to.skip_binder();
518                        let rhs_arg: I::GenericArg = normalizes_to.term.into();
519                        let idx = stalled_vars
520                            .iter()
521                            .rposition(|arg| *arg == rhs_arg)
522                            .expect("expected unconstrained arg");
523                        stalled_vars.swap_remove(idx);
524                    }
525
526                    // Remove the canonicalized universal vars, since we only care about stalled existentials.
527                    let mut sub_roots = Vec::new();
528                    stalled_vars.retain(|arg| match arg.kind() {
529                        // Lifetimes can never stall goals.
530                        ty::GenericArgKind::Lifetime(_) => false,
531                        ty::GenericArgKind::Type(ty) => match ty.kind() {
532                            ty::Infer(ty::TyVar(vid)) => {
533                                sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
534                                true
535                            }
536                            ty::Infer(_) => true,
537                            ty::Param(_) | ty::Placeholder(_) => false,
538                            _ => unreachable!("unexpected orig_value: {ty:?}"),
539                        },
540                        ty::GenericArgKind::Const(ct) => match ct.kind() {
541                            ty::ConstKind::Infer(_) => true,
542                            ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => false,
543                            _ => unreachable!("unexpected orig_value: {ct:?}"),
544                        },
545                    });
546
547                    Some(GoalStalledOn {
548                        num_opaques: canonical_goal
549                            .canonical
550                            .value
551                            .predefined_opaques_in_body
552                            .len(),
553                        stalled_vars,
554                        sub_roots,
555                        stalled_certainty: certainty,
556                    })
557                }
558            },
559        };
560
561        Ok((
562            normalization_nested_goals,
563            GoalEvaluation { goal, certainty, has_changed, stalled_on },
564        ))
565    }
566
567    pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
568        let Goal { param_env, predicate } = goal;
569        let kind = predicate.kind();
570        if let Some(kind) = kind.no_bound_vars() {
571            match kind {
572                ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
573                    self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
574                }
575                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
576                    self.compute_host_effect_goal(Goal { param_env, predicate })
577                }
578                ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
579                    self.compute_projection_goal(Goal { param_env, predicate })
580                }
581                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
582                    self.compute_type_outlives_goal(Goal { param_env, predicate })
583                }
584                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
585                    self.compute_region_outlives_goal(Goal { param_env, predicate })
586                }
587                ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
588                    self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
589                }
590                ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
591                    self.compute_unstable_feature_goal(param_env, symbol)
592                }
593                ty::PredicateKind::Subtype(predicate) => {
594                    self.compute_subtype_goal(Goal { param_env, predicate })
595                }
596                ty::PredicateKind::Coerce(predicate) => {
597                    self.compute_coerce_goal(Goal { param_env, predicate })
598                }
599                ty::PredicateKind::DynCompatible(trait_def_id) => {
600                    self.compute_dyn_compatible_goal(trait_def_id)
601                }
602                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
603                    self.compute_well_formed_goal(Goal { param_env, predicate: term })
604                }
605                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
606                    self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
607                }
608                ty::PredicateKind::ConstEquate(_, _) => {
609                    panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
610                }
611                ty::PredicateKind::NormalizesTo(predicate) => {
612                    self.compute_normalizes_to_goal(Goal { param_env, predicate })
613                }
614                ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
615                    .compute_alias_relate_goal(Goal {
616                        param_env,
617                        predicate: (lhs, rhs, direction),
618                    }),
619                ty::PredicateKind::Ambiguous => {
620                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
621                }
622            }
623        } else {
624            self.enter_forall(kind, |ecx, kind| {
625                let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind));
626                ecx.add_goal(GoalSource::InstantiateHigherRanked, goal);
627                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
628            })
629        }
630    }
631
632    // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
633    // the certainty of all the goals.
634    #[instrument(level = "trace", skip(self))]
635    pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
636        for _ in 0..FIXPOINT_STEP_LIMIT {
637            match self.evaluate_added_goals_step() {
638                Ok(None) => {}
639                Ok(Some(cert)) => return Ok(cert),
640                Err(NoSolution) => {
641                    self.tainted = Err(NoSolution);
642                    return Err(NoSolution);
643                }
644            }
645        }
646
647        debug!("try_evaluate_added_goals: encountered overflow");
648        Ok(Certainty::overflow(false))
649    }
650
651    /// Iterate over all added goals: returning `Ok(Some(_))` in case we can stop rerunning.
652    ///
653    /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
654    fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
655        let cx = self.cx();
656        // If this loop did not result in any progress, what's our final certainty.
657        let mut unchanged_certainty = Some(Certainty::Yes);
658        for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
659            if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
660                match certainty {
661                    Certainty::Yes => {}
662                    Certainty::Maybe { .. } => {
663                        self.nested_goals.push((source, goal, None));
664                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
665                    }
666                }
667                continue;
668            }
669
670            // We treat normalizes-to goals specially here. In each iteration we take the
671            // RHS of the projection, replace it with a fresh inference variable, and only
672            // after evaluating that goal do we equate the fresh inference variable with the
673            // actual RHS of the predicate.
674            //
675            // This is both to improve caching, and to avoid using the RHS of the
676            // projection predicate to influence the normalizes-to candidate we select.
677            //
678            // Forgetting to replace the RHS with a fresh inference variable when we evaluate
679            // this goal results in an ICE.
680            if let Some(pred) = goal.predicate.as_normalizes_to() {
681                // We should never encounter higher-ranked normalizes-to goals.
682                let pred = pred.no_bound_vars().unwrap();
683                // Replace the goal with an unconstrained infer var, so the
684                // RHS does not affect projection candidate assembly.
685                let unconstrained_rhs = self.next_term_infer_of_kind(pred.term);
686                let unconstrained_goal =
687                    goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
688
689                let (
690                    NestedNormalizationGoals(nested_goals),
691                    GoalEvaluation { goal, certainty, stalled_on, has_changed: _ },
692                ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on)?;
693                // Add the nested goals from normalization to our own nested goals.
694                trace!(?nested_goals);
695                self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None)));
696
697                // Finally, equate the goal's RHS with the unconstrained var.
698                //
699                // SUBTLE:
700                // We structurally relate aliases here. This is necessary
701                // as we otherwise emit a nested `AliasRelate` goal in case the
702                // returned term is a rigid alias, resulting in overflow.
703                //
704                // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
705                // start out as an unconstrained inference variable so any aliases get
706                // fully normalized when instantiating it.
707                //
708                // FIXME: Strictly speaking this may be incomplete if the normalized-to
709                // type contains an ambiguous alias referencing bound regions. We should
710                // consider changing this to only use "shallow structural equality".
711                self.eq_structurally_relating_aliases(
712                    goal.param_env,
713                    pred.term,
714                    unconstrained_rhs,
715                )?;
716
717                // We only look at the `projection_ty` part here rather than
718                // looking at the "has changed" return from evaluate_goal,
719                // because we expect the `unconstrained_rhs` part of the predicate
720                // to have changed -- that means we actually normalized successfully!
721                // FIXME: Do we need to eagerly resolve here? Or should we check
722                // if the cache key has any changed vars?
723                let with_resolved_vars = self.resolve_vars_if_possible(goal);
724                if pred.alias
725                    != with_resolved_vars
726                        .predicate
727                        .as_normalizes_to()
728                        .unwrap()
729                        .no_bound_vars()
730                        .unwrap()
731                        .alias
732                {
733                    unchanged_certainty = None;
734                }
735
736                match certainty {
737                    Certainty::Yes => {}
738                    Certainty::Maybe { .. } => {
739                        self.nested_goals.push((source, with_resolved_vars, stalled_on));
740                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
741                    }
742                }
743            } else {
744                let GoalEvaluation { goal, certainty, has_changed, stalled_on } =
745                    self.evaluate_goal(source, goal, stalled_on)?;
746                if has_changed == HasChanged::Yes {
747                    unchanged_certainty = None;
748                }
749
750                match certainty {
751                    Certainty::Yes => {}
752                    Certainty::Maybe { .. } => {
753                        self.nested_goals.push((source, goal, stalled_on));
754                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
755                    }
756                }
757            }
758        }
759
760        Ok(unchanged_certainty)
761    }
762
763    /// Record impl args in the proof tree for later access by `InspectCandidate`.
764    pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs) {
765        self.inspect.record_impl_args(self.delegate, self.max_input_universe, impl_args)
766    }
767
768    pub(super) fn cx(&self) -> I {
769        self.delegate.cx()
770    }
771
772    #[instrument(level = "debug", skip(self))]
773    pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
774        goal.predicate =
775            goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
776        self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
777        self.nested_goals.push((source, goal, None));
778    }
779
780    #[instrument(level = "trace", skip(self, goals))]
781    pub(super) fn add_goals(
782        &mut self,
783        source: GoalSource,
784        goals: impl IntoIterator<Item = Goal<I, I::Predicate>>,
785    ) {
786        for goal in goals {
787            self.add_goal(source, goal);
788        }
789    }
790
791    pub(super) fn next_region_var(&mut self) -> I::Region {
792        let region = self.delegate.next_region_infer();
793        self.inspect.add_var_value(region);
794        region
795    }
796
797    pub(super) fn next_ty_infer(&mut self) -> I::Ty {
798        let ty = self.delegate.next_ty_infer();
799        self.inspect.add_var_value(ty);
800        ty
801    }
802
803    pub(super) fn next_const_infer(&mut self) -> I::Const {
804        let ct = self.delegate.next_const_infer();
805        self.inspect.add_var_value(ct);
806        ct
807    }
808
809    /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
810    /// If `kind` is an integer inference variable this will still return a ty infer var.
811    pub(super) fn next_term_infer_of_kind(&mut self, term: I::Term) -> I::Term {
812        match term.kind() {
813            ty::TermKind::Ty(_) => self.next_ty_infer().into(),
814            ty::TermKind::Const(_) => self.next_const_infer().into(),
815        }
816    }
817
818    /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
819    ///
820    /// This is the case if the `term` does not occur in any other part of the predicate
821    /// and is able to name all other placeholder and inference variables.
822    #[instrument(level = "trace", skip(self), ret)]
823    pub(super) fn term_is_fully_unconstrained(&self, goal: Goal<I, ty::NormalizesTo<I>>) -> bool {
824        let universe_of_term = match goal.predicate.term.kind() {
825            ty::TermKind::Ty(ty) => {
826                if let ty::Infer(ty::TyVar(vid)) = ty.kind() {
827                    self.delegate.universe_of_ty(vid).unwrap()
828                } else {
829                    return false;
830                }
831            }
832            ty::TermKind::Const(ct) => {
833                if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
834                    self.delegate.universe_of_ct(vid).unwrap()
835                } else {
836                    return false;
837                }
838            }
839        };
840
841        struct ContainsTermOrNotNameable<'a, D: SolverDelegate<Interner = I>, I: Interner> {
842            term: I::Term,
843            universe_of_term: ty::UniverseIndex,
844            delegate: &'a D,
845            cache: HashSet<I::Ty>,
846        }
847
848        impl<D: SolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, D, I> {
849            fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
850                if self.universe_of_term.can_name(universe) {
851                    ControlFlow::Continue(())
852                } else {
853                    ControlFlow::Break(())
854                }
855            }
856        }
857
858        impl<D: SolverDelegate<Interner = I>, I: Interner> TypeVisitor<I>
859            for ContainsTermOrNotNameable<'_, D, I>
860        {
861            type Result = ControlFlow<()>;
862            fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
863                if self.cache.contains(&t) {
864                    return ControlFlow::Continue(());
865                }
866
867                match t.kind() {
868                    ty::Infer(ty::TyVar(vid)) => {
869                        if let ty::TermKind::Ty(term) = self.term.kind()
870                            && let ty::Infer(ty::TyVar(term_vid)) = term.kind()
871                            && self.delegate.root_ty_var(vid) == self.delegate.root_ty_var(term_vid)
872                        {
873                            return ControlFlow::Break(());
874                        }
875
876                        self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?;
877                    }
878                    ty::Placeholder(p) => self.check_nameable(p.universe())?,
879                    _ => {
880                        if t.has_non_region_infer() || t.has_placeholders() {
881                            t.super_visit_with(self)?
882                        }
883                    }
884                }
885
886                assert!(self.cache.insert(t));
887                ControlFlow::Continue(())
888            }
889
890            fn visit_const(&mut self, c: I::Const) -> Self::Result {
891                match c.kind() {
892                    ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
893                        if let ty::TermKind::Const(term) = self.term.kind()
894                            && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
895                            && self.delegate.root_const_var(vid)
896                                == self.delegate.root_const_var(term_vid)
897                        {
898                            return ControlFlow::Break(());
899                        }
900
901                        self.check_nameable(self.delegate.universe_of_ct(vid).unwrap())
902                    }
903                    ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()),
904                    _ => {
905                        if c.has_non_region_infer() || c.has_placeholders() {
906                            c.super_visit_with(self)
907                        } else {
908                            ControlFlow::Continue(())
909                        }
910                    }
911                }
912            }
913
914            fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
915                if p.has_non_region_infer() || p.has_placeholders() {
916                    p.super_visit_with(self)
917                } else {
918                    ControlFlow::Continue(())
919                }
920            }
921
922            fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
923                if c.has_non_region_infer() || c.has_placeholders() {
924                    c.super_visit_with(self)
925                } else {
926                    ControlFlow::Continue(())
927                }
928            }
929        }
930
931        let mut visitor = ContainsTermOrNotNameable {
932            delegate: self.delegate,
933            universe_of_term,
934            term: goal.predicate.term,
935            cache: Default::default(),
936        };
937        goal.predicate.alias.visit_with(&mut visitor).is_continue()
938            && goal.param_env.visit_with(&mut visitor).is_continue()
939    }
940
941    pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
942        self.delegate.sub_unify_ty_vids_raw(a, b)
943    }
944
945    #[instrument(level = "trace", skip(self, param_env), ret)]
946    pub(super) fn eq<T: Relate<I>>(
947        &mut self,
948        param_env: I::ParamEnv,
949        lhs: T,
950        rhs: T,
951    ) -> Result<(), NoSolution> {
952        self.relate(param_env, lhs, ty::Variance::Invariant, rhs)
953    }
954
955    /// This should be used when relating a rigid alias with another type.
956    ///
957    /// Normally we emit a nested `AliasRelate` when equating an inference
958    /// variable and an alias. This causes us to instead constrain the inference
959    /// variable to the alias without emitting a nested alias relate goals.
960    #[instrument(level = "trace", skip(self, param_env), ret)]
961    pub(super) fn relate_rigid_alias_non_alias(
962        &mut self,
963        param_env: I::ParamEnv,
964        alias: ty::AliasTerm<I>,
965        variance: ty::Variance,
966        term: I::Term,
967    ) -> Result<(), NoSolution> {
968        // NOTE: this check is purely an optimization, the structural eq would
969        // always fail if the term is not an inference variable.
970        if term.is_infer() {
971            let cx = self.cx();
972            // We need to relate `alias` to `term` treating only the outermost
973            // constructor as rigid, relating any contained generic arguments as
974            // normal. We do this by first structurally equating the `term`
975            // with the alias constructor instantiated with unconstrained infer vars,
976            // and then relate this with the whole `alias`.
977            //
978            // Alternatively we could modify `Equate` for this case by adding another
979            // variant to `StructurallyRelateAliases`.
980            let identity_args = self.fresh_args_for_item(alias.def_id);
981            let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
982            let ctor_term = rigid_ctor.to_term(cx);
983            let obligations = self.delegate.eq_structurally_relating_aliases(
984                param_env,
985                term,
986                ctor_term,
987                self.origin_span,
988            )?;
989            debug_assert!(obligations.is_empty());
990            self.relate(param_env, alias, variance, rigid_ctor)
991        } else {
992            Err(NoSolution)
993        }
994    }
995
996    /// This sohuld only be used when we're either instantiating a previously
997    /// unconstrained "return value" or when we're sure that all aliases in
998    /// the types are rigid.
999    #[instrument(level = "trace", skip(self, param_env), ret)]
1000    pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
1001        &mut self,
1002        param_env: I::ParamEnv,
1003        lhs: T,
1004        rhs: T,
1005    ) -> Result<(), NoSolution> {
1006        let result = self.delegate.eq_structurally_relating_aliases(
1007            param_env,
1008            lhs,
1009            rhs,
1010            self.origin_span,
1011        )?;
1012        assert_eq!(result, vec![]);
1013        Ok(())
1014    }
1015
1016    #[instrument(level = "trace", skip(self, param_env), ret)]
1017    pub(super) fn sub<T: Relate<I>>(
1018        &mut self,
1019        param_env: I::ParamEnv,
1020        sub: T,
1021        sup: T,
1022    ) -> Result<(), NoSolution> {
1023        self.relate(param_env, sub, ty::Variance::Covariant, sup)
1024    }
1025
1026    #[instrument(level = "trace", skip(self, param_env), ret)]
1027    pub(super) fn relate<T: Relate<I>>(
1028        &mut self,
1029        param_env: I::ParamEnv,
1030        lhs: T,
1031        variance: ty::Variance,
1032        rhs: T,
1033    ) -> Result<(), NoSolution> {
1034        let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
1035        for &goal in goals.iter() {
1036            let source = match goal.predicate.kind().skip_binder() {
1037                ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
1038                    GoalSource::TypeRelating
1039                }
1040                // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive?
1041                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc,
1042                p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
1043            };
1044            self.add_goal(source, goal);
1045        }
1046        Ok(())
1047    }
1048
1049    /// Equates two values returning the nested goals without adding them
1050    /// to the nested goals of the `EvalCtxt`.
1051    ///
1052    /// If possible, try using `eq` instead which automatically handles nested
1053    /// goals correctly.
1054    #[instrument(level = "trace", skip(self, param_env), ret)]
1055    pub(super) fn eq_and_get_goals<T: Relate<I>>(
1056        &self,
1057        param_env: I::ParamEnv,
1058        lhs: T,
1059        rhs: T,
1060    ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
1061        Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
1062    }
1063
1064    pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
1065        &self,
1066        value: ty::Binder<I, T>,
1067    ) -> T {
1068        self.delegate.instantiate_binder_with_infer(value)
1069    }
1070
1071    /// `enter_forall`, but takes `&mut self` and passes it back through the
1072    /// callback since it can't be aliased during the call.
1073    pub(super) fn enter_forall<T: TypeFoldable<I>, U>(
1074        &mut self,
1075        value: ty::Binder<I, T>,
1076        f: impl FnOnce(&mut Self, T) -> U,
1077    ) -> U {
1078        self.delegate.enter_forall(value, |value| f(self, value))
1079    }
1080
1081    pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
1082    where
1083        T: TypeFoldable<I>,
1084    {
1085        self.delegate.resolve_vars_if_possible(value)
1086    }
1087
1088    pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty {
1089        self.delegate.shallow_resolve(ty)
1090    }
1091
1092    pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region {
1093        if let ty::ReVar(vid) = r.kind() {
1094            self.delegate.opportunistic_resolve_lt_var(vid)
1095        } else {
1096            r
1097        }
1098    }
1099
1100    pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
1101        let args = self.delegate.fresh_args_for_item(def_id);
1102        for arg in args.iter() {
1103            self.inspect.add_var_value(arg);
1104        }
1105        args
1106    }
1107
1108    pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
1109        self.delegate.register_ty_outlives(ty, lt, self.origin_span);
1110    }
1111
1112    pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
1113        // `'a: 'b` ==> `'b <= 'a`
1114        self.delegate.sub_regions(b, a, self.origin_span);
1115    }
1116
1117    /// Computes the list of goals required for `arg` to be well-formed
1118    pub(super) fn well_formed_goals(
1119        &self,
1120        param_env: I::ParamEnv,
1121        term: I::Term,
1122    ) -> Option<Vec<Goal<I, I::Predicate>>> {
1123        self.delegate.well_formed_goals(param_env, term)
1124    }
1125
1126    pub(super) fn trait_ref_is_knowable(
1127        &mut self,
1128        param_env: I::ParamEnv,
1129        trait_ref: ty::TraitRef<I>,
1130    ) -> Result<bool, NoSolution> {
1131        let delegate = self.delegate;
1132        let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty);
1133        coherence::trait_ref_is_knowable(&**delegate, trait_ref, lazily_normalize_ty)
1134            .map(|is_knowable| is_knowable.is_ok())
1135    }
1136
1137    pub(super) fn fetch_eligible_assoc_item(
1138        &self,
1139        goal_trait_ref: ty::TraitRef<I>,
1140        trait_assoc_def_id: I::DefId,
1141        impl_def_id: I::ImplId,
1142    ) -> Result<Option<I::DefId>, I::ErrorGuaranteed> {
1143        self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
1144    }
1145
1146    #[instrument(level = "debug", skip(self), ret)]
1147    pub(super) fn register_hidden_type_in_storage(
1148        &mut self,
1149        opaque_type_key: ty::OpaqueTypeKey<I>,
1150        hidden_ty: I::Ty,
1151    ) -> Option<I::Ty> {
1152        self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span)
1153    }
1154
1155    pub(super) fn add_item_bounds_for_hidden_type(
1156        &mut self,
1157        opaque_def_id: I::DefId,
1158        opaque_args: I::GenericArgs,
1159        param_env: I::ParamEnv,
1160        hidden_ty: I::Ty,
1161    ) {
1162        let mut goals = Vec::new();
1163        self.delegate.add_item_bounds_for_hidden_type(
1164            opaque_def_id,
1165            opaque_args,
1166            param_env,
1167            hidden_ty,
1168            &mut goals,
1169        );
1170        self.add_goals(GoalSource::AliasWellFormed, goals);
1171    }
1172
1173    // Try to evaluate a const, or return `None` if the const is too generic.
1174    // This doesn't mean the const isn't evaluatable, though, and should be treated
1175    // as an ambiguity rather than no-solution.
1176    pub(super) fn evaluate_const(
1177        &self,
1178        param_env: I::ParamEnv,
1179        uv: ty::UnevaluatedConst<I>,
1180    ) -> Option<I::Const> {
1181        self.delegate.evaluate_const(param_env, uv)
1182    }
1183
1184    pub(super) fn is_transmutable(
1185        &mut self,
1186        dst: I::Ty,
1187        src: I::Ty,
1188        assume: I::Const,
1189    ) -> Result<Certainty, NoSolution> {
1190        self.delegate.is_transmutable(dst, src, assume)
1191    }
1192
1193    pub(super) fn replace_bound_vars<T: TypeFoldable<I>>(
1194        &self,
1195        t: T,
1196        universes: &mut Vec<Option<ty::UniverseIndex>>,
1197    ) -> T {
1198        BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, t).0
1199    }
1200
1201    pub(super) fn may_use_unstable_feature(
1202        &self,
1203        param_env: I::ParamEnv,
1204        symbol: I::Symbol,
1205    ) -> bool {
1206        may_use_unstable_feature(&**self.delegate, param_env, symbol)
1207    }
1208
1209    pub(crate) fn opaques_with_sub_unified_hidden_type(
1210        &self,
1211        self_ty: I::Ty,
1212    ) -> Vec<ty::AliasTy<I>> {
1213        if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() {
1214            self.delegate.opaques_with_sub_unified_hidden_type(vid)
1215        } else {
1216            vec![]
1217        }
1218    }
1219
1220    /// To return the constraints of a canonical query to the caller, we canonicalize:
1221    ///
1222    /// - `var_values`: a map from bound variables in the canonical goal to
1223    ///   the values inferred while solving the instantiated goal.
1224    /// - `external_constraints`: additional constraints which aren't expressible
1225    ///   using simple unification of inference variables.
1226    ///
1227    /// This takes the `shallow_certainty` which represents whether we're confident
1228    /// that the final result of the current goal only depends on the nested goals.
1229    ///
1230    /// In case this is `Certainty::Maybe`, there may still be additional nested goals
1231    /// or inference constraints required for this candidate to be hold. The candidate
1232    /// always requires all already added constraints and nested goals.
1233    #[instrument(level = "trace", skip(self), ret)]
1234    pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
1235        &mut self,
1236        shallow_certainty: Certainty,
1237    ) -> QueryResult<I> {
1238        self.inspect.make_canonical_response(shallow_certainty);
1239
1240        let goals_certainty = self.try_evaluate_added_goals()?;
1241        assert_eq!(
1242            self.tainted,
1243            Ok(()),
1244            "EvalCtxt is tainted -- nested goals may have been dropped in a \
1245            previous call to `try_evaluate_added_goals!`"
1246        );
1247
1248        // We only check for leaks from universes which were entered inside
1249        // of the query.
1250        self.delegate.leak_check(self.max_input_universe).map_err(|NoSolution| {
1251            trace!("failed the leak check");
1252            NoSolution
1253        })?;
1254
1255        let (certainty, normalization_nested_goals) =
1256            match (self.current_goal_kind, shallow_certainty) {
1257                // When normalizing, we've replaced the expected term with an unconstrained
1258                // inference variable. This means that we dropped information which could
1259                // have been important. We handle this by instead returning the nested goals
1260                // to the caller, where they are then handled. We only do so if we do not
1261                // need to recompute the `NormalizesTo` goal afterwards to avoid repeatedly
1262                // uplifting its nested goals. This is the case if the `shallow_certainty` is
1263                // `Certainty::Yes`.
1264                (CurrentGoalKind::NormalizesTo, Certainty::Yes) => {
1265                    let goals = std::mem::take(&mut self.nested_goals);
1266                    // As we return all ambiguous nested goals, we can ignore the certainty
1267                    // returned by `self.try_evaluate_added_goals()`.
1268                    if goals.is_empty() {
1269                        assert!(matches!(goals_certainty, Certainty::Yes));
1270                    }
1271                    (
1272                        Certainty::Yes,
1273                        NestedNormalizationGoals(
1274                            goals.into_iter().map(|(s, g, _)| (s, g)).collect(),
1275                        ),
1276                    )
1277                }
1278                _ => {
1279                    let certainty = shallow_certainty.and(goals_certainty);
1280                    (certainty, NestedNormalizationGoals::empty())
1281                }
1282            };
1283
1284        if let Certainty::Maybe {
1285            cause: cause @ MaybeCause::Overflow { keep_constraints: false, .. },
1286            opaque_types_jank,
1287        } = certainty
1288        {
1289            // If we have overflow, it's probable that we're substituting a type
1290            // into itself infinitely and any partial substitutions in the query
1291            // response are probably not useful anyways, so just return an empty
1292            // query response.
1293            //
1294            // This may prevent us from potentially useful inference, e.g.
1295            // 2 candidates, one ambiguous and one overflow, which both
1296            // have the same inference constraints.
1297            //
1298            // Changing this to retain some constraints in the future
1299            // won't be a breaking change, so this is good enough for now.
1300            return Ok(self.make_ambiguous_response_no_constraints(cause, opaque_types_jank));
1301        }
1302
1303        let external_constraints =
1304            self.compute_external_query_constraints(certainty, normalization_nested_goals);
1305        let (var_values, mut external_constraints) =
1306            eager_resolve_vars(self.delegate, (self.var_values, external_constraints));
1307
1308        // Remove any trivial or duplicated region constraints once we've resolved regions
1309        let mut unique = HashSet::default();
1310        external_constraints.region_constraints.retain(|outlives| {
1311            outlives.0.as_region().is_none_or(|re| re != outlives.1) && unique.insert(*outlives)
1312        });
1313
1314        let canonical = canonicalize_response(
1315            self.delegate,
1316            self.max_input_universe,
1317            Response {
1318                var_values,
1319                certainty,
1320                external_constraints: self.cx().mk_external_constraints(external_constraints),
1321            },
1322        );
1323
1324        // HACK: We bail with overflow if the response would have too many non-region
1325        // inference variables. This tends to only happen if we encounter a lot of
1326        // ambiguous alias types which get replaced with fresh inference variables
1327        // during generalization. This prevents hangs caused by an exponential blowup,
1328        // see tests/ui/traits/next-solver/coherence-alias-hang.rs.
1329        match self.current_goal_kind {
1330            // We don't do so for `NormalizesTo` goals as we erased the expected term and
1331            // bailing with overflow here would prevent us from detecting a type-mismatch,
1332            // causing a coherence error in diesel, see #131969. We still bail with overflow
1333            // when later returning from the parent AliasRelate goal.
1334            CurrentGoalKind::NormalizesTo => {}
1335            CurrentGoalKind::Misc | CurrentGoalKind::CoinductiveTrait => {
1336                let num_non_region_vars = canonical
1337                    .variables
1338                    .iter()
1339                    .filter(|c| !c.is_region() && c.is_existential())
1340                    .count();
1341                if num_non_region_vars > self.cx().recursion_limit() {
1342                    debug!(?num_non_region_vars, "too many inference variables -> overflow");
1343                    return Ok(self.make_ambiguous_response_no_constraints(
1344                        MaybeCause::Overflow {
1345                            suggest_increasing_limit: true,
1346                            keep_constraints: false,
1347                        },
1348                        OpaqueTypesJank::AllGood,
1349                    ));
1350                }
1351            }
1352        }
1353
1354        Ok(canonical)
1355    }
1356
1357    /// Constructs a totally unconstrained, ambiguous response to a goal.
1358    ///
1359    /// Take care when using this, since often it's useful to respond with
1360    /// ambiguity but return constrained variables to guide inference.
1361    pub(in crate::solve) fn make_ambiguous_response_no_constraints(
1362        &self,
1363        cause: MaybeCause,
1364        opaque_types_jank: OpaqueTypesJank,
1365    ) -> CanonicalResponse<I> {
1366        response_no_constraints_raw(
1367            self.cx(),
1368            self.max_input_universe,
1369            self.variables,
1370            Certainty::Maybe { cause, opaque_types_jank },
1371        )
1372    }
1373
1374    /// Computes the region constraints and *new* opaque types registered when
1375    /// proving a goal.
1376    ///
1377    /// If an opaque was already constrained before proving this goal, then the
1378    /// external constraints do not need to record that opaque, since if it is
1379    /// further constrained by inference, that will be passed back in the var
1380    /// values.
1381    #[instrument(level = "trace", skip(self), ret)]
1382    fn compute_external_query_constraints(
1383        &self,
1384        certainty: Certainty,
1385        normalization_nested_goals: NestedNormalizationGoals<I>,
1386    ) -> ExternalConstraintsData<I> {
1387        // We only return region constraints once the certainty is `Yes`. This
1388        // is necessary as we may drop nested goals on ambiguity, which may result
1389        // in unconstrained inference variables in the region constraints. It also
1390        // prevents us from emitting duplicate region constraints, avoiding some
1391        // unnecessary work. This slightly weakens the leak check in case it uses
1392        // region constraints from an ambiguous nested goal. This is tested in both
1393        // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and
1394        // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`.
1395        let region_constraints = if certainty == Certainty::Yes {
1396            self.delegate.make_deduplicated_outlives_constraints()
1397        } else {
1398            Default::default()
1399        };
1400
1401        // We only return *newly defined* opaque types from canonical queries.
1402        //
1403        // Constraints for any existing opaque types are already tracked by changes
1404        // to the `var_values`.
1405        let opaque_types = self
1406            .delegate
1407            .clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries);
1408
1409        ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
1410    }
1411}
1412
1413/// Eagerly replace aliases with inference variables, emitting `AliasRelate`
1414/// goals, used when adding goals to the `EvalCtxt`. We compute the
1415/// `AliasRelate` goals before evaluating the actual goal to get all the
1416/// constraints we can.
1417///
1418/// This is a performance optimization to more eagerly detect cycles during trait
1419/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
1420///
1421/// The emitted goals get evaluated in the context of the parent goal; by
1422/// replacing aliases in nested goals we essentially pull the normalization out of
1423/// the nested goal. We want to treat the goal as if the normalization still happens
1424/// inside of the nested goal by inheriting the `step_kind` of the nested goal and
1425/// storing it in the `GoalSource` of the emitted `AliasRelate` goals.
1426/// This is necessary for tests/ui/sized/coinductive-1.rs to compile.
1427struct ReplaceAliasWithInfer<'me, 'a, D, I>
1428where
1429    D: SolverDelegate<Interner = I>,
1430    I: Interner,
1431{
1432    ecx: &'me mut EvalCtxt<'a, D>,
1433    param_env: I::ParamEnv,
1434    normalization_goal_source: GoalSource,
1435    cache: HashMap<I::Ty, I::Ty>,
1436}
1437
1438impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I>
1439where
1440    D: SolverDelegate<Interner = I>,
1441    I: Interner,
1442{
1443    fn new(
1444        ecx: &'me mut EvalCtxt<'a, D>,
1445        for_goal_source: GoalSource,
1446        param_env: I::ParamEnv,
1447    ) -> Self {
1448        let step_kind = ecx.step_kind_for_source(for_goal_source);
1449        ReplaceAliasWithInfer {
1450            ecx,
1451            param_env,
1452            normalization_goal_source: GoalSource::NormalizeGoal(step_kind),
1453            cache: Default::default(),
1454        }
1455    }
1456}
1457
1458impl<D, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, D, I>
1459where
1460    D: SolverDelegate<Interner = I>,
1461    I: Interner,
1462{
1463    fn cx(&self) -> I {
1464        self.ecx.cx()
1465    }
1466
1467    fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
1468        match ty.kind() {
1469            ty::Alias(..) if !ty.has_escaping_bound_vars() => {
1470                let infer_ty = self.ecx.next_ty_infer();
1471                let normalizes_to = ty::PredicateKind::AliasRelate(
1472                    ty.into(),
1473                    infer_ty.into(),
1474                    ty::AliasRelationDirection::Equate,
1475                );
1476                self.ecx.add_goal(
1477                    self.normalization_goal_source,
1478                    Goal::new(self.cx(), self.param_env, normalizes_to),
1479                );
1480                infer_ty
1481            }
1482            _ => {
1483                if !ty.has_aliases() {
1484                    ty
1485                } else if let Some(&entry) = self.cache.get(&ty) {
1486                    return entry;
1487                } else {
1488                    let res = ty.super_fold_with(self);
1489                    assert!(self.cache.insert(ty, res).is_none());
1490                    res
1491                }
1492            }
1493        }
1494    }
1495
1496    fn fold_const(&mut self, ct: I::Const) -> I::Const {
1497        match ct.kind() {
1498            ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
1499                let infer_ct = self.ecx.next_const_infer();
1500                let normalizes_to = ty::PredicateKind::AliasRelate(
1501                    ct.into(),
1502                    infer_ct.into(),
1503                    ty::AliasRelationDirection::Equate,
1504                );
1505                self.ecx.add_goal(
1506                    self.normalization_goal_source,
1507                    Goal::new(self.cx(), self.param_env, normalizes_to),
1508                );
1509                infer_ct
1510            }
1511            _ => ct.super_fold_with(self),
1512        }
1513    }
1514
1515    fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate {
1516        if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
1517    }
1518}
1519
1520/// Do not call this directly, use the `tcx` query instead.
1521pub fn evaluate_root_goal_for_proof_tree_raw_provider<
1522    D: SolverDelegate<Interner = I>,
1523    I: Interner,
1524>(
1525    cx: I,
1526    canonical_goal: CanonicalInput<I>,
1527) -> (QueryResult<I>, I::Probe) {
1528    let mut inspect = inspect::ProofTreeBuilder::new();
1529    let canonical_result = SearchGraph::<D>::evaluate_root_goal_for_proof_tree(
1530        cx,
1531        cx.recursion_limit(),
1532        canonical_goal,
1533        &mut inspect,
1534    );
1535    let final_revision = inspect.unwrap();
1536    (canonical_result, cx.mk_probe(final_revision))
1537}
1538
1539/// Evaluate a goal to build a proof tree.
1540///
1541/// This is a copy of [EvalCtxt::evaluate_goal_raw] which avoids relying on the
1542/// [EvalCtxt] and uses a separate cache.
1543pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>, I: Interner>(
1544    delegate: &D,
1545    goal: Goal<I, I::Predicate>,
1546    origin_span: I::Span,
1547) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
1548    let opaque_types = delegate.clone_opaque_types_lookup_table();
1549    let (goal, opaque_types) = eager_resolve_vars(delegate, (goal, opaque_types));
1550
1551    let (orig_values, canonical_goal) = canonicalize_goal(delegate, goal, &opaque_types);
1552
1553    let (canonical_result, final_revision) =
1554        delegate.cx().evaluate_root_goal_for_proof_tree_raw(canonical_goal);
1555
1556    let proof_tree = inspect::GoalEvaluation {
1557        uncanonicalized_goal: goal,
1558        orig_values,
1559        final_revision,
1560        result: canonical_result,
1561    };
1562
1563    let response = match canonical_result {
1564        Err(e) => return (Err(e), proof_tree),
1565        Ok(response) => response,
1566    };
1567
1568    let (normalization_nested_goals, _certainty) = instantiate_and_apply_query_response(
1569        delegate,
1570        goal.param_env,
1571        &proof_tree.orig_values,
1572        response,
1573        origin_span,
1574    );
1575
1576    (Ok(normalization_nested_goals), proof_tree)
1577}