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