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