Skip to main content

rustc_next_trait_solver/solve/
trait_goals.rs

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

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
                    NoSolutionOrRerunNonErased> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let (candidates, failed_candidate_info) =
                self.assemble_and_evaluate_candidates(goal,
                        AssembleCandidatesFrom::All)?;
            let candidate_preference_mode =
                CandidatePreferenceMode::compute(self.cx(),
                    goal.predicate.def_id());
            self.merge_trait_candidates(candidate_preference_mode, candidates,
                    failed_candidate_info).map_err(Into::into)
        }
    }
}#[instrument(level = "trace", skip(self))]
1622    pub(super) fn compute_trait_goal(
1623        &mut self,
1624        goal: Goal<I, TraitPredicate<I>>,
1625    ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1626    {
1627        let (candidates, failed_candidate_info) =
1628            self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1629        let candidate_preference_mode =
1630            CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1631        self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1632            .map_err(Into::into)
1633    }
1634
1635    fn try_stall_coroutine(
1636        &mut self,
1637        self_ty: I::Ty,
1638    ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1639        if let ty::Coroutine(def_id, _) = self_ty.kind() {
1640            match self.typing_mode() {
1641                TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1642                    if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1643                    {
1644                        return Some(self.forced_ambiguity(MaybeInfo {
1645                            cause: MaybeCause::Ambiguity,
1646                            opaque_types_jank: OpaqueTypesJank::AllGood,
1647                            stalled_on_coroutines: StalledOnCoroutines::Yes,
1648                        }));
1649                    }
1650                }
1651                TypingMode::ErasedNotCoherence(MayBeErased) => {
1652                    // Trying to continue here isn't worth it.
1653                    return Some(
1654                        match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1655                            Err(e) => Err(e.into()),
1656                        },
1657                    );
1658                }
1659                TypingMode::Coherence
1660                | TypingMode::PostAnalysis
1661                | TypingMode::Reflection
1662                | TypingMode::Codegen
1663                | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1664                | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1665            }
1666        }
1667
1668        None
1669    }
1670}