rustc_next_trait_solver/solve/
trait_goals.rs

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