rustc_next_trait_solver/solve/assembly/
mod.rs

1//! Code shared by trait and projection goals for candidate assembly.
2
3pub(super) mod structural_traits;
4
5use std::cell::Cell;
6use std::ops::ControlFlow;
7
8use derive_where::derive_where;
9use rustc_type_ir::inherent::*;
10use rustc_type_ir::lang_items::TraitSolverLangItem;
11use rustc_type_ir::solve::SizedTraitKind;
12use rustc_type_ir::{
13    self as ty, Interner, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable,
14    TypeVisitableExt as _, TypeVisitor, TypingMode, Upcast as _, elaborate,
15};
16use tracing::{debug, instrument};
17
18use super::trait_goals::TraitGoalProvenVia;
19use super::{has_only_region_constraints, inspect};
20use crate::delegate::SolverDelegate;
21use crate::solve::inspect::ProbeKind;
22use crate::solve::{
23    BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource,
24    MaybeCause, NoSolution, ParamEnvSource, QueryResult, has_no_inference_or_external_constraints,
25};
26
27enum AliasBoundKind {
28    SelfBounds,
29    NonSelfBounds,
30}
31
32/// A candidate is a possible way to prove a goal.
33///
34/// It consists of both the `source`, which describes how that goal would be proven,
35/// and the `result` when using the given `source`.
36#[derive_where(Clone, Debug; I: Interner)]
37pub(super) struct Candidate<I: Interner> {
38    pub(super) source: CandidateSource<I>,
39    pub(super) result: CanonicalResponse<I>,
40}
41
42/// Methods used to assemble candidates for either trait or projection goals.
43pub(super) trait GoalKind<D, I = <D as SolverDelegate>::Interner>:
44    TypeFoldable<I> + Copy + Eq + std::fmt::Display
45where
46    D: SolverDelegate<Interner = I>,
47    I: Interner,
48{
49    fn self_ty(self) -> I::Ty;
50
51    fn trait_ref(self, cx: I) -> ty::TraitRef<I>;
52
53    fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self;
54
55    fn trait_def_id(self, cx: I) -> I::DefId;
56
57    /// Consider a clause, which consists of a "assumption" and some "requirements",
58    /// to satisfy a goal. If the requirements hold, then attempt to satisfy our
59    /// goal by equating it with the assumption.
60    fn probe_and_consider_implied_clause(
61        ecx: &mut EvalCtxt<'_, D>,
62        parent_source: CandidateSource<I>,
63        goal: Goal<I, Self>,
64        assumption: I::Clause,
65        requirements: impl IntoIterator<Item = (GoalSource, Goal<I, I::Predicate>)>,
66    ) -> Result<Candidate<I>, NoSolution> {
67        Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
68            for (nested_source, goal) in requirements {
69                ecx.add_goal(nested_source, goal);
70            }
71            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
72        })
73    }
74
75    /// Consider a clause specifically for a `dyn Trait` self type. This requires
76    /// additionally checking all of the supertraits and object bounds to hold,
77    /// since they're not implied by the well-formedness of the object type.
78    fn probe_and_consider_object_bound_candidate(
79        ecx: &mut EvalCtxt<'_, D>,
80        source: CandidateSource<I>,
81        goal: Goal<I, Self>,
82        assumption: I::Clause,
83    ) -> Result<Candidate<I>, NoSolution> {
84        Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
85            let cx = ecx.cx();
86            let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else {
87                panic!("expected object type in `probe_and_consider_object_bound_candidate`");
88            };
89            match structural_traits::predicates_for_object_candidate(
90                ecx,
91                goal.param_env,
92                goal.predicate.trait_ref(cx),
93                bounds,
94            ) {
95                Ok(requirements) => {
96                    ecx.add_goals(GoalSource::ImplWhereBound, requirements);
97                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
98                }
99                Err(_) => {
100                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
101                }
102            }
103        })
104    }
105
106    /// Assemble additional assumptions for an alias that are not included
107    /// in the item bounds of the alias. For now, this is limited to the
108    /// `explicit_implied_const_bounds` for an associated type.
109    fn consider_additional_alias_assumptions(
110        ecx: &mut EvalCtxt<'_, D>,
111        goal: Goal<I, Self>,
112        alias_ty: ty::AliasTy<I>,
113    ) -> Vec<Candidate<I>>;
114
115    fn probe_and_consider_param_env_candidate(
116        ecx: &mut EvalCtxt<'_, D>,
117        goal: Goal<I, Self>,
118        assumption: I::Clause,
119    ) -> Result<Candidate<I>, NoSolution> {
120        Self::fast_reject_assumption(ecx, goal, assumption)?;
121
122        // Dealing with `ParamEnv` candidates is a bit of a mess as we need to lazily
123        // check whether the candidate is global while considering normalization.
124        //
125        // We need to write into `source` inside of `match_assumption`, but need to access it
126        // in `probe` even if the candidate does not apply before we get there. We handle this
127        // by using a `Cell` here. We only ever write into it inside of `match_assumption`.
128        let source = Cell::new(CandidateSource::ParamEnv(ParamEnvSource::Global));
129        ecx.probe(|result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
130            source: source.get(),
131            result: *result,
132        })
133        .enter(|ecx| {
134            Self::match_assumption(ecx, goal, assumption, |ecx| {
135                ecx.try_evaluate_added_goals()?;
136                source.set(ecx.characterize_param_env_assumption(goal.param_env, assumption)?);
137                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
138            })
139        })
140        .map(|result| Candidate { source: source.get(), result })
141    }
142
143    /// Try equating an assumption predicate against a goal's predicate. If it
144    /// holds, then execute the `then` callback, which should do any additional
145    /// work, then produce a response (typically by executing
146    /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
147    fn probe_and_match_goal_against_assumption(
148        ecx: &mut EvalCtxt<'_, D>,
149        source: CandidateSource<I>,
150        goal: Goal<I, Self>,
151        assumption: I::Clause,
152        then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
153    ) -> Result<Candidate<I>, NoSolution> {
154        Self::fast_reject_assumption(ecx, goal, assumption)?;
155
156        ecx.probe_trait_candidate(source)
157            .enter(|ecx| Self::match_assumption(ecx, goal, assumption, then))
158    }
159
160    /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`]
161    /// and `DefId`.
162    fn fast_reject_assumption(
163        ecx: &mut EvalCtxt<'_, D>,
164        goal: Goal<I, Self>,
165        assumption: I::Clause,
166    ) -> Result<(), NoSolution>;
167
168    /// Relate the goal and assumption.
169    fn match_assumption(
170        ecx: &mut EvalCtxt<'_, D>,
171        goal: Goal<I, Self>,
172        assumption: I::Clause,
173        then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
174    ) -> QueryResult<I>;
175
176    fn consider_impl_candidate(
177        ecx: &mut EvalCtxt<'_, D>,
178        goal: Goal<I, Self>,
179        impl_def_id: I::DefId,
180    ) -> Result<Candidate<I>, NoSolution>;
181
182    /// If the predicate contained an error, we want to avoid emitting unnecessary trait
183    /// errors but still want to emit errors for other trait goals. We have some special
184    /// handling for this case.
185    ///
186    /// Trait goals always hold while projection goals never do. This is a bit arbitrary
187    /// but prevents incorrect normalization while hiding any trait errors.
188    fn consider_error_guaranteed_candidate(
189        ecx: &mut EvalCtxt<'_, D>,
190        guar: I::ErrorGuaranteed,
191    ) -> Result<Candidate<I>, NoSolution>;
192
193    /// A type implements an `auto trait` if its components do as well.
194    ///
195    /// These components are given by built-in rules from
196    /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
197    fn consider_auto_trait_candidate(
198        ecx: &mut EvalCtxt<'_, D>,
199        goal: Goal<I, Self>,
200    ) -> Result<Candidate<I>, NoSolution>;
201
202    /// A trait alias holds if the RHS traits and `where` clauses hold.
203    fn consider_trait_alias_candidate(
204        ecx: &mut EvalCtxt<'_, D>,
205        goal: Goal<I, Self>,
206    ) -> Result<Candidate<I>, NoSolution>;
207
208    /// A type is `Sized` if its tail component is `Sized` and a type is `MetaSized` if its tail
209    /// component is `MetaSized`.
210    ///
211    /// These components are given by built-in rules from
212    /// [`structural_traits::instantiate_constituent_tys_for_sizedness_trait`].
213    fn consider_builtin_sizedness_candidates(
214        ecx: &mut EvalCtxt<'_, D>,
215        goal: Goal<I, Self>,
216        sizedness: SizedTraitKind,
217    ) -> Result<Candidate<I>, NoSolution>;
218
219    /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
220    ///
221    /// These components are given by built-in rules from
222    /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
223    fn consider_builtin_copy_clone_candidate(
224        ecx: &mut EvalCtxt<'_, D>,
225        goal: Goal<I, Self>,
226    ) -> Result<Candidate<I>, NoSolution>;
227
228    /// A type is a `FnPtr` if it is of `FnPtr` type.
229    fn consider_builtin_fn_ptr_trait_candidate(
230        ecx: &mut EvalCtxt<'_, D>,
231        goal: Goal<I, Self>,
232    ) -> Result<Candidate<I>, NoSolution>;
233
234    /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
235    /// family of traits where `A` is given by the signature of the type.
236    fn consider_builtin_fn_trait_candidates(
237        ecx: &mut EvalCtxt<'_, D>,
238        goal: Goal<I, Self>,
239        kind: ty::ClosureKind,
240    ) -> Result<Candidate<I>, NoSolution>;
241
242    /// An async closure is known to implement the `AsyncFn<A>` family of traits
243    /// where `A` is given by the signature of the type.
244    fn consider_builtin_async_fn_trait_candidates(
245        ecx: &mut EvalCtxt<'_, D>,
246        goal: Goal<I, Self>,
247        kind: ty::ClosureKind,
248    ) -> Result<Candidate<I>, NoSolution>;
249
250    /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
251    /// is used internally to delay computation for async closures until after
252    /// upvar analysis is performed in HIR typeck.
253    fn consider_builtin_async_fn_kind_helper_candidate(
254        ecx: &mut EvalCtxt<'_, D>,
255        goal: Goal<I, Self>,
256    ) -> Result<Candidate<I>, NoSolution>;
257
258    /// `Tuple` is implemented if the `Self` type is a tuple.
259    fn consider_builtin_tuple_candidate(
260        ecx: &mut EvalCtxt<'_, D>,
261        goal: Goal<I, Self>,
262    ) -> Result<Candidate<I>, NoSolution>;
263
264    /// `Pointee` is always implemented.
265    ///
266    /// See the projection implementation for the `Metadata` types for all of
267    /// the built-in types. For structs, the metadata type is given by the struct
268    /// tail.
269    fn consider_builtin_pointee_candidate(
270        ecx: &mut EvalCtxt<'_, D>,
271        goal: Goal<I, Self>,
272    ) -> Result<Candidate<I>, NoSolution>;
273
274    /// A coroutine (that comes from an `async` desugaring) is known to implement
275    /// `Future<Output = O>`, where `O` is given by the coroutine's return type
276    /// that was computed during type-checking.
277    fn consider_builtin_future_candidate(
278        ecx: &mut EvalCtxt<'_, D>,
279        goal: Goal<I, Self>,
280    ) -> Result<Candidate<I>, NoSolution>;
281
282    /// A coroutine (that comes from a `gen` desugaring) is known to implement
283    /// `Iterator<Item = O>`, where `O` is given by the generator's yield type
284    /// that was computed during type-checking.
285    fn consider_builtin_iterator_candidate(
286        ecx: &mut EvalCtxt<'_, D>,
287        goal: Goal<I, Self>,
288    ) -> Result<Candidate<I>, NoSolution>;
289
290    /// A coroutine (that comes from a `gen` desugaring) is known to implement
291    /// `FusedIterator`
292    fn consider_builtin_fused_iterator_candidate(
293        ecx: &mut EvalCtxt<'_, D>,
294        goal: Goal<I, Self>,
295    ) -> Result<Candidate<I>, NoSolution>;
296
297    fn consider_builtin_async_iterator_candidate(
298        ecx: &mut EvalCtxt<'_, D>,
299        goal: Goal<I, Self>,
300    ) -> Result<Candidate<I>, NoSolution>;
301
302    /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
303    /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
304    /// and return types of the coroutine computed during type-checking.
305    fn consider_builtin_coroutine_candidate(
306        ecx: &mut EvalCtxt<'_, D>,
307        goal: Goal<I, Self>,
308    ) -> Result<Candidate<I>, NoSolution>;
309
310    fn consider_builtin_discriminant_kind_candidate(
311        ecx: &mut EvalCtxt<'_, D>,
312        goal: Goal<I, Self>,
313    ) -> Result<Candidate<I>, NoSolution>;
314
315    fn consider_builtin_destruct_candidate(
316        ecx: &mut EvalCtxt<'_, D>,
317        goal: Goal<I, Self>,
318    ) -> Result<Candidate<I>, NoSolution>;
319
320    fn consider_builtin_transmute_candidate(
321        ecx: &mut EvalCtxt<'_, D>,
322        goal: Goal<I, Self>,
323    ) -> Result<Candidate<I>, NoSolution>;
324
325    fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
326        ecx: &mut EvalCtxt<'_, D>,
327        goal: Goal<I, Self>,
328    ) -> Result<Candidate<I>, NoSolution>;
329
330    /// Consider (possibly several) candidates to upcast or unsize a type to another
331    /// type, excluding the coercion of a sized type into a `dyn Trait`.
332    ///
333    /// We return the `BuiltinImplSource` for each candidate as it is needed
334    /// for unsize coercion in hir typeck and because it is difficult to
335    /// otherwise recompute this for codegen. This is a bit of a mess but the
336    /// easiest way to maintain the existing behavior for now.
337    fn consider_structural_builtin_unsize_candidates(
338        ecx: &mut EvalCtxt<'_, D>,
339        goal: Goal<I, Self>,
340    ) -> Vec<Candidate<I>>;
341}
342
343/// Allows callers of `assemble_and_evaluate_candidates` to choose whether to limit
344/// candidate assembly to param-env and alias-bound candidates.
345///
346/// On top of being a micro-optimization, as it avoids doing unnecessary work when
347/// a param-env trait bound candidate shadows impls for normalization, this is also
348/// required to prevent query cycles due to RPITIT inference. See the issue at:
349/// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/173>.
350pub(super) enum AssembleCandidatesFrom {
351    All,
352    /// Only assemble candidates from the environment and alias bounds, ignoring
353    /// user-written and built-in impls. We only expect `ParamEnv` and `AliasBound`
354    /// candidates to be assembled.
355    EnvAndBounds,
356}
357
358impl<D, I> EvalCtxt<'_, D>
359where
360    D: SolverDelegate<Interner = I>,
361    I: Interner,
362{
363    pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>(
364        &mut self,
365        goal: Goal<I, G>,
366        assemble_from: AssembleCandidatesFrom,
367    ) -> Vec<Candidate<I>> {
368        let Ok(normalized_self_ty) =
369            self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
370        else {
371            return vec![];
372        };
373
374        if normalized_self_ty.is_ty_var() {
375            debug!("self type has been normalized to infer");
376            return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect();
377        }
378
379        let goal: Goal<I, G> = goal
380            .with(self.cx(), goal.predicate.with_replaced_self_ty(self.cx(), normalized_self_ty));
381        // Vars that show up in the rest of the goal substs may have been constrained by
382        // normalizing the self type as well, since type variables are not uniquified.
383        let goal = self.resolve_vars_if_possible(goal);
384
385        let mut candidates = vec![];
386
387        if let TypingMode::Coherence = self.typing_mode()
388            && let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal)
389        {
390            return vec![candidate];
391        }
392
393        self.assemble_alias_bound_candidates(goal, &mut candidates);
394        self.assemble_param_env_candidates(goal, &mut candidates);
395
396        match assemble_from {
397            AssembleCandidatesFrom::All => {
398                self.assemble_builtin_impl_candidates(goal, &mut candidates);
399                // For performance we only assemble impls if there are no candidates
400                // which would shadow them. This is necessary to avoid hangs in rayon,
401                // see trait-system-refactor-initiative#109 for more details.
402                //
403                // We always assemble builtin impls as trivial builtin impls have a higher
404                // priority than where-clauses.
405                //
406                // We only do this if any such candidate applies without any constraints
407                // as we may want to weaken inference guidance in the future and don't want
408                // to worry about causing major performance regressions when doing so.
409                // See trait-system-refactor-initiative#226 for some ideas here.
410                if TypingMode::Coherence == self.typing_mode()
411                    || !candidates.iter().any(|c| {
412                        matches!(
413                            c.source,
414                            CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)
415                                | CandidateSource::AliasBound
416                        ) && has_no_inference_or_external_constraints(c.result)
417                    })
418                {
419                    self.assemble_impl_candidates(goal, &mut candidates);
420                    self.assemble_object_bound_candidates(goal, &mut candidates);
421                }
422            }
423            AssembleCandidatesFrom::EnvAndBounds => {}
424        }
425
426        candidates
427    }
428
429    pub(super) fn forced_ambiguity(
430        &mut self,
431        cause: MaybeCause,
432    ) -> Result<Candidate<I>, NoSolution> {
433        // This may fail if `try_evaluate_added_goals` overflows because it
434        // fails to reach a fixpoint but ends up getting an error after
435        // running for some additional step.
436        //
437        // cc trait-system-refactor-initiative#105
438        let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
439        let certainty = Certainty::Maybe(cause);
440        self.probe_trait_candidate(source)
441            .enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty))
442    }
443
444    #[instrument(level = "trace", skip_all)]
445    fn assemble_impl_candidates<G: GoalKind<D>>(
446        &mut self,
447        goal: Goal<I, G>,
448        candidates: &mut Vec<Candidate<I>>,
449    ) {
450        let cx = self.cx();
451        cx.for_each_relevant_impl(
452            goal.predicate.trait_def_id(cx),
453            goal.predicate.self_ty(),
454            |impl_def_id| {
455                // For every `default impl`, there's always a non-default `impl`
456                // that will *also* apply. There's no reason to register a candidate
457                // for this impl, since it is *not* proof that the trait goal holds.
458                if cx.impl_is_default(impl_def_id) {
459                    return;
460                }
461
462                match G::consider_impl_candidate(self, goal, impl_def_id) {
463                    Ok(candidate) => candidates.push(candidate),
464                    Err(NoSolution) => (),
465                }
466            },
467        );
468    }
469
470    #[instrument(level = "trace", skip_all)]
471    fn assemble_builtin_impl_candidates<G: GoalKind<D>>(
472        &mut self,
473        goal: Goal<I, G>,
474        candidates: &mut Vec<Candidate<I>>,
475    ) {
476        let cx = self.cx();
477        let trait_def_id = goal.predicate.trait_def_id(cx);
478
479        // N.B. When assembling built-in candidates for lang items that are also
480        // `auto` traits, then the auto trait candidate that is assembled in
481        // `consider_auto_trait_candidate` MUST be disqualified to remain sound.
482        //
483        // Instead of adding the logic here, it's a better idea to add it in
484        // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
485        // `solve::trait_goals` instead.
486        let result = if let Err(guar) = goal.predicate.error_reported() {
487            G::consider_error_guaranteed_candidate(self, guar)
488        } else if cx.trait_is_auto(trait_def_id) {
489            G::consider_auto_trait_candidate(self, goal)
490        } else if cx.trait_is_alias(trait_def_id) {
491            G::consider_trait_alias_candidate(self, goal)
492        } else {
493            match cx.as_lang_item(trait_def_id) {
494                Some(TraitSolverLangItem::Sized) => {
495                    G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
496                }
497                Some(TraitSolverLangItem::MetaSized) => {
498                    G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
499                }
500                Some(TraitSolverLangItem::PointeeSized) => {
501                    unreachable!("`PointeeSized` is removed during lowering");
502                }
503                Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
504                    G::consider_builtin_copy_clone_candidate(self, goal)
505                }
506                Some(TraitSolverLangItem::Fn) => {
507                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
508                }
509                Some(TraitSolverLangItem::FnMut) => {
510                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnMut)
511                }
512                Some(TraitSolverLangItem::FnOnce) => {
513                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnOnce)
514                }
515                Some(TraitSolverLangItem::AsyncFn) => {
516                    G::consider_builtin_async_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
517                }
518                Some(TraitSolverLangItem::AsyncFnMut) => {
519                    G::consider_builtin_async_fn_trait_candidates(
520                        self,
521                        goal,
522                        ty::ClosureKind::FnMut,
523                    )
524                }
525                Some(TraitSolverLangItem::AsyncFnOnce) => {
526                    G::consider_builtin_async_fn_trait_candidates(
527                        self,
528                        goal,
529                        ty::ClosureKind::FnOnce,
530                    )
531                }
532                Some(TraitSolverLangItem::FnPtrTrait) => {
533                    G::consider_builtin_fn_ptr_trait_candidate(self, goal)
534                }
535                Some(TraitSolverLangItem::AsyncFnKindHelper) => {
536                    G::consider_builtin_async_fn_kind_helper_candidate(self, goal)
537                }
538                Some(TraitSolverLangItem::Tuple) => G::consider_builtin_tuple_candidate(self, goal),
539                Some(TraitSolverLangItem::PointeeTrait) => {
540                    G::consider_builtin_pointee_candidate(self, goal)
541                }
542                Some(TraitSolverLangItem::Future) => {
543                    G::consider_builtin_future_candidate(self, goal)
544                }
545                Some(TraitSolverLangItem::Iterator) => {
546                    G::consider_builtin_iterator_candidate(self, goal)
547                }
548                Some(TraitSolverLangItem::FusedIterator) => {
549                    G::consider_builtin_fused_iterator_candidate(self, goal)
550                }
551                Some(TraitSolverLangItem::AsyncIterator) => {
552                    G::consider_builtin_async_iterator_candidate(self, goal)
553                }
554                Some(TraitSolverLangItem::Coroutine) => {
555                    G::consider_builtin_coroutine_candidate(self, goal)
556                }
557                Some(TraitSolverLangItem::DiscriminantKind) => {
558                    G::consider_builtin_discriminant_kind_candidate(self, goal)
559                }
560                Some(TraitSolverLangItem::Destruct) => {
561                    G::consider_builtin_destruct_candidate(self, goal)
562                }
563                Some(TraitSolverLangItem::TransmuteTrait) => {
564                    G::consider_builtin_transmute_candidate(self, goal)
565                }
566                Some(TraitSolverLangItem::BikeshedGuaranteedNoDrop) => {
567                    G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
568                }
569                _ => Err(NoSolution),
570            }
571        };
572
573        candidates.extend(result);
574
575        // There may be multiple unsize candidates for a trait with several supertraits:
576        // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
577        if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) {
578            candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
579        }
580    }
581
582    #[instrument(level = "trace", skip_all)]
583    fn assemble_param_env_candidates<G: GoalKind<D>>(
584        &mut self,
585        goal: Goal<I, G>,
586        candidates: &mut Vec<Candidate<I>>,
587    ) {
588        for assumption in goal.param_env.caller_bounds().iter() {
589            candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption));
590        }
591    }
592
593    #[instrument(level = "trace", skip_all)]
594    fn assemble_alias_bound_candidates<G: GoalKind<D>>(
595        &mut self,
596        goal: Goal<I, G>,
597        candidates: &mut Vec<Candidate<I>>,
598    ) {
599        let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
600            ecx.assemble_alias_bound_candidates_recur(
601                goal.predicate.self_ty(),
602                goal,
603                candidates,
604                AliasBoundKind::SelfBounds,
605            );
606        });
607    }
608
609    /// For some deeply nested `<T>::A::B::C::D` rigid associated type,
610    /// we should explore the item bounds for all levels, since the
611    /// `associated_type_bounds` feature means that a parent associated
612    /// type may carry bounds for a nested associated type.
613    ///
614    /// If we have a projection, check that its self type is a rigid projection.
615    /// If so, continue searching by recursively calling after normalization.
616    // FIXME: This may recurse infinitely, but I can't seem to trigger it without
617    // hitting another overflow error something. Add a depth parameter needed later.
618    fn assemble_alias_bound_candidates_recur<G: GoalKind<D>>(
619        &mut self,
620        self_ty: I::Ty,
621        goal: Goal<I, G>,
622        candidates: &mut Vec<Candidate<I>>,
623        consider_self_bounds: AliasBoundKind,
624    ) {
625        let (kind, alias_ty) = match self_ty.kind() {
626            ty::Bool
627            | ty::Char
628            | ty::Int(_)
629            | ty::Uint(_)
630            | ty::Float(_)
631            | ty::Adt(_, _)
632            | ty::Foreign(_)
633            | ty::Str
634            | ty::Array(_, _)
635            | ty::Pat(_, _)
636            | ty::Slice(_)
637            | ty::RawPtr(_, _)
638            | ty::Ref(_, _, _)
639            | ty::FnDef(_, _)
640            | ty::FnPtr(..)
641            | ty::UnsafeBinder(_)
642            | ty::Dynamic(..)
643            | ty::Closure(..)
644            | ty::CoroutineClosure(..)
645            | ty::Coroutine(..)
646            | ty::CoroutineWitness(..)
647            | ty::Never
648            | ty::Tuple(_)
649            | ty::Param(_)
650            | ty::Placeholder(..)
651            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
652            | ty::Error(_) => return,
653            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => {
654                panic!("unexpected self type for `{goal:?}`")
655            }
656
657            ty::Infer(ty::TyVar(_)) => {
658                // If we hit infer when normalizing the self type of an alias,
659                // then bail with ambiguity. We should never encounter this on
660                // the *first* iteration of this recursive function.
661                if let Ok(result) =
662                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
663                {
664                    candidates.push(Candidate { source: CandidateSource::AliasBound, result });
665                }
666                return;
667            }
668
669            ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
670            ty::Alias(ty::Inherent | ty::Free, _) => {
671                self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF"));
672                return;
673            }
674        };
675
676        match consider_self_bounds {
677            AliasBoundKind::SelfBounds => {
678                for assumption in self
679                    .cx()
680                    .item_self_bounds(alias_ty.def_id)
681                    .iter_instantiated(self.cx(), alias_ty.args)
682                {
683                    candidates.extend(G::probe_and_consider_implied_clause(
684                        self,
685                        CandidateSource::AliasBound,
686                        goal,
687                        assumption,
688                        [],
689                    ));
690                }
691            }
692            AliasBoundKind::NonSelfBounds => {
693                for assumption in self
694                    .cx()
695                    .item_non_self_bounds(alias_ty.def_id)
696                    .iter_instantiated(self.cx(), alias_ty.args)
697                {
698                    candidates.extend(G::probe_and_consider_implied_clause(
699                        self,
700                        CandidateSource::AliasBound,
701                        goal,
702                        assumption,
703                        [],
704                    ));
705                }
706            }
707        }
708
709        candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
710
711        if kind != ty::Projection {
712            return;
713        }
714
715        // Recurse on the self type of the projection.
716        match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) {
717            Ok(next_self_ty) => self.assemble_alias_bound_candidates_recur(
718                next_self_ty,
719                goal,
720                candidates,
721                AliasBoundKind::NonSelfBounds,
722            ),
723            Err(NoSolution) => {}
724        }
725    }
726
727    #[instrument(level = "trace", skip_all)]
728    fn assemble_object_bound_candidates<G: GoalKind<D>>(
729        &mut self,
730        goal: Goal<I, G>,
731        candidates: &mut Vec<Candidate<I>>,
732    ) {
733        let cx = self.cx();
734        if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) {
735            return;
736        }
737
738        let self_ty = goal.predicate.self_ty();
739        let bounds = match self_ty.kind() {
740            ty::Bool
741            | ty::Char
742            | ty::Int(_)
743            | ty::Uint(_)
744            | ty::Float(_)
745            | ty::Adt(_, _)
746            | ty::Foreign(_)
747            | ty::Str
748            | ty::Array(_, _)
749            | ty::Pat(_, _)
750            | ty::Slice(_)
751            | ty::RawPtr(_, _)
752            | ty::Ref(_, _, _)
753            | ty::FnDef(_, _)
754            | ty::FnPtr(..)
755            | ty::UnsafeBinder(_)
756            | ty::Alias(..)
757            | ty::Closure(..)
758            | ty::CoroutineClosure(..)
759            | ty::Coroutine(..)
760            | ty::CoroutineWitness(..)
761            | ty::Never
762            | ty::Tuple(_)
763            | ty::Param(_)
764            | ty::Placeholder(..)
765            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
766            | ty::Error(_) => return,
767            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
768            | ty::Bound(..) => panic!("unexpected self type for `{goal:?}`"),
769            ty::Dynamic(bounds, ..) => bounds,
770        };
771
772        // Do not consider built-in object impls for dyn-incompatible types.
773        if bounds.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
774            return;
775        }
776
777        // Consider all of the auto-trait and projection bounds, which don't
778        // need to be recorded as a `BuiltinImplSource::Object` since they don't
779        // really have a vtable base...
780        for bound in bounds.iter() {
781            match bound.skip_binder() {
782                ty::ExistentialPredicate::Trait(_) => {
783                    // Skip principal
784                }
785                ty::ExistentialPredicate::Projection(_)
786                | ty::ExistentialPredicate::AutoTrait(_) => {
787                    candidates.extend(G::probe_and_consider_object_bound_candidate(
788                        self,
789                        CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
790                        goal,
791                        bound.with_self_ty(cx, self_ty),
792                    ));
793                }
794            }
795        }
796
797        // FIXME: We only need to do *any* of this if we're considering a trait goal,
798        // since we don't need to look at any supertrait or anything if we are doing
799        // a projection goal.
800        if let Some(principal) = bounds.principal() {
801            let principal_trait_ref = principal.with_self_ty(cx, self_ty);
802            for (idx, assumption) in elaborate::supertraits(cx, principal_trait_ref).enumerate() {
803                candidates.extend(G::probe_and_consider_object_bound_candidate(
804                    self,
805                    CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)),
806                    goal,
807                    assumption.upcast(cx),
808                ));
809            }
810        }
811    }
812
813    /// In coherence we have to not only care about all impls we know about, but
814    /// also consider impls which may get added in a downstream or sibling crate
815    /// or which an upstream impl may add in a minor release.
816    ///
817    /// To do so we return a single ambiguous candidate in case such an unknown
818    /// impl could apply to the current goal.
819    #[instrument(level = "trace", skip_all)]
820    fn consider_coherence_unknowable_candidate<G: GoalKind<D>>(
821        &mut self,
822        goal: Goal<I, G>,
823    ) -> Result<Candidate<I>, NoSolution> {
824        self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(|ecx| {
825            let cx = ecx.cx();
826            let trait_ref = goal.predicate.trait_ref(cx);
827            if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
828                Err(NoSolution)
829            } else {
830                // While the trait bound itself may be unknowable, we may be able to
831                // prove that a super trait is not implemented. For this, we recursively
832                // prove the super trait bounds of the current goal.
833                //
834                // We skip the goal itself as that one would cycle.
835                let predicate: I::Predicate = trait_ref.upcast(cx);
836                ecx.add_goals(
837                    GoalSource::Misc,
838                    elaborate::elaborate(cx, [predicate])
839                        .skip(1)
840                        .map(|predicate| goal.with(cx, predicate)),
841                );
842                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
843            }
844        })
845    }
846}
847
848pub(super) enum AllowInferenceConstraints {
849    Yes,
850    No,
851}
852
853impl<D, I> EvalCtxt<'_, D>
854where
855    D: SolverDelegate<Interner = I>,
856    I: Interner,
857{
858    /// Check whether we can ignore impl candidates due to specialization.
859    ///
860    /// This is only necessary for `feature(specialization)` and seems quite ugly.
861    pub(super) fn filter_specialized_impls(
862        &mut self,
863        allow_inference_constraints: AllowInferenceConstraints,
864        candidates: &mut Vec<Candidate<I>>,
865    ) {
866        match self.typing_mode() {
867            TypingMode::Coherence => return,
868            TypingMode::Analysis { .. }
869            | TypingMode::Borrowck { .. }
870            | TypingMode::PostBorrowckAnalysis { .. }
871            | TypingMode::PostAnalysis => {}
872        }
873
874        let mut i = 0;
875        'outer: while i < candidates.len() {
876            let CandidateSource::Impl(victim_def_id) = candidates[i].source else {
877                i += 1;
878                continue;
879            };
880
881            for (j, c) in candidates.iter().enumerate() {
882                if i == j {
883                    continue;
884                }
885
886                let CandidateSource::Impl(other_def_id) = c.source else {
887                    continue;
888                };
889
890                // See if we can toss out `victim` based on specialization.
891                //
892                // While this requires us to know *for sure* that the `lhs` impl applies
893                // we still use modulo regions here. This is fine as specialization currently
894                // assumes that specializing impls have to be always applicable, meaning that
895                // the only allowed region constraints may be constraints also present on the default impl.
896                if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes)
897                    || has_only_region_constraints(c.result)
898                {
899                    if self.cx().impl_specializes(other_def_id, victim_def_id) {
900                        candidates.remove(i);
901                        continue 'outer;
902                    }
903                }
904            }
905
906            i += 1;
907        }
908    }
909
910    /// Assemble and merge candidates for goals which are related to an underlying trait
911    /// goal. Right now, this is normalizes-to and host effect goals.
912    ///
913    /// We sadly can't simply take all possible candidates for normalization goals
914    /// and check whether they result in the same constraints. We want to make sure
915    /// that trying to normalize an alias doesn't result in constraints which aren't
916    /// otherwise required.
917    ///
918    /// Most notably, when proving a trait goal by via a where-bound, we should not
919    /// normalize via impls which have stricter region constraints than the where-bound:
920    ///
921    /// ```rust
922    /// trait Trait<'a> {
923    ///     type Assoc;
924    /// }
925    ///
926    /// impl<'a, T: 'a> Trait<'a> for T {
927    ///     type Assoc = u32;
928    /// }
929    ///
930    /// fn with_bound<'a, T: Trait<'a>>(_value: T::Assoc) {}
931    /// ```
932    ///
933    /// The where-bound of `with_bound` doesn't specify the associated type, so we would
934    /// only be able to normalize `<T as Trait<'a>>::Assoc` by using the impl. This impl
935    /// adds a `T: 'a` bound however, which would result in a region error. Given that the
936    /// user explicitly wrote that `T: Trait<'a>` holds, this is undesirable and we instead
937    /// treat the alias as rigid.
938    ///
939    /// See trait-system-refactor-initiative#124 for more details.
940    #[instrument(level = "debug", skip(self, inject_normalize_to_rigid_candidate), ret)]
941    pub(super) fn assemble_and_merge_candidates<G: GoalKind<D>>(
942        &mut self,
943        proven_via: Option<TraitGoalProvenVia>,
944        goal: Goal<I, G>,
945        inject_normalize_to_rigid_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
946    ) -> QueryResult<I> {
947        let Some(proven_via) = proven_via else {
948            // We don't care about overflow. If proving the trait goal overflowed, then
949            // it's enough to report an overflow error for that, we don't also have to
950            // overflow during normalization.
951            //
952            // We use `forced_ambiguity` here over `make_ambiguous_response_no_constraints`
953            // because the former will also record a built-in candidate in the inspector.
954            return self.forced_ambiguity(MaybeCause::Ambiguity).map(|cand| cand.result);
955        };
956
957        match proven_via {
958            TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
959                // Even when a trait bound has been proven using a where-bound, we
960                // still need to consider alias-bounds for normalization, see
961                // `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
962                let mut candidates: Vec<_> = self
963                    .assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::EnvAndBounds);
964
965                // We still need to prefer where-bounds over alias-bounds however.
966                // See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
967                if candidates.iter().any(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
968                    candidates.retain(|c| matches!(c.source, CandidateSource::ParamEnv(_)));
969                } else if candidates.is_empty() {
970                    // If the trait goal has been proven by using the environment, we want to treat
971                    // aliases as rigid if there are no applicable projection bounds in the environment.
972                    return inject_normalize_to_rigid_candidate(self);
973                }
974
975                if let Some(response) = self.try_merge_candidates(&candidates) {
976                    Ok(response)
977                } else {
978                    self.flounder(&candidates)
979                }
980            }
981            TraitGoalProvenVia::Misc => {
982                let mut candidates =
983                    self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
984
985                // Prefer "orphaned" param-env normalization predicates, which are used
986                // (for example, and ideally only) when proving item bounds for an impl.
987                let candidates_from_env: Vec<_> = candidates
988                    .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
989                    .collect();
990                if let Some(response) = self.try_merge_candidates(&candidates_from_env) {
991                    return Ok(response);
992                }
993
994                // We drop specialized impls to allow normalization via a final impl here. In case
995                // the specializing impl has different inference constraints from the specialized
996                // impl, proving the trait goal is already ambiguous, so we never get here. This
997                // means we can just ignore inference constraints and don't have to special-case
998                // constraining the normalized-to `term`.
999                self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates);
1000                if let Some(response) = self.try_merge_candidates(&candidates) {
1001                    Ok(response)
1002                } else {
1003                    self.flounder(&candidates)
1004                }
1005            }
1006        }
1007    }
1008
1009    /// Compute whether a param-env assumption is global or non-global after normalizing it.
1010    ///
1011    /// This is necessary because, for example, given:
1012    ///
1013    /// ```ignore,rust
1014    /// where
1015    ///     T: Trait<Assoc = u32>,
1016    ///     i32: From<T::Assoc>,
1017    /// ```
1018    ///
1019    /// The `i32: From<T::Assoc>` bound is non-global before normalization, but is global after.
1020    /// Since the old trait solver normalized param-envs eagerly, we want to emulate this
1021    /// behavior lazily.
1022    fn characterize_param_env_assumption(
1023        &mut self,
1024        param_env: I::ParamEnv,
1025        assumption: I::Clause,
1026    ) -> Result<CandidateSource<I>, NoSolution> {
1027        // FIXME: This should be fixed, but it also requires changing the behavior
1028        // in the old solver which is currently relied on.
1029        if assumption.has_bound_vars() {
1030            return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal));
1031        }
1032
1033        match assumption.visit_with(&mut FindParamInClause {
1034            ecx: self,
1035            param_env,
1036            universes: vec![],
1037        }) {
1038            ControlFlow::Break(Err(NoSolution)) => Err(NoSolution),
1039            ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)),
1040            ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)),
1041        }
1042    }
1043}
1044
1045struct FindParamInClause<'a, 'b, D: SolverDelegate<Interner = I>, I: Interner> {
1046    ecx: &'a mut EvalCtxt<'b, D>,
1047    param_env: I::ParamEnv,
1048    universes: Vec<Option<ty::UniverseIndex>>,
1049}
1050
1051impl<D, I> TypeVisitor<I> for FindParamInClause<'_, '_, D, I>
1052where
1053    D: SolverDelegate<Interner = I>,
1054    I: Interner,
1055{
1056    type Result = ControlFlow<Result<(), NoSolution>>;
1057
1058    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
1059        self.universes.push(None);
1060        t.super_visit_with(self)?;
1061        self.universes.pop();
1062        ControlFlow::Continue(())
1063    }
1064
1065    fn visit_ty(&mut self, ty: I::Ty) -> Self::Result {
1066        let ty = self.ecx.replace_bound_vars(ty, &mut self.universes);
1067        let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else {
1068            return ControlFlow::Break(Err(NoSolution));
1069        };
1070
1071        if let ty::Placeholder(p) = ty.kind() {
1072            if p.universe() == ty::UniverseIndex::ROOT {
1073                ControlFlow::Break(Ok(()))
1074            } else {
1075                ControlFlow::Continue(())
1076            }
1077        } else if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
1078            ty.super_visit_with(self)
1079        } else {
1080            ControlFlow::Continue(())
1081        }
1082    }
1083
1084    fn visit_const(&mut self, ct: I::Const) -> Self::Result {
1085        let ct = self.ecx.replace_bound_vars(ct, &mut self.universes);
1086        let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else {
1087            return ControlFlow::Break(Err(NoSolution));
1088        };
1089
1090        if let ty::ConstKind::Placeholder(p) = ct.kind() {
1091            if p.universe() == ty::UniverseIndex::ROOT {
1092                ControlFlow::Break(Ok(()))
1093            } else {
1094                ControlFlow::Continue(())
1095            }
1096        } else if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
1097            ct.super_visit_with(self)
1098        } else {
1099            ControlFlow::Continue(())
1100        }
1101    }
1102
1103    fn visit_region(&mut self, r: I::Region) -> Self::Result {
1104        match self.ecx.eager_resolve_region(r).kind() {
1105            ty::ReStatic | ty::ReError(_) | ty::ReBound(..) => ControlFlow::Continue(()),
1106            ty::RePlaceholder(p) => {
1107                if p.universe() == ty::UniverseIndex::ROOT {
1108                    ControlFlow::Break(Ok(()))
1109                } else {
1110                    ControlFlow::Continue(())
1111                }
1112            }
1113            ty::ReVar(_) => ControlFlow::Break(Ok(())),
1114            ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) => {
1115                unreachable!("unexpected region in param-env clause")
1116            }
1117        }
1118    }
1119}