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