Skip to main content

rustc_next_trait_solver/solve/
trait_goals.rs

1//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
2
3use rustc_type_ir::data_structures::IndexSet;
4use rustc_type_ir::fast_reject::DeepRejectCtxt;
5use rustc_type_ir::inherent::*;
6use rustc_type_ir::lang_items::SolverTraitLangItem;
7use rustc_type_ir::solve::{
8    AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, ExternalConstraintsData, MaybeInfo,
9    NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased,
10    RerunReason, RerunResultExt, SizedTraitKind,
11};
12use rustc_type_ir::{
13    self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability,
14    Region, TraitClause, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _,
15    elaborate,
16};
17use tracing::{debug, instrument, trace, warn};
18
19use crate::delegate::SolverDelegate;
20use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
21use crate::solve::assembly::{
22    self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
23};
24use crate::solve::inspect::ProbeKind;
25use crate::solve::{
26    BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
27    MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines,
28    has_only_region_constraints,
29};
30
31impl<D, I> assembly::GoalKind<D> for TraitClause<I>
32where
33    D: SolverDelegate<Interner = I>,
34    I: Interner,
35{
36    fn self_ty(self) -> I::Ty {
37        self.self_ty()
38    }
39
40    fn trait_ref(self, _: I) -> ty::TraitRef<I> {
41        self.trait_ref
42    }
43
44    fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
45        self.with_replaced_self_ty(cx, self_ty)
46    }
47
48    fn trait_def_id(self, _: I) -> I::TraitId {
49        self.def_id()
50    }
51
52    fn consider_additional_alias_assumptions(
53        _ecx: &mut EvalCtxt<'_, D>,
54        _goal: Goal<I, Self>,
55        _alias_ty: ty::AliasTy<I>,
56    ) -> Vec<Candidate<I>> {
57        ::alloc::vec::Vec::new()vec![]
58    }
59
60    fn consider_impl_candidate(
61        ecx: &mut EvalCtxt<'_, D>,
62        goal: Goal<I, TraitClause<I>>,
63        goal_trait_ref: TraitRef<I>,
64        impl_def_id: I::ImplId,
65        then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
66    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
67        let cx = ecx.cx();
68
69        let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
70        if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
71            .args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args)
72        {
73            return Err(NoSolution.into());
74        }
75
76        // For every `default impl`, there's always a non-default `impl` that will *also* apply.
77        // There's no reason to register a candidate for this impl, since it is *not* proof that
78        // the trait goal holds.
79        if cx.impl_is_default(impl_def_id) {
80            return Err(NoSolution.into());
81        }
82
83        match (cx.impl_polarity(impl_def_id), goal.predicate.polarity) {
84            // Impl matches polarity
85            (ty::ImplPolarity::Positive, ty::ClausePolarity::Positive)
86            | (ty::ImplPolarity::Negative, ty::ClausePolarity::Negative) => {}
87
88            // Impl doesn't match polarity
89            (ty::ImplPolarity::Positive, ty::ClausePolarity::Negative)
90            | (ty::ImplPolarity::Negative, ty::ClausePolarity::Positive) => {
91                return Err(NoSolution.into());
92            }
93        }
94
95        if ecx.typing_mode().is_reflection() && !cx.is_fully_generic_for_reflection(impl_def_id) {
96            return Err(NoSolution.into());
97        }
98
99        ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
100            let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
101            ecx.record_impl_args(impl_args);
102            let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
103
104            ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
105            let where_clause_bounds = cx
106                .clauses_of(impl_def_id.into())
107                .iter_instantiated(cx, impl_args)
108                .map(Unnormalized::skip_norm_wip)
109                .map(|clause| goal.with(cx, clause));
110            ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
111
112            // We currently elaborate all supertrait outlives obligations from impls.
113            // This can be removed when we actually do coinduction correctly, and prove
114            // all supertrait obligations unconditionally.
115            ecx.add_goals(
116                GoalSource::Misc,
117                cx.impl_super_outlives(impl_def_id)
118                    .iter_instantiated(cx, impl_args)
119                    .map(Unnormalized::skip_norm_wip)
120                    .map(|pred| goal.with(cx, pred)),
121            )?;
122
123            then(ecx)
124        })
125    }
126
127    fn consider_error_guaranteed_candidate(
128        ecx: &mut EvalCtxt<'_, D>,
129        _goal: Goal<I, Self>,
130        _guar: I::ErrorGuaranteed,
131    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
132        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
133            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
134    }
135
136    fn fast_reject_assumption(
137        ecx: &mut EvalCtxt<'_, D>,
138        goal: Goal<I, Self>,
139        assumption: I::Clause,
140    ) -> Result<(), NoSolution> {
141        fn trait_def_id_matches<I: Interner>(
142            cx: I,
143            clause_def_id: I::TraitId,
144            goal_def_id: I::TraitId,
145            polarity: ClausePolarity,
146        ) -> bool {
147            clause_def_id == goal_def_id
148            // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
149            // check for a `MetaSized` supertrait being matched against a `Sized` assumption.
150            //
151            // `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this.
152                || (polarity == ClausePolarity::Positive
153                    && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
154                    && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
155        }
156
157        if let Some(trait_clause) = assumption.as_trait_clause()
158            && trait_clause.polarity() == goal.predicate.polarity
159            && trait_def_id_matches(
160                ecx.cx(),
161                trait_clause.def_id(),
162                goal.predicate.def_id(),
163                goal.predicate.polarity,
164            )
165            && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
166                goal.predicate.trait_ref.args,
167                trait_clause.skip_binder().trait_ref.args,
168            )
169        {
170            return Ok(());
171        } else {
172            Err(NoSolution)
173        }
174    }
175
176    fn match_assumption(
177        ecx: &mut EvalCtxt<'_, D>,
178        goal: Goal<I, Self>,
179        assumption: I::Clause,
180        then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
181    ) -> QueryResultOrRerunNonErased<I> {
182        let trait_clause = assumption.as_trait_clause().unwrap();
183
184        // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
185        // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
186        // are syntactic sugar for a lack of bounds so don't need this.
187        // We don't need to check polarity, `fast_reject_assumption` already rejected non-`Positive`
188        // polarity `Sized` assumptions as matching non-`Positive` `MetaSized` goals.
189        if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
190            && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
191        {
192            let meta_sized_clause =
193                trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
194            return Self::match_assumption(ecx, goal, meta_sized_clause, then);
195        }
196
197        let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
198        ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
199
200        then(ecx)
201    }
202
203    fn consider_auto_trait_candidate(
204        ecx: &mut EvalCtxt<'_, D>,
205        goal: Goal<I, Self>,
206    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
207        let cx = ecx.cx();
208        if goal.predicate.polarity != ty::ClausePolarity::Positive {
209            return Err(NoSolution.into());
210        }
211
212        if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
213            return result;
214        }
215
216        // Only consider auto impls of unsafe traits when there are no unsafe
217        // fields.
218        if cx.trait_is_unsafe(goal.predicate.def_id())
219            && goal.predicate.self_ty().has_unsafe_fields()
220        {
221            return Err(NoSolution.into());
222        }
223
224        // We leak the implemented auto traits of opaques outside of their defining scope.
225        // This depends on `typeck` of the defining scope of that opaque, which may result in
226        // fatal query cycles.
227        //
228        // We only get to this point if we're outside of the defining scope as we'd otherwise
229        // be able to normalize the opaque type. We may also cycle in case `typeck` of a defining
230        // scope relies on the current context, e.g. either because it also leaks auto trait
231        // bounds of opaques defined in the current context or by evaluating the current item.
232        //
233        // To avoid this we don't try to leak auto trait bounds if they can also be proven via
234        // item bounds of the opaque. These bounds are always applicable as auto traits must not
235        // have any generic parameters. They would also get preferred over the impl candidate
236        // when merging candidates anyways.
237        //
238        // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs.
239        if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) =
240            goal.predicate.self_ty().kind()
241        {
242            if true {
    if !(is_rigid == ty::IsRigid::Yes) {
        ::core::panicking::panic("assertion failed: is_rigid == ty::IsRigid::Yes")
    };
};debug_assert!(is_rigid == ty::IsRigid::Yes);
243            return ecx.consider_auto_trait_candidate_for_opaque_ty(goal, def_id, args);
244        }
245
246        // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
247        if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
248            return cand;
249        }
250
251        ecx.probe_and_evaluate_goal_for_constituent_tys(
252            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
253            goal,
254            structural_traits::instantiate_constituent_tys_for_auto_trait,
255        )
256    }
257
258    fn consider_trait_alias_candidate(
259        ecx: &mut EvalCtxt<'_, D>,
260        goal: Goal<I, Self>,
261    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
262        if goal.predicate.polarity != ty::ClausePolarity::Positive {
263            return Err(NoSolution.into());
264        }
265
266        let cx = ecx.cx();
267
268        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
269            let nested_obligations = cx
270                .clauses_of(goal.predicate.def_id().into())
271                .iter_instantiated(cx, goal.predicate.trait_ref.args)
272                .map(Unnormalized::skip_norm_wip)
273                .map(|c| goal.with(cx, c));
274            // While you could think of trait aliases to have a single builtin impl
275            // which uses its implied trait bounds as where-clauses, using
276            // `GoalSource::ImplWhereClause` here would be incorrect, as we also
277            // impl them, which means we're "stepping out of the impl constructor"
278            // again. To handle this, we treat these cycles as ambiguous for now.
279            ecx.add_goals(GoalSource::Misc, nested_obligations)?;
280            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
281        })
282    }
283
284    fn consider_builtin_sizedness_candidates(
285        ecx: &mut EvalCtxt<'_, D>,
286        goal: Goal<I, Self>,
287        sizedness: SizedTraitKind,
288    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
289        if goal.predicate.polarity != ty::ClausePolarity::Positive {
290            return Err(NoSolution.into());
291        }
292
293        ecx.probe_and_evaluate_goal_for_constituent_tys(
294            CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
295            goal,
296            |ecx, ty| {
297                structural_traits::instantiate_constituent_tys_for_sizedness_trait(
298                    ecx, sizedness, ty,
299                )
300            },
301        )
302    }
303
304    fn consider_builtin_copy_clone_candidate(
305        ecx: &mut EvalCtxt<'_, D>,
306        goal: Goal<I, Self>,
307    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
308        if goal.predicate.polarity != ty::ClausePolarity::Positive {
309            return Err(NoSolution.into());
310        }
311
312        // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
313        if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
314            return cand;
315        }
316
317        ecx.probe_and_evaluate_goal_for_constituent_tys(
318            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
319            goal,
320            structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
321        )
322    }
323
324    fn consider_builtin_fn_ptr_trait_candidate(
325        ecx: &mut EvalCtxt<'_, D>,
326        goal: Goal<I, Self>,
327    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
328        let self_ty = goal.predicate.self_ty();
329        match goal.predicate.polarity {
330            // impl FnPtr for FnPtr {}
331            ty::ClausePolarity::Positive => {
332                if self_ty.is_fn_ptr() {
333                    ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
334                        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
335                    })
336                } else {
337                    Err(NoSolution.into())
338                }
339            }
340            //  impl !FnPtr for T where T != FnPtr && T is rigid {}
341            ty::ClausePolarity::Negative => {
342                // If a type is rigid and not a fn ptr, then we know for certain
343                // that it does *not* implement `FnPtr`.
344                if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
345                    ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
346                        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
347                    })
348                } else {
349                    Err(NoSolution.into())
350                }
351            }
352        }
353    }
354
355    fn consider_builtin_fn_trait_candidates(
356        ecx: &mut EvalCtxt<'_, D>,
357        goal: Goal<I, Self>,
358        goal_kind: ty::ClosureKind,
359    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
360        if goal.predicate.polarity != ty::ClausePolarity::Positive {
361            return Err(NoSolution.into());
362        }
363
364        let cx = ecx.cx();
365        let Some(tupled_inputs_and_output) =
366            structural_traits::extract_tupled_inputs_and_output_from_callable(
367                cx,
368                goal.predicate.self_ty(),
369                goal_kind,
370            )?
371        else {
372            return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
373        };
374        let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
375
376        // A built-in `Fn` impl only holds if the output is sized.
377        // (FIXME: technically we only need to check this if the type is a fn ptr...)
378        let output_is_sized_pred =
379            ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
380
381        let pred =
382            ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
383                .upcast(cx);
384        Self::probe_and_consider_implied_clause(
385            ecx,
386            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
387            goal,
388            pred,
389            [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
390        )
391    }
392
393    fn consider_builtin_async_fn_trait_candidates(
394        ecx: &mut EvalCtxt<'_, D>,
395        goal: Goal<I, Self>,
396        goal_kind: ty::ClosureKind,
397    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
398        if goal.predicate.polarity != ty::ClausePolarity::Positive {
399            return Err(NoSolution.into());
400        }
401
402        let cx = ecx.cx();
403        let (tupled_inputs_and_output_and_coroutine, nested_preds) =
404            structural_traits::extract_tupled_inputs_and_output_from_async_callable(
405                cx,
406                goal.predicate.self_ty(),
407                goal_kind,
408                // This region doesn't matter because we're throwing away the coroutine type
409                Region::new_static(cx),
410            )?;
411        let AsyncCallableRelevantTypes {
412            tupled_inputs_ty,
413            output_coroutine_ty,
414            coroutine_return_ty: _,
415        } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
416
417        // A built-in `AsyncFn` impl only holds if the output is sized.
418        // (FIXME: technically we only need to check this if the type is a fn ptr...)
419        let output_is_sized_pred = ty::TraitRef::new(
420            cx,
421            cx.require_trait_lang_item(SolverTraitLangItem::Sized),
422            [output_coroutine_ty],
423        );
424
425        let pred = ty::TraitRef::new(
426            cx,
427            goal.predicate.def_id(),
428            [goal.predicate.self_ty(), tupled_inputs_ty],
429        )
430        .upcast(cx);
431        Self::probe_and_consider_implied_clause(
432            ecx,
433            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
434            goal,
435            pred,
436            [goal.with(cx, output_is_sized_pred)]
437                .into_iter()
438                .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
439                .map(|goal| (GoalSource::ImplWhereBound, goal)),
440        )
441    }
442
443    fn consider_builtin_async_fn_kind_helper_candidate(
444        ecx: &mut EvalCtxt<'_, D>,
445        goal: Goal<I, Self>,
446    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
447        let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
448            ::core::panicking::panic("explicit panic");panic!();
449        };
450
451        let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
452            // We don't need to worry about the self type being an infer var.
453            return Err(NoSolution.into());
454        };
455        let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
456        if closure_kind.extends(goal_kind) {
457            ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
458                .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
459        } else {
460            Err(NoSolution.into())
461        }
462    }
463
464    /// ```rust, ignore (not valid rust syntax)
465    /// impl Tuple for () {}
466    /// impl Tuple for (T1,) {}
467    /// impl Tuple for (T1, T2) {}
468    /// impl Tuple for (T1, .., Tn) {}
469    /// ```
470    fn consider_builtin_tuple_candidate(
471        ecx: &mut EvalCtxt<'_, D>,
472        goal: Goal<I, Self>,
473    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
474        if goal.predicate.polarity != ty::ClausePolarity::Positive {
475            return Err(NoSolution.into());
476        }
477
478        if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
479            ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
480                .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
481        } else {
482            Err(NoSolution.into())
483        }
484    }
485
486    fn consider_builtin_pointee_candidate(
487        ecx: &mut EvalCtxt<'_, D>,
488        goal: Goal<I, Self>,
489    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
490        if goal.predicate.polarity != ty::ClausePolarity::Positive {
491            return Err(NoSolution.into());
492        }
493
494        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
495            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
496    }
497
498    fn consider_builtin_future_candidate(
499        ecx: &mut EvalCtxt<'_, D>,
500        goal: Goal<I, Self>,
501    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
502        if goal.predicate.polarity != ty::ClausePolarity::Positive {
503            return Err(NoSolution.into());
504        }
505
506        let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
507            return Err(NoSolution.into());
508        };
509
510        // Coroutines are not futures unless they come from `async` desugaring
511        let cx = ecx.cx();
512        if !cx.coroutine_is_async(def_id) {
513            return Err(NoSolution.into());
514        }
515
516        // Async coroutine unconditionally implement `Future`
517        // Technically, we need to check that the future output type is Sized,
518        // but that's already proven by the coroutine being WF.
519        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
520            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
521    }
522
523    fn consider_builtin_iterator_candidate(
524        ecx: &mut EvalCtxt<'_, D>,
525        goal: Goal<I, Self>,
526    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
527        if goal.predicate.polarity != ty::ClausePolarity::Positive {
528            return Err(NoSolution.into());
529        }
530
531        let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
532            return Err(NoSolution.into());
533        };
534
535        // Coroutines are not iterators unless they come from `gen` desugaring
536        let cx = ecx.cx();
537        if !cx.coroutine_is_gen(def_id) {
538            return Err(NoSolution.into());
539        }
540
541        // Gen coroutines unconditionally implement `Iterator`
542        // Technically, we need to check that the iterator output type is Sized,
543        // but that's already proven by the coroutines being WF.
544        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
545            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
546    }
547
548    fn consider_builtin_fused_iterator_candidate(
549        ecx: &mut EvalCtxt<'_, D>,
550        goal: Goal<I, Self>,
551    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
552        if goal.predicate.polarity != ty::ClausePolarity::Positive {
553            return Err(NoSolution.into());
554        }
555
556        let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
557            return Err(NoSolution.into());
558        };
559
560        // Coroutines are not iterators unless they come from `gen` desugaring
561        let cx = ecx.cx();
562        if !cx.coroutine_is_gen(def_id) {
563            return Err(NoSolution.into());
564        }
565
566        // Gen coroutines unconditionally implement `FusedIterator`.
567        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
568            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
569    }
570
571    fn consider_builtin_async_iterator_candidate(
572        ecx: &mut EvalCtxt<'_, D>,
573        goal: Goal<I, Self>,
574    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
575        if goal.predicate.polarity != ty::ClausePolarity::Positive {
576            return Err(NoSolution.into());
577        }
578
579        let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
580            return Err(NoSolution.into());
581        };
582
583        // Coroutines are not iterators unless they come from `gen` desugaring
584        let cx = ecx.cx();
585        if !cx.coroutine_is_async_gen(def_id) {
586            return Err(NoSolution.into());
587        }
588
589        // Gen coroutines unconditionally implement `Iterator`
590        // Technically, we need to check that the iterator output type is Sized,
591        // but that's already proven by the coroutines being WF.
592        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
593            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
594    }
595
596    fn consider_builtin_coroutine_candidate(
597        ecx: &mut EvalCtxt<'_, D>,
598        goal: Goal<I, Self>,
599    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
600        if goal.predicate.polarity != ty::ClausePolarity::Positive {
601            return Err(NoSolution.into());
602        }
603
604        let self_ty = goal.predicate.self_ty();
605        let ty::Coroutine(def_id, args) = self_ty.kind() else {
606            return Err(NoSolution.into());
607        };
608
609        // `async`-desugared coroutines do not implement the coroutine trait
610        let cx = ecx.cx();
611        if !cx.is_general_coroutine(def_id) {
612            return Err(NoSolution.into());
613        }
614
615        let coroutine = args.as_coroutine();
616        Self::probe_and_consider_implied_clause(
617            ecx,
618            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
619            goal,
620            ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
621                .upcast(cx),
622            // Technically, we need to check that the coroutine types are Sized,
623            // but that's already proven by the coroutine being WF.
624            [],
625        )
626    }
627
628    fn consider_builtin_discriminant_kind_candidate(
629        ecx: &mut EvalCtxt<'_, D>,
630        goal: Goal<I, Self>,
631    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
632        if goal.predicate.polarity != ty::ClausePolarity::Positive {
633            return Err(NoSolution.into());
634        }
635
636        // `DiscriminantKind` is automatically implemented for every type.
637        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
638            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
639    }
640
641    fn consider_builtin_destruct_candidate(
642        ecx: &mut EvalCtxt<'_, D>,
643        goal: Goal<I, Self>,
644    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
645        if goal.predicate.polarity != ty::ClausePolarity::Positive {
646            return Err(NoSolution.into());
647        }
648
649        // `Destruct` is automatically implemented for every type in
650        // non-const environments.
651        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
652            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
653    }
654
655    fn consider_builtin_transmute_candidate(
656        ecx: &mut EvalCtxt<'_, D>,
657        goal: Goal<I, Self>,
658    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
659        if goal.predicate.polarity != ty::ClausePolarity::Positive {
660            return Err(NoSolution.into());
661        }
662
663        // `rustc_transmute` does not have support for type or const params
664        if goal.predicate.has_non_region_placeholders() {
665            return Err(NoSolution.into());
666        }
667
668        // Match the old solver by treating unresolved inference variables as
669        // ambiguous until `rustc_transmute` can compute their layout.
670        if goal.has_non_region_infer() {
671            return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
672        }
673
674        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
675            |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
676                let assume = ecx.structurally_normalize_const(
677                    goal.param_env,
678                    goal.predicate.trait_ref.args.const_at(2),
679                )?;
680
681                let certainty = ecx.is_transmutable(
682                    goal.predicate.trait_ref.args.type_at(0),
683                    goal.predicate.trait_ref.args.type_at(1),
684                    assume,
685                )?;
686                ecx.evaluate_added_goals_and_make_canonical_response(certainty)
687            },
688        )
689    }
690
691    /// NOTE: This is implemented as a built-in goal and not a set of impls like:
692    ///
693    /// ```rust,ignore (illustrative)
694    /// impl<T> BikeshedGuaranteedNoDrop for T where T: Copy {}
695    /// impl<T> BikeshedGuaranteedNoDrop for ManuallyDrop<T> {}
696    /// ```
697    ///
698    /// because these impls overlap, and I'd rather not build a coherence hack for
699    /// this harmless overlap.
700    ///
701    /// This trait is indirectly exposed on stable, so do *not* extend the set of types that
702    /// implement the trait without FCP!
703    fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
704        ecx: &mut EvalCtxt<'_, D>,
705        goal: Goal<I, Self>,
706    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
707        if goal.predicate.polarity != ty::ClausePolarity::Positive {
708            return Err(NoSolution.into());
709        }
710
711        let cx = ecx.cx();
712        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
713            let ty = goal.predicate.self_ty();
714            match ty.kind() {
715                // `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`.
716                ty::Ref(..) => {}
717                // `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`.
718                ty::Adt(def, _) if def.is_manually_drop() => {}
719                // Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if
720                // their constituent types implement `BikeshedGuaranteedNoDrop`.
721                ty::Tuple(tys) => {
722                    ecx.add_goals(
723                        GoalSource::ImplWhereBound,
724                        tys.iter().map(|elem_ty| {
725                            goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
726                        }),
727                    )?;
728                }
729                ty::Array(elem_ty, _) => {
730                    ecx.add_goal(
731                        GoalSource::ImplWhereBound,
732                        goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
733                    )?;
734                }
735
736                // All other types implement `BikeshedGuaranteedNoDrop` only if
737                // they implement `Copy`. We could be smart here and short-circuit
738                // some trivially `Copy`/`!Copy` types, but there's no benefit.
739                ty::FnDef(..)
740                | ty::FnPtr(..)
741                | ty::Error(_)
742                | ty::Uint(_)
743                | ty::Int(_)
744                | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
745                | ty::Bool
746                | ty::Float(_)
747                | ty::Char
748                | ty::RawPtr(..)
749                | ty::Never
750                | ty::Pat(..)
751                | ty::Dynamic(..)
752                | ty::Str
753                | ty::Slice(_)
754                | ty::Foreign(..)
755                | ty::Adt(..)
756                | ty::Alias(..)
757                | ty::Param(_)
758                | ty::Placeholder(..)
759                | ty::Closure(..)
760                | ty::CoroutineClosure(..)
761                | ty::Coroutine(..)
762                | ty::UnsafeBinder(_)
763                | ty::CoroutineWitness(..) => {
764                    ecx.add_goal(
765                        GoalSource::ImplWhereBound,
766                        goal.with(
767                            cx,
768                            ty::TraitRef::new(
769                                cx,
770                                cx.require_trait_lang_item(SolverTraitLangItem::Copy),
771                                [ty],
772                            ),
773                        ),
774                    )?;
775                }
776
777                ty::Bound(..)
778                | ty::Infer(
779                    ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
780                ) => {
781                    { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
782                }
783            }
784
785            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
786        })
787    }
788
789    /// ```ignore (builtin impl example)
790    /// trait Trait {
791    ///     fn foo(&self);
792    /// }
793    /// // results in the following builtin impl
794    /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
795    /// ```
796    fn consider_structural_builtin_unsize_candidates(
797        ecx: &mut EvalCtxt<'_, D>,
798        goal: Goal<I, Self>,
799    ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
800        if goal.predicate.polarity != ty::ClausePolarity::Positive {
801            return Ok(::alloc::vec::Vec::new()vec![]);
802        }
803
804        let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
805            |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
806                let a_ty = goal.predicate.self_ty();
807                // We need to normalize the b_ty since it's matched structurally
808                // in the other functions below.
809                let b_ty = ecx.structurally_normalize_ty(
810                    goal.param_env,
811                    goal.predicate.trait_ref.args.type_at(1),
812                )?;
813
814                let goal = goal.with(ecx.cx(), (a_ty, b_ty));
815                match (a_ty.kind(), b_ty.kind()) {
816                    (ty::Infer(ty::TyVar(..)), ..) => {
    ::core::panicking::panic_fmt(format_args!("unexpected infer {0:?} {1:?}",
            a_ty, b_ty));
}panic!("unexpected infer {a_ty:?} {b_ty:?}"),
817
818                    (_, ty::Infer(ty::TyVar(..))) => {
819                        Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?]))vec![ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?])
820                    }
821
822                    // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`.
823                    (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => Ok(ecx
824                        .consider_builtin_dyn_upcast_candidates(
825                            goal, a_data, a_region, b_data, b_region,
826                        )),
827
828                    // `T` -> `dyn Trait` unsizing.
829                    (_, ty::Dynamic(b_region, b_data)) => Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region,
                        b_data)?]))vec![
830                        ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data)?,
831                    ]),
832
833                    // `[T; N]` -> `[T]` unsizing
834                    (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
835                        Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?]))vec![ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?])
836                    }
837
838                    // `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
839                    (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
840                        if a_def.is_struct() && a_def == b_def =>
841                    {
842                        Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?]))vec![ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?])
843                    }
844
845                    _ => Err(NoSolution.into()),
846                }
847            },
848        );
849
850        match result.map_err_to_rerun()? {
851            Ok(resp) => Ok(resp),
852            Err(NoSolution) => Ok(::alloc::vec::Vec::new()vec![]),
853        }
854    }
855
856    fn consider_builtin_try_as_dyn_candidate(
857        ecx: &mut EvalCtxt<'_, D>,
858        goal: Goal<I, Self>,
859    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
860        if goal.predicate.polarity != ty::ClausePolarity::Positive {
861            return Err(NoSolution.into());
862        }
863        let cx = ecx.cx();
864
865        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
866            let self_ty = goal.predicate.self_ty();
867            let ty_lifetime = goal.predicate.trait_ref.args.region_at(1);
868            match self_ty.kind() {
869                ty::Dynamic(bounds, lifetime) => {
870                    for bound in bounds.iter() {
871                        match bound.skip_binder() {
872                            ExistentialPredicate::Trait(_) => {}
873                            // FIXME(try_as_dyn): check what kind of projections we can allow
874                            ExistentialPredicate::Projection(_) => return Err(NoSolution.into()),
875                            // Auto traits do not affect lifetimes outside of specialization,
876                            // which is disabled in reflection.
877                            ExistentialPredicate::AutoTrait(_) => {}
878                        }
879                    }
880                    ecx.add_goal(
881                        GoalSource::Misc,
882                        goal.with(cx, ty::OutlivesClause(ty_lifetime, lifetime)),
883                    )?;
884                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
885                }
886
887                ty::Bound(..)
888                | ty::Infer(
889                    ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
890                ) => {
891                    {
    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
            self_ty));
}panic!("unexpected type `{self_ty:?}`")
892                }
893
894                _ => Err(NoSolution.into()),
895            }
896        })
897    }
898
899    fn consider_builtin_field_candidate(
900        ecx: &mut EvalCtxt<'_, D>,
901        goal: Goal<I, Self>,
902    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
903        if goal.predicate.polarity != ty::ClausePolarity::Positive {
904            return Err(NoSolution.into());
905        }
906        if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
907            && let Some(FieldInfo { base, ty, .. }) =
908                def.field_representing_type_info(ecx.cx(), args)
909            && {
910                let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
911                // FIXME: add better support for builtin impls of traits that check for the bounds
912                // on the trait definition in std.
913
914                // NOTE: these bounds have to be kept in sync with the definition of the `Field`
915                // trait in `library/core/src/field.rs` as well as the old trait solver `fn
916                // assemble_candidates_for_field_trait` in
917                // `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`.
918                ecx.add_goal(
919                    GoalSource::ImplWhereBound,
920                    Goal {
921                        param_env: goal.param_env,
922                        predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
923                    },
924                )?;
925                ecx.add_goal(
926                    GoalSource::ImplWhereBound,
927                    Goal {
928                        param_env: goal.param_env,
929                        predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
930                    },
931                )?;
932                // FIXME(field_projections): This function does some questionable incomplete stuff by
933                // returning `Err(NoSolution)` on ambiguity.
934                ecx.try_evaluate_added_goals()? == Certainty::Yes
935            }
936            && match base.kind() {
937                ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
938                ty::Tuple(..) => true,
939                _ => false,
940            }
941        {
942            ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
943                .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
944        } else {
945            Err(NoSolution.into())
946        }
947    }
948}
949
950/// Small helper function to change the `def_id` of a trait predicate - this is not normally
951/// something that you want to do, as different traits will require different args and so making
952/// it easy to change the trait is something of a footgun, but it is useful in the narrow
953/// circumstance of changing from `MetaSized` to `Sized`, which happens as part of the lazy
954/// elaboration of sizedness candidates.
955#[inline(always)]
956fn trait_predicate_with_def_id<I: Interner>(
957    cx: I,
958    clause: ty::Binder<I, ty::TraitClause<I>>,
959    did: I::TraitId,
960) -> I::Clause {
961    clause
962        .map_bound(|c| TraitClause {
963            trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
964            polarity: c.polarity,
965        })
966        .upcast(cx)
967}
968
969impl<D, I> EvalCtxt<'_, D>
970where
971    D: SolverDelegate<Interner = I>,
972    I: Interner,
973{
974    /// Trait upcasting allows for coercions between trait objects:
975    /// ```ignore (builtin impl example)
976    /// trait Super {}
977    /// trait Trait: Super {}
978    /// // results in builtin impls upcasting to a super trait
979    /// impl<'a, 'b: 'a> Unsize<dyn Super + 'a> for dyn Trait + 'b {}
980    /// // and impls removing auto trait bounds.
981    /// impl<'a, 'b: 'a> Unsize<dyn Trait + 'a> for dyn Trait + Send + 'b {}
982    /// ```
983    fn consider_builtin_dyn_upcast_candidates(
984        &mut self,
985        goal: Goal<I, (I::Ty, I::Ty)>,
986        a_data: I::BoundExistentialPredicates,
987        a_region: Region<I>,
988        b_data: I::BoundExistentialPredicates,
989        b_region: Region<I>,
990    ) -> Vec<Candidate<I>> {
991        let cx = self.cx();
992        let Goal { predicate: (a_ty, _b_ty), .. } = goal;
993
994        let mut responses = ::alloc::vec::Vec::new()vec![];
995        // If the principal def ids match (or are both none), then we're not doing
996        // trait upcasting. We're just removing auto traits (or shortening the lifetime).
997        let b_principal_def_id = b_data.principal_def_id();
998        if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
999            responses.extend(self.consider_builtin_upcast_to_principal(
1000                goal,
1001                CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
1002                a_data,
1003                a_region,
1004                b_data,
1005                b_region,
1006                a_data.principal(),
1007            ));
1008        } else if let Some(a_principal) = a_data.principal() {
1009            for (idx, new_a_principal) in
1010                elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
1011                    .enumerate()
1012                    .skip(1)
1013            {
1014                responses.extend(self.consider_builtin_upcast_to_principal(
1015                    goal,
1016                    CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
1017                    a_data,
1018                    a_region,
1019                    b_data,
1020                    b_region,
1021                    Some(new_a_principal.map_bound(|trait_ref| {
1022                        ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
1023                    })),
1024                ));
1025            }
1026        }
1027
1028        responses
1029    }
1030
1031    fn consider_builtin_unsize_to_dyn_candidate(
1032        &mut self,
1033        goal: Goal<I, (I::Ty, I::Ty)>,
1034        b_data: I::BoundExistentialPredicates,
1035        b_region: Region<I>,
1036    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1037        let cx = self.cx();
1038        let Goal { predicate: (a_ty, _), .. } = goal;
1039
1040        // Can only unsize to an dyn-compatible trait.
1041        if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1042            return Err(NoSolution.into());
1043        }
1044
1045        self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1046            // Check that the type implements all of the predicates of the trait object.
1047            // (i.e. the principal, all of the associated types match, and any auto traits)
1048            ecx.add_goals(
1049                GoalSource::ImplWhereBound,
1050                b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1051            )?;
1052
1053            // The type must be `Sized` to be unsized.
1054            ecx.add_goal(
1055                GoalSource::ImplWhereBound,
1056                goal.with(
1057                    cx,
1058                    ty::TraitRef::new(
1059                        cx,
1060                        cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1061                        [a_ty],
1062                    ),
1063                ),
1064            )?;
1065
1066            // The type must outlive the lifetime of the `dyn` we're unsizing into.
1067            ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesClause(a_ty, b_region)))?;
1068            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1069        })
1070    }
1071
1072    fn consider_builtin_upcast_to_principal(
1073        &mut self,
1074        goal: Goal<I, (I::Ty, I::Ty)>,
1075        source: CandidateSource<I>,
1076        a_data: I::BoundExistentialPredicates,
1077        a_region: Region<I>,
1078        b_data: I::BoundExistentialPredicates,
1079        b_region: Region<I>,
1080        upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1081    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1082        let param_env = goal.param_env;
1083
1084        // We may upcast to auto traits that are either explicitly listed in
1085        // the object type's bounds, or implied by the principal trait ref's
1086        // supertraits.
1087        let a_auto_traits: IndexSet<I::TraitId> = a_data
1088            .auto_traits()
1089            .into_iter()
1090            .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1091                self.cx()
1092                    .supertrait_def_ids(principal_def_id)
1093                    .filter(|def_id| self.cx().trait_is_auto(*def_id))
1094            }))
1095            .collect();
1096
1097        // More than one projection in a_ty's bounds may match the projection
1098        // in b_ty's bound. Use this to first determine *which* apply without
1099        // having any inference side-effects. We process obligations because
1100        // unification may initially succeed due to deferred projection equality.
1101        let projection_may_match =
1102            |ecx: &mut EvalCtxt<'_, D>,
1103             source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1104             target_projection: ty::Binder<I, ty::ExistentialProjection<I>>|
1105             -> Result<bool, RerunNonErased> {
1106                if source_projection.item_def_id() != target_projection.item_def_id() {
1107                    return Ok(false);
1108                }
1109                match ecx.probe(|_| ProbeKind::ProjectionCompatibility).enter(|ecx| {
1110                    let target_projection = ecx.deeply_resolve_ignoring_regions(target_projection);
1111                    ecx.enter_forall_with_assumptions(
1112                        target_projection,
1113                        param_env,
1114                        |ecx, target_projection| {
1115                            let source_projection =
1116                                ecx.instantiate_binder_with_infer(source_projection);
1117                            ecx.eq(param_env, source_projection, target_projection)?;
1118                            ecx.try_evaluate_added_goals()
1119                        },
1120                    )
1121                }) {
1122                    Ok(_) => Ok(true),
1123                    Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false),
1124                    Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun),
1125                }
1126            };
1127
1128        self.probe_trait_candidate(source).enter(|ecx| {
1129            for bound in b_data.iter() {
1130                match bound.skip_binder() {
1131                    // Check that a's supertrait (upcast_principal) is compatible
1132                    // with the target (b_ty).
1133                    ty::ExistentialPredicate::Trait(target_principal) => {
1134                        let source_principal = upcast_principal.unwrap();
1135                        let target_principal = bound.rebind(target_principal);
1136                        // We might unify infer vars in previous iterations.
1137                        let target_principal =
1138                            ecx.deeply_resolve_ignoring_regions(target_principal);
1139                        ecx.enter_forall_with_assumptions(
1140                            target_principal,
1141                            param_env,
1142                            |ecx, target_principal| {
1143                                let source_principal =
1144                                    ecx.instantiate_binder_with_infer(source_principal);
1145                                ecx.eq(param_env, source_principal, target_principal)?;
1146                                ecx.try_evaluate_added_goals()
1147                            },
1148                        )?;
1149                    }
1150                    // Check that b_ty's projection is satisfied by exactly one of
1151                    // a_ty's projections. First, we look through the list to see if
1152                    // any match. If not, error. Then, if *more* than one matches, we
1153                    // return ambiguity. Otherwise, if exactly one matches, equate
1154                    // it with b_ty's projection.
1155                    ty::ExistentialPredicate::Projection(target_projection) => {
1156                        let target_projection = bound.rebind(target_projection);
1157                        let mut matching_projection = None;
1158                        for source_projection in a_data.projection_bounds() {
1159                            if projection_may_match(ecx, source_projection, target_projection)? {
1160                                if matching_projection.is_some() {
1161                                    return ecx.evaluate_added_goals_and_make_canonical_response(
1162                                        Certainty::AMBIGUOUS,
1163                                    );
1164                                }
1165                                matching_projection = Some(source_projection);
1166                            }
1167                        }
1168                        let Some(matching) = matching_projection else {
1169                            return Err(NoSolution.into());
1170                        };
1171
1172                        // We might unify infer vars in previous iterations.
1173                        let target_projection =
1174                            ecx.deeply_resolve_ignoring_regions(target_projection);
1175                        ecx.enter_forall_with_assumptions(
1176                            target_projection,
1177                            param_env,
1178                            |ecx, target_projection| {
1179                                let source_projection = ecx.instantiate_binder_with_infer(matching);
1180                                ecx.eq(param_env, source_projection, target_projection)?;
1181                                ecx.try_evaluate_added_goals()
1182                            },
1183                        )?;
1184                    }
1185                    // Check that b_ty's auto traits are present in a_ty's bounds.
1186                    ty::ExistentialPredicate::AutoTrait(def_id) => {
1187                        if !a_auto_traits.contains(&def_id) {
1188                            return Err(NoSolution.into());
1189                        }
1190                    }
1191                }
1192            }
1193
1194            // Also require that a_ty's lifetime outlives b_ty's lifetime.
1195            ecx.add_goal(
1196                GoalSource::ImplWhereBound,
1197                Goal::new(ecx.cx(), param_env, ty::OutlivesClause(a_region, b_region)),
1198            )?;
1199
1200            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1201        })
1202    }
1203
1204    /// We have the following builtin impls for arrays:
1205    /// ```ignore (builtin impl example)
1206    /// impl<T: ?Sized, const N: usize> Unsize<[T]> for [T; N] {}
1207    /// ```
1208    /// While the impl itself could theoretically not be builtin,
1209    /// the actual unsizing behavior is builtin. Its also easier to
1210    /// make all impls of `Unsize` builtin as we're able to use
1211    /// `#[rustc_deny_explicit_impl]` in this case.
1212    fn consider_builtin_array_unsize(
1213        &mut self,
1214        goal: Goal<I, (I::Ty, I::Ty)>,
1215        a_elem_ty: I::Ty,
1216        b_elem_ty: I::Ty,
1217    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1218        self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1219        self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1220            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1221    }
1222
1223    /// We generate a builtin `Unsize` impls for structs with generic parameters only
1224    /// mentioned by the last field.
1225    /// ```ignore (builtin impl example)
1226    /// struct Foo<T, U: ?Sized> {
1227    ///     sized_field: Vec<T>,
1228    ///     unsizable: Box<U>,
1229    /// }
1230    /// // results in the following builtin impl
1231    /// impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<Foo<T, V>> for Foo<T, U>
1232    /// where
1233    ///     Box<U>: Unsize<Box<V>>,
1234    /// {}
1235    /// ```
1236    fn consider_builtin_struct_unsize(
1237        &mut self,
1238        goal: Goal<I, (I::Ty, I::Ty)>,
1239        def: I::AdtDef,
1240        a_args: I::GenericArgs,
1241        b_args: I::GenericArgs,
1242    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1243        let cx = self.cx();
1244        let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1245
1246        let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1247        // We must be unsizing some type parameters. This also implies
1248        // that the struct has a tail field.
1249        if unsizing_params.is_empty() {
1250            return Err(NoSolution.into());
1251        }
1252
1253        let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1254
1255        let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1256        let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1257
1258        // Instantiate just the unsizing params from B into A. The type after
1259        // this instantiation must be equal to B. This is so we don't unsize
1260        // unrelated type parameters.
1261        let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1262            if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1263        }));
1264        let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1265
1266        // Finally, we require that `TailA: Unsize<TailB>` for the tail field
1267        // types.
1268        self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1269        self.add_goal(
1270            GoalSource::ImplWhereBound,
1271            goal.with(
1272                cx,
1273                ty::TraitRef::new(
1274                    cx,
1275                    cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1276                    [a_tail_ty, b_tail_ty],
1277                ),
1278            ),
1279        )?;
1280        self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1281            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1282    }
1283
1284    fn consider_auto_trait_candidate_for_opaque_ty(
1285        &mut self,
1286        goal: Goal<I, TraitClause<I>>,
1287        def_id: I::OpaqueTyId,
1288        args: I::GenericArgs,
1289    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1290        let cx = self.cx();
1291        let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
1292
1293        for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() {
1294            if item_bound.as_trait_clause().is_some_and(|b| b.def_id() == goal.predicate.def_id()) {
1295                return Err(NoSolution.into());
1296            }
1297        }
1298
1299        let candidate = self.probe_trait_candidate(source).enter(|ecx| {
1300            let hidden_ty = cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip();
1301            ecx.add_goal(
1302                GoalSource::ImplWhereBound,
1303                goal.with(cx, goal.predicate.with_replaced_self_ty(cx, hidden_ty)),
1304            )?;
1305            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1306        })?;
1307
1308        // Proving an auto trait for the hidden type must not constrain inference
1309        // variables, as that would leak the hidden type itself.
1310        if !candidate.result.value.var_values.is_identity_modulo_regions() {
1311            return self.forced_ambiguity(MaybeInfo::AMBIGUOUS);
1312        }
1313
1314        let ExternalConstraintsData {
1315            region_constraints: _,
1316            ref opaque_types,
1317            ref normalization_nested_goals,
1318        } = *candidate.result.value.external_constraints;
1319        if true {
    if !normalization_nested_goals.is_empty() {
        ::core::panicking::panic("assertion failed: normalization_nested_goals.is_empty()")
    };
};debug_assert!(normalization_nested_goals.is_empty());
1320
1321        // New defining uses may leak an opaque's hidden type into the caller's
1322        // inference state. This is safe after typeck, where hidden types are already
1323        // fixed and only regions are inferred, but not during typeck while hidden
1324        // types may still contain inference variables.
1325        if !opaque_types.is_empty() {
1326            let typing_mode = self.typing_mode();
1327
1328            match typing_mode {
1329                // We're inferring regions of opaque types, but
1330                // the type itself is already fully known, no way
1331                // to leak the hidden type.
1332                TypingMode::PostTypeckUntilBorrowck { .. } => {}
1333                // We're inferring the hidden type of opaques, could
1334                // leak types through it.
1335                TypingMode::Typeck { .. } => {
1336                    return self.forced_ambiguity(MaybeInfo::AMBIGUOUS);
1337                }
1338                // we never add new uses to the opaque type storage
1339                TypingMode::Coherence
1340                | TypingMode::PostBorrowck { .. }
1341                | TypingMode::Reflection
1342                | TypingMode::PostAnalysis
1343                | TypingMode::Codegen
1344                | TypingMode::ErasedNotCoherence(MayBeErased) => {
1345                    {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("we never add new uses to opaque types in typing mode {0:?}",
                typing_mode)));
};unreachable!(
1346                        "we never add new uses to opaque types in typing mode {typing_mode:?}"
1347                    );
1348                }
1349            }
1350        }
1351
1352        Ok(candidate)
1353    }
1354
1355    // Return `Some` if there is an impl (built-in or user provided) that may
1356    // hold for the self type of the goal, which for coherence and soundness
1357    // purposes must disqualify the built-in auto impl assembled by considering
1358    // the type's constituent types.
1359    fn disqualify_auto_trait_candidate_due_to_possible_impl(
1360        &mut self,
1361        goal: Goal<I, TraitClause<I>>,
1362    ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1363        let self_ty = goal.predicate.self_ty();
1364        let check_impls = || {
1365            let mut disqualifying_impl = None;
1366            self.cx().for_each_relevant_impl(goal.predicate.trait_ref, |impl_def_id| {
1367                disqualifying_impl = Some(impl_def_id);
1368            });
1369            if let Some(def_id) = disqualifying_impl {
1370                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1370",
                        "rustc_next_trait_solver::solve::trait_goals",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
                        ::tracing_core::__macro_support::Option::Some(1370u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("def_id")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("def_id");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("goal")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("goal");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1371                // No need to actually consider the candidate here,
1372                // since we do that in `consider_impl_candidate`.
1373                return Some(Err(NoSolution.into()));
1374            } else {
1375                None
1376            }
1377        };
1378
1379        match self_ty.kind() {
1380            // Stall int and float vars until they are resolved to a concrete
1381            // numerical type. That's because the check for impls below treats
1382            // int vars as matching any impl. Even if we filtered such impls,
1383            // we probably don't want to treat an `impl !AutoTrait for i32` as
1384            // disqualifying the built-in auto impl for `i64: AutoTrait` either.
1385            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1386                Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1387            }
1388
1389            // Backward compatibility for default auto traits.
1390            // Test: ui/traits/default_auto_traits/extern-types.rs
1391            ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1392
1393            // These types cannot be structurally decomposed into constituent
1394            // types, and therefore have no built-in auto impl.
1395            ty::Dynamic(..)
1396            | ty::Param(..)
1397            | ty::Foreign(..)
1398            | ty::Alias(
1399                ty::IsRigid::Yes,
1400                ty::AliasTy {
1401                    kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1402                    ..
1403                },
1404            )
1405            | ty::Placeholder(..) => Some(Err(NoSolution.into())),
1406
1407            // Coroutines have one special built-in candidate, `Unpin`, which
1408            // takes precedence over the structural auto trait candidate being
1409            // assembled.
1410            ty::Coroutine(def_id, _)
1411                if self
1412                    .cx()
1413                    .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1414            {
1415                match self.cx().coroutine_movability(def_id) {
1416                    Movability::Static => Some(Err(NoSolution.into())),
1417                    Movability::Movable => Some(
1418                        self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1419                            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1420                        }),
1421                    ),
1422                }
1423            }
1424
1425            // If we still have an alias here, it must be rigid. For opaques, it's always
1426            // okay to consider auto traits because that'll reveal its hidden type. For
1427            // non-opaque aliases, we will not assemble any candidates since there's no way
1428            // to further look into its type.
1429            ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => None,
1430
1431            // For rigid types, any possible implementation that could apply to
1432            // the type (even if after unification and processing nested goals
1433            // it does not hold) will disqualify the built-in auto impl.
1434            //
1435            // We've originally had a more permissive check here which resulted
1436            // in unsoundness, see #84857.
1437            ty::Bool
1438            | ty::Char
1439            | ty::Int(_)
1440            | ty::Uint(_)
1441            | ty::Float(_)
1442            | ty::Str
1443            | ty::Array(_, _)
1444            | ty::Pat(_, _)
1445            | ty::Slice(_)
1446            | ty::RawPtr(_, _)
1447            | ty::Ref(_, _, _)
1448            | ty::FnDef(_, _)
1449            | ty::FnPtr(..)
1450            | ty::Closure(..)
1451            | ty::CoroutineClosure(..)
1452            | ty::Coroutine(_, _)
1453            | ty::CoroutineWitness(..)
1454            | ty::Never
1455            | ty::Tuple(_)
1456            | ty::Adt(_, _)
1457            | ty::UnsafeBinder(_) => check_impls(),
1458            ty::Error(_) => None,
1459
1460            ty::Infer(_) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(_, _) => {
1461                {
    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
            self_ty));
}panic!("unexpected type `{self_ty:?}`")
1462            }
1463        }
1464    }
1465
1466    /// Convenience function for traits that are structural, i.e. that only
1467    /// have nested subgoals that only change the self type. Unlike other
1468    /// evaluate-like helpers, this does a probe, so it doesn't need to be
1469    /// wrapped in one.
1470    fn probe_and_evaluate_goal_for_constituent_tys(
1471        &mut self,
1472        source: CandidateSource<I>,
1473        goal: Goal<I, TraitClause<I>>,
1474        constituent_tys: impl Fn(
1475            &EvalCtxt<'_, D>,
1476            I::Ty,
1477        ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1478    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1479        self.probe_trait_candidate(source).enter(|ecx| {
1480            let goals = ecx.enter_forall_with_assumptions(
1481                constituent_tys(ecx, goal.predicate.self_ty())?,
1482                goal.param_env,
1483                |ecx, tys| {
1484                    tys.into_iter()
1485                        .map(|ty| {
1486                            goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1487                        })
1488                        .collect::<Vec<_>>()
1489                },
1490            );
1491            ecx.add_goals(GoalSource::ImplWhereBound, goals)?;
1492            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1493        })
1494    }
1495}
1496
1497/// How we've proven this trait goal.
1498///
1499/// This is used by `NormalizesTo` goals to only normalize
1500/// by using the same 'kind of candidate' we've used to prove
1501/// its corresponding trait goal. Most notably, we do not
1502/// normalize by using an impl if the trait goal has been
1503/// proven via a `ParamEnv` candidate.
1504///
1505/// This is necessary to avoid unnecessary region constraints,
1506/// see trait-system-refactor-initiative#125 for more details.
1507#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TraitGoalProvenVia {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                TraitGoalProvenVia::Misc => "Misc",
                TraitGoalProvenVia::ParamEnv => "ParamEnv",
                TraitGoalProvenVia::AliasBound => "AliasBound",
            })
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TraitGoalProvenVia { }
#[automatically_derived]
impl ::core::clone::Clone for TraitGoalProvenVia {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TraitGoalProvenVia { }Copy)]
1508pub(super) enum TraitGoalProvenVia {
1509    /// We've proven the trait goal by something which is
1510    /// is not a non-global where-bound or an alias-bound.
1511    ///
1512    /// This means we don't disable any candidates during
1513    /// normalization.
1514    Misc,
1515    ParamEnv,
1516    AliasBound,
1517}
1518
1519impl<D, I> EvalCtxt<'_, D>
1520where
1521    D: SolverDelegate<Interner = I>,
1522    I: Interner,
1523{
1524    /// FIXME(#57893): For backwards compatibility with the old trait solver implementation,
1525    /// we need to handle overlap between builtin and user-written impls for trait objects.
1526    ///
1527    /// This overlap is unsound in general and something which we intend to fix separately.
1528    /// To avoid blocking the stabilization of the trait solver, we add this hack to avoid
1529    /// breakage in cases which are *mostly fine*™. Importantly, this preference is strictly
1530    /// weaker than the old behavior.
1531    ///
1532    /// We only prefer builtin over user-written impls if there are no inference constraints.
1533    /// Importantly, we also only prefer the builtin impls for trait goals, and not during
1534    /// normalization. This means the only case where this special-case results in exploitable
1535    /// unsoundness should be lifetime dependent user-written impls.
1536    pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1537        if self.typing_mode().is_coherence() {
1538            return;
1539        }
1540
1541        if candidates
1542            .iter()
1543            .find(|c| {
1544                #[allow(non_exhaustive_omitted_patterns)] match c.source {
    CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
    _ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1545            })
1546            .is_some_and(|c| has_only_region_constraints(c.result))
1547        {
1548            candidates.retain(|c| {
1549                if #[allow(non_exhaustive_omitted_patterns)] match c.source {
    CandidateSource::Impl(_) => true,
    _ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1550                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1550",
                        "rustc_next_trait_solver::solve::trait_goals",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
                        ::tracing_core::__macro_support::Option::Some(1550u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("c")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("c");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1551                    false
1552                } else {
1553                    true
1554                }
1555            });
1556        }
1557    }
1558
1559    {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("merge_trait_candidates",
                                "rustc_next_trait_solver::solve::trait_goals",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
                                ::tracing_core::__macro_support::Option::Some(1559u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("candidate_preference_mode")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("candidate_preference_mode");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("candidates")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("candidates");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("failed_candidate_info")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("failed_candidate_info");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidate_preference_mode)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidates)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&failed_candidate_info)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return:
                                Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
                                NoSolution> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        if self.typing_mode().is_coherence() {
                            return if let Some((response, _)) =
                                        self.try_merge_candidates(&candidates) {
                                    Ok((response, Some(TraitGoalProvenVia::Misc)))
                                } else { self.flounder(&candidates).map(|r| (r, None)) };
                        }
                        let mut trivial_builtin_impls =
                            candidates.iter().filter(|c|
                                    {

                                        #[allow(non_exhaustive_omitted_patterns)]
                                        match c.source {
                                            CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial) =>
                                                true,
                                            _ => false,
                                        }
                                    });
                        if let Some(candidate) = trivial_builtin_impls.next() {
                            if !trivial_builtin_impls.next().is_none() {
                                ::core::panicking::panic("assertion failed: trivial_builtin_impls.next().is_none()")
                            };
                            return Ok((candidate.result,
                                        Some(TraitGoalProvenVia::Misc)));
                        }
                        if #[allow(non_exhaustive_omitted_patterns)] match candidate_preference_mode
                                    {
                                    CandidatePreferenceMode::Marker => true,
                                    _ => false,
                                } &&
                                candidates.iter().any(|c|
                                        {

                                            #[allow(non_exhaustive_omitted_patterns)]
                                            match c.source {
                                                CandidateSource::AliasBound(AliasBoundKind::SelfBounds) =>
                                                    true,
                                                _ => false,
                                            }
                                        }) {
                            let alias_bounds: Vec<_> =
                                candidates.extract_if(..,
                                        |c|
                                            #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                                CandidateSource::AliasBound(..) => true,
                                                _ => false,
                                            }).collect();
                            return if let Some((response, _)) =
                                        self.try_merge_candidates(&alias_bounds) {
                                    Ok((response, Some(TraitGoalProvenVia::AliasBound)))
                                } else {
                                    Ok((self.bail_with_ambiguity(&alias_bounds), None))
                                };
                        }
                        let has_non_global_where_bounds =
                            candidates.iter().any(|c|
                                    #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                        CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) =>
                                            true,
                                        _ => false,
                                    });
                        if has_non_global_where_bounds {
                            let where_bounds: Vec<_> =
                                candidates.extract_if(..,
                                        |c|
                                            #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                                CandidateSource::ParamEnv(_) => true,
                                                _ => false,
                                            }).collect();
                            let Some((response, info)) =
                                self.try_merge_candidates(&where_bounds) else {
                                    return Ok((self.bail_with_ambiguity(&where_bounds), None));
                                };
                            match info {
                                MergeCandidateInfo::AlwaysApplicable(i) => {
                                    for (j, c) in where_bounds.into_iter().enumerate() {
                                        if i != j {
                                            self.ignore_candidate_head_usages(c.head_usages)
                                        }
                                    }
                                    self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
                                }
                                MergeCandidateInfo::EqualResponse => {}
                            }
                            return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
                        }
                        if candidates.iter().any(|c|
                                    #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                        CandidateSource::AliasBound(_) => true,
                                        _ => false,
                                    }) {
                            let alias_bounds: Vec<_> =
                                candidates.extract_if(..,
                                        |c|
                                            #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                                CandidateSource::AliasBound(_) => true,
                                                _ => false,
                                            }).collect();
                            return if let Some((response, _)) =
                                        self.try_merge_candidates(&alias_bounds) {
                                    Ok((response, Some(TraitGoalProvenVia::AliasBound)))
                                } else {
                                    Ok((self.bail_with_ambiguity(&alias_bounds), None))
                                };
                        }
                        self.filter_specialized_impls(AllowInferenceConstraints::No,
                            &mut candidates);
                        self.unsound_prefer_builtin_dyn_impl(&mut candidates);
                        let proven_via =
                            if candidates.iter().all(|c|
                                        #[allow(non_exhaustive_omitted_patterns)] match c.source {
                                            CandidateSource::ParamEnv(ParamEnvSource::Global) => true,
                                            _ => false,
                                        }) {
                                TraitGoalProvenVia::ParamEnv
                            } else {
                                candidates.retain(|c|
                                        !#[allow(non_exhaustive_omitted_patterns)] match c.source {
                                                CandidateSource::ParamEnv(ParamEnvSource::Global) => true,
                                                _ => false,
                                            });
                                TraitGoalProvenVia::Misc
                            };
                        if let Some((response, _)) =
                                self.try_merge_candidates(&candidates) {
                            Ok((response, Some(proven_via)))
                        } else { self.flounder(&candidates).map(|r| (r, None)) }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1559",
                        "rustc_next_trait_solver::solve::trait_goals",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
                        ::tracing_core::__macro_support::Option::Some(1559u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(self), ret)]
1560    pub(super) fn merge_trait_candidates(
1561        &mut self,
1562        candidate_preference_mode: CandidatePreferenceMode,
1563        mut candidates: Vec<Candidate<I>>,
1564        failed_candidate_info: FailedCandidateInfo,
1565    ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1566        if self.typing_mode().is_coherence() {
1567            return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1568                Ok((response, Some(TraitGoalProvenVia::Misc)))
1569            } else {
1570                self.flounder(&candidates).map(|r| (r, None))
1571            };
1572        }
1573
1574        // We prefer trivial builtin candidates, i.e. builtin impls without any
1575        // nested requirements, over all others. This is a fix for #53123 and
1576        // prevents where-bounds from accidentally extending the lifetime of a
1577        // variable.
1578        let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1579            matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1580        });
1581        if let Some(candidate) = trivial_builtin_impls.next() {
1582            // There should only ever be a single trivial builtin candidate
1583            // as they would otherwise overlap.
1584            assert!(trivial_builtin_impls.next().is_none());
1585            return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1586        }
1587
1588        // Extract non-nested alias bound candidates, will be preferred over where bounds if
1589        // we're proving an auto-trait, sizedness trait or default trait.
1590        if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1591            && candidates.iter().any(|c| {
1592                matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1593            })
1594        {
1595            let alias_bounds: Vec<_> = candidates
1596                .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1597                .collect();
1598            return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1599                Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1600            } else {
1601                Ok((self.bail_with_ambiguity(&alias_bounds), None))
1602            };
1603        }
1604
1605        // If there are non-global where-bounds, prefer where-bounds
1606        // (including global ones) over everything else.
1607        let has_non_global_where_bounds = candidates
1608            .iter()
1609            .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1610        if has_non_global_where_bounds {
1611            let where_bounds: Vec<_> = candidates
1612                .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1613                .collect();
1614            let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1615                return Ok((self.bail_with_ambiguity(&where_bounds), None));
1616            };
1617            match info {
1618                // If there's an always applicable candidate, the result of all
1619                // other candidates does not matter. This means we can ignore
1620                // them when checking whether we've reached a fixpoint.
1621                //
1622                // We always prefer the first always applicable candidate, even if a
1623                // later candidate is also always applicable and would result in fewer
1624                // reruns. We could slightly improve this by e.g. searching for another
1625                // always applicable candidate which doesn't depend on any cycle heads.
1626                //
1627                // NOTE: This is optimization is observable in case there is an always
1628                // applicable global candidate and another non-global candidate which only
1629                // applies because of a provisional result. I can't even think of a test
1630                // case where this would occur and even then, this would not be unsound.
1631                // Supporting this makes the code more involved, so I am just going to
1632                // ignore this for now.
1633                MergeCandidateInfo::AlwaysApplicable(i) => {
1634                    for (j, c) in where_bounds.into_iter().enumerate() {
1635                        if i != j {
1636                            self.ignore_candidate_head_usages(c.head_usages)
1637                        }
1638                    }
1639                    // If a where-bound does not apply, we don't actually get a
1640                    // candidate for it. We manually track the head usages
1641                    // of all failed `ParamEnv` candidates instead.
1642                    self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1643                }
1644                MergeCandidateInfo::EqualResponse => {}
1645            }
1646            return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1647        }
1648
1649        // Next, prefer any alias bound (nested or otherwise).
1650        if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1651            let alias_bounds: Vec<_> = candidates
1652                .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1653                .collect();
1654            return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1655                Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1656            } else {
1657                Ok((self.bail_with_ambiguity(&alias_bounds), None))
1658            };
1659        }
1660
1661        self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1662        self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1663
1664        // If there are *only* global where bounds, then make sure to return that this
1665        // is still reported as being proven-via the param-env so that rigid projections
1666        // operate correctly. Otherwise, drop all global where-bounds before merging the
1667        // remaining candidates.
1668        let proven_via = if candidates
1669            .iter()
1670            .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1671        {
1672            TraitGoalProvenVia::ParamEnv
1673        } else {
1674            candidates
1675                .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1676            TraitGoalProvenVia::Misc
1677        };
1678
1679        if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1680            Ok((response, Some(proven_via)))
1681        } else {
1682            self.flounder(&candidates).map(|r| (r, None))
1683        }
1684    }
1685
1686    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("compute_trait_goal",
                                    "rustc_next_trait_solver::solve::trait_goals",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/6eeff9a52c3e35c4c4cbf5651f342dcd2191866f/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
                                    ::tracing_core::__macro_support::Option::Some(1686u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("goal")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("goal");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
                    NoSolutionOrRerunNonErased> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let (candidates, failed_candidate_info) =
                self.assemble_and_evaluate_candidates(goal,
                        AssembleCandidatesFrom::All)?;
            let candidate_preference_mode =
                CandidatePreferenceMode::compute(self.cx(),
                    goal.predicate.def_id());
            self.merge_trait_candidates(candidate_preference_mode, candidates,
                    failed_candidate_info).map_err(Into::into)
        }
    }
}#[instrument(level = "trace", skip(self))]
1687    pub(super) fn compute_trait_goal(
1688        &mut self,
1689        goal: Goal<I, TraitClause<I>>,
1690    ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1691    {
1692        let (candidates, failed_candidate_info) =
1693            self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1694        let candidate_preference_mode =
1695            CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1696        self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1697            .map_err(Into::into)
1698    }
1699
1700    fn try_stall_coroutine(
1701        &mut self,
1702        self_ty: I::Ty,
1703    ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1704        if let ty::Coroutine(def_id, _) = self_ty.kind() {
1705            match self.typing_mode() {
1706                TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1707                    if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1708                    {
1709                        return Some(self.forced_ambiguity(MaybeInfo {
1710                            cause: MaybeCause::Ambiguity,
1711                            opaque_types_jank: OpaqueTypesJank::AllGood,
1712                            stalled_on_coroutines: StalledOnCoroutines::Yes,
1713                        }));
1714                    }
1715                }
1716                TypingMode::ErasedNotCoherence(MayBeErased) => {
1717                    // Trying to continue here isn't worth it.
1718                    return Some(
1719                        match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1720                            Err(e) => Err(e.into()),
1721                        },
1722                    );
1723                }
1724                TypingMode::Coherence
1725                | TypingMode::PostAnalysis
1726                | TypingMode::Reflection
1727                | TypingMode::Codegen
1728                | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1729                | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1730            }
1731        }
1732
1733        None
1734    }
1735}