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