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,
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_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> =
380            goal.with(self.cx(), goal.predicate.with_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_impl_candidates(goal, &mut candidates);
399                self.assemble_builtin_impl_candidates(goal, &mut candidates);
400                self.assemble_object_bound_candidates(goal, &mut candidates);
401            }
402            AssembleCandidatesFrom::EnvAndBounds => {}
403        }
404
405        candidates
406    }
407
408    pub(super) fn forced_ambiguity(
409        &mut self,
410        cause: MaybeCause,
411    ) -> Result<Candidate<I>, NoSolution> {
412        // This may fail if `try_evaluate_added_goals` overflows because it
413        // fails to reach a fixpoint but ends up getting an error after
414        // running for some additional step.
415        //
416        // cc trait-system-refactor-initiative#105
417        let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
418        let certainty = Certainty::Maybe(cause);
419        self.probe_trait_candidate(source)
420            .enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty))
421    }
422
423    #[instrument(level = "trace", skip_all)]
424    fn assemble_impl_candidates<G: GoalKind<D>>(
425        &mut self,
426        goal: Goal<I, G>,
427        candidates: &mut Vec<Candidate<I>>,
428    ) {
429        let cx = self.cx();
430        cx.for_each_relevant_impl(
431            goal.predicate.trait_def_id(cx),
432            goal.predicate.self_ty(),
433            |impl_def_id| {
434                // For every `default impl`, there's always a non-default `impl`
435                // that will *also* apply. There's no reason to register a candidate
436                // for this impl, since it is *not* proof that the trait goal holds.
437                if cx.impl_is_default(impl_def_id) {
438                    return;
439                }
440
441                match G::consider_impl_candidate(self, goal, impl_def_id) {
442                    Ok(candidate) => candidates.push(candidate),
443                    Err(NoSolution) => (),
444                }
445            },
446        );
447    }
448
449    #[instrument(level = "trace", skip_all)]
450    fn assemble_builtin_impl_candidates<G: GoalKind<D>>(
451        &mut self,
452        goal: Goal<I, G>,
453        candidates: &mut Vec<Candidate<I>>,
454    ) {
455        let cx = self.cx();
456        let trait_def_id = goal.predicate.trait_def_id(cx);
457
458        // N.B. When assembling built-in candidates for lang items that are also
459        // `auto` traits, then the auto trait candidate that is assembled in
460        // `consider_auto_trait_candidate` MUST be disqualified to remain sound.
461        //
462        // Instead of adding the logic here, it's a better idea to add it in
463        // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
464        // `solve::trait_goals` instead.
465        let result = if let Err(guar) = goal.predicate.error_reported() {
466            G::consider_error_guaranteed_candidate(self, guar)
467        } else if cx.trait_is_auto(trait_def_id) {
468            G::consider_auto_trait_candidate(self, goal)
469        } else if cx.trait_is_alias(trait_def_id) {
470            G::consider_trait_alias_candidate(self, goal)
471        } else {
472            match cx.as_lang_item(trait_def_id) {
473                Some(TraitSolverLangItem::Sized) => {
474                    G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
475                }
476                Some(TraitSolverLangItem::MetaSized) => {
477                    G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
478                }
479                Some(TraitSolverLangItem::PointeeSized) => {
480                    unreachable!("`PointeeSized` is removed during lowering");
481                }
482                Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
483                    G::consider_builtin_copy_clone_candidate(self, goal)
484                }
485                Some(TraitSolverLangItem::Fn) => {
486                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
487                }
488                Some(TraitSolverLangItem::FnMut) => {
489                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnMut)
490                }
491                Some(TraitSolverLangItem::FnOnce) => {
492                    G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnOnce)
493                }
494                Some(TraitSolverLangItem::AsyncFn) => {
495                    G::consider_builtin_async_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
496                }
497                Some(TraitSolverLangItem::AsyncFnMut) => {
498                    G::consider_builtin_async_fn_trait_candidates(
499                        self,
500                        goal,
501                        ty::ClosureKind::FnMut,
502                    )
503                }
504                Some(TraitSolverLangItem::AsyncFnOnce) => {
505                    G::consider_builtin_async_fn_trait_candidates(
506                        self,
507                        goal,
508                        ty::ClosureKind::FnOnce,
509                    )
510                }
511                Some(TraitSolverLangItem::FnPtrTrait) => {
512                    G::consider_builtin_fn_ptr_trait_candidate(self, goal)
513                }
514                Some(TraitSolverLangItem::AsyncFnKindHelper) => {
515                    G::consider_builtin_async_fn_kind_helper_candidate(self, goal)
516                }
517                Some(TraitSolverLangItem::Tuple) => G::consider_builtin_tuple_candidate(self, goal),
518                Some(TraitSolverLangItem::PointeeTrait) => {
519                    G::consider_builtin_pointee_candidate(self, goal)
520                }
521                Some(TraitSolverLangItem::Future) => {
522                    G::consider_builtin_future_candidate(self, goal)
523                }
524                Some(TraitSolverLangItem::Iterator) => {
525                    G::consider_builtin_iterator_candidate(self, goal)
526                }
527                Some(TraitSolverLangItem::FusedIterator) => {
528                    G::consider_builtin_fused_iterator_candidate(self, goal)
529                }
530                Some(TraitSolverLangItem::AsyncIterator) => {
531                    G::consider_builtin_async_iterator_candidate(self, goal)
532                }
533                Some(TraitSolverLangItem::Coroutine) => {
534                    G::consider_builtin_coroutine_candidate(self, goal)
535                }
536                Some(TraitSolverLangItem::DiscriminantKind) => {
537                    G::consider_builtin_discriminant_kind_candidate(self, goal)
538                }
539                Some(TraitSolverLangItem::Destruct) => {
540                    G::consider_builtin_destruct_candidate(self, goal)
541                }
542                Some(TraitSolverLangItem::TransmuteTrait) => {
543                    G::consider_builtin_transmute_candidate(self, goal)
544                }
545                Some(TraitSolverLangItem::BikeshedGuaranteedNoDrop) => {
546                    G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
547                }
548                _ => Err(NoSolution),
549            }
550        };
551
552        candidates.extend(result);
553
554        // There may be multiple unsize candidates for a trait with several supertraits:
555        // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
556        if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) {
557            candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
558        }
559    }
560
561    #[instrument(level = "trace", skip_all)]
562    fn assemble_param_env_candidates<G: GoalKind<D>>(
563        &mut self,
564        goal: Goal<I, G>,
565        candidates: &mut Vec<Candidate<I>>,
566    ) {
567        for assumption in goal.param_env.caller_bounds().iter() {
568            candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption));
569        }
570    }
571
572    #[instrument(level = "trace", skip_all)]
573    fn assemble_alias_bound_candidates<G: GoalKind<D>>(
574        &mut self,
575        goal: Goal<I, G>,
576        candidates: &mut Vec<Candidate<I>>,
577    ) {
578        let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
579            ecx.assemble_alias_bound_candidates_recur(
580                goal.predicate.self_ty(),
581                goal,
582                candidates,
583                AliasBoundKind::SelfBounds,
584            );
585        });
586    }
587
588    /// For some deeply nested `<T>::A::B::C::D` rigid associated type,
589    /// we should explore the item bounds for all levels, since the
590    /// `associated_type_bounds` feature means that a parent associated
591    /// type may carry bounds for a nested associated type.
592    ///
593    /// If we have a projection, check that its self type is a rigid projection.
594    /// If so, continue searching by recursively calling after normalization.
595    // FIXME: This may recurse infinitely, but I can't seem to trigger it without
596    // hitting another overflow error something. Add a depth parameter needed later.
597    fn assemble_alias_bound_candidates_recur<G: GoalKind<D>>(
598        &mut self,
599        self_ty: I::Ty,
600        goal: Goal<I, G>,
601        candidates: &mut Vec<Candidate<I>>,
602        consider_self_bounds: AliasBoundKind,
603    ) {
604        let (kind, alias_ty) = match self_ty.kind() {
605            ty::Bool
606            | ty::Char
607            | ty::Int(_)
608            | ty::Uint(_)
609            | ty::Float(_)
610            | ty::Adt(_, _)
611            | ty::Foreign(_)
612            | ty::Str
613            | ty::Array(_, _)
614            | ty::Pat(_, _)
615            | ty::Slice(_)
616            | ty::RawPtr(_, _)
617            | ty::Ref(_, _, _)
618            | ty::FnDef(_, _)
619            | ty::FnPtr(..)
620            | ty::UnsafeBinder(_)
621            | ty::Dynamic(..)
622            | ty::Closure(..)
623            | ty::CoroutineClosure(..)
624            | ty::Coroutine(..)
625            | ty::CoroutineWitness(..)
626            | ty::Never
627            | ty::Tuple(_)
628            | ty::Param(_)
629            | ty::Placeholder(..)
630            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
631            | ty::Error(_) => return,
632            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => {
633                panic!("unexpected self type for `{goal:?}`")
634            }
635
636            ty::Infer(ty::TyVar(_)) => {
637                // If we hit infer when normalizing the self type of an alias,
638                // then bail with ambiguity. We should never encounter this on
639                // the *first* iteration of this recursive function.
640                if let Ok(result) =
641                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
642                {
643                    candidates.push(Candidate { source: CandidateSource::AliasBound, result });
644                }
645                return;
646            }
647
648            ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
649            ty::Alias(ty::Inherent | ty::Free, _) => {
650                self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF"));
651                return;
652            }
653        };
654
655        match consider_self_bounds {
656            AliasBoundKind::SelfBounds => {
657                for assumption in self
658                    .cx()
659                    .item_self_bounds(alias_ty.def_id)
660                    .iter_instantiated(self.cx(), alias_ty.args)
661                {
662                    candidates.extend(G::probe_and_consider_implied_clause(
663                        self,
664                        CandidateSource::AliasBound,
665                        goal,
666                        assumption,
667                        [],
668                    ));
669                }
670            }
671            AliasBoundKind::NonSelfBounds => {
672                for assumption in self
673                    .cx()
674                    .item_non_self_bounds(alias_ty.def_id)
675                    .iter_instantiated(self.cx(), alias_ty.args)
676                {
677                    candidates.extend(G::probe_and_consider_implied_clause(
678                        self,
679                        CandidateSource::AliasBound,
680                        goal,
681                        assumption,
682                        [],
683                    ));
684                }
685            }
686        }
687
688        candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
689
690        if kind != ty::Projection {
691            return;
692        }
693
694        // Recurse on the self type of the projection.
695        match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) {
696            Ok(next_self_ty) => self.assemble_alias_bound_candidates_recur(
697                next_self_ty,
698                goal,
699                candidates,
700                AliasBoundKind::NonSelfBounds,
701            ),
702            Err(NoSolution) => {}
703        }
704    }
705
706    #[instrument(level = "trace", skip_all)]
707    fn assemble_object_bound_candidates<G: GoalKind<D>>(
708        &mut self,
709        goal: Goal<I, G>,
710        candidates: &mut Vec<Candidate<I>>,
711    ) {
712        let cx = self.cx();
713        if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) {
714            return;
715        }
716
717        let self_ty = goal.predicate.self_ty();
718        let bounds = match self_ty.kind() {
719            ty::Bool
720            | ty::Char
721            | ty::Int(_)
722            | ty::Uint(_)
723            | ty::Float(_)
724            | ty::Adt(_, _)
725            | ty::Foreign(_)
726            | ty::Str
727            | ty::Array(_, _)
728            | ty::Pat(_, _)
729            | ty::Slice(_)
730            | ty::RawPtr(_, _)
731            | ty::Ref(_, _, _)
732            | ty::FnDef(_, _)
733            | ty::FnPtr(..)
734            | ty::UnsafeBinder(_)
735            | ty::Alias(..)
736            | ty::Closure(..)
737            | ty::CoroutineClosure(..)
738            | ty::Coroutine(..)
739            | ty::CoroutineWitness(..)
740            | ty::Never
741            | ty::Tuple(_)
742            | ty::Param(_)
743            | ty::Placeholder(..)
744            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
745            | ty::Error(_) => return,
746            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
747            | ty::Bound(..) => panic!("unexpected self type for `{goal:?}`"),
748            ty::Dynamic(bounds, ..) => bounds,
749        };
750
751        // Do not consider built-in object impls for dyn-incompatible types.
752        if bounds.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
753            return;
754        }
755
756        // Consider all of the auto-trait and projection bounds, which don't
757        // need to be recorded as a `BuiltinImplSource::Object` since they don't
758        // really have a vtable base...
759        for bound in bounds.iter() {
760            match bound.skip_binder() {
761                ty::ExistentialPredicate::Trait(_) => {
762                    // Skip principal
763                }
764                ty::ExistentialPredicate::Projection(_)
765                | ty::ExistentialPredicate::AutoTrait(_) => {
766                    candidates.extend(G::probe_and_consider_object_bound_candidate(
767                        self,
768                        CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
769                        goal,
770                        bound.with_self_ty(cx, self_ty),
771                    ));
772                }
773            }
774        }
775
776        // FIXME: We only need to do *any* of this if we're considering a trait goal,
777        // since we don't need to look at any supertrait or anything if we are doing
778        // a projection goal.
779        if let Some(principal) = bounds.principal() {
780            let principal_trait_ref = principal.with_self_ty(cx, self_ty);
781            for (idx, assumption) in elaborate::supertraits(cx, principal_trait_ref).enumerate() {
782                candidates.extend(G::probe_and_consider_object_bound_candidate(
783                    self,
784                    CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)),
785                    goal,
786                    assumption.upcast(cx),
787                ));
788            }
789        }
790    }
791
792    /// In coherence we have to not only care about all impls we know about, but
793    /// also consider impls which may get added in a downstream or sibling crate
794    /// or which an upstream impl may add in a minor release.
795    ///
796    /// To do so we return a single ambiguous candidate in case such an unknown
797    /// impl could apply to the current goal.
798    #[instrument(level = "trace", skip_all)]
799    fn consider_coherence_unknowable_candidate<G: GoalKind<D>>(
800        &mut self,
801        goal: Goal<I, G>,
802    ) -> Result<Candidate<I>, NoSolution> {
803        self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(|ecx| {
804            let cx = ecx.cx();
805            let trait_ref = goal.predicate.trait_ref(cx);
806            if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
807                Err(NoSolution)
808            } else {
809                // While the trait bound itself may be unknowable, we may be able to
810                // prove that a super trait is not implemented. For this, we recursively
811                // prove the super trait bounds of the current goal.
812                //
813                // We skip the goal itself as that one would cycle.
814                let predicate: I::Predicate = trait_ref.upcast(cx);
815                ecx.add_goals(
816                    GoalSource::Misc,
817                    elaborate::elaborate(cx, [predicate])
818                        .skip(1)
819                        .map(|predicate| goal.with(cx, predicate)),
820                );
821                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
822            }
823        })
824    }
825}
826
827pub(super) enum AllowInferenceConstraints {
828    Yes,
829    No,
830}
831
832impl<D, I> EvalCtxt<'_, D>
833where
834    D: SolverDelegate<Interner = I>,
835    I: Interner,
836{
837    /// Check whether we can ignore impl candidates due to specialization.
838    ///
839    /// This is only necessary for `feature(specialization)` and seems quite ugly.
840    pub(super) fn filter_specialized_impls(
841        &mut self,
842        allow_inference_constraints: AllowInferenceConstraints,
843        candidates: &mut Vec<Candidate<I>>,
844    ) {
845        match self.typing_mode() {
846            TypingMode::Coherence => return,
847            TypingMode::Analysis { .. }
848            | TypingMode::Borrowck { .. }
849            | TypingMode::PostBorrowckAnalysis { .. }
850            | TypingMode::PostAnalysis => {}
851        }
852
853        let mut i = 0;
854        'outer: while i < candidates.len() {
855            let CandidateSource::Impl(victim_def_id) = candidates[i].source else {
856                i += 1;
857                continue;
858            };
859
860            for (j, c) in candidates.iter().enumerate() {
861                if i == j {
862                    continue;
863                }
864
865                let CandidateSource::Impl(other_def_id) = c.source else {
866                    continue;
867                };
868
869                // See if we can toss out `victim` based on specialization.
870                //
871                // While this requires us to know *for sure* that the `lhs` impl applies
872                // we still use modulo regions here. This is fine as specialization currently
873                // assumes that specializing impls have to be always applicable, meaning that
874                // the only allowed region constraints may be constraints also present on the default impl.
875                if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes)
876                    || has_only_region_constraints(c.result)
877                {
878                    if self.cx().impl_specializes(other_def_id, victim_def_id) {
879                        candidates.remove(i);
880                        continue 'outer;
881                    }
882                }
883            }
884
885            i += 1;
886        }
887    }
888
889    /// Assemble and merge candidates for goals which are related to an underlying trait
890    /// goal. Right now, this is normalizes-to and host effect goals.
891    ///
892    /// We sadly can't simply take all possible candidates for normalization goals
893    /// and check whether they result in the same constraints. We want to make sure
894    /// that trying to normalize an alias doesn't result in constraints which aren't
895    /// otherwise required.
896    ///
897    /// Most notably, when proving a trait goal by via a where-bound, we should not
898    /// normalize via impls which have stricter region constraints than the where-bound:
899    ///
900    /// ```rust
901    /// trait Trait<'a> {
902    ///     type Assoc;
903    /// }
904    ///
905    /// impl<'a, T: 'a> Trait<'a> for T {
906    ///     type Assoc = u32;
907    /// }
908    ///
909    /// fn with_bound<'a, T: Trait<'a>>(_value: T::Assoc) {}
910    /// ```
911    ///
912    /// The where-bound of `with_bound` doesn't specify the associated type, so we would
913    /// only be able to normalize `<T as Trait<'a>>::Assoc` by using the impl. This impl
914    /// adds a `T: 'a` bound however, which would result in a region error. Given that the
915    /// user explicitly wrote that `T: Trait<'a>` holds, this is undesirable and we instead
916    /// treat the alias as rigid.
917    ///
918    /// See trait-system-refactor-initiative#124 for more details.
919    #[instrument(level = "debug", skip(self, inject_normalize_to_rigid_candidate), ret)]
920    pub(super) fn assemble_and_merge_candidates<G: GoalKind<D>>(
921        &mut self,
922        proven_via: Option<TraitGoalProvenVia>,
923        goal: Goal<I, G>,
924        inject_normalize_to_rigid_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
925    ) -> QueryResult<I> {
926        let Some(proven_via) = proven_via else {
927            // We don't care about overflow. If proving the trait goal overflowed, then
928            // it's enough to report an overflow error for that, we don't also have to
929            // overflow during normalization.
930            //
931            // We use `forced_ambiguity` here over `make_ambiguous_response_no_constraints`
932            // because the former will also record a built-in candidate in the inspector.
933            return self.forced_ambiguity(MaybeCause::Ambiguity).map(|cand| cand.result);
934        };
935
936        match proven_via {
937            TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
938                // Even when a trait bound has been proven using a where-bound, we
939                // still need to consider alias-bounds for normalization, see
940                // `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
941                let candidates_from_env_and_bounds: Vec<_> = self
942                    .assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::EnvAndBounds);
943
944                // We still need to prefer where-bounds over alias-bounds however.
945                // See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
946                let mut considered_candidates: Vec<_> = if candidates_from_env_and_bounds
947                    .iter()
948                    .any(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
949                {
950                    candidates_from_env_and_bounds
951                        .into_iter()
952                        .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
953                        .map(|c| c.result)
954                        .collect()
955                } else {
956                    candidates_from_env_and_bounds.into_iter().map(|c| c.result).collect()
957                };
958
959                // If the trait goal has been proven by using the environment, we want to treat
960                // aliases as rigid if there are no applicable projection bounds in the environment.
961                if considered_candidates.is_empty() {
962                    if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
963                        considered_candidates.push(response);
964                    }
965                }
966
967                if let Some(response) = self.try_merge_responses(&considered_candidates) {
968                    Ok(response)
969                } else {
970                    self.flounder(&considered_candidates)
971                }
972            }
973            TraitGoalProvenVia::Misc => {
974                let mut candidates =
975                    self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
976
977                // Prefer "orphaned" param-env normalization predicates, which are used
978                // (for example, and ideally only) when proving item bounds for an impl.
979                let candidates_from_env: Vec<_> = candidates
980                    .iter()
981                    .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
982                    .map(|c| c.result)
983                    .collect();
984                if let Some(response) = self.try_merge_responses(&candidates_from_env) {
985                    return Ok(response);
986                }
987
988                // We drop specialized impls to allow normalization via a final impl here. In case
989                // the specializing impl has different inference constraints from the specialized
990                // impl, proving the trait goal is already ambiguous, so we never get here. This
991                // means we can just ignore inference constraints and don't have to special-case
992                // constraining the normalized-to `term`.
993                self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates);
994
995                let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
996                if let Some(response) = self.try_merge_responses(&responses) {
997                    Ok(response)
998                } else {
999                    self.flounder(&responses)
1000                }
1001            }
1002        }
1003    }
1004
1005    /// Compute whether a param-env assumption is global or non-global after normalizing it.
1006    ///
1007    /// This is necessary because, for example, given:
1008    ///
1009    /// ```ignore,rust
1010    /// where
1011    ///     T: Trait<Assoc = u32>,
1012    ///     i32: From<T::Assoc>,
1013    /// ```
1014    ///
1015    /// The `i32: From<T::Assoc>` bound is non-global before normalization, but is global after.
1016    /// Since the old trait solver normalized param-envs eagerly, we want to emulate this
1017    /// behavior lazily.
1018    fn characterize_param_env_assumption(
1019        &mut self,
1020        param_env: I::ParamEnv,
1021        assumption: I::Clause,
1022    ) -> Result<CandidateSource<I>, NoSolution> {
1023        // FIXME: This should be fixed, but it also requires changing the behavior
1024        // in the old solver which is currently relied on.
1025        if assumption.has_bound_vars() {
1026            return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal));
1027        }
1028
1029        match assumption.visit_with(&mut FindParamInClause {
1030            ecx: self,
1031            param_env,
1032            universes: vec![],
1033        }) {
1034            ControlFlow::Break(Err(NoSolution)) => Err(NoSolution),
1035            ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)),
1036            ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)),
1037        }
1038    }
1039}
1040
1041struct FindParamInClause<'a, 'b, D: SolverDelegate<Interner = I>, I: Interner> {
1042    ecx: &'a mut EvalCtxt<'b, D>,
1043    param_env: I::ParamEnv,
1044    universes: Vec<Option<ty::UniverseIndex>>,
1045}
1046
1047impl<D, I> TypeVisitor<I> for FindParamInClause<'_, '_, D, I>
1048where
1049    D: SolverDelegate<Interner = I>,
1050    I: Interner,
1051{
1052    type Result = ControlFlow<Result<(), NoSolution>>;
1053
1054    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
1055        self.universes.push(None);
1056        t.super_visit_with(self)?;
1057        self.universes.pop();
1058        ControlFlow::Continue(())
1059    }
1060
1061    fn visit_ty(&mut self, ty: I::Ty) -> Self::Result {
1062        let ty = self.ecx.replace_bound_vars(ty, &mut self.universes);
1063        let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else {
1064            return ControlFlow::Break(Err(NoSolution));
1065        };
1066
1067        if let ty::Placeholder(p) = ty.kind() {
1068            if p.universe() == ty::UniverseIndex::ROOT {
1069                ControlFlow::Break(Ok(()))
1070            } else {
1071                ControlFlow::Continue(())
1072            }
1073        } else if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
1074            ty.super_visit_with(self)
1075        } else {
1076            ControlFlow::Continue(())
1077        }
1078    }
1079
1080    fn visit_const(&mut self, ct: I::Const) -> Self::Result {
1081        let ct = self.ecx.replace_bound_vars(ct, &mut self.universes);
1082        let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else {
1083            return ControlFlow::Break(Err(NoSolution));
1084        };
1085
1086        if let ty::ConstKind::Placeholder(p) = ct.kind() {
1087            if p.universe() == ty::UniverseIndex::ROOT {
1088                ControlFlow::Break(Ok(()))
1089            } else {
1090                ControlFlow::Continue(())
1091            }
1092        } else if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
1093            ct.super_visit_with(self)
1094        } else {
1095            ControlFlow::Continue(())
1096        }
1097    }
1098
1099    fn visit_region(&mut self, r: I::Region) -> Self::Result {
1100        match self.ecx.eager_resolve_region(r).kind() {
1101            ty::ReStatic | ty::ReError(_) | ty::ReBound(..) => ControlFlow::Continue(()),
1102            ty::RePlaceholder(p) => {
1103                if p.universe() == ty::UniverseIndex::ROOT {
1104                    ControlFlow::Break(Ok(()))
1105                } else {
1106                    ControlFlow::Continue(())
1107                }
1108            }
1109            ty::ReVar(_) => ControlFlow::Break(Ok(())),
1110            ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) => {
1111                unreachable!("unexpected region in param-env clause")
1112            }
1113        }
1114    }
1115}