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