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            // These goal sources are likely unproductive and can be changed to
301            // `PathKind::Inductive`. Keeping them as unknown until we're confident
302            // about this and have an example where it is necessary.
303            GoalSource::AliasBoundConstCondition | GoalSource::AliasWellFormed => PathKind::Unknown,
304        }
305    }
306
307    /// Creates a root evaluation context and search graph. This should only be
308    /// used from outside of any evaluation, and other methods should be preferred
309    /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]).
310    pub(super) fn enter_root<R>(
311        delegate: &D,
312        root_depth: usize,
313        origin_span: I::Span,
314        f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
315    ) -> R {
316        let mut search_graph = SearchGraph::new(root_depth);
317
318        let mut ecx = EvalCtxt {
319            delegate,
320            search_graph: &mut search_graph,
321            nested_goals: Default::default(),
322            inspect: inspect::EvaluationStepBuilder::new_noop(),
323
324            // Only relevant when canonicalizing the response,
325            // which we don't do within this evaluation context.
326            max_input_universe: ty::UniverseIndex::ROOT,
327            initial_opaque_types_storage_num_entries: Default::default(),
328            variables: Default::default(),
329            var_values: CanonicalVarValues::dummy(),
330            current_goal_kind: CurrentGoalKind::Misc,
331            origin_span,
332            tainted: Ok(()),
333        };
334        let result = f(&mut ecx);
335        assert!(
336            ecx.nested_goals.is_empty(),
337            "root `EvalCtxt` should not have any goals added to it"
338        );
339        assert!(search_graph.is_empty());
340        result
341    }
342
343    /// Creates a nested evaluation context that shares the same search graph as the
344    /// one passed in. This is suitable for evaluation, granted that the search graph
345    /// has had the nested goal recorded on its stack. This method only be used by
346    /// `search_graph::Delegate::compute_goal`.
347    ///
348    /// This function takes care of setting up the inference context, setting the anchor,
349    /// and registering opaques from the canonicalized input.
350    pub(super) fn enter_canonical<R>(
351        cx: I,
352        search_graph: &'a mut SearchGraph<D>,
353        canonical_input: CanonicalInput<I>,
354        proof_tree_builder: &mut inspect::ProofTreeBuilder<D>,
355        f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
356    ) -> R {
357        let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input);
358        for (key, ty) in input.predefined_opaques_in_body.iter() {
359            let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy());
360            // It may be possible that two entries in the opaque type storage end up
361            // with the same key after resolving contained inference variables.
362            //
363            // We could put them in the duplicate list but don't have to. The opaques we
364            // encounter here are already tracked in the caller, so there's no need to
365            // also store them here. We'd take them out when computing the query response
366            // and then discard them, as they're already present in the input.
367            //
368            // Ideally we'd drop duplicate opaque type definitions when computing
369            // the canonical input. This is more annoying to implement and may cause a
370            // perf regression, so we do it inside of the query for now.
371            if let Some(prev) = prev {
372                debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
373            }
374        }
375
376        let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries();
377        let mut ecx = EvalCtxt {
378            delegate,
379            variables: canonical_input.canonical.variables,
380            var_values,
381            current_goal_kind: CurrentGoalKind::from_query_input(cx, input),
382            max_input_universe: canonical_input.canonical.max_universe,
383            initial_opaque_types_storage_num_entries,
384            search_graph,
385            nested_goals: Default::default(),
386            origin_span: I::Span::dummy(),
387            tainted: Ok(()),
388            inspect: proof_tree_builder.new_evaluation_step(var_values),
389        };
390
391        let result = f(&mut ecx, input.goal);
392        ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe);
393        proof_tree_builder.finish_evaluation_step(ecx.inspect);
394
395        // When creating a query response we clone the opaque type constraints
396        // instead of taking them. This would cause an ICE here, since we have
397        // assertions against dropping an `InferCtxt` without taking opaques.
398        // FIXME: Once we remove support for the old impl we can remove this.
399        // FIXME: Could we make `build_with_canonical` into `enter_with_canonical` and call this at the end?
400        delegate.reset_opaque_types();
401
402        result
403    }
404
405    pub(super) fn ignore_candidate_head_usages(&mut self, usages: CandidateHeadUsages) {
406        self.search_graph.ignore_candidate_head_usages(usages);
407    }
408
409    /// Recursively evaluates `goal`, returning whether any inference vars have
410    /// been constrained and the certainty of the result.
411    fn evaluate_goal(
412        &mut self,
413        source: GoalSource,
414        goal: Goal<I, I::Predicate>,
415        stalled_on: Option<GoalStalledOn<I>>,
416    ) -> Result<GoalEvaluation<I>, NoSolution> {
417        let (normalization_nested_goals, goal_evaluation) =
418            self.evaluate_goal_raw(source, goal, stalled_on)?;
419        assert!(normalization_nested_goals.is_empty());
420        Ok(goal_evaluation)
421    }
422
423    /// Recursively evaluates `goal`, returning the nested goals in case
424    /// the nested goal is a `NormalizesTo` goal.
425    ///
426    /// As all other goal kinds do not return any nested goals and
427    /// `NormalizesTo` is only used by `AliasRelate`, all other callsites
428    /// should use [`EvalCtxt::evaluate_goal`] which discards that empty
429    /// storage.
430    pub(super) fn evaluate_goal_raw(
431        &mut self,
432        source: GoalSource,
433        goal: Goal<I, I::Predicate>,
434        stalled_on: Option<GoalStalledOn<I>>,
435    ) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
436        // If we have run this goal before, and it was stalled, check that any of the goal's
437        // args have changed. Otherwise, we don't need to re-run the goal because it'll remain
438        // stalled, since it'll canonicalize the same way and evaluation is pure.
439        if let Some(GoalStalledOn {
440            num_opaques,
441            ref stalled_vars,
442            ref sub_roots,
443            stalled_certainty,
444        }) = stalled_on
445            && !stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
446            && !sub_roots
447                .iter()
448                .any(|&vid| self.delegate.sub_unification_table_root_var(vid) != vid)
449            && !self.delegate.opaque_types_storage_num_entries().needs_reevaluation(num_opaques)
450        {
451            return Ok((
452                NestedNormalizationGoals::empty(),
453                GoalEvaluation {
454                    goal,
455                    certainty: stalled_certainty,
456                    has_changed: HasChanged::No,
457                    stalled_on,
458                },
459            ));
460        }
461
462        // We only care about one entry per `OpaqueTypeKey` here,
463        // so we only canonicalize the lookup table and ignore
464        // duplicate entries.
465        let opaque_types = self.delegate.clone_opaque_types_lookup_table();
466        let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
467
468        let (orig_values, canonical_goal) = canonicalize_goal(self.delegate, goal, &opaque_types);
469        let canonical_result = self.search_graph.evaluate_goal(
470            self.cx(),
471            canonical_goal,
472            self.step_kind_for_source(source),
473            &mut inspect::ProofTreeBuilder::new_noop(),
474        );
475        let response = match canonical_result {
476            Err(e) => return Err(e),
477            Ok(response) => response,
478        };
479
480        let has_changed =
481            if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
482
483        let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response(
484            self.delegate,
485            goal.param_env,
486            &orig_values,
487            response,
488            self.origin_span,
489        );
490
491        // FIXME: We previously had an assert here that checked that recomputing
492        // a goal after applying its constraints did not change its response.
493        //
494        // This assert was removed as it did not hold for goals constraining
495        // an inference variable to a recursive alias, e.g. in
496        // tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs.
497        //
498        // Once we have decided on how to handle trait-system-refactor-initiative#75,
499        // we should re-add an assert here.
500
501        let stalled_on = match certainty {
502            Certainty::Yes => None,
503            Certainty::Maybe { .. } => match has_changed {
504                // FIXME: We could recompute a *new* set of stalled variables by walking
505                // through the orig values, resolving, and computing the root vars of anything
506                // that is not resolved. Only when *these* have changed is it meaningful
507                // to recompute this goal.
508                HasChanged::Yes => None,
509                HasChanged::No => {
510                    let mut stalled_vars = orig_values;
511
512                    // Remove the unconstrained RHS arg, which is expected to have changed.
513                    if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
514                        let normalizes_to = normalizes_to.skip_binder();
515                        let rhs_arg: I::GenericArg = normalizes_to.term.into();
516                        let idx = stalled_vars
517                            .iter()
518                            .rposition(|arg| *arg == rhs_arg)
519                            .expect("expected unconstrained arg");
520                        stalled_vars.swap_remove(idx);
521                    }
522
523                    // Remove the canonicalized universal vars, since we only care about stalled existentials.
524                    let mut sub_roots = Vec::new();
525                    stalled_vars.retain(|arg| match arg.kind() {
526                        // Lifetimes can never stall goals.
527                        ty::GenericArgKind::Lifetime(_) => false,
528                        ty::GenericArgKind::Type(ty) => match ty.kind() {
529                            ty::Infer(ty::TyVar(vid)) => {
530                                sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
531                                true
532                            }
533                            ty::Infer(_) => true,
534                            ty::Param(_) | ty::Placeholder(_) => false,
535                            _ => unreachable!("unexpected orig_value: {ty:?}"),
536                        },
537                        ty::GenericArgKind::Const(ct) => match ct.kind() {
538                            ty::ConstKind::Infer(_) => true,
539                            ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => false,
540                            _ => unreachable!("unexpected orig_value: {ct:?}"),
541                        },
542                    });
543
544                    Some(GoalStalledOn {
545                        num_opaques: canonical_goal
546                            .canonical
547                            .value
548                            .predefined_opaques_in_body
549                            .len(),
550                        stalled_vars,
551                        sub_roots,
552                        stalled_certainty: certainty,
553                    })
554                }
555            },
556        };
557
558        Ok((
559            normalization_nested_goals,
560            GoalEvaluation { goal, certainty, has_changed, stalled_on },
561        ))
562    }
563
564    pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
565        let Goal { param_env, predicate } = goal;
566        let kind = predicate.kind();
567        self.enter_forall(kind, |ecx, kind| match kind {
568            ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
569                ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
570            }
571            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
572                ecx.compute_host_effect_goal(Goal { param_env, predicate })
573            }
574            ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
575                ecx.compute_projection_goal(Goal { param_env, predicate })
576            }
577            ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
578                ecx.compute_type_outlives_goal(Goal { param_env, predicate })
579            }
580            ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
581                ecx.compute_region_outlives_goal(Goal { param_env, predicate })
582            }
583            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
584                ecx.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
585            }
586            ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
587                ecx.compute_unstable_feature_goal(param_env, symbol)
588            }
589            ty::PredicateKind::Subtype(predicate) => {
590                ecx.compute_subtype_goal(Goal { param_env, predicate })
591            }
592            ty::PredicateKind::Coerce(predicate) => {
593                ecx.compute_coerce_goal(Goal { param_env, predicate })
594            }
595            ty::PredicateKind::DynCompatible(trait_def_id) => {
596                ecx.compute_dyn_compatible_goal(trait_def_id)
597            }
598            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
599                ecx.compute_well_formed_goal(Goal { param_env, predicate: term })
600            }
601            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
602                ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
603            }
604            ty::PredicateKind::ConstEquate(_, _) => {
605                panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
606            }
607            ty::PredicateKind::NormalizesTo(predicate) => {
608                ecx.compute_normalizes_to_goal(Goal { param_env, predicate })
609            }
610            ty::PredicateKind::AliasRelate(lhs, rhs, direction) => {
611                ecx.compute_alias_relate_goal(Goal { param_env, predicate: (lhs, rhs, direction) })
612            }
613            ty::PredicateKind::Ambiguous => {
614                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
615            }
616        })
617    }
618
619    // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
620    // the certainty of all the goals.
621    #[instrument(level = "trace", skip(self))]
622    pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
623        for _ in 0..FIXPOINT_STEP_LIMIT {
624            match self.evaluate_added_goals_step() {
625                Ok(None) => {}
626                Ok(Some(cert)) => return Ok(cert),
627                Err(NoSolution) => {
628                    self.tainted = Err(NoSolution);
629                    return Err(NoSolution);
630                }
631            }
632        }
633
634        debug!("try_evaluate_added_goals: encountered overflow");
635        Ok(Certainty::overflow(false))
636    }
637
638    /// Iterate over all added goals: returning `Ok(Some(_))` in case we can stop rerunning.
639    ///
640    /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
641    fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
642        let cx = self.cx();
643        // If this loop did not result in any progress, what's our final certainty.
644        let mut unchanged_certainty = Some(Certainty::Yes);
645        for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
646            if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
647                match certainty {
648                    Certainty::Yes => {}
649                    Certainty::Maybe { .. } => {
650                        self.nested_goals.push((source, goal, None));
651                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
652                    }
653                }
654                continue;
655            }
656
657            // We treat normalizes-to goals specially here. In each iteration we take the
658            // RHS of the projection, replace it with a fresh inference variable, and only
659            // after evaluating that goal do we equate the fresh inference variable with the
660            // actual RHS of the predicate.
661            //
662            // This is both to improve caching, and to avoid using the RHS of the
663            // projection predicate to influence the normalizes-to candidate we select.
664            //
665            // Forgetting to replace the RHS with a fresh inference variable when we evaluate
666            // this goal results in an ICE.
667            if let Some(pred) = goal.predicate.as_normalizes_to() {
668                // We should never encounter higher-ranked normalizes-to goals.
669                let pred = pred.no_bound_vars().unwrap();
670                // Replace the goal with an unconstrained infer var, so the
671                // RHS does not affect projection candidate assembly.
672                let unconstrained_rhs = self.next_term_infer_of_kind(pred.term);
673                let unconstrained_goal =
674                    goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
675
676                let (
677                    NestedNormalizationGoals(nested_goals),
678                    GoalEvaluation { goal, certainty, stalled_on, has_changed: _ },
679                ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on)?;
680                // Add the nested goals from normalization to our own nested goals.
681                trace!(?nested_goals);
682                self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None)));
683
684                // Finally, equate the goal's RHS with the unconstrained var.
685                //
686                // SUBTLE:
687                // We structurally relate aliases here. This is necessary
688                // as we otherwise emit a nested `AliasRelate` goal in case the
689                // returned term is a rigid alias, resulting in overflow.
690                //
691                // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
692                // start out as an unconstrained inference variable so any aliases get
693                // fully normalized when instantiating it.
694                //
695                // FIXME: Strictly speaking this may be incomplete if the normalized-to
696                // type contains an ambiguous alias referencing bound regions. We should
697                // consider changing this to only use "shallow structural equality".
698                self.eq_structurally_relating_aliases(
699                    goal.param_env,
700                    pred.term,
701                    unconstrained_rhs,
702                )?;
703
704                // We only look at the `projection_ty` part here rather than
705                // looking at the "has changed" return from evaluate_goal,
706                // because we expect the `unconstrained_rhs` part of the predicate
707                // to have changed -- that means we actually normalized successfully!
708                // FIXME: Do we need to eagerly resolve here? Or should we check
709                // if the cache key has any changed vars?
710                let with_resolved_vars = self.resolve_vars_if_possible(goal);
711                if pred.alias
712                    != with_resolved_vars
713                        .predicate
714                        .as_normalizes_to()
715                        .unwrap()
716                        .no_bound_vars()
717                        .unwrap()
718                        .alias
719                {
720                    unchanged_certainty = None;
721                }
722
723                match certainty {
724                    Certainty::Yes => {}
725                    Certainty::Maybe { .. } => {
726                        self.nested_goals.push((source, with_resolved_vars, stalled_on));
727                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
728                    }
729                }
730            } else {
731                let GoalEvaluation { goal, certainty, has_changed, stalled_on } =
732                    self.evaluate_goal(source, goal, stalled_on)?;
733                if has_changed == HasChanged::Yes {
734                    unchanged_certainty = None;
735                }
736
737                match certainty {
738                    Certainty::Yes => {}
739                    Certainty::Maybe { .. } => {
740                        self.nested_goals.push((source, goal, stalled_on));
741                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
742                    }
743                }
744            }
745        }
746
747        Ok(unchanged_certainty)
748    }
749
750    /// Record impl args in the proof tree for later access by `InspectCandidate`.
751    pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs) {
752        self.inspect.record_impl_args(self.delegate, self.max_input_universe, impl_args)
753    }
754
755    pub(super) fn cx(&self) -> I {
756        self.delegate.cx()
757    }
758
759    #[instrument(level = "debug", skip(self))]
760    pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
761        goal.predicate =
762            goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
763        self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
764        self.nested_goals.push((source, goal, None));
765    }
766
767    #[instrument(level = "trace", skip(self, goals))]
768    pub(super) fn add_goals(
769        &mut self,
770        source: GoalSource,
771        goals: impl IntoIterator<Item = Goal<I, I::Predicate>>,
772    ) {
773        for goal in goals {
774            self.add_goal(source, goal);
775        }
776    }
777
778    pub(super) fn next_region_var(&mut self) -> I::Region {
779        let region = self.delegate.next_region_infer();
780        self.inspect.add_var_value(region);
781        region
782    }
783
784    pub(super) fn next_ty_infer(&mut self) -> I::Ty {
785        let ty = self.delegate.next_ty_infer();
786        self.inspect.add_var_value(ty);
787        ty
788    }
789
790    pub(super) fn next_const_infer(&mut self) -> I::Const {
791        let ct = self.delegate.next_const_infer();
792        self.inspect.add_var_value(ct);
793        ct
794    }
795
796    /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
797    /// If `kind` is an integer inference variable this will still return a ty infer var.
798    pub(super) fn next_term_infer_of_kind(&mut self, term: I::Term) -> I::Term {
799        match term.kind() {
800            ty::TermKind::Ty(_) => self.next_ty_infer().into(),
801            ty::TermKind::Const(_) => self.next_const_infer().into(),
802        }
803    }
804
805    /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
806    ///
807    /// This is the case if the `term` does not occur in any other part of the predicate
808    /// and is able to name all other placeholder and inference variables.
809    #[instrument(level = "trace", skip(self), ret)]
810    pub(super) fn term_is_fully_unconstrained(&self, goal: Goal<I, ty::NormalizesTo<I>>) -> bool {
811        let universe_of_term = match goal.predicate.term.kind() {
812            ty::TermKind::Ty(ty) => {
813                if let ty::Infer(ty::TyVar(vid)) = ty.kind() {
814                    self.delegate.universe_of_ty(vid).unwrap()
815                } else {
816                    return false;
817                }
818            }
819            ty::TermKind::Const(ct) => {
820                if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
821                    self.delegate.universe_of_ct(vid).unwrap()
822                } else {
823                    return false;
824                }
825            }
826        };
827
828        struct ContainsTermOrNotNameable<'a, D: SolverDelegate<Interner = I>, I: Interner> {
829            term: I::Term,
830            universe_of_term: ty::UniverseIndex,
831            delegate: &'a D,
832            cache: HashSet<I::Ty>,
833        }
834
835        impl<D: SolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, D, I> {
836            fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
837                if self.universe_of_term.can_name(universe) {
838                    ControlFlow::Continue(())
839                } else {
840                    ControlFlow::Break(())
841                }
842            }
843        }
844
845        impl<D: SolverDelegate<Interner = I>, I: Interner> TypeVisitor<I>
846            for ContainsTermOrNotNameable<'_, D, I>
847        {
848            type Result = ControlFlow<()>;
849            fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
850                if self.cache.contains(&t) {
851                    return ControlFlow::Continue(());
852                }
853
854                match t.kind() {
855                    ty::Infer(ty::TyVar(vid)) => {
856                        if let ty::TermKind::Ty(term) = self.term.kind()
857                            && let ty::Infer(ty::TyVar(term_vid)) = term.kind()
858                            && self.delegate.root_ty_var(vid) == self.delegate.root_ty_var(term_vid)
859                        {
860                            return ControlFlow::Break(());
861                        }
862
863                        self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?;
864                    }
865                    ty::Placeholder(p) => self.check_nameable(p.universe())?,
866                    _ => {
867                        if t.has_non_region_infer() || t.has_placeholders() {
868                            t.super_visit_with(self)?
869                        }
870                    }
871                }
872
873                assert!(self.cache.insert(t));
874                ControlFlow::Continue(())
875            }
876
877            fn visit_const(&mut self, c: I::Const) -> Self::Result {
878                match c.kind() {
879                    ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
880                        if let ty::TermKind::Const(term) = self.term.kind()
881                            && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
882                            && self.delegate.root_const_var(vid)
883                                == self.delegate.root_const_var(term_vid)
884                        {
885                            return ControlFlow::Break(());
886                        }
887
888                        self.check_nameable(self.delegate.universe_of_ct(vid).unwrap())
889                    }
890                    ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()),
891                    _ => {
892                        if c.has_non_region_infer() || c.has_placeholders() {
893                            c.super_visit_with(self)
894                        } else {
895                            ControlFlow::Continue(())
896                        }
897                    }
898                }
899            }
900
901            fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
902                if p.has_non_region_infer() || p.has_placeholders() {
903                    p.super_visit_with(self)
904                } else {
905                    ControlFlow::Continue(())
906                }
907            }
908
909            fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
910                if c.has_non_region_infer() || c.has_placeholders() {
911                    c.super_visit_with(self)
912                } else {
913                    ControlFlow::Continue(())
914                }
915            }
916        }
917
918        let mut visitor = ContainsTermOrNotNameable {
919            delegate: self.delegate,
920            universe_of_term,
921            term: goal.predicate.term,
922            cache: Default::default(),
923        };
924        goal.predicate.alias.visit_with(&mut visitor).is_continue()
925            && goal.param_env.visit_with(&mut visitor).is_continue()
926    }
927
928    pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
929        self.delegate.sub_unify_ty_vids_raw(a, b)
930    }
931
932    #[instrument(level = "trace", skip(self, param_env), ret)]
933    pub(super) fn eq<T: Relate<I>>(
934        &mut self,
935        param_env: I::ParamEnv,
936        lhs: T,
937        rhs: T,
938    ) -> Result<(), NoSolution> {
939        self.relate(param_env, lhs, ty::Variance::Invariant, rhs)
940    }
941
942    /// This should be used when relating a rigid alias with another type.
943    ///
944    /// Normally we emit a nested `AliasRelate` when equating an inference
945    /// variable and an alias. This causes us to instead constrain the inference
946    /// variable to the alias without emitting a nested alias relate goals.
947    #[instrument(level = "trace", skip(self, param_env), ret)]
948    pub(super) fn relate_rigid_alias_non_alias(
949        &mut self,
950        param_env: I::ParamEnv,
951        alias: ty::AliasTerm<I>,
952        variance: ty::Variance,
953        term: I::Term,
954    ) -> Result<(), NoSolution> {
955        // NOTE: this check is purely an optimization, the structural eq would
956        // always fail if the term is not an inference variable.
957        if term.is_infer() {
958            let cx = self.cx();
959            // We need to relate `alias` to `term` treating only the outermost
960            // constructor as rigid, relating any contained generic arguments as
961            // normal. We do this by first structurally equating the `term`
962            // with the alias constructor instantiated with unconstrained infer vars,
963            // and then relate this with the whole `alias`.
964            //
965            // Alternatively we could modify `Equate` for this case by adding another
966            // variant to `StructurallyRelateAliases`.
967            let identity_args = self.fresh_args_for_item(alias.def_id);
968            let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
969            let ctor_term = rigid_ctor.to_term(cx);
970            let obligations = self.delegate.eq_structurally_relating_aliases(
971                param_env,
972                term,
973                ctor_term,
974                self.origin_span,
975            )?;
976            debug_assert!(obligations.is_empty());
977            self.relate(param_env, alias, variance, rigid_ctor)
978        } else {
979            Err(NoSolution)
980        }
981    }
982
983    /// This should only be used when we're either instantiating a previously
984    /// unconstrained "return value" or when we're sure that all aliases in
985    /// the types are rigid.
986    #[instrument(level = "trace", skip(self, param_env), ret)]
987    pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
988        &mut self,
989        param_env: I::ParamEnv,
990        lhs: T,
991        rhs: T,
992    ) -> Result<(), NoSolution> {
993        let result = self.delegate.eq_structurally_relating_aliases(
994            param_env,
995            lhs,
996            rhs,
997            self.origin_span,
998        )?;
999        assert_eq!(result, vec![]);
1000        Ok(())
1001    }
1002
1003    #[instrument(level = "trace", skip(self, param_env), ret)]
1004    pub(super) fn sub<T: Relate<I>>(
1005        &mut self,
1006        param_env: I::ParamEnv,
1007        sub: T,
1008        sup: T,
1009    ) -> Result<(), NoSolution> {
1010        self.relate(param_env, sub, ty::Variance::Covariant, sup)
1011    }
1012
1013    #[instrument(level = "trace", skip(self, param_env), ret)]
1014    pub(super) fn relate<T: Relate<I>>(
1015        &mut self,
1016        param_env: I::ParamEnv,
1017        lhs: T,
1018        variance: ty::Variance,
1019        rhs: T,
1020    ) -> Result<(), NoSolution> {
1021        let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
1022        for &goal in goals.iter() {
1023            let source = match goal.predicate.kind().skip_binder() {
1024                ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
1025                    GoalSource::TypeRelating
1026                }
1027                // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive?
1028                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc,
1029                p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
1030            };
1031            self.add_goal(source, goal);
1032        }
1033        Ok(())
1034    }
1035
1036    /// Equates two values returning the nested goals without adding them
1037    /// to the nested goals of the `EvalCtxt`.
1038    ///
1039    /// If possible, try using `eq` instead which automatically handles nested
1040    /// goals correctly.
1041    #[instrument(level = "trace", skip(self, param_env), ret)]
1042    pub(super) fn eq_and_get_goals<T: Relate<I>>(
1043        &self,
1044        param_env: I::ParamEnv,
1045        lhs: T,
1046        rhs: T,
1047    ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
1048        Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
1049    }
1050
1051    pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
1052        &self,
1053        value: ty::Binder<I, T>,
1054    ) -> T {
1055        self.delegate.instantiate_binder_with_infer(value)
1056    }
1057
1058    /// `enter_forall`, but takes `&mut self` and passes it back through the
1059    /// callback since it can't be aliased during the call.
1060    pub(super) fn enter_forall<T: TypeFoldable<I>, U>(
1061        &mut self,
1062        value: ty::Binder<I, T>,
1063        f: impl FnOnce(&mut Self, T) -> U,
1064    ) -> U {
1065        self.delegate.enter_forall(value, |value| f(self, value))
1066    }
1067
1068    pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
1069    where
1070        T: TypeFoldable<I>,
1071    {
1072        self.delegate.resolve_vars_if_possible(value)
1073    }
1074
1075    pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty {
1076        self.delegate.shallow_resolve(ty)
1077    }
1078
1079    pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region {
1080        if let ty::ReVar(vid) = r.kind() {
1081            self.delegate.opportunistic_resolve_lt_var(vid)
1082        } else {
1083            r
1084        }
1085    }
1086
1087    pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
1088        let args = self.delegate.fresh_args_for_item(def_id);
1089        for arg in args.iter() {
1090            self.inspect.add_var_value(arg);
1091        }
1092        args
1093    }
1094
1095    pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
1096        self.delegate.register_ty_outlives(ty, lt, self.origin_span);
1097    }
1098
1099    pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
1100        // `'a: 'b` ==> `'b <= 'a`
1101        self.delegate.sub_regions(b, a, self.origin_span);
1102    }
1103
1104    /// Computes the list of goals required for `arg` to be well-formed
1105    pub(super) fn well_formed_goals(
1106        &self,
1107        param_env: I::ParamEnv,
1108        term: I::Term,
1109    ) -> Option<Vec<Goal<I, I::Predicate>>> {
1110        self.delegate.well_formed_goals(param_env, term)
1111    }
1112
1113    pub(super) fn trait_ref_is_knowable(
1114        &mut self,
1115        param_env: I::ParamEnv,
1116        trait_ref: ty::TraitRef<I>,
1117    ) -> Result<bool, NoSolution> {
1118        let delegate = self.delegate;
1119        let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty);
1120        coherence::trait_ref_is_knowable(&**delegate, trait_ref, lazily_normalize_ty)
1121            .map(|is_knowable| is_knowable.is_ok())
1122    }
1123
1124    pub(super) fn fetch_eligible_assoc_item(
1125        &self,
1126        goal_trait_ref: ty::TraitRef<I>,
1127        trait_assoc_def_id: I::DefId,
1128        impl_def_id: I::ImplId,
1129    ) -> Result<Option<I::DefId>, I::ErrorGuaranteed> {
1130        self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
1131    }
1132
1133    #[instrument(level = "debug", skip(self), ret)]
1134    pub(super) fn register_hidden_type_in_storage(
1135        &mut self,
1136        opaque_type_key: ty::OpaqueTypeKey<I>,
1137        hidden_ty: I::Ty,
1138    ) -> Option<I::Ty> {
1139        self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span)
1140    }
1141
1142    pub(super) fn add_item_bounds_for_hidden_type(
1143        &mut self,
1144        opaque_def_id: I::DefId,
1145        opaque_args: I::GenericArgs,
1146        param_env: I::ParamEnv,
1147        hidden_ty: I::Ty,
1148    ) {
1149        let mut goals = Vec::new();
1150        self.delegate.add_item_bounds_for_hidden_type(
1151            opaque_def_id,
1152            opaque_args,
1153            param_env,
1154            hidden_ty,
1155            &mut goals,
1156        );
1157        self.add_goals(GoalSource::AliasWellFormed, goals);
1158    }
1159
1160    // Try to evaluate a const, or return `None` if the const is too generic.
1161    // This doesn't mean the const isn't evaluatable, though, and should be treated
1162    // as an ambiguity rather than no-solution.
1163    pub(super) fn evaluate_const(
1164        &self,
1165        param_env: I::ParamEnv,
1166        uv: ty::UnevaluatedConst<I>,
1167    ) -> Option<I::Const> {
1168        self.delegate.evaluate_const(param_env, uv)
1169    }
1170
1171    pub(super) fn is_transmutable(
1172        &mut self,
1173        dst: I::Ty,
1174        src: I::Ty,
1175        assume: I::Const,
1176    ) -> Result<Certainty, NoSolution> {
1177        self.delegate.is_transmutable(dst, src, assume)
1178    }
1179
1180    pub(super) fn replace_bound_vars<T: TypeFoldable<I>>(
1181        &self,
1182        t: T,
1183        universes: &mut Vec<Option<ty::UniverseIndex>>,
1184    ) -> T {
1185        BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, t).0
1186    }
1187
1188    pub(super) fn may_use_unstable_feature(
1189        &self,
1190        param_env: I::ParamEnv,
1191        symbol: I::Symbol,
1192    ) -> bool {
1193        may_use_unstable_feature(&**self.delegate, param_env, symbol)
1194    }
1195
1196    pub(crate) fn opaques_with_sub_unified_hidden_type(
1197        &self,
1198        self_ty: I::Ty,
1199    ) -> Vec<ty::AliasTy<I>> {
1200        if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() {
1201            self.delegate.opaques_with_sub_unified_hidden_type(vid)
1202        } else {
1203            vec![]
1204        }
1205    }
1206
1207    /// To return the constraints of a canonical query to the caller, we canonicalize:
1208    ///
1209    /// - `var_values`: a map from bound variables in the canonical goal to
1210    ///   the values inferred while solving the instantiated goal.
1211    /// - `external_constraints`: additional constraints which aren't expressible
1212    ///   using simple unification of inference variables.
1213    ///
1214    /// This takes the `shallow_certainty` which represents whether we're confident
1215    /// that the final result of the current goal only depends on the nested goals.
1216    ///
1217    /// In case this is `Certainty::Maybe`, there may still be additional nested goals
1218    /// or inference constraints required for this candidate to be hold. The candidate
1219    /// always requires all already added constraints and nested goals.
1220    #[instrument(level = "trace", skip(self), ret)]
1221    pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
1222        &mut self,
1223        shallow_certainty: Certainty,
1224    ) -> QueryResult<I> {
1225        self.inspect.make_canonical_response(shallow_certainty);
1226
1227        let goals_certainty = self.try_evaluate_added_goals()?;
1228        assert_eq!(
1229            self.tainted,
1230            Ok(()),
1231            "EvalCtxt is tainted -- nested goals may have been dropped in a \
1232            previous call to `try_evaluate_added_goals!`"
1233        );
1234
1235        // We only check for leaks from universes which were entered inside
1236        // of the query.
1237        self.delegate.leak_check(self.max_input_universe).map_err(|NoSolution| {
1238            trace!("failed the leak check");
1239            NoSolution
1240        })?;
1241
1242        let (certainty, normalization_nested_goals) =
1243            match (self.current_goal_kind, shallow_certainty) {
1244                // When normalizing, we've replaced the expected term with an unconstrained
1245                // inference variable. This means that we dropped information which could
1246                // have been important. We handle this by instead returning the nested goals
1247                // to the caller, where they are then handled. We only do so if we do not
1248                // need to recompute the `NormalizesTo` goal afterwards to avoid repeatedly
1249                // uplifting its nested goals. This is the case if the `shallow_certainty` is
1250                // `Certainty::Yes`.
1251                (CurrentGoalKind::NormalizesTo, Certainty::Yes) => {
1252                    let goals = std::mem::take(&mut self.nested_goals);
1253                    // As we return all ambiguous nested goals, we can ignore the certainty
1254                    // returned by `self.try_evaluate_added_goals()`.
1255                    if goals.is_empty() {
1256                        assert!(matches!(goals_certainty, Certainty::Yes));
1257                    }
1258                    (
1259                        Certainty::Yes,
1260                        NestedNormalizationGoals(
1261                            goals.into_iter().map(|(s, g, _)| (s, g)).collect(),
1262                        ),
1263                    )
1264                }
1265                _ => {
1266                    let certainty = shallow_certainty.and(goals_certainty);
1267                    (certainty, NestedNormalizationGoals::empty())
1268                }
1269            };
1270
1271        if let Certainty::Maybe {
1272            cause: cause @ MaybeCause::Overflow { keep_constraints: false, .. },
1273            opaque_types_jank,
1274        } = certainty
1275        {
1276            // If we have overflow, it's probable that we're substituting a type
1277            // into itself infinitely and any partial substitutions in the query
1278            // response are probably not useful anyways, so just return an empty
1279            // query response.
1280            //
1281            // This may prevent us from potentially useful inference, e.g.
1282            // 2 candidates, one ambiguous and one overflow, which both
1283            // have the same inference constraints.
1284            //
1285            // Changing this to retain some constraints in the future
1286            // won't be a breaking change, so this is good enough for now.
1287            return Ok(self.make_ambiguous_response_no_constraints(cause, opaque_types_jank));
1288        }
1289
1290        let external_constraints =
1291            self.compute_external_query_constraints(certainty, normalization_nested_goals);
1292        let (var_values, mut external_constraints) =
1293            eager_resolve_vars(self.delegate, (self.var_values, external_constraints));
1294
1295        // Remove any trivial or duplicated region constraints once we've resolved regions
1296        let mut unique = HashSet::default();
1297        external_constraints.region_constraints.retain(|outlives| {
1298            outlives.0.as_region().is_none_or(|re| re != outlives.1) && unique.insert(*outlives)
1299        });
1300
1301        let canonical = canonicalize_response(
1302            self.delegate,
1303            self.max_input_universe,
1304            Response {
1305                var_values,
1306                certainty,
1307                external_constraints: self.cx().mk_external_constraints(external_constraints),
1308            },
1309        );
1310
1311        Ok(canonical)
1312    }
1313
1314    /// Constructs a totally unconstrained, ambiguous response to a goal.
1315    ///
1316    /// Take care when using this, since often it's useful to respond with
1317    /// ambiguity but return constrained variables to guide inference.
1318    pub(in crate::solve) fn make_ambiguous_response_no_constraints(
1319        &self,
1320        cause: MaybeCause,
1321        opaque_types_jank: OpaqueTypesJank,
1322    ) -> CanonicalResponse<I> {
1323        response_no_constraints_raw(
1324            self.cx(),
1325            self.max_input_universe,
1326            self.variables,
1327            Certainty::Maybe { cause, opaque_types_jank },
1328        )
1329    }
1330
1331    /// Computes the region constraints and *new* opaque types registered when
1332    /// proving a goal.
1333    ///
1334    /// If an opaque was already constrained before proving this goal, then the
1335    /// external constraints do not need to record that opaque, since if it is
1336    /// further constrained by inference, that will be passed back in the var
1337    /// values.
1338    #[instrument(level = "trace", skip(self), ret)]
1339    fn compute_external_query_constraints(
1340        &self,
1341        certainty: Certainty,
1342        normalization_nested_goals: NestedNormalizationGoals<I>,
1343    ) -> ExternalConstraintsData<I> {
1344        // We only return region constraints once the certainty is `Yes`. This
1345        // is necessary as we may drop nested goals on ambiguity, which may result
1346        // in unconstrained inference variables in the region constraints. It also
1347        // prevents us from emitting duplicate region constraints, avoiding some
1348        // unnecessary work. This slightly weakens the leak check in case it uses
1349        // region constraints from an ambiguous nested goal. This is tested in both
1350        // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and
1351        // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`.
1352        let region_constraints = if certainty == Certainty::Yes {
1353            self.delegate.make_deduplicated_outlives_constraints()
1354        } else {
1355            Default::default()
1356        };
1357
1358        // We only return *newly defined* opaque types from canonical queries.
1359        //
1360        // Constraints for any existing opaque types are already tracked by changes
1361        // to the `var_values`.
1362        let opaque_types = self
1363            .delegate
1364            .clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries);
1365
1366        ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
1367    }
1368}
1369
1370/// Eagerly replace aliases with inference variables, emitting `AliasRelate`
1371/// goals, used when adding goals to the `EvalCtxt`. We compute the
1372/// `AliasRelate` goals before evaluating the actual goal to get all the
1373/// constraints we can.
1374///
1375/// This is a performance optimization to more eagerly detect cycles during trait
1376/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
1377///
1378/// The emitted goals get evaluated in the context of the parent goal; by
1379/// replacing aliases in nested goals we essentially pull the normalization out of
1380/// the nested goal. We want to treat the goal as if the normalization still happens
1381/// inside of the nested goal by inheriting the `step_kind` of the nested goal and
1382/// storing it in the `GoalSource` of the emitted `AliasRelate` goals.
1383/// This is necessary for tests/ui/sized/coinductive-1.rs to compile.
1384struct ReplaceAliasWithInfer<'me, 'a, D, I>
1385where
1386    D: SolverDelegate<Interner = I>,
1387    I: Interner,
1388{
1389    ecx: &'me mut EvalCtxt<'a, D>,
1390    param_env: I::ParamEnv,
1391    normalization_goal_source: GoalSource,
1392    cache: HashMap<I::Ty, I::Ty>,
1393}
1394
1395impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I>
1396where
1397    D: SolverDelegate<Interner = I>,
1398    I: Interner,
1399{
1400    fn new(
1401        ecx: &'me mut EvalCtxt<'a, D>,
1402        for_goal_source: GoalSource,
1403        param_env: I::ParamEnv,
1404    ) -> Self {
1405        let step_kind = ecx.step_kind_for_source(for_goal_source);
1406        ReplaceAliasWithInfer {
1407            ecx,
1408            param_env,
1409            normalization_goal_source: GoalSource::NormalizeGoal(step_kind),
1410            cache: Default::default(),
1411        }
1412    }
1413}
1414
1415impl<D, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, D, I>
1416where
1417    D: SolverDelegate<Interner = I>,
1418    I: Interner,
1419{
1420    fn cx(&self) -> I {
1421        self.ecx.cx()
1422    }
1423
1424    fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
1425        match ty.kind() {
1426            ty::Alias(..) if !ty.has_escaping_bound_vars() => {
1427                let infer_ty = self.ecx.next_ty_infer();
1428                let normalizes_to = ty::PredicateKind::AliasRelate(
1429                    ty.into(),
1430                    infer_ty.into(),
1431                    ty::AliasRelationDirection::Equate,
1432                );
1433                self.ecx.add_goal(
1434                    self.normalization_goal_source,
1435                    Goal::new(self.cx(), self.param_env, normalizes_to),
1436                );
1437                infer_ty
1438            }
1439            _ => {
1440                if !ty.has_aliases() {
1441                    ty
1442                } else if let Some(&entry) = self.cache.get(&ty) {
1443                    return entry;
1444                } else {
1445                    let res = ty.super_fold_with(self);
1446                    assert!(self.cache.insert(ty, res).is_none());
1447                    res
1448                }
1449            }
1450        }
1451    }
1452
1453    fn fold_const(&mut self, ct: I::Const) -> I::Const {
1454        match ct.kind() {
1455            ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
1456                let infer_ct = self.ecx.next_const_infer();
1457                let normalizes_to = ty::PredicateKind::AliasRelate(
1458                    ct.into(),
1459                    infer_ct.into(),
1460                    ty::AliasRelationDirection::Equate,
1461                );
1462                self.ecx.add_goal(
1463                    self.normalization_goal_source,
1464                    Goal::new(self.cx(), self.param_env, normalizes_to),
1465                );
1466                infer_ct
1467            }
1468            _ => ct.super_fold_with(self),
1469        }
1470    }
1471
1472    fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate {
1473        if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
1474    }
1475}
1476
1477/// Do not call this directly, use the `tcx` query instead.
1478pub fn evaluate_root_goal_for_proof_tree_raw_provider<
1479    D: SolverDelegate<Interner = I>,
1480    I: Interner,
1481>(
1482    cx: I,
1483    canonical_goal: CanonicalInput<I>,
1484) -> (QueryResult<I>, I::Probe) {
1485    let mut inspect = inspect::ProofTreeBuilder::new();
1486    let canonical_result = SearchGraph::<D>::evaluate_root_goal_for_proof_tree(
1487        cx,
1488        cx.recursion_limit(),
1489        canonical_goal,
1490        &mut inspect,
1491    );
1492    let final_revision = inspect.unwrap();
1493    (canonical_result, cx.mk_probe(final_revision))
1494}
1495
1496/// Evaluate a goal to build a proof tree.
1497///
1498/// This is a copy of [EvalCtxt::evaluate_goal_raw] which avoids relying on the
1499/// [EvalCtxt] and uses a separate cache.
1500pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>, I: Interner>(
1501    delegate: &D,
1502    goal: Goal<I, I::Predicate>,
1503    origin_span: I::Span,
1504) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
1505    let opaque_types = delegate.clone_opaque_types_lookup_table();
1506    let (goal, opaque_types) = eager_resolve_vars(delegate, (goal, opaque_types));
1507
1508    let (orig_values, canonical_goal) = canonicalize_goal(delegate, goal, &opaque_types);
1509
1510    let (canonical_result, final_revision) =
1511        delegate.cx().evaluate_root_goal_for_proof_tree_raw(canonical_goal);
1512
1513    let proof_tree = inspect::GoalEvaluation {
1514        uncanonicalized_goal: goal,
1515        orig_values,
1516        final_revision,
1517        result: canonical_result,
1518    };
1519
1520    let response = match canonical_result {
1521        Err(e) => return (Err(e), proof_tree),
1522        Ok(response) => response,
1523    };
1524
1525    let (normalization_nested_goals, _certainty) = instantiate_and_apply_query_response(
1526        delegate,
1527        goal.param_env,
1528        &proof_tree.orig_values,
1529        response,
1530        origin_span,
1531    );
1532
1533    (Ok(normalization_nested_goals), proof_tree)
1534}