rustc_next_trait_solver/solve/
trait_goals.rs

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