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