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