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