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