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