rustc_trait_selection/traits/
project.rs

1//! Code for projecting associated types out of trait references.
2
3use std::ops::ControlFlow;
4
5use rustc_data_structures::sso::SsoHashSet;
6use rustc_data_structures::stack::ensure_sufficient_stack;
7use rustc_errors::ErrorGuaranteed;
8use rustc_hir::def::DefKind;
9use rustc_hir::lang_items::LangItem;
10use rustc_infer::infer::resolve::OpportunisticRegionResolver;
11use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
12use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
13use rustc_middle::traits::select::OverflowError;
14use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
15use rustc_middle::ty::fast_reject::DeepRejectCtxt;
16use rustc_middle::ty::fold::TypeFoldable;
17use rustc_middle::ty::visit::TypeVisitableExt;
18use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
19use rustc_middle::{bug, span_bug};
20use rustc_span::sym;
21use rustc_type_ir::elaborate;
22use thin_vec::thin_vec;
23use tracing::{debug, instrument};
24
25use super::{
26    MismatchedProjectionTypes, Normalized, NormalizedTerm, Obligation, ObligationCause,
27    PredicateObligation, ProjectionCacheEntry, ProjectionCacheKey, Selection, SelectionContext,
28    SelectionError, specialization_graph, translate_args, util,
29};
30use crate::errors::InherentProjectionNormalizationOverflow;
31use crate::infer::{BoundRegionConversionTime, InferOk};
32use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
33use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
34use crate::traits::select::ProjectionMatchesProjection;
35
36pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
37
38pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
39
40pub type ProjectionTermObligation<'tcx> = Obligation<'tcx, ty::AliasTerm<'tcx>>;
41
42pub(super) struct InProgress;
43
44/// When attempting to resolve `<T as TraitRef>::Name` ...
45#[derive(Debug)]
46pub enum ProjectionError<'tcx> {
47    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
48    TooManyCandidates,
49
50    /// ...an error occurred matching `T : TraitRef`
51    TraitSelectionError(SelectionError<'tcx>),
52}
53
54#[derive(PartialEq, Eq, Debug)]
55enum ProjectionCandidate<'tcx> {
56    /// From a where-clause in the env or object type
57    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
58
59    /// From the definition of `Trait` when you have something like
60    /// `<<A as Trait>::B as Trait2>::C`.
61    TraitDef(ty::PolyProjectionPredicate<'tcx>),
62
63    /// Bounds specified on an object type
64    Object(ty::PolyProjectionPredicate<'tcx>),
65
66    /// Built-in bound for a dyn async fn in trait
67    ObjectRpitit,
68
69    /// From an "impl" (or a "pseudo-impl" returned by select)
70    Select(Selection<'tcx>),
71}
72
73enum ProjectionCandidateSet<'tcx> {
74    None,
75    Single(ProjectionCandidate<'tcx>),
76    Ambiguous,
77    Error(SelectionError<'tcx>),
78}
79
80impl<'tcx> ProjectionCandidateSet<'tcx> {
81    fn mark_ambiguous(&mut self) {
82        *self = ProjectionCandidateSet::Ambiguous;
83    }
84
85    fn mark_error(&mut self, err: SelectionError<'tcx>) {
86        *self = ProjectionCandidateSet::Error(err);
87    }
88
89    // Returns true if the push was successful, or false if the candidate
90    // was discarded -- this could be because of ambiguity, or because
91    // a higher-priority candidate is already there.
92    fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool {
93        use self::ProjectionCandidate::*;
94        use self::ProjectionCandidateSet::*;
95
96        // This wacky variable is just used to try and
97        // make code readable and avoid confusing paths.
98        // It is assigned a "value" of `()` only on those
99        // paths in which we wish to convert `*self` to
100        // ambiguous (and return false, because the candidate
101        // was not used). On other paths, it is not assigned,
102        // and hence if those paths *could* reach the code that
103        // comes after the match, this fn would not compile.
104        let convert_to_ambiguous;
105
106        match self {
107            None => {
108                *self = Single(candidate);
109                return true;
110            }
111
112            Single(current) => {
113                // Duplicates can happen inside ParamEnv. In the case, we
114                // perform a lazy deduplication.
115                if current == &candidate {
116                    return false;
117                }
118
119                // Prefer where-clauses. As in select, if there are multiple
120                // candidates, we prefer where-clause candidates over impls. This
121                // may seem a bit surprising, since impls are the source of
122                // "truth" in some sense, but in fact some of the impls that SEEM
123                // applicable are not, because of nested obligations. Where
124                // clauses are the safer choice. See the comment on
125                // `select::SelectionCandidate` and #21974 for more details.
126                match (current, candidate) {
127                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
128                    (ParamEnv(..), _) => return false,
129                    (_, ParamEnv(..)) => bug!(
130                        "should never prefer non-param-env candidates over param-env candidates"
131                    ),
132                    (_, _) => convert_to_ambiguous = (),
133                }
134            }
135
136            Ambiguous | Error(..) => {
137                return false;
138            }
139        }
140
141        // We only ever get here when we moved from a single candidate
142        // to ambiguous.
143        let () = convert_to_ambiguous;
144        *self = Ambiguous;
145        false
146    }
147}
148
149/// States returned from `poly_project_and_unify_type`. Takes the place
150/// of the old return type, which was:
151/// ```ignore (not-rust)
152/// Result<
153///     Result<Option<PredicateObligations<'tcx>>, InProgress>,
154///     MismatchedProjectionTypes<'tcx>,
155/// >
156/// ```
157pub(super) enum ProjectAndUnifyResult<'tcx> {
158    /// The projection bound holds subject to the given obligations. If the
159    /// projection cannot be normalized because the required trait bound does
160    /// not hold, this is returned, with `obligations` being a predicate that
161    /// cannot be proven.
162    Holds(PredicateObligations<'tcx>),
163    /// The projection cannot be normalized due to ambiguity. Resolving some
164    /// inference variables in the projection may fix this.
165    FailedNormalization,
166    /// The project cannot be normalized because `poly_project_and_unify_type`
167    /// is called recursively while normalizing the same projection.
168    Recursive,
169    // the projection can be normalized, but is not equal to the expected type.
170    // Returns the type error that arose from the mismatch.
171    MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>),
172}
173
174/// Evaluates constraints of the form:
175/// ```ignore (not-rust)
176/// for<...> <T as Trait>::U == V
177/// ```
178/// If successful, this may result in additional obligations. Also returns
179/// the projection cache key used to track these additional obligations.
180#[instrument(level = "debug", skip(selcx))]
181pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
182    selcx: &mut SelectionContext<'cx, 'tcx>,
183    obligation: &PolyProjectionObligation<'tcx>,
184) -> ProjectAndUnifyResult<'tcx> {
185    let infcx = selcx.infcx;
186    let r = infcx.commit_if_ok(|_snapshot| {
187        let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate);
188
189        let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
190        match project_and_unify_term(selcx, &placeholder_obligation) {
191            ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
192            other => Ok(other),
193        }
194    });
195
196    match r {
197        Ok(inner) => inner,
198        Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err),
199    }
200}
201
202/// Evaluates constraints of the form:
203/// ```ignore (not-rust)
204/// <T as Trait>::U == V
205/// ```
206/// If successful, this may result in additional obligations.
207///
208/// See [poly_project_and_unify_term] for an explanation of the return value.
209#[instrument(level = "debug", skip(selcx))]
210fn project_and_unify_term<'cx, 'tcx>(
211    selcx: &mut SelectionContext<'cx, 'tcx>,
212    obligation: &ProjectionObligation<'tcx>,
213) -> ProjectAndUnifyResult<'tcx> {
214    let mut obligations = PredicateObligations::new();
215
216    let infcx = selcx.infcx;
217    let normalized = match opt_normalize_projection_term(
218        selcx,
219        obligation.param_env,
220        obligation.predicate.projection_term,
221        obligation.cause.clone(),
222        obligation.recursion_depth,
223        &mut obligations,
224    ) {
225        Ok(Some(n)) => n,
226        Ok(None) => return ProjectAndUnifyResult::FailedNormalization,
227        Err(InProgress) => return ProjectAndUnifyResult::Recursive,
228    };
229    debug!(?normalized, ?obligations, "project_and_unify_type result");
230    let actual = obligation.predicate.term;
231    // For an example where this is necessary see tests/ui/impl-trait/nested-return-type2.rs
232    // This allows users to omit re-mentioning all bounds on an associated type and just use an
233    // `impl Trait` for the assoc type to add more bounds.
234    let InferOk { value: actual, obligations: new } =
235        selcx.infcx.replace_opaque_types_with_inference_vars(
236            actual,
237            obligation.cause.body_id,
238            obligation.cause.span,
239            obligation.param_env,
240        );
241    obligations.extend(new);
242
243    // Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait`
244    match infcx.at(&obligation.cause, obligation.param_env).eq(
245        DefineOpaqueTypes::Yes,
246        normalized,
247        actual,
248    ) {
249        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
250            obligations.extend(inferred_obligations);
251            ProjectAndUnifyResult::Holds(obligations)
252        }
253        Err(err) => {
254            debug!("equating types encountered error {:?}", err);
255            ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err })
256        }
257    }
258}
259
260/// The guts of `normalize`: normalize a specific projection like `<T
261/// as Trait>::Item`. The result is always a type (and possibly
262/// additional obligations). If ambiguity arises, which implies that
263/// there are unresolved type variables in the projection, we will
264/// instantiate it with a fresh type variable `$X` and generate a new
265/// obligation `<T as Trait>::Item == $X` for later.
266pub fn normalize_projection_ty<'a, 'b, 'tcx>(
267    selcx: &'a mut SelectionContext<'b, 'tcx>,
268    param_env: ty::ParamEnv<'tcx>,
269    projection_ty: ty::AliasTy<'tcx>,
270    cause: ObligationCause<'tcx>,
271    depth: usize,
272    obligations: &mut PredicateObligations<'tcx>,
273) -> Term<'tcx> {
274    opt_normalize_projection_term(
275        selcx,
276        param_env,
277        projection_ty.into(),
278        cause.clone(),
279        depth,
280        obligations,
281    )
282    .ok()
283    .flatten()
284    .unwrap_or_else(move || {
285        // if we bottom out in ambiguity, create a type variable
286        // and a deferred predicate to resolve this when more type
287        // information is available.
288
289        selcx
290            .infcx
291            .projection_ty_to_infer(param_env, projection_ty, cause, depth + 1, obligations)
292            .into()
293    })
294}
295
296/// The guts of `normalize`: normalize a specific projection like `<T
297/// as Trait>::Item`. The result is always a type (and possibly
298/// additional obligations). Returns `None` in the case of ambiguity,
299/// which indicates that there are unbound type variables.
300///
301/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
302/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
303/// often immediately appended to another obligations vector. So now this
304/// function takes an obligations vector and appends to it directly, which is
305/// slightly uglier but avoids the need for an extra short-lived allocation.
306#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
307pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
308    selcx: &'a mut SelectionContext<'b, 'tcx>,
309    param_env: ty::ParamEnv<'tcx>,
310    projection_term: ty::AliasTerm<'tcx>,
311    cause: ObligationCause<'tcx>,
312    depth: usize,
313    obligations: &mut PredicateObligations<'tcx>,
314) -> Result<Option<Term<'tcx>>, InProgress> {
315    let infcx = selcx.infcx;
316    debug_assert!(!selcx.infcx.next_trait_solver());
317    let projection_term = infcx.resolve_vars_if_possible(projection_term);
318    let cache_key = ProjectionCacheKey::new(projection_term, param_env);
319
320    // FIXME(#20304) For now, I am caching here, which is good, but it
321    // means we don't capture the type variables that are created in
322    // the case of ambiguity. Which means we may create a large stream
323    // of such variables. OTOH, if we move the caching up a level, we
324    // would not benefit from caching when proving `T: Trait<U=Foo>`
325    // bounds. It might be the case that we want two distinct caches,
326    // or else another kind of cache entry.
327    let cache_entry = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
328    match cache_entry {
329        Ok(()) => debug!("no cache"),
330        Err(ProjectionCacheEntry::Ambiguous) => {
331            // If we found ambiguity the last time, that means we will continue
332            // to do so until some type in the key changes (and we know it
333            // hasn't, because we just fully resolved it).
334            debug!("found cache entry: ambiguous");
335            return Ok(None);
336        }
337        Err(ProjectionCacheEntry::InProgress) => {
338            // Under lazy normalization, this can arise when
339            // bootstrapping. That is, imagine an environment with a
340            // where-clause like `A::B == u32`. Now, if we are asked
341            // to normalize `A::B`, we will want to check the
342            // where-clauses in scope. So we will try to unify `A::B`
343            // with `A::B`, which can trigger a recursive
344            // normalization.
345
346            debug!("found cache entry: in-progress");
347
348            // Cache that normalizing this projection resulted in a cycle. This
349            // should ensure that, unless this happens within a snapshot that's
350            // rolled back, fulfillment or evaluation will notice the cycle.
351            infcx.inner.borrow_mut().projection_cache().recur(cache_key);
352            return Err(InProgress);
353        }
354        Err(ProjectionCacheEntry::Recur) => {
355            debug!("recur cache");
356            return Err(InProgress);
357        }
358        Err(ProjectionCacheEntry::NormalizedTerm { ty, complete: _ }) => {
359            // This is the hottest path in this function.
360            //
361            // If we find the value in the cache, then return it along
362            // with the obligations that went along with it. Note
363            // that, when using a fulfillment context, these
364            // obligations could in principle be ignored: they have
365            // already been registered when the cache entry was
366            // created (and hence the new ones will quickly be
367            // discarded as duplicated). But when doing trait
368            // evaluation this is not the case, and dropping the trait
369            // evaluations can causes ICEs (e.g., #43132).
370            debug!(?ty, "found normalized ty");
371            obligations.extend(ty.obligations);
372            return Ok(Some(ty.value));
373        }
374        Err(ProjectionCacheEntry::Error) => {
375            debug!("opt_normalize_projection_type: found error");
376            let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
377            obligations.extend(result.obligations);
378            return Ok(Some(result.value));
379        }
380    }
381
382    let obligation =
383        Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_term);
384
385    match project(selcx, &obligation) {
386        Ok(Projected::Progress(Progress {
387            term: projected_term,
388            obligations: mut projected_obligations,
389        })) => {
390            // if projection succeeded, then what we get out of this
391            // is also non-normalized (consider: it was derived from
392            // an impl, where-clause etc) and hence we must
393            // re-normalize it
394
395            let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
396
397            let mut result = if projected_term.has_aliases() {
398                let normalized_ty = normalize_with_depth_to(
399                    selcx,
400                    param_env,
401                    cause,
402                    depth + 1,
403                    projected_term,
404                    &mut projected_obligations,
405                );
406
407                Normalized { value: normalized_ty, obligations: projected_obligations }
408            } else {
409                Normalized { value: projected_term, obligations: projected_obligations }
410            };
411
412            let mut deduped = SsoHashSet::with_capacity(result.obligations.len());
413            result.obligations.retain(|obligation| deduped.insert(obligation.clone()));
414
415            infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
416            obligations.extend(result.obligations);
417            Ok(Some(result.value))
418        }
419        Ok(Projected::NoProgress(projected_ty)) => {
420            let result =
421                Normalized { value: projected_ty, obligations: PredicateObligations::new() };
422            infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
423            // No need to extend `obligations`.
424            Ok(Some(result.value))
425        }
426        Err(ProjectionError::TooManyCandidates) => {
427            debug!("opt_normalize_projection_type: too many candidates");
428            infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
429            Ok(None)
430        }
431        Err(ProjectionError::TraitSelectionError(_)) => {
432            debug!("opt_normalize_projection_type: ERROR");
433            // if we got an error processing the `T as Trait` part,
434            // just return `ty::err` but add the obligation `T :
435            // Trait`, which when processed will cause the error to be
436            // reported later
437            infcx.inner.borrow_mut().projection_cache().error(cache_key);
438            let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
439            obligations.extend(result.obligations);
440            Ok(Some(result.value))
441        }
442    }
443}
444
445/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
446/// hold. In various error cases, we cannot generate a valid
447/// normalized projection. Therefore, we create an inference variable
448/// return an associated obligation that, when fulfilled, will lead to
449/// an error.
450///
451/// Note that we used to return `Error` here, but that was quite
452/// dubious -- the premise was that an error would *eventually* be
453/// reported, when the obligation was processed. But in general once
454/// you see an `Error` you are supposed to be able to assume that an
455/// error *has been* reported, so that you can take whatever heuristic
456/// paths you want to take. To make things worse, it was possible for
457/// cycles to arise, where you basically had a setup like `<MyType<$0>
458/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
459/// Trait>::Foo>` to `[type error]` would lead to an obligation of
460/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
461/// an error for this obligation, but we legitimately should not,
462/// because it contains `[type error]`. Yuck! (See issue #29857 for
463/// one case where this arose.)
464fn normalize_to_error<'a, 'tcx>(
465    selcx: &SelectionContext<'a, 'tcx>,
466    param_env: ty::ParamEnv<'tcx>,
467    projection_term: ty::AliasTerm<'tcx>,
468    cause: ObligationCause<'tcx>,
469    depth: usize,
470) -> NormalizedTerm<'tcx> {
471    let trait_ref = ty::Binder::dummy(projection_term.trait_ref(selcx.tcx()));
472    let new_value = match projection_term.kind(selcx.tcx()) {
473        ty::AliasTermKind::ProjectionTy
474        | ty::AliasTermKind::InherentTy
475        | ty::AliasTermKind::OpaqueTy
476        | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
477        ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
478            selcx.infcx.next_const_var(cause.span).into()
479        }
480    };
481    let mut obligations = PredicateObligations::new();
482    obligations.push(Obligation {
483        cause,
484        recursion_depth: depth,
485        param_env,
486        predicate: trait_ref.upcast(selcx.tcx()),
487    });
488    Normalized { value: new_value, obligations }
489}
490
491/// Confirm and normalize the given inherent projection.
492#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
493pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
494    selcx: &'a mut SelectionContext<'b, 'tcx>,
495    param_env: ty::ParamEnv<'tcx>,
496    alias_ty: ty::AliasTy<'tcx>,
497    cause: ObligationCause<'tcx>,
498    depth: usize,
499    obligations: &mut PredicateObligations<'tcx>,
500) -> Ty<'tcx> {
501    let tcx = selcx.tcx();
502
503    if !tcx.recursion_limit().value_within_limit(depth) {
504        // Halt compilation because it is important that overflows never be masked.
505        tcx.dcx().emit_fatal(InherentProjectionNormalizationOverflow {
506            span: cause.span,
507            ty: alias_ty.to_string(),
508        });
509    }
510
511    let args = compute_inherent_assoc_ty_args(
512        selcx,
513        param_env,
514        alias_ty,
515        cause.clone(),
516        depth,
517        obligations,
518    );
519
520    // Register the obligations arising from the impl and from the associated type itself.
521    let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, args);
522    for (predicate, span) in predicates {
523        let predicate = normalize_with_depth_to(
524            selcx,
525            param_env,
526            cause.clone(),
527            depth + 1,
528            predicate,
529            obligations,
530        );
531
532        let nested_cause = ObligationCause::new(
533            cause.span,
534            cause.body_id,
535            // FIXME(inherent_associated_types): Since we can't pass along the self type to the
536            // cause code, inherent projections will be printed with identity instantiation in
537            // diagnostics which is not ideal.
538            // Consider creating separate cause codes for this specific situation.
539            ObligationCauseCode::WhereClause(alias_ty.def_id, span),
540        );
541
542        obligations.push(Obligation::with_depth(
543            tcx,
544            nested_cause,
545            depth + 1,
546            param_env,
547            predicate,
548        ));
549    }
550
551    let ty = tcx.type_of(alias_ty.def_id).instantiate(tcx, args);
552
553    let mut ty = selcx.infcx.resolve_vars_if_possible(ty);
554    if ty.has_aliases() {
555        ty = normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, ty, obligations);
556    }
557
558    ty
559}
560
561pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
562    selcx: &'a mut SelectionContext<'b, 'tcx>,
563    param_env: ty::ParamEnv<'tcx>,
564    alias_ty: ty::AliasTy<'tcx>,
565    cause: ObligationCause<'tcx>,
566    depth: usize,
567    obligations: &mut PredicateObligations<'tcx>,
568) -> ty::GenericArgsRef<'tcx> {
569    let tcx = selcx.tcx();
570
571    let impl_def_id = tcx.parent(alias_ty.def_id);
572    let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
573
574    let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
575    if !selcx.infcx.next_trait_solver() {
576        impl_ty = normalize_with_depth_to(
577            selcx,
578            param_env,
579            cause.clone(),
580            depth + 1,
581            impl_ty,
582            obligations,
583        );
584    }
585
586    // Infer the generic parameters of the impl by unifying the
587    // impl type with the self type of the projection.
588    let mut self_ty = alias_ty.self_ty();
589    if !selcx.infcx.next_trait_solver() {
590        self_ty = normalize_with_depth_to(
591            selcx,
592            param_env,
593            cause.clone(),
594            depth + 1,
595            self_ty,
596            obligations,
597        );
598    }
599
600    match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::Yes, impl_ty, self_ty) {
601        Ok(mut ok) => obligations.append(&mut ok.obligations),
602        Err(_) => {
603            tcx.dcx().span_bug(
604                cause.span,
605                format!("{self_ty:?} was equal to {impl_ty:?} during selection but now it is not"),
606            );
607        }
608    }
609
610    alias_ty.rebase_inherent_args_onto_impl(impl_args, tcx)
611}
612
613enum Projected<'tcx> {
614    Progress(Progress<'tcx>),
615    NoProgress(ty::Term<'tcx>),
616}
617
618struct Progress<'tcx> {
619    term: ty::Term<'tcx>,
620    obligations: PredicateObligations<'tcx>,
621}
622
623impl<'tcx> Progress<'tcx> {
624    fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
625        Progress { term: Ty::new_error(tcx, guar).into(), obligations: PredicateObligations::new() }
626    }
627
628    fn with_addl_obligations(mut self, mut obligations: PredicateObligations<'tcx>) -> Self {
629        self.obligations.append(&mut obligations);
630        self
631    }
632}
633
634/// Computes the result of a projection type (if we can).
635///
636/// IMPORTANT:
637/// - `obligation` must be fully normalized
638#[instrument(level = "info", skip(selcx))]
639fn project<'cx, 'tcx>(
640    selcx: &mut SelectionContext<'cx, 'tcx>,
641    obligation: &ProjectionTermObligation<'tcx>,
642) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
643    if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
644        // This should really be an immediate error, but some existing code
645        // relies on being able to recover from this.
646        return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow(
647            OverflowError::Canonical,
648        )));
649    }
650
651    if let Err(guar) = obligation.predicate.error_reported() {
652        return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar)));
653    }
654
655    let mut candidates = ProjectionCandidateSet::None;
656
657    // Make sure that the following procedures are kept in order. ParamEnv
658    // needs to be first because it has highest priority, and Select checks
659    // the return value of push_candidate which assumes it's ran at last.
660    assemble_candidates_from_param_env(selcx, obligation, &mut candidates);
661
662    assemble_candidates_from_trait_def(selcx, obligation, &mut candidates);
663
664    assemble_candidates_from_object_ty(selcx, obligation, &mut candidates);
665
666    if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates {
667        // Avoid normalization cycle from selection (see
668        // `assemble_candidates_from_object_ty`).
669        // FIXME(lazy_normalization): Lazy normalization should save us from
670        // having to special case this.
671    } else {
672        assemble_candidates_from_impls(selcx, obligation, &mut candidates);
673    };
674
675    match candidates {
676        ProjectionCandidateSet::Single(candidate) => {
677            Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
678        }
679        ProjectionCandidateSet::None => {
680            let tcx = selcx.tcx();
681            let term = match tcx.def_kind(obligation.predicate.def_id) {
682                DefKind::AssocTy => Ty::new_projection_from_args(
683                    tcx,
684                    obligation.predicate.def_id,
685                    obligation.predicate.args,
686                )
687                .into(),
688                DefKind::AssocConst => ty::Const::new_unevaluated(
689                    tcx,
690                    ty::UnevaluatedConst::new(
691                        obligation.predicate.def_id,
692                        obligation.predicate.args,
693                    ),
694                )
695                .into(),
696                kind => {
697                    bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id))
698                }
699            };
700
701            Ok(Projected::NoProgress(term))
702        }
703        // Error occurred while trying to processing impls.
704        ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)),
705        // Inherent ambiguity that prevents us from even enumerating the
706        // candidates.
707        ProjectionCandidateSet::Ambiguous => Err(ProjectionError::TooManyCandidates),
708    }
709}
710
711/// The first thing we have to do is scan through the parameter
712/// environment to see whether there are any projection predicates
713/// there that can answer this question.
714fn assemble_candidates_from_param_env<'cx, 'tcx>(
715    selcx: &mut SelectionContext<'cx, 'tcx>,
716    obligation: &ProjectionTermObligation<'tcx>,
717    candidate_set: &mut ProjectionCandidateSet<'tcx>,
718) {
719    assemble_candidates_from_predicates(
720        selcx,
721        obligation,
722        candidate_set,
723        ProjectionCandidate::ParamEnv,
724        obligation.param_env.caller_bounds().iter(),
725        false,
726    );
727}
728
729/// In the case of a nested projection like `<<A as Foo>::FooT as Bar>::BarT`, we may find
730/// that the definition of `Foo` has some clues:
731///
732/// ```ignore (illustrative)
733/// trait Foo {
734///     type FooT : Bar<BarT=i32>
735/// }
736/// ```
737///
738/// Here, for example, we could conclude that the result is `i32`.
739fn assemble_candidates_from_trait_def<'cx, 'tcx>(
740    selcx: &mut SelectionContext<'cx, 'tcx>,
741    obligation: &ProjectionTermObligation<'tcx>,
742    candidate_set: &mut ProjectionCandidateSet<'tcx>,
743) {
744    debug!("assemble_candidates_from_trait_def(..)");
745    let mut ambiguous = false;
746    selcx.for_each_item_bound(
747        obligation.predicate.self_ty(),
748        |selcx, clause, _| {
749            let Some(clause) = clause.as_projection_clause() else {
750                return ControlFlow::Continue(());
751            };
752            if clause.item_def_id() != obligation.predicate.def_id {
753                return ControlFlow::Continue(());
754            }
755
756            let is_match =
757                selcx.infcx.probe(|_| selcx.match_projection_projections(obligation, clause, true));
758
759            match is_match {
760                ProjectionMatchesProjection::Yes => {
761                    candidate_set.push_candidate(ProjectionCandidate::TraitDef(clause));
762
763                    if !obligation.predicate.has_non_region_infer() {
764                        // HACK: Pick the first trait def candidate for a fully
765                        // inferred predicate. This is to allow duplicates that
766                        // differ only in normalization.
767                        return ControlFlow::Break(());
768                    }
769                }
770                ProjectionMatchesProjection::Ambiguous => {
771                    candidate_set.mark_ambiguous();
772                }
773                ProjectionMatchesProjection::No => {}
774            }
775
776            ControlFlow::Continue(())
777        },
778        // `ProjectionCandidateSet` is borrowed in the above closure,
779        // so just mark ambiguous outside of the closure.
780        || ambiguous = true,
781    );
782
783    if ambiguous {
784        candidate_set.mark_ambiguous();
785    }
786}
787
788/// In the case of a trait object like
789/// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
790/// predicate in the trait object.
791///
792/// We don't go through the select candidate for these bounds to avoid cycles:
793/// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
794/// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
795/// this then has to be normalized without having to prove
796/// `dyn Iterator<Item = ()>: Iterator` again.
797fn assemble_candidates_from_object_ty<'cx, 'tcx>(
798    selcx: &mut SelectionContext<'cx, 'tcx>,
799    obligation: &ProjectionTermObligation<'tcx>,
800    candidate_set: &mut ProjectionCandidateSet<'tcx>,
801) {
802    debug!("assemble_candidates_from_object_ty(..)");
803
804    let tcx = selcx.tcx();
805
806    if !tcx.trait_def(obligation.predicate.trait_def_id(tcx)).implement_via_object {
807        return;
808    }
809
810    let self_ty = obligation.predicate.self_ty();
811    let object_ty = selcx.infcx.shallow_resolve(self_ty);
812    let data = match object_ty.kind() {
813        ty::Dynamic(data, ..) => data,
814        ty::Infer(ty::TyVar(_)) => {
815            // If the self-type is an inference variable, then it MAY wind up
816            // being an object type, so induce an ambiguity.
817            candidate_set.mark_ambiguous();
818            return;
819        }
820        _ => return,
821    };
822    let env_predicates = data
823        .projection_bounds()
824        .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
825        .map(|p| p.with_self_ty(tcx, object_ty).upcast(tcx));
826
827    assemble_candidates_from_predicates(
828        selcx,
829        obligation,
830        candidate_set,
831        ProjectionCandidate::Object,
832        env_predicates,
833        false,
834    );
835
836    // `dyn Trait` automagically project their AFITs to `dyn* Future`.
837    if tcx.is_impl_trait_in_trait(obligation.predicate.def_id)
838        && let Some(out_trait_def_id) = data.principal_def_id()
839        && let rpitit_trait_def_id = tcx.parent(obligation.predicate.def_id)
840        && elaborate::supertrait_def_ids(tcx, out_trait_def_id)
841            .any(|trait_def_id| trait_def_id == rpitit_trait_def_id)
842    {
843        candidate_set.push_candidate(ProjectionCandidate::ObjectRpitit);
844    }
845}
846
847#[instrument(
848    level = "debug",
849    skip(selcx, candidate_set, ctor, env_predicates, potentially_unnormalized_candidates)
850)]
851fn assemble_candidates_from_predicates<'cx, 'tcx>(
852    selcx: &mut SelectionContext<'cx, 'tcx>,
853    obligation: &ProjectionTermObligation<'tcx>,
854    candidate_set: &mut ProjectionCandidateSet<'tcx>,
855    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>,
856    env_predicates: impl Iterator<Item = ty::Clause<'tcx>>,
857    potentially_unnormalized_candidates: bool,
858) {
859    let infcx = selcx.infcx;
860    let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
861    for predicate in env_predicates {
862        let bound_predicate = predicate.kind();
863        if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
864            let data = bound_predicate.rebind(data);
865            if data.item_def_id() != obligation.predicate.def_id {
866                continue;
867            }
868
869            if !drcx
870                .args_may_unify(obligation.predicate.args, data.skip_binder().projection_term.args)
871            {
872                continue;
873            }
874
875            let is_match = infcx.probe(|_| {
876                selcx.match_projection_projections(
877                    obligation,
878                    data,
879                    potentially_unnormalized_candidates,
880                )
881            });
882
883            match is_match {
884                ProjectionMatchesProjection::Yes => {
885                    candidate_set.push_candidate(ctor(data));
886
887                    if potentially_unnormalized_candidates
888                        && !obligation.predicate.has_non_region_infer()
889                    {
890                        // HACK: Pick the first trait def candidate for a fully
891                        // inferred predicate. This is to allow duplicates that
892                        // differ only in normalization.
893                        return;
894                    }
895                }
896                ProjectionMatchesProjection::Ambiguous => {
897                    candidate_set.mark_ambiguous();
898                }
899                ProjectionMatchesProjection::No => {}
900            }
901        }
902    }
903}
904
905#[instrument(level = "debug", skip(selcx, obligation, candidate_set))]
906fn assemble_candidates_from_impls<'cx, 'tcx>(
907    selcx: &mut SelectionContext<'cx, 'tcx>,
908    obligation: &ProjectionTermObligation<'tcx>,
909    candidate_set: &mut ProjectionCandidateSet<'tcx>,
910) {
911    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
912    // start out by selecting the predicate `T as TraitRef<...>`:
913    let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
914    let trait_obligation = obligation.with(selcx.tcx(), trait_ref);
915    let _ = selcx.infcx.commit_if_ok(|_| {
916        let impl_source = match selcx.select(&trait_obligation) {
917            Ok(Some(impl_source)) => impl_source,
918            Ok(None) => {
919                candidate_set.mark_ambiguous();
920                return Err(());
921            }
922            Err(e) => {
923                debug!(error = ?e, "selection error");
924                candidate_set.mark_error(e);
925                return Err(());
926            }
927        };
928
929        let eligible = match &impl_source {
930            ImplSource::UserDefined(impl_data) => {
931                // We have to be careful when projecting out of an
932                // impl because of specialization. If we are not in
933                // codegen (i.e., projection mode is not "any"), and the
934                // impl's type is declared as default, then we disable
935                // projection (even if the trait ref is fully
936                // monomorphic). In the case where trait ref is not
937                // fully monomorphic (i.e., includes type parameters),
938                // this is because those type parameters may
939                // ultimately be bound to types from other crates that
940                // may have specialized impls we can't see. In the
941                // case where the trait ref IS fully monomorphic, this
942                // is a policy decision that we made in the RFC in
943                // order to preserve flexibility for the crate that
944                // defined the specializable impl to specialize later
945                // for existing types.
946                //
947                // In either case, we handle this by not adding a
948                // candidate for an impl if it contains a `default`
949                // type.
950                //
951                // NOTE: This should be kept in sync with the similar code in
952                // `rustc_ty_utils::instance::resolve_associated_item()`.
953                match specialization_graph::assoc_def(
954                    selcx.tcx(),
955                    impl_data.impl_def_id,
956                    obligation.predicate.def_id,
957                ) {
958                    Ok(node_item) => {
959                        if node_item.is_final() {
960                            // Non-specializable items are always projectable.
961                            true
962                        } else {
963                            // Only reveal a specializable default if we're past type-checking
964                            // and the obligation is monomorphic, otherwise passes such as
965                            // transmute checking and polymorphic MIR optimizations could
966                            // get a result which isn't correct for all monomorphizations.
967                            match selcx.infcx.typing_mode() {
968                                TypingMode::Coherence
969                                | TypingMode::Analysis { .. }
970                                | TypingMode::PostBorrowckAnalysis { .. } => {
971                                    debug!(
972                                        assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
973                                        ?obligation.predicate,
974                                        "not eligible due to default",
975                                    );
976                                    false
977                                }
978                                TypingMode::PostAnalysis => {
979                                    // NOTE(eddyb) inference variables can resolve to parameters, so
980                                    // assume `poly_trait_ref` isn't monomorphic, if it contains any.
981                                    let poly_trait_ref =
982                                        selcx.infcx.resolve_vars_if_possible(trait_ref);
983                                    !poly_trait_ref.still_further_specializable()
984                                }
985                            }
986                        }
987                    }
988                    // Always project `ErrorGuaranteed`, since this will just help
989                    // us propagate `TyKind::Error` around which suppresses ICEs
990                    // and spurious, unrelated inference errors.
991                    Err(ErrorGuaranteed { .. }) => true,
992                }
993            }
994            ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, _) => {
995                // While a builtin impl may be known to exist, the associated type may not yet
996                // be known. Any type with multiple potential associated types is therefore
997                // not eligible.
998                let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
999
1000                let tcx = selcx.tcx();
1001                let lang_items = selcx.tcx().lang_items();
1002                if [
1003                    lang_items.coroutine_trait(),
1004                    lang_items.future_trait(),
1005                    lang_items.iterator_trait(),
1006                    lang_items.async_iterator_trait(),
1007                    lang_items.fn_trait(),
1008                    lang_items.fn_mut_trait(),
1009                    lang_items.fn_once_trait(),
1010                    lang_items.async_fn_trait(),
1011                    lang_items.async_fn_mut_trait(),
1012                    lang_items.async_fn_once_trait(),
1013                ]
1014                .contains(&Some(trait_ref.def_id))
1015                {
1016                    true
1017                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnKindHelper) {
1018                    // FIXME(async_closures): Validity constraints here could be cleaned up.
1019                    if obligation.predicate.args.type_at(0).is_ty_var()
1020                        || obligation.predicate.args.type_at(4).is_ty_var()
1021                        || obligation.predicate.args.type_at(5).is_ty_var()
1022                    {
1023                        candidate_set.mark_ambiguous();
1024                        true
1025                    } else {
1026                        obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
1027                            && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
1028                    }
1029                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::DiscriminantKind) {
1030                    match self_ty.kind() {
1031                        ty::Bool
1032                        | ty::Char
1033                        | ty::Int(_)
1034                        | ty::Uint(_)
1035                        | ty::Float(_)
1036                        | ty::Adt(..)
1037                        | ty::Foreign(_)
1038                        | ty::Str
1039                        | ty::Array(..)
1040                        | ty::Pat(..)
1041                        | ty::Slice(_)
1042                        | ty::RawPtr(..)
1043                        | ty::Ref(..)
1044                        | ty::FnDef(..)
1045                        | ty::FnPtr(..)
1046                        | ty::Dynamic(..)
1047                        | ty::Closure(..)
1048                        | ty::CoroutineClosure(..)
1049                        | ty::Coroutine(..)
1050                        | ty::CoroutineWitness(..)
1051                        | ty::Never
1052                        | ty::Tuple(..)
1053                        // Integers and floats always have `u8` as their discriminant.
1054                        | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
1055
1056                        ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1057
1058                        // type parameters, opaques, and unnormalized projections don't have
1059                        // a known discriminant and may need to be normalized further or rely
1060                        // on param env for discriminant projections
1061                        ty::Param(_)
1062                        | ty::Alias(..)
1063                        | ty::Bound(..)
1064                        | ty::Placeholder(..)
1065                        | ty::Infer(..)
1066                        | ty::Error(_) => false,
1067                    }
1068                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncDestruct) {
1069                    match self_ty.kind() {
1070                        ty::Bool
1071                        | ty::Char
1072                        | ty::Int(_)
1073                        | ty::Uint(_)
1074                        | ty::Float(_)
1075                        | ty::Adt(..)
1076                        | ty::Str
1077                        | ty::Array(..)
1078                        | ty::Slice(_)
1079                        | ty::RawPtr(..)
1080                        | ty::Ref(..)
1081                        | ty::FnDef(..)
1082                        | ty::FnPtr(..)
1083                        | ty::UnsafeBinder(_)
1084                        | ty::Dynamic(..)
1085                        | ty::Closure(..)
1086                        | ty::CoroutineClosure(..)
1087                        | ty::Coroutine(..)
1088                        | ty::CoroutineWitness(..)
1089                        | ty::Pat(..)
1090                        | ty::Never
1091                        | ty::Tuple(..)
1092                        | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
1093
1094                        // type parameters, opaques, and unnormalized projections don't have
1095                        // a known async destructor and may need to be normalized further or rely
1096                        // on param env for async destructor projections
1097                        ty::Param(_)
1098                        | ty::Foreign(_)
1099                        | ty::Alias(..)
1100                        | ty::Bound(..)
1101                        | ty::Placeholder(..)
1102                        | ty::Infer(_)
1103                        | ty::Error(_) => false,
1104                    }
1105                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
1106                    let tail = selcx.tcx().struct_tail_raw(
1107                        self_ty,
1108                        |ty| {
1109                            // We throw away any obligations we get from this, since we normalize
1110                            // and confirm these obligations once again during confirmation
1111                            normalize_with_depth(
1112                                selcx,
1113                                obligation.param_env,
1114                                obligation.cause.clone(),
1115                                obligation.recursion_depth + 1,
1116                                ty,
1117                            )
1118                            .value
1119                        },
1120                        || {},
1121                    );
1122
1123                    match tail.kind() {
1124                        ty::Bool
1125                        | ty::Char
1126                        | ty::Int(_)
1127                        | ty::Uint(_)
1128                        | ty::Float(_)
1129                        | ty::Str
1130                        | ty::Array(..)
1131                        | ty::Pat(..)
1132                        | ty::Slice(_)
1133                        | ty::RawPtr(..)
1134                        | ty::Ref(..)
1135                        | ty::FnDef(..)
1136                        | ty::FnPtr(..)
1137                        | ty::Dynamic(..)
1138                        | ty::Closure(..)
1139                        | ty::CoroutineClosure(..)
1140                        | ty::Coroutine(..)
1141                        | ty::CoroutineWitness(..)
1142                        | ty::Never
1143                        // Extern types have unit metadata, according to RFC 2850
1144                        | ty::Foreign(_)
1145                        // If returned by `struct_tail` this is a unit struct
1146                        // without any fields, or not a struct, and therefore is Sized.
1147                        | ty::Adt(..)
1148                        // If returned by `struct_tail` this is the empty tuple.
1149                        | ty::Tuple(..)
1150                        // Integers and floats are always Sized, and so have unit type metadata.
1151                        | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
1152                        // This happens if we reach the recursion limit when finding the struct tail.
1153                        | ty::Error(..) => true,
1154
1155                        // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
1156                        // Otherwise, type parameters, opaques, and unnormalized projections have
1157                        // unit metadata if they're known (e.g. by the param_env) to be sized.
1158                        ty::Param(_) | ty::Alias(..)
1159                            if self_ty != tail
1160                                || selcx.infcx.predicate_must_hold_modulo_regions(
1161                                    &obligation.with(
1162                                        selcx.tcx(),
1163                                        ty::TraitRef::new(
1164                                            selcx.tcx(),
1165                                            selcx.tcx().require_lang_item(
1166                                                LangItem::Sized,
1167                                                Some(obligation.cause.span),
1168                                            ),
1169                                            [self_ty],
1170                                        ),
1171                                    ),
1172                                ) =>
1173                        {
1174                            true
1175                        }
1176
1177                        ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1178
1179                        // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
1180                        ty::Param(_)
1181                        | ty::Alias(..)
1182                        | ty::Bound(..)
1183                        | ty::Placeholder(..)
1184                        | ty::Infer(..) => {
1185                            if tail.has_infer_types() {
1186                                candidate_set.mark_ambiguous();
1187                            }
1188                            false
1189                        }
1190                    }
1191                } else if tcx.trait_is_auto(trait_ref.def_id) {
1192                    tcx.dcx().span_delayed_bug(
1193                        tcx.def_span(obligation.predicate.def_id),
1194                        "associated types not allowed on auto traits",
1195                    );
1196                    false
1197                } else {
1198                    bug!("unexpected builtin trait with associated type: {trait_ref:?}")
1199                }
1200            }
1201            ImplSource::Param(..) => {
1202                // This case tell us nothing about the value of an
1203                // associated type. Consider:
1204                //
1205                // ```
1206                // trait SomeTrait { type Foo; }
1207                // fn foo<T:SomeTrait>(...) { }
1208                // ```
1209                //
1210                // If the user writes `<T as SomeTrait>::Foo`, then the `T
1211                // : SomeTrait` binding does not help us decide what the
1212                // type `Foo` is (at least, not more specifically than
1213                // what we already knew).
1214                //
1215                // But wait, you say! What about an example like this:
1216                //
1217                // ```
1218                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
1219                // ```
1220                //
1221                // Doesn't the `T : SomeTrait<Foo=usize>` predicate help
1222                // resolve `T::Foo`? And of course it does, but in fact
1223                // that single predicate is desugared into two predicates
1224                // in the compiler: a trait predicate (`T : SomeTrait`) and a
1225                // projection. And the projection where clause is handled
1226                // in `assemble_candidates_from_param_env`.
1227                false
1228            }
1229            ImplSource::Builtin(BuiltinImplSource::Object { .. }, _) => {
1230                // Handled by the `Object` projection candidate. See
1231                // `assemble_candidates_from_object_ty` for an explanation of
1232                // why we special case object types.
1233                false
1234            }
1235            ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
1236            | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
1237                // These traits have no associated types.
1238                selcx.tcx().dcx().span_delayed_bug(
1239                    obligation.cause.span,
1240                    format!("Cannot project an associated type from `{impl_source:?}`"),
1241                );
1242                return Err(());
1243            }
1244        };
1245
1246        if eligible {
1247            if candidate_set.push_candidate(ProjectionCandidate::Select(impl_source)) {
1248                Ok(())
1249            } else {
1250                Err(())
1251            }
1252        } else {
1253            Err(())
1254        }
1255    });
1256}
1257
1258fn confirm_candidate<'cx, 'tcx>(
1259    selcx: &mut SelectionContext<'cx, 'tcx>,
1260    obligation: &ProjectionTermObligation<'tcx>,
1261    candidate: ProjectionCandidate<'tcx>,
1262) -> Progress<'tcx> {
1263    debug!(?obligation, ?candidate, "confirm_candidate");
1264    let mut progress = match candidate {
1265        ProjectionCandidate::ParamEnv(poly_projection)
1266        | ProjectionCandidate::Object(poly_projection) => {
1267            confirm_param_env_candidate(selcx, obligation, poly_projection, false)
1268        }
1269
1270        ProjectionCandidate::TraitDef(poly_projection) => {
1271            confirm_param_env_candidate(selcx, obligation, poly_projection, true)
1272        }
1273
1274        ProjectionCandidate::Select(impl_source) => {
1275            confirm_select_candidate(selcx, obligation, impl_source)
1276        }
1277
1278        ProjectionCandidate::ObjectRpitit => confirm_object_rpitit_candidate(selcx, obligation),
1279    };
1280
1281    // When checking for cycle during evaluation, we compare predicates with
1282    // "syntactic" equality. Since normalization generally introduces a type
1283    // with new region variables, we need to resolve them to existing variables
1284    // when possible for this to work. See `auto-trait-projection-recursion.rs`
1285    // for a case where this matters.
1286    if progress.term.has_infer_regions() {
1287        progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx));
1288    }
1289    progress
1290}
1291
1292fn confirm_select_candidate<'cx, 'tcx>(
1293    selcx: &mut SelectionContext<'cx, 'tcx>,
1294    obligation: &ProjectionTermObligation<'tcx>,
1295    impl_source: Selection<'tcx>,
1296) -> Progress<'tcx> {
1297    match impl_source {
1298        ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
1299        ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, data) => {
1300            let tcx = selcx.tcx();
1301            let trait_def_id = obligation.predicate.trait_def_id(tcx);
1302            if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
1303                confirm_coroutine_candidate(selcx, obligation, data)
1304            } else if tcx.is_lang_item(trait_def_id, LangItem::Future) {
1305                confirm_future_candidate(selcx, obligation, data)
1306            } else if tcx.is_lang_item(trait_def_id, LangItem::Iterator) {
1307                confirm_iterator_candidate(selcx, obligation, data)
1308            } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncIterator) {
1309                confirm_async_iterator_candidate(selcx, obligation, data)
1310            } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
1311                if obligation.predicate.self_ty().is_closure()
1312                    || obligation.predicate.self_ty().is_coroutine_closure()
1313                {
1314                    confirm_closure_candidate(selcx, obligation, data)
1315                } else {
1316                    confirm_fn_pointer_candidate(selcx, obligation, data)
1317                }
1318            } else if selcx.tcx().async_fn_trait_kind_from_def_id(trait_def_id).is_some() {
1319                confirm_async_closure_candidate(selcx, obligation, data)
1320            } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncFnKindHelper) {
1321                confirm_async_fn_kind_helper_candidate(selcx, obligation, data)
1322            } else {
1323                confirm_builtin_candidate(selcx, obligation, data)
1324            }
1325        }
1326        ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
1327        | ImplSource::Param(..)
1328        | ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
1329        | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
1330            // we don't create Select candidates with this kind of resolution
1331            span_bug!(
1332                obligation.cause.span,
1333                "Cannot project an associated type from `{:?}`",
1334                impl_source
1335            )
1336        }
1337    }
1338}
1339
1340fn confirm_coroutine_candidate<'cx, 'tcx>(
1341    selcx: &mut SelectionContext<'cx, 'tcx>,
1342    obligation: &ProjectionTermObligation<'tcx>,
1343    nested: PredicateObligations<'tcx>,
1344) -> Progress<'tcx> {
1345    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1346    let ty::Coroutine(_, args) = self_ty.kind() else {
1347        unreachable!(
1348            "expected coroutine self type for built-in coroutine candidate, found {self_ty}"
1349        )
1350    };
1351    let coroutine_sig = args.as_coroutine().sig();
1352    let Normalized { value: coroutine_sig, obligations } = normalize_with_depth(
1353        selcx,
1354        obligation.param_env,
1355        obligation.cause.clone(),
1356        obligation.recursion_depth + 1,
1357        coroutine_sig,
1358    );
1359
1360    debug!(?obligation, ?coroutine_sig, ?obligations, "confirm_coroutine_candidate");
1361
1362    let tcx = selcx.tcx();
1363
1364    let coroutine_def_id = tcx.require_lang_item(LangItem::Coroutine, None);
1365
1366    let (trait_ref, yield_ty, return_ty) = super::util::coroutine_trait_ref_and_outputs(
1367        tcx,
1368        coroutine_def_id,
1369        obligation.predicate.self_ty(),
1370        coroutine_sig,
1371    );
1372
1373    let ty = if tcx.is_lang_item(obligation.predicate.def_id, LangItem::CoroutineReturn) {
1374        return_ty
1375    } else if tcx.is_lang_item(obligation.predicate.def_id, LangItem::CoroutineYield) {
1376        yield_ty
1377    } else {
1378        span_bug!(
1379            tcx.def_span(obligation.predicate.def_id),
1380            "unexpected associated type: `Coroutine::{}`",
1381            tcx.item_name(obligation.predicate.def_id),
1382        );
1383    };
1384
1385    let predicate = ty::ProjectionPredicate {
1386        projection_term: ty::AliasTerm::new_from_args(
1387            tcx,
1388            obligation.predicate.def_id,
1389            trait_ref.args,
1390        ),
1391        term: ty.into(),
1392    };
1393
1394    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1395        .with_addl_obligations(nested)
1396        .with_addl_obligations(obligations)
1397}
1398
1399fn confirm_future_candidate<'cx, 'tcx>(
1400    selcx: &mut SelectionContext<'cx, 'tcx>,
1401    obligation: &ProjectionTermObligation<'tcx>,
1402    nested: PredicateObligations<'tcx>,
1403) -> Progress<'tcx> {
1404    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1405    let ty::Coroutine(_, args) = self_ty.kind() else {
1406        unreachable!(
1407            "expected coroutine self type for built-in async future candidate, found {self_ty}"
1408        )
1409    };
1410    let coroutine_sig = args.as_coroutine().sig();
1411    let Normalized { value: coroutine_sig, obligations } = normalize_with_depth(
1412        selcx,
1413        obligation.param_env,
1414        obligation.cause.clone(),
1415        obligation.recursion_depth + 1,
1416        coroutine_sig,
1417    );
1418
1419    debug!(?obligation, ?coroutine_sig, ?obligations, "confirm_future_candidate");
1420
1421    let tcx = selcx.tcx();
1422    let fut_def_id = tcx.require_lang_item(LangItem::Future, None);
1423
1424    let (trait_ref, return_ty) = super::util::future_trait_ref_and_outputs(
1425        tcx,
1426        fut_def_id,
1427        obligation.predicate.self_ty(),
1428        coroutine_sig,
1429    );
1430
1431    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
1432
1433    let predicate = ty::ProjectionPredicate {
1434        projection_term: ty::AliasTerm::new_from_args(
1435            tcx,
1436            obligation.predicate.def_id,
1437            trait_ref.args,
1438        ),
1439        term: return_ty.into(),
1440    };
1441
1442    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1443        .with_addl_obligations(nested)
1444        .with_addl_obligations(obligations)
1445}
1446
1447fn confirm_iterator_candidate<'cx, 'tcx>(
1448    selcx: &mut SelectionContext<'cx, 'tcx>,
1449    obligation: &ProjectionTermObligation<'tcx>,
1450    nested: PredicateObligations<'tcx>,
1451) -> Progress<'tcx> {
1452    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1453    let ty::Coroutine(_, args) = self_ty.kind() else {
1454        unreachable!("expected coroutine self type for built-in gen candidate, found {self_ty}")
1455    };
1456    let gen_sig = args.as_coroutine().sig();
1457    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
1458        selcx,
1459        obligation.param_env,
1460        obligation.cause.clone(),
1461        obligation.recursion_depth + 1,
1462        gen_sig,
1463    );
1464
1465    debug!(?obligation, ?gen_sig, ?obligations, "confirm_iterator_candidate");
1466
1467    let tcx = selcx.tcx();
1468    let iter_def_id = tcx.require_lang_item(LangItem::Iterator, None);
1469
1470    let (trait_ref, yield_ty) = super::util::iterator_trait_ref_and_outputs(
1471        tcx,
1472        iter_def_id,
1473        obligation.predicate.self_ty(),
1474        gen_sig,
1475    );
1476
1477    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
1478
1479    let predicate = ty::ProjectionPredicate {
1480        projection_term: ty::AliasTerm::new_from_args(
1481            tcx,
1482            obligation.predicate.def_id,
1483            trait_ref.args,
1484        ),
1485        term: yield_ty.into(),
1486    };
1487
1488    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1489        .with_addl_obligations(nested)
1490        .with_addl_obligations(obligations)
1491}
1492
1493fn confirm_async_iterator_candidate<'cx, 'tcx>(
1494    selcx: &mut SelectionContext<'cx, 'tcx>,
1495    obligation: &ProjectionTermObligation<'tcx>,
1496    nested: PredicateObligations<'tcx>,
1497) -> Progress<'tcx> {
1498    let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
1499    else {
1500        unreachable!()
1501    };
1502    let gen_sig = args.as_coroutine().sig();
1503    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
1504        selcx,
1505        obligation.param_env,
1506        obligation.cause.clone(),
1507        obligation.recursion_depth + 1,
1508        gen_sig,
1509    );
1510
1511    debug!(?obligation, ?gen_sig, ?obligations, "confirm_async_iterator_candidate");
1512
1513    let tcx = selcx.tcx();
1514    let iter_def_id = tcx.require_lang_item(LangItem::AsyncIterator, None);
1515
1516    let (trait_ref, yield_ty) = super::util::async_iterator_trait_ref_and_outputs(
1517        tcx,
1518        iter_def_id,
1519        obligation.predicate.self_ty(),
1520        gen_sig,
1521    );
1522
1523    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
1524
1525    let ty::Adt(_poll_adt, args) = *yield_ty.kind() else {
1526        bug!();
1527    };
1528    let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else {
1529        bug!();
1530    };
1531    let item_ty = args.type_at(0);
1532
1533    let predicate = ty::ProjectionPredicate {
1534        projection_term: ty::AliasTerm::new_from_args(
1535            tcx,
1536            obligation.predicate.def_id,
1537            trait_ref.args,
1538        ),
1539        term: item_ty.into(),
1540    };
1541
1542    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1543        .with_addl_obligations(nested)
1544        .with_addl_obligations(obligations)
1545}
1546
1547fn confirm_builtin_candidate<'cx, 'tcx>(
1548    selcx: &mut SelectionContext<'cx, 'tcx>,
1549    obligation: &ProjectionTermObligation<'tcx>,
1550    data: PredicateObligations<'tcx>,
1551) -> Progress<'tcx> {
1552    let tcx = selcx.tcx();
1553    let self_ty = obligation.predicate.self_ty();
1554    let item_def_id = obligation.predicate.def_id;
1555    let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
1556    let args = tcx.mk_args(&[self_ty.into()]);
1557    let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) {
1558        let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
1559        assert_eq!(discriminant_def_id, item_def_id);
1560
1561        (self_ty.discriminant_ty(tcx).into(), PredicateObligations::new())
1562    } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) {
1563        let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0];
1564        assert_eq!(destructor_def_id, item_def_id);
1565
1566        (self_ty.async_destructor_ty(tcx).into(), PredicateObligations::new())
1567    } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) {
1568        let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
1569        assert_eq!(metadata_def_id, item_def_id);
1570
1571        let mut obligations = PredicateObligations::new();
1572        let normalize = |ty| {
1573            normalize_with_depth_to(
1574                selcx,
1575                obligation.param_env,
1576                obligation.cause.clone(),
1577                obligation.recursion_depth + 1,
1578                ty,
1579                &mut obligations,
1580            )
1581        };
1582        let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| {
1583            if tail == self_ty {
1584                // This is the "fallback impl" for type parameters, unnormalizable projections
1585                // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
1586                // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
1587                // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
1588                let sized_predicate = ty::TraitRef::new(
1589                    tcx,
1590                    tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span)),
1591                    [self_ty],
1592                );
1593                obligations.push(obligation.with(tcx, sized_predicate));
1594                tcx.types.unit
1595            } else {
1596                // We know that `self_ty` has the same metadata as `tail`. This allows us
1597                // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`.
1598                Ty::new_projection(tcx, metadata_def_id, [tail])
1599            }
1600        });
1601        (metadata_ty.into(), obligations)
1602    } else {
1603        bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate);
1604    };
1605
1606    let predicate = ty::ProjectionPredicate {
1607        projection_term: ty::AliasTerm::new_from_args(tcx, item_def_id, args),
1608        term,
1609    };
1610
1611    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1612        .with_addl_obligations(obligations)
1613        .with_addl_obligations(data)
1614}
1615
1616fn confirm_fn_pointer_candidate<'cx, 'tcx>(
1617    selcx: &mut SelectionContext<'cx, 'tcx>,
1618    obligation: &ProjectionTermObligation<'tcx>,
1619    nested: PredicateObligations<'tcx>,
1620) -> Progress<'tcx> {
1621    let tcx = selcx.tcx();
1622    let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1623    let sig = fn_type.fn_sig(tcx);
1624    let Normalized { value: sig, obligations } = normalize_with_depth(
1625        selcx,
1626        obligation.param_env,
1627        obligation.cause.clone(),
1628        obligation.recursion_depth + 1,
1629        sig,
1630    );
1631
1632    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
1633        .with_addl_obligations(nested)
1634        .with_addl_obligations(obligations)
1635}
1636
1637fn confirm_closure_candidate<'cx, 'tcx>(
1638    selcx: &mut SelectionContext<'cx, 'tcx>,
1639    obligation: &ProjectionTermObligation<'tcx>,
1640    nested: PredicateObligations<'tcx>,
1641) -> Progress<'tcx> {
1642    let tcx = selcx.tcx();
1643    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1644    let closure_sig = match *self_ty.kind() {
1645        ty::Closure(_, args) => args.as_closure().sig(),
1646
1647        // Construct a "normal" `FnOnce` signature for coroutine-closure. This is
1648        // basically duplicated with the `AsyncFnOnce::CallOnce` confirmation, but
1649        // I didn't see a good way to unify those.
1650        ty::CoroutineClosure(def_id, args) => {
1651            let args = args.as_coroutine_closure();
1652            let kind_ty = args.kind_ty();
1653            args.coroutine_closure_sig().map_bound(|sig| {
1654                // If we know the kind and upvars, use that directly.
1655                // Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay
1656                // the projection, like the `AsyncFn*` traits do.
1657                let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind()
1658                    // Fall back to projection if upvars aren't constrained
1659                    && !args.tupled_upvars_ty().is_ty_var()
1660                {
1661                    sig.to_coroutine_given_kind_and_upvars(
1662                        tcx,
1663                        args.parent_args(),
1664                        tcx.coroutine_for_closure(def_id),
1665                        ty::ClosureKind::FnOnce,
1666                        tcx.lifetimes.re_static,
1667                        args.tupled_upvars_ty(),
1668                        args.coroutine_captures_by_ref_ty(),
1669                    )
1670                } else {
1671                    let upvars_projection_def_id =
1672                        tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
1673                    let tupled_upvars_ty = Ty::new_projection(
1674                        tcx,
1675                        upvars_projection_def_id,
1676                        [
1677                            ty::GenericArg::from(kind_ty),
1678                            Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce).into(),
1679                            tcx.lifetimes.re_static.into(),
1680                            sig.tupled_inputs_ty.into(),
1681                            args.tupled_upvars_ty().into(),
1682                            args.coroutine_captures_by_ref_ty().into(),
1683                        ],
1684                    );
1685                    sig.to_coroutine(
1686                        tcx,
1687                        args.parent_args(),
1688                        Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce),
1689                        tcx.coroutine_for_closure(def_id),
1690                        tupled_upvars_ty,
1691                    )
1692                };
1693                tcx.mk_fn_sig(
1694                    [sig.tupled_inputs_ty],
1695                    output_ty,
1696                    sig.c_variadic,
1697                    sig.safety,
1698                    sig.abi,
1699                )
1700            })
1701        }
1702
1703        _ => {
1704            unreachable!("expected closure self type for closure candidate, found {self_ty}");
1705        }
1706    };
1707
1708    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
1709        selcx,
1710        obligation.param_env,
1711        obligation.cause.clone(),
1712        obligation.recursion_depth + 1,
1713        closure_sig,
1714    );
1715
1716    debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
1717
1718    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
1719        .with_addl_obligations(nested)
1720        .with_addl_obligations(obligations)
1721}
1722
1723fn confirm_callable_candidate<'cx, 'tcx>(
1724    selcx: &mut SelectionContext<'cx, 'tcx>,
1725    obligation: &ProjectionTermObligation<'tcx>,
1726    fn_sig: ty::PolyFnSig<'tcx>,
1727    flag: util::TupleArgumentsFlag,
1728) -> Progress<'tcx> {
1729    let tcx = selcx.tcx();
1730
1731    debug!(?obligation, ?fn_sig, "confirm_callable_candidate");
1732
1733    let fn_once_def_id = tcx.require_lang_item(LangItem::FnOnce, None);
1734    let fn_once_output_def_id = tcx.require_lang_item(LangItem::FnOnceOutput, None);
1735
1736    let predicate = super::util::closure_trait_ref_and_return_type(
1737        tcx,
1738        fn_once_def_id,
1739        obligation.predicate.self_ty(),
1740        fn_sig,
1741        flag,
1742    )
1743    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
1744        projection_term: ty::AliasTerm::new_from_args(tcx, fn_once_output_def_id, trait_ref.args),
1745        term: ret_type.into(),
1746    });
1747
1748    confirm_param_env_candidate(selcx, obligation, predicate, true)
1749}
1750
1751fn confirm_async_closure_candidate<'cx, 'tcx>(
1752    selcx: &mut SelectionContext<'cx, 'tcx>,
1753    obligation: &ProjectionTermObligation<'tcx>,
1754    nested: PredicateObligations<'tcx>,
1755) -> Progress<'tcx> {
1756    let tcx = selcx.tcx();
1757    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1758
1759    let goal_kind =
1760        tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap();
1761    let env_region = match goal_kind {
1762        ty::ClosureKind::Fn | ty::ClosureKind::FnMut => obligation.predicate.args.region_at(2),
1763        ty::ClosureKind::FnOnce => tcx.lifetimes.re_static,
1764    };
1765    let item_name = tcx.item_name(obligation.predicate.def_id);
1766
1767    let poly_cache_entry = match *self_ty.kind() {
1768        ty::CoroutineClosure(def_id, args) => {
1769            let args = args.as_coroutine_closure();
1770            let kind_ty = args.kind_ty();
1771            let sig = args.coroutine_closure_sig().skip_binder();
1772
1773            let term = match item_name {
1774                sym::CallOnceFuture | sym::CallRefFuture => {
1775                    if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
1776                        // Fall back to projection if upvars aren't constrained
1777                        && !args.tupled_upvars_ty().is_ty_var()
1778                    {
1779                        if !closure_kind.extends(goal_kind) {
1780                            bug!("we should not be confirming if the closure kind is not met");
1781                        }
1782                        sig.to_coroutine_given_kind_and_upvars(
1783                            tcx,
1784                            args.parent_args(),
1785                            tcx.coroutine_for_closure(def_id),
1786                            goal_kind,
1787                            env_region,
1788                            args.tupled_upvars_ty(),
1789                            args.coroutine_captures_by_ref_ty(),
1790                        )
1791                    } else {
1792                        let upvars_projection_def_id =
1793                            tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
1794                        // When we don't know the closure kind (and therefore also the closure's upvars,
1795                        // which are computed at the same time), we must delay the computation of the
1796                        // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
1797                        // goal functions similarly to the old `ClosureKind` predicate, and ensures that
1798                        // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
1799                        // will project to the right upvars for the generator, appending the inputs and
1800                        // coroutine upvars respecting the closure kind.
1801                        // N.B. No need to register a `AsyncFnKindHelper` goal here, it's already in `nested`.
1802                        let tupled_upvars_ty = Ty::new_projection(
1803                            tcx,
1804                            upvars_projection_def_id,
1805                            [
1806                                ty::GenericArg::from(kind_ty),
1807                                Ty::from_closure_kind(tcx, goal_kind).into(),
1808                                env_region.into(),
1809                                sig.tupled_inputs_ty.into(),
1810                                args.tupled_upvars_ty().into(),
1811                                args.coroutine_captures_by_ref_ty().into(),
1812                            ],
1813                        );
1814                        sig.to_coroutine(
1815                            tcx,
1816                            args.parent_args(),
1817                            Ty::from_closure_kind(tcx, goal_kind),
1818                            tcx.coroutine_for_closure(def_id),
1819                            tupled_upvars_ty,
1820                        )
1821                    }
1822                }
1823                sym::Output => sig.return_ty,
1824                name => bug!("no such associated type: {name}"),
1825            };
1826            let projection_term = match item_name {
1827                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
1828                    tcx,
1829                    obligation.predicate.def_id,
1830                    [self_ty, sig.tupled_inputs_ty],
1831                ),
1832                sym::CallRefFuture => ty::AliasTerm::new(
1833                    tcx,
1834                    obligation.predicate.def_id,
1835                    [ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()],
1836                ),
1837                name => bug!("no such associated type: {name}"),
1838            };
1839
1840            args.coroutine_closure_sig()
1841                .rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
1842        }
1843        ty::FnDef(..) | ty::FnPtr(..) => {
1844            let bound_sig = self_ty.fn_sig(tcx);
1845            let sig = bound_sig.skip_binder();
1846
1847            let term = match item_name {
1848                sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
1849                sym::Output => {
1850                    let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
1851                    Ty::new_projection(tcx, future_output_def_id, [sig.output()])
1852                }
1853                name => bug!("no such associated type: {name}"),
1854            };
1855            let projection_term = match item_name {
1856                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
1857                    tcx,
1858                    obligation.predicate.def_id,
1859                    [self_ty, Ty::new_tup(tcx, sig.inputs())],
1860                ),
1861                sym::CallRefFuture => ty::AliasTerm::new(
1862                    tcx,
1863                    obligation.predicate.def_id,
1864                    [
1865                        ty::GenericArg::from(self_ty),
1866                        Ty::new_tup(tcx, sig.inputs()).into(),
1867                        env_region.into(),
1868                    ],
1869                ),
1870                name => bug!("no such associated type: {name}"),
1871            };
1872
1873            bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
1874        }
1875        ty::Closure(_, args) => {
1876            let args = args.as_closure();
1877            let bound_sig = args.sig();
1878            let sig = bound_sig.skip_binder();
1879
1880            let term = match item_name {
1881                sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
1882                sym::Output => {
1883                    let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
1884                    Ty::new_projection(tcx, future_output_def_id, [sig.output()])
1885                }
1886                name => bug!("no such associated type: {name}"),
1887            };
1888            let projection_term = match item_name {
1889                sym::CallOnceFuture | sym::Output => {
1890                    ty::AliasTerm::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]])
1891                }
1892                sym::CallRefFuture => ty::AliasTerm::new(
1893                    tcx,
1894                    obligation.predicate.def_id,
1895                    [ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()],
1896                ),
1897                name => bug!("no such associated type: {name}"),
1898            };
1899
1900            bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
1901        }
1902        _ => bug!("expected callable type for AsyncFn candidate"),
1903    };
1904
1905    confirm_param_env_candidate(selcx, obligation, poly_cache_entry, true)
1906        .with_addl_obligations(nested)
1907}
1908
1909fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>(
1910    selcx: &mut SelectionContext<'cx, 'tcx>,
1911    obligation: &ProjectionTermObligation<'tcx>,
1912    nested: PredicateObligations<'tcx>,
1913) -> Progress<'tcx> {
1914    let [
1915        // We already checked that the goal_kind >= closure_kind
1916        _closure_kind_ty,
1917        goal_kind_ty,
1918        borrow_region,
1919        tupled_inputs_ty,
1920        tupled_upvars_ty,
1921        coroutine_captures_by_ref_ty,
1922    ] = **obligation.predicate.args
1923    else {
1924        bug!();
1925    };
1926
1927    let predicate = ty::ProjectionPredicate {
1928        projection_term: ty::AliasTerm::new_from_args(
1929            selcx.tcx(),
1930            obligation.predicate.def_id,
1931            obligation.predicate.args,
1932        ),
1933        term: ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
1934            selcx.tcx(),
1935            goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(),
1936            tupled_inputs_ty.expect_ty(),
1937            tupled_upvars_ty.expect_ty(),
1938            coroutine_captures_by_ref_ty.expect_ty(),
1939            borrow_region.expect_region(),
1940        )
1941        .into(),
1942    };
1943
1944    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
1945        .with_addl_obligations(nested)
1946}
1947
1948fn confirm_param_env_candidate<'cx, 'tcx>(
1949    selcx: &mut SelectionContext<'cx, 'tcx>,
1950    obligation: &ProjectionTermObligation<'tcx>,
1951    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
1952    potentially_unnormalized_candidate: bool,
1953) -> Progress<'tcx> {
1954    let infcx = selcx.infcx;
1955    let cause = &obligation.cause;
1956    let param_env = obligation.param_env;
1957
1958    let cache_entry = infcx.instantiate_binder_with_fresh_vars(
1959        cause.span,
1960        BoundRegionConversionTime::HigherRankedType,
1961        poly_cache_entry,
1962    );
1963
1964    let cache_projection = cache_entry.projection_term;
1965    let mut nested_obligations = PredicateObligations::new();
1966    let obligation_projection = obligation.predicate;
1967    let obligation_projection = ensure_sufficient_stack(|| {
1968        normalize_with_depth_to(
1969            selcx,
1970            obligation.param_env,
1971            obligation.cause.clone(),
1972            obligation.recursion_depth + 1,
1973            obligation_projection,
1974            &mut nested_obligations,
1975        )
1976    });
1977    let cache_projection = if potentially_unnormalized_candidate {
1978        ensure_sufficient_stack(|| {
1979            normalize_with_depth_to(
1980                selcx,
1981                obligation.param_env,
1982                obligation.cause.clone(),
1983                obligation.recursion_depth + 1,
1984                cache_projection,
1985                &mut nested_obligations,
1986            )
1987        })
1988    } else {
1989        cache_projection
1990    };
1991
1992    debug!(?cache_projection, ?obligation_projection);
1993
1994    match infcx.at(cause, param_env).eq(
1995        DefineOpaqueTypes::Yes,
1996        cache_projection,
1997        obligation_projection,
1998    ) {
1999        Ok(InferOk { value: _, obligations }) => {
2000            nested_obligations.extend(obligations);
2001            assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
2002            // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take
2003            // a term instead.
2004            Progress { term: cache_entry.term, obligations: nested_obligations }
2005        }
2006        Err(e) => {
2007            let msg = format!(
2008                "Failed to unify obligation `{obligation:?}` with poly_projection `{poly_cache_entry:?}`: {e:?}",
2009            );
2010            debug!("confirm_param_env_candidate: {}", msg);
2011            let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg);
2012            Progress { term: err.into(), obligations: PredicateObligations::new() }
2013        }
2014    }
2015}
2016
2017fn confirm_impl_candidate<'cx, 'tcx>(
2018    selcx: &mut SelectionContext<'cx, 'tcx>,
2019    obligation: &ProjectionTermObligation<'tcx>,
2020    impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
2021) -> Progress<'tcx> {
2022    let tcx = selcx.tcx();
2023
2024    let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
2025
2026    let assoc_item_id = obligation.predicate.def_id;
2027    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
2028
2029    let param_env = obligation.param_env;
2030    let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
2031        Ok(assoc_ty) => assoc_ty,
2032        Err(guar) => return Progress::error(tcx, guar),
2033    };
2034    if !assoc_ty.item.defaultness(tcx).has_value() {
2035        // This means that the impl is missing a definition for the
2036        // associated type. This error will be reported by the type
2037        // checker method `check_impl_items_against_trait`, so here we
2038        // just return Error.
2039        debug!(
2040            "confirm_impl_candidate: no associated type {:?} for {:?}",
2041            assoc_ty.item.name, obligation.predicate
2042        );
2043        return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested };
2044    }
2045    // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
2046    //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
2047    //
2048    // * `obligation.predicate.args` is `[Vec<u32>, S]`
2049    // * `args` is `[u32]`
2050    // * `args` ends up as `[u32, S]`
2051    let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
2052    let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
2053    let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
2054    let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
2055        let did = assoc_ty.item.def_id;
2056        let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
2057        let uv = ty::UnevaluatedConst::new(did, identity_args);
2058        ty::EarlyBinder::bind(ty::Const::new_unevaluated(tcx, uv).into())
2059    } else {
2060        tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into())
2061    };
2062    if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
2063        let err = Ty::new_error_with_message(
2064            tcx,
2065            obligation.cause.span,
2066            "impl item and trait item have different parameters",
2067        );
2068        Progress { term: err.into(), obligations: nested }
2069    } else {
2070        assoc_ty_own_obligations(selcx, obligation, &mut nested);
2071        Progress { term: term.instantiate(tcx, args), obligations: nested }
2072    }
2073}
2074
2075fn confirm_object_rpitit_candidate<'cx, 'tcx>(
2076    selcx: &mut SelectionContext<'cx, 'tcx>,
2077    obligation: &ProjectionTermObligation<'tcx>,
2078) -> Progress<'tcx> {
2079    let tcx = selcx.tcx();
2080    let mut obligations = thin_vec![];
2081
2082    // Compute an intersection lifetime for all the input components of this GAT.
2083    let intersection =
2084        selcx.infcx.next_region_var(RegionVariableOrigin::MiscVariable(obligation.cause.span));
2085    for component in obligation.predicate.args {
2086        match component.unpack() {
2087            ty::GenericArgKind::Lifetime(lt) => {
2088                obligations.push(obligation.with(tcx, ty::OutlivesPredicate(lt, intersection)));
2089            }
2090            ty::GenericArgKind::Type(ty) => {
2091                obligations.push(obligation.with(tcx, ty::OutlivesPredicate(ty, intersection)));
2092            }
2093            ty::GenericArgKind::Const(_ct) => {
2094                // Consts have no outlives...
2095            }
2096        }
2097    }
2098
2099    Progress {
2100        term: Ty::new_dynamic(
2101            tcx,
2102            tcx.item_bounds_to_existential_predicates(
2103                obligation.predicate.def_id,
2104                obligation.predicate.args,
2105            ),
2106            intersection,
2107            ty::DynStar,
2108        )
2109        .into(),
2110        obligations,
2111    }
2112}
2113
2114// Get obligations corresponding to the predicates from the where-clause of the
2115// associated type itself.
2116fn assoc_ty_own_obligations<'cx, 'tcx>(
2117    selcx: &mut SelectionContext<'cx, 'tcx>,
2118    obligation: &ProjectionTermObligation<'tcx>,
2119    nested: &mut PredicateObligations<'tcx>,
2120) {
2121    let tcx = selcx.tcx();
2122    let predicates = tcx
2123        .predicates_of(obligation.predicate.def_id)
2124        .instantiate_own(tcx, obligation.predicate.args);
2125    for (predicate, span) in predicates {
2126        let normalized = normalize_with_depth_to(
2127            selcx,
2128            obligation.param_env,
2129            obligation.cause.clone(),
2130            obligation.recursion_depth + 1,
2131            predicate,
2132            nested,
2133        );
2134
2135        let nested_cause = if matches!(
2136            obligation.cause.code(),
2137            ObligationCauseCode::CompareImplItem { .. }
2138                | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
2139                | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
2140        ) {
2141            obligation.cause.clone()
2142        } else {
2143            ObligationCause::new(
2144                obligation.cause.span,
2145                obligation.cause.body_id,
2146                ObligationCauseCode::WhereClause(obligation.predicate.def_id, span),
2147            )
2148        };
2149        nested.push(Obligation::with_depth(
2150            tcx,
2151            nested_cause,
2152            obligation.recursion_depth + 1,
2153            obligation.param_env,
2154            normalized,
2155        ));
2156    }
2157}
2158
2159pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
2160    fn from_poly_projection_obligation(
2161        selcx: &mut SelectionContext<'cx, 'tcx>,
2162        obligation: &PolyProjectionObligation<'tcx>,
2163    ) -> Option<Self>;
2164}
2165
2166impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
2167    fn from_poly_projection_obligation(
2168        selcx: &mut SelectionContext<'cx, 'tcx>,
2169        obligation: &PolyProjectionObligation<'tcx>,
2170    ) -> Option<Self> {
2171        let infcx = selcx.infcx;
2172        // We don't do cross-snapshot caching of obligations with escaping regions,
2173        // so there's no cache key to use
2174        obligation.predicate.no_bound_vars().map(|predicate| {
2175            ProjectionCacheKey::new(
2176                // We don't attempt to match up with a specific type-variable state
2177                // from a specific call to `opt_normalize_projection_type` - if
2178                // there's no precise match, the original cache entry is "stranded"
2179                // anyway.
2180                infcx.resolve_vars_if_possible(predicate.projection_term),
2181                obligation.param_env,
2182            )
2183        })
2184    }
2185}