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