rustc_hir_analysis/hir_ty_lowering/
bounds.rs

1use std::ops::ControlFlow;
2
3use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
4use rustc_errors::codes::*;
5use rustc_errors::struct_span_code_err;
6use rustc_hir as hir;
7use rustc_hir::def::{DefKind, Res};
8use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
9use rustc_hir::{AmbigArg, PolyTraitRef};
10use rustc_middle::bug;
11use rustc_middle::ty::{
12    self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
13    TypeVisitor, Upcast,
14};
15use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
16use rustc_trait_selection::traits;
17use smallvec::SmallVec;
18use tracing::{debug, instrument};
19
20use super::errors::GenericsArgsErrExtend;
21use crate::errors;
22use crate::hir_ty_lowering::{
23    AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
24};
25
26#[derive(Debug, Default)]
27struct CollectedBound {
28    /// `Trait`
29    positive: bool,
30    /// `?Trait`
31    maybe: bool,
32    /// `!Trait`
33    negative: bool,
34}
35
36impl CollectedBound {
37    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered.
38    fn any(&self) -> bool {
39        self.positive || self.maybe || self.negative
40    }
41}
42
43#[derive(Debug)]
44struct CollectedSizednessBounds {
45    // Collected `Sized` bounds
46    sized: CollectedBound,
47    // Collected `MetaSized` bounds
48    meta_sized: CollectedBound,
49    // Collected `PointeeSized` bounds
50    pointee_sized: CollectedBound,
51}
52
53impl CollectedSizednessBounds {
54    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered for `Sized`,
55    /// `MetaSized` or `PointeeSized`.
56    fn any(&self) -> bool {
57        self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
58    }
59}
60
61fn search_bounds_for<'tcx>(
62    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
63    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
64    mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
65) {
66    let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
67        for hir_bound in hir_bounds {
68            let hir::GenericBound::Trait(ptr) = hir_bound else {
69                continue;
70            };
71
72            f(ptr)
73        }
74    };
75
76    search_bounds(hir_bounds);
77    if let Some((self_ty, where_clause)) = self_ty_where_predicates {
78        for clause in where_clause {
79            if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
80                && pred.is_param_bound(self_ty.to_def_id())
81            {
82                search_bounds(pred.bounds);
83            }
84        }
85    }
86}
87
88fn collect_relaxed_bounds<'tcx>(
89    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
90    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
91) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
92    let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
93    search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
94        if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
95            relaxed_bounds.push(ptr);
96        }
97    });
98    relaxed_bounds
99}
100
101fn collect_bounds<'a, 'tcx>(
102    hir_bounds: &'a [hir::GenericBound<'tcx>],
103    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
104    target_did: DefId,
105) -> CollectedBound {
106    let mut collect_into = CollectedBound::default();
107    search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
108        if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
109            return;
110        }
111
112        match ptr.modifiers.polarity {
113            hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
114            hir::BoundPolarity::Negative(_) => collect_into.negative = true,
115            hir::BoundPolarity::Positive => collect_into.positive = true,
116        }
117    });
118    collect_into
119}
120
121fn collect_sizedness_bounds<'tcx>(
122    tcx: TyCtxt<'tcx>,
123    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
124    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
125    span: Span,
126) -> CollectedSizednessBounds {
127    let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
128    let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
129
130    let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
131    let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
132
133    let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
134    let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
135
136    CollectedSizednessBounds { sized, meta_sized, pointee_sized }
137}
138
139/// Add a trait bound for `did`.
140fn add_trait_bound<'tcx>(
141    tcx: TyCtxt<'tcx>,
142    bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
143    self_ty: Ty<'tcx>,
144    did: DefId,
145    span: Span,
146) {
147    let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
148    // Preferable to put sizedness obligations first, since we report better errors for `Sized`
149    // ambiguity.
150    bounds.insert(0, (trait_ref.upcast(tcx), span));
151}
152
153impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
154    /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
155    ///
156    /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
157    ///   sizedness bounds are present.
158    /// - On traits and trait aliases, add default `MetaSized` supertrait if no explicit sizedness
159    ///   bounds are present.
160    /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if
161    ///   a `?Sized` bound is present.
162    pub(crate) fn add_sizedness_bounds(
163        &self,
164        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
165        self_ty: Ty<'tcx>,
166        hir_bounds: &'tcx [hir::GenericBound<'tcx>],
167        self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
168        trait_did: Option<LocalDefId>,
169        span: Span,
170    ) {
171        let tcx = self.tcx();
172
173        // Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
174        if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
175            return;
176        }
177
178        let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
179        let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
180
181        // If adding sizedness bounds to a trait, then there are some relevant early exits
182        if let Some(trait_did) = trait_did {
183            let trait_did = trait_did.to_def_id();
184            // Never add a default supertrait to `PointeeSized`.
185            if trait_did == pointee_sized_did {
186                return;
187            }
188            // Don't add default sizedness supertraits to auto traits because it isn't possible to
189            // relax an automatically added supertrait on the defn itself.
190            if tcx.trait_is_auto(trait_did) {
191                return;
192            }
193        } else {
194            // Report invalid relaxed bounds.
195            // FIXME: Since we only call this validation function here in this function, we only
196            //        fully validate relaxed bounds in contexts where we perform
197            //        "sized elaboration". In most cases that doesn't matter because we *usually*
198            //        reject such relaxed bounds outright during AST lowering.
199            //        However, this can easily get out of sync! Ideally, we would perform this step
200            //        where we are guaranteed to catch *all* bounds like in
201            //        `Self::lower_poly_trait_ref`. List of concrete issues:
202            //        FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
203            //                                  bounds or associated type bounds (ATB)!
204            //        FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
205            //                                     AST lowering should reject them outright.
206            let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
207            self.check_and_report_invalid_relaxed_bounds(bounds);
208        }
209
210        let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
211        if (collected.sized.maybe || collected.sized.negative)
212            && !collected.sized.positive
213            && !collected.meta_sized.any()
214            && !collected.pointee_sized.any()
215        {
216            // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any
217            // other explicit ones) - this can happen for trait aliases as well as bounds.
218            add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
219        } else if !collected.any() {
220            if trait_did.is_some() {
221                // If there are no explicit sizedness bounds on a trait then add a default
222                // `MetaSized` supertrait.
223                add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
224            } else {
225                // If there are no explicit sizedness bounds on a parameter then add a default
226                // `Sized` bound.
227                let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
228                add_trait_bound(tcx, bounds, self_ty, sized_did, span);
229            }
230        }
231    }
232
233    /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
234    /// or associated items.
235    ///
236    /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
237    /// should be added everywhere, including super bounds. However this causes a huge performance
238    /// costs. For optimization purposes instead of adding default supertraits, bounds
239    /// are added to the associated items:
240    ///
241    /// ```ignore(illustrative)
242    /// // Default bounds are generated in the following way:
243    /// trait Trait {
244    ///     fn foo(&self) where Self: Leak {}
245    /// }
246    ///
247    /// // instead of this:
248    /// trait Trait: Leak {
249    ///     fn foo(&self) {}
250    /// }
251    /// ```
252    /// It is not always possible to do this because of backward compatibility:
253    ///
254    /// ```ignore(illustrative)
255    /// pub trait Trait<Rhs = Self> {}
256    /// pub trait Trait1 : Trait {}
257    /// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
258    /// ```
259    ///
260    /// or:
261    ///
262    /// ```ignore(illustrative)
263    /// trait Trait {
264    ///     type Type where Self: Sized;
265    /// }
266    /// trait Trait2<T> : Trait<Type = T> {}
267    /// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit  `Self: DefaultAutoTrait` in `Trait::Type`
268    /// ```
269    ///
270    /// Therefore, `experimental_default_bounds` are still being added to supertraits if
271    /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
272    fn requires_default_supertraits(
273        &self,
274        hir_bounds: &'tcx [hir::GenericBound<'tcx>],
275        hir_generics: &'tcx hir::Generics<'tcx>,
276    ) -> bool {
277        struct TraitInfoCollector;
278
279        impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
280            type Result = ControlFlow<()>;
281
282            fn visit_assoc_item_constraint(
283                &mut self,
284                _constraint: &'tcx hir::AssocItemConstraint<'tcx>,
285            ) -> Self::Result {
286                ControlFlow::Break(())
287            }
288
289            fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
290                if matches!(
291                    &t.kind,
292                    hir::TyKind::Path(hir::QPath::Resolved(
293                        _,
294                        hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
295                    ))
296                ) {
297                    return ControlFlow::Break(());
298                }
299                hir::intravisit::walk_ty(self, t)
300            }
301        }
302
303        let mut found = false;
304        for bound in hir_bounds {
305            found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
306        }
307        found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
308        found
309    }
310
311    /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
312    /// they are not added as super trait bounds to the trait itself. See
313    /// `requires_default_supertraits` for more information.
314    pub(crate) fn add_default_trait_item_bounds(
315        &self,
316        trait_item: &hir::TraitItem<'tcx>,
317        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
318    ) {
319        let tcx = self.tcx();
320        if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
321            return;
322        }
323
324        let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
325        let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
326            unreachable!();
327        };
328
329        let (trait_generics, trait_bounds) = match parent_trait.kind {
330            hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
331            hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
332            _ => unreachable!(),
333        };
334
335        if !self.requires_default_supertraits(trait_bounds, trait_generics) {
336            let self_ty_where_predicates = (parent, trait_item.generics.predicates);
337            self.add_default_traits(
338                bounds,
339                tcx.types.self_param,
340                &[],
341                Some(self_ty_where_predicates),
342                trait_item.span,
343            );
344        }
345    }
346
347    /// Lazily sets `experimental_default_bounds` to true on trait super bounds.
348    /// See `requires_default_supertraits` for more information.
349    pub(crate) fn add_default_super_traits(
350        &self,
351        trait_def_id: LocalDefId,
352        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
353        hir_bounds: &'tcx [hir::GenericBound<'tcx>],
354        hir_generics: &'tcx hir::Generics<'tcx>,
355        span: Span,
356    ) {
357        if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
358            return;
359        }
360
361        assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
362        if self.requires_default_supertraits(hir_bounds, hir_generics) {
363            let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
364            self.add_default_traits(
365                bounds,
366                self.tcx().types.self_param,
367                hir_bounds,
368                Some(self_ty_where_predicates),
369                span,
370            );
371        }
372    }
373
374    pub(crate) fn add_default_traits(
375        &self,
376        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
377        self_ty: Ty<'tcx>,
378        hir_bounds: &[hir::GenericBound<'tcx>],
379        self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
380        span: Span,
381    ) {
382        self.tcx().default_traits().iter().for_each(|default_trait| {
383            self.add_default_trait(
384                *default_trait,
385                bounds,
386                self_ty,
387                hir_bounds,
388                self_ty_where_predicates,
389                span,
390            );
391        });
392    }
393
394    /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate.
395    ///
396    /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
397    pub(crate) fn add_default_trait(
398        &self,
399        trait_: hir::LangItem,
400        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
401        self_ty: Ty<'tcx>,
402        hir_bounds: &[hir::GenericBound<'tcx>],
403        self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
404        span: Span,
405    ) {
406        let tcx = self.tcx();
407        let trait_id = tcx.lang_items().get(trait_);
408        if let Some(trait_id) = trait_id
409            && self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
410        {
411            add_trait_bound(tcx, bounds, self_ty, trait_id, span);
412        }
413    }
414
415    /// Returns `true` if default trait bound should be added.
416    fn should_add_default_traits<'a>(
417        &self,
418        trait_def_id: DefId,
419        hir_bounds: &'a [hir::GenericBound<'tcx>],
420        self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
421    ) -> bool {
422        let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
423        !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
424    }
425
426    /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
427    ///
428    /// ### Examples
429    ///
430    /// ```ignore (illustrative)
431    /// fn foo<T>() where for<'a> T: Trait<'a> + Copy {}
432    /// //                ^^^^^^^ ^  ^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
433    /// //                |       |
434    /// //                |       `param_ty`, in ty form
435    /// //                `bound_vars`, in ty form
436    ///
437    /// fn bar<T>() where T: for<'a> Trait<'a> + Copy {} // no overarching `bound_vars` here!
438    /// //                ^  ^^^^^^^^^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
439    /// //                |
440    /// //                `param_ty`, in ty form
441    /// ```
442    ///
443    /// ### A Note on Binders
444    ///
445    /// There is an implied binder around `param_ty` and `hir_bounds`.
446    /// See `lower_poly_trait_ref` for more details.
447    #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
448    pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
449        &self,
450        param_ty: Ty<'tcx>,
451        hir_bounds: I,
452        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
453        bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
454        predicate_filter: PredicateFilter,
455    ) where
456        'tcx: 'hir,
457    {
458        for hir_bound in hir_bounds {
459            // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
460            // we skip over any traits that don't define the given associated type.
461            if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
462                if let Some(trait_ref) = hir_bound.trait_ref()
463                    && let Some(trait_did) = trait_ref.trait_def_id()
464                    && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
465                {
466                    // Okay
467                } else {
468                    continue;
469                }
470            }
471
472            match hir_bound {
473                hir::GenericBound::Trait(poly_trait_ref) => {
474                    let _ = self.lower_poly_trait_ref(
475                        poly_trait_ref,
476                        param_ty,
477                        bounds,
478                        predicate_filter,
479                    );
480                }
481                hir::GenericBound::Outlives(lifetime) => {
482                    // `ConstIfConst` is only interested in `[const]` bounds.
483                    if matches!(
484                        predicate_filter,
485                        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
486                    ) {
487                        continue;
488                    }
489
490                    let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
491                    let bound = ty::Binder::bind_with_vars(
492                        ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
493                        bound_vars,
494                    );
495                    bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
496                }
497                hir::GenericBound::Use(..) => {
498                    // We don't actually lower `use` into the type layer.
499                }
500            }
501        }
502    }
503
504    /// Lower an associated item constraint from the HIR into `bounds`.
505    ///
506    /// ### A Note on Binders
507    ///
508    /// Given something like `T: for<'a> Iterator<Item = &'a u32>`,
509    /// the `trait_ref` here will be `for<'a> T: Iterator`.
510    /// The `constraint` data however is from *inside* the binder
511    /// (e.g., `&'a u32`) and hence may reference bound regions.
512    #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
513    pub(super) fn lower_assoc_item_constraint(
514        &self,
515        hir_ref_id: hir::HirId,
516        trait_ref: ty::PolyTraitRef<'tcx>,
517        constraint: &hir::AssocItemConstraint<'tcx>,
518        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
519        duplicates: &mut FxIndexMap<DefId, Span>,
520        path_span: Span,
521        predicate_filter: PredicateFilter,
522    ) -> Result<(), ErrorGuaranteed> {
523        let tcx = self.tcx();
524
525        let assoc_tag = if constraint.gen_args.parenthesized
526            == hir::GenericArgsParentheses::ReturnTypeNotation
527        {
528            ty::AssocTag::Fn
529        } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
530            constraint.kind
531        {
532            ty::AssocTag::Const
533        } else {
534            ty::AssocTag::Type
535        };
536
537        // Given something like `U: Trait<T = X>`, we want to produce a predicate like
538        // `<U as Trait>::T = X`.
539        // This is somewhat subtle in the event that `T` is defined in a supertrait of `Trait`,
540        // because in that case we need to upcast. I.e., we want to produce
541        // `<B as SuperTrait<i32>>::T == X` for `B: SubTrait<T = X>` where
542        //
543        //     trait SubTrait: SuperTrait<i32> {}
544        //     trait SuperTrait<A> { type T; }
545        let candidate = if self.probe_trait_that_defines_assoc_item(
546            trait_ref.def_id(),
547            assoc_tag,
548            constraint.ident,
549        ) {
550            // Simple case: The assoc item is defined in the current trait.
551            trait_ref
552        } else {
553            // Otherwise, we have to walk through the supertraits to find
554            // one that does define it.
555            self.probe_single_bound_for_assoc_item(
556                || traits::supertraits(tcx, trait_ref),
557                AssocItemQSelf::Trait(trait_ref.def_id()),
558                assoc_tag,
559                constraint.ident,
560                path_span,
561                Some(constraint),
562            )?
563        };
564
565        let assoc_item = self
566            .probe_assoc_item(
567                constraint.ident,
568                assoc_tag,
569                hir_ref_id,
570                constraint.span,
571                candidate.def_id(),
572            )
573            .expect("failed to find associated item");
574
575        duplicates
576            .entry(assoc_item.def_id)
577            .and_modify(|prev_span| {
578                self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
579                    span: constraint.span,
580                    prev_span: *prev_span,
581                    item_name: constraint.ident,
582                    def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
583                });
584            })
585            .or_insert(constraint.span);
586
587        let projection_term = if let ty::AssocTag::Fn = assoc_tag {
588            let bound_vars = tcx.late_bound_vars(constraint.hir_id);
589            ty::Binder::bind_with_vars(
590                self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
591                bound_vars,
592            )
593        } else {
594            // Create the generic arguments for the associated type or constant by joining the
595            // parent arguments (the arguments of the trait) and the own arguments (the ones of
596            // the associated item itself) and construct an alias type using them.
597            let alias_term = candidate.map_bound(|trait_ref| {
598                let item_segment = hir::PathSegment {
599                    ident: constraint.ident,
600                    hir_id: constraint.hir_id,
601                    res: Res::Err,
602                    args: Some(constraint.gen_args),
603                    infer_args: false,
604                };
605
606                let alias_args = self.lower_generic_args_of_assoc_item(
607                    path_span,
608                    assoc_item.def_id,
609                    &item_segment,
610                    trait_ref.args,
611                );
612                debug!(?alias_args);
613
614                ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
615            });
616
617            // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
618            if let Some(const_arg) = constraint.ct()
619                && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
620            {
621                let ty = alias_term
622                    .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
623                let ty =
624                    check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
625                tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
626            }
627
628            alias_term
629        };
630
631        match constraint.kind {
632            hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
633                return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
634                    span: constraint.span,
635                }));
636            }
637            // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>`
638            // to a projection predicate: `<T as Iterator>::Item = u32`.
639            hir::AssocItemConstraintKind::Equality { term } => {
640                let term = match term {
641                    hir::Term::Ty(ty) => self.lower_ty(ty).into(),
642                    hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
643                };
644
645                // Find any late-bound regions declared in `ty` that are not
646                // declared in the trait-ref or assoc_item. These are not well-formed.
647                //
648                // Example:
649                //
650                //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
651                //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
652                let late_bound_in_projection_ty =
653                    tcx.collect_constrained_late_bound_regions(projection_term);
654                let late_bound_in_term =
655                    tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
656                debug!(?late_bound_in_projection_ty);
657                debug!(?late_bound_in_term);
658
659                // FIXME: point at the type params that don't have appropriate lifetimes:
660                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
661                //                         ----  ----     ^^^^^^^
662                // NOTE(associated_const_equality): This error should be impossible to trigger
663                //                                  with associated const equality constraints.
664                self.validate_late_bound_regions(
665                    late_bound_in_projection_ty,
666                    late_bound_in_term,
667                    |br_name| {
668                        struct_span_code_err!(
669                            self.dcx(),
670                            constraint.span,
671                            E0582,
672                            "binding for associated type `{}` references {}, \
673                             which does not appear in the trait input types",
674                            constraint.ident,
675                            br_name
676                        )
677                    },
678                );
679
680                match predicate_filter {
681                    PredicateFilter::All
682                    | PredicateFilter::SelfOnly
683                    | PredicateFilter::SelfAndAssociatedTypeBounds => {
684                        let bound = projection_term.map_bound(|projection_term| {
685                            ty::ClauseKind::Projection(ty::ProjectionPredicate {
686                                projection_term,
687                                term,
688                            })
689                        });
690                        bounds.push((bound.upcast(tcx), constraint.span));
691                    }
692                    // SelfTraitThatDefines is only interested in trait predicates.
693                    PredicateFilter::SelfTraitThatDefines(_) => {}
694                    // `ConstIfConst` is only interested in `[const]` bounds.
695                    PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
696                }
697            }
698            // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
699            // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
700            hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
701                match predicate_filter {
702                    PredicateFilter::All
703                    | PredicateFilter::SelfAndAssociatedTypeBounds
704                    | PredicateFilter::ConstIfConst => {
705                        let projection_ty = projection_term
706                            .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
707                        // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
708                        // parameter to have a skipped binder.
709                        let param_ty =
710                            Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
711                        self.lower_bounds(
712                            param_ty,
713                            hir_bounds,
714                            bounds,
715                            projection_ty.bound_vars(),
716                            predicate_filter,
717                        );
718                    }
719                    PredicateFilter::SelfOnly
720                    | PredicateFilter::SelfTraitThatDefines(_)
721                    | PredicateFilter::SelfConstIfConst => {}
722                }
723            }
724        }
725        Ok(())
726    }
727
728    /// Lower a type, possibly specially handling the type if it's a return type notation
729    /// which we otherwise deny in other positions.
730    pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
731        let hir::TyKind::Path(qpath) = hir_ty.kind else {
732            return self.lower_ty(hir_ty);
733        };
734
735        let tcx = self.tcx();
736        match qpath {
737            hir::QPath::Resolved(opt_self_ty, path)
738                if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
739                    && item_segment.args.is_some_and(|args| {
740                        matches!(
741                            args.parenthesized,
742                            hir::GenericArgsParentheses::ReturnTypeNotation
743                        )
744                    }) =>
745            {
746                // We don't allow generics on the module segments.
747                let _ =
748                    self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
749
750                let item_def_id = match path.res {
751                    Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
752                    Res::Err => {
753                        return Ty::new_error_with_message(
754                            tcx,
755                            hir_ty.span,
756                            "failed to resolve RTN",
757                        );
758                    }
759                    _ => bug!("only expected method resolution for fully qualified RTN"),
760                };
761                let trait_def_id = tcx.parent(item_def_id);
762
763                // Good error for `where Trait::method(..): Send`.
764                let Some(self_ty) = opt_self_ty else {
765                    let guar = self.report_missing_self_ty_for_resolved_path(
766                        trait_def_id,
767                        hir_ty.span,
768                        item_segment,
769                        ty::AssocTag::Type,
770                    );
771                    return Ty::new_error(tcx, guar);
772                };
773                let self_ty = self.lower_ty(self_ty);
774
775                let trait_ref = self.lower_mono_trait_ref(
776                    hir_ty.span,
777                    trait_def_id,
778                    self_ty,
779                    trait_segment,
780                    false,
781                );
782
783                // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
784                // in `resolve_bound_vars`, we stash the explicit bound vars of the where
785                // clause onto the item segment of the RTN type. This allows us to know
786                // how many bound vars are *not* coming from the signature of the function
787                // from lowering RTN itself.
788                //
789                // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
790                // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
791                // parent) will include `'a` AND all the early- and late-bound vars of the
792                // method. But when lowering the RTN type, we just want the list of vars
793                // we used to resolve the trait ref. We explicitly stored those back onto
794                // the item segment, since there's no other good place to put them.
795                let candidate =
796                    ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
797
798                match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
799                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
800                    Err(guar) => Ty::new_error(tcx, guar),
801                }
802            }
803            hir::QPath::TypeRelative(hir_self_ty, segment)
804                if segment.args.is_some_and(|args| {
805                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
806                }) =>
807            {
808                let self_ty = self.lower_ty(hir_self_ty);
809                let (item_def_id, bound) = match self.resolve_type_relative_path(
810                    self_ty,
811                    hir_self_ty,
812                    ty::AssocTag::Fn,
813                    segment,
814                    hir_ty.hir_id,
815                    hir_ty.span,
816                    None,
817                ) {
818                    Ok(result) => result,
819                    Err(guar) => return Ty::new_error(tcx, guar),
820                };
821
822                // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
823                // which may happen via a higher-ranked where clause or supertrait.
824                // This is the same restrictions as associated types; even though we could
825                // support it, it just makes things a lot more difficult to support in
826                // `resolve_bound_vars`, since we'd need to introduce those as elided
827                // bound vars on the where clause too.
828                if bound.has_bound_vars() {
829                    return Ty::new_error(
830                        tcx,
831                        self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
832                            span: hir_ty.span,
833                            inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
834                            bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
835                            mpart_sugg: None,
836                            what: tcx.def_descr(item_def_id),
837                        }),
838                    );
839                }
840
841                match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
842                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
843                    Err(guar) => Ty::new_error(tcx, guar),
844                }
845            }
846            _ => self.lower_ty(hir_ty),
847        }
848    }
849
850    /// Do the common parts of lowering an RTN type. This involves extending the
851    /// candidate binder to include all of the early- and late-bound vars that are
852    /// defined on the function itself, and constructing a projection to the RPITIT
853    /// return type of that function.
854    fn lower_return_type_notation_ty(
855        &self,
856        candidate: ty::PolyTraitRef<'tcx>,
857        item_def_id: DefId,
858        path_span: Span,
859    ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
860        let tcx = self.tcx();
861        let mut emitted_bad_param_err = None;
862        // If we have an method return type bound, then we need to instantiate
863        // the method's early bound params with suitable late-bound params.
864        let mut num_bound_vars = candidate.bound_vars().len();
865        let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
866            let arg = match param.kind {
867                ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
868                    tcx,
869                    ty::INNERMOST,
870                    ty::BoundRegion {
871                        var: ty::BoundVar::from_usize(num_bound_vars),
872                        kind: ty::BoundRegionKind::Named(param.def_id),
873                    },
874                )
875                .into(),
876                ty::GenericParamDefKind::Type { .. } => {
877                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
878                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
879                            span: path_span,
880                            param_span: tcx.def_span(param.def_id),
881                        })
882                    });
883                    Ty::new_error(tcx, guar).into()
884                }
885                ty::GenericParamDefKind::Const { .. } => {
886                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
887                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
888                            span: path_span,
889                            param_span: tcx.def_span(param.def_id),
890                        })
891                    });
892                    ty::Const::new_error(tcx, guar).into()
893                }
894            };
895            num_bound_vars += 1;
896            arg
897        });
898
899        // Next, we need to check that the return-type notation is being used on
900        // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
901        let output = tcx.fn_sig(item_def_id).skip_binder().output();
902        let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
903            && tcx.is_impl_trait_in_trait(alias_ty.def_id)
904        {
905            alias_ty
906        } else {
907            return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
908                span: path_span,
909                ty: tcx.liberate_late_bound_regions(item_def_id, output),
910                fn_span: tcx.hir_span_if_local(item_def_id),
911                note: (),
912            }));
913        };
914
915        // Finally, move the fn return type's bound vars over to account for the early bound
916        // params (and trait ref's late bound params). This logic is very similar to
917        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
918        // and it's no coincidence why.
919        let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
920        Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
921    }
922}
923
924/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
925///
926/// FIXME(const_generics): This is a temporary and semi-artificial restriction until the
927/// arrival of *generic const generics*[^1].
928///
929/// It might actually be possible that we can already support early-bound generic params
930/// in such types if we just lifted some more checks in other places, too, for example
931/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
932/// probably gate this behind another feature flag.
933///
934/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
935fn check_assoc_const_binding_type<'tcx>(
936    cx: &dyn HirTyLowerer<'tcx>,
937    assoc_const: Ident,
938    ty: ty::Binder<'tcx, Ty<'tcx>>,
939    hir_id: hir::HirId,
940) -> Ty<'tcx> {
941    // We can't perform the checks for early-bound params during name resolution unlike E0770
942    // because this information depends on *type* resolution.
943    // We can't perform these checks in `resolve_bound_vars` either for the same reason.
944    // Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
945    // resolved type of `Trait::C` in order to know if it references `'a` or not.
946
947    let ty = ty.skip_binder();
948    if !ty.has_param() && !ty.has_escaping_bound_vars() {
949        return ty;
950    }
951
952    let mut collector = GenericParamAndBoundVarCollector {
953        cx,
954        params: Default::default(),
955        vars: Default::default(),
956        depth: ty::INNERMOST,
957    };
958    let mut guar = ty.visit_with(&mut collector).break_value();
959
960    let tcx = cx.tcx();
961    let ty_note = ty
962        .make_suggestable(tcx, false, None)
963        .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
964
965    let enclosing_item_owner_id = tcx
966        .hir_parent_owner_iter(hir_id)
967        .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
968        .unwrap();
969    let generics = tcx.generics_of(enclosing_item_owner_id);
970    for index in collector.params {
971        let param = generics.param_at(index as _, tcx);
972        let is_self_param = param.name == kw::SelfUpper;
973        guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
974            span: assoc_const.span,
975            assoc_const,
976            param_name: param.name,
977            param_def_kind: tcx.def_descr(param.def_id),
978            param_category: if is_self_param {
979                "self"
980            } else if param.kind.is_synthetic() {
981                "synthetic"
982            } else {
983                "normal"
984            },
985            param_defined_here_label:
986                (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
987            ty_note,
988        }));
989    }
990    for var_def_id in collector.vars {
991        guar.get_or_insert(cx.dcx().emit_err(
992            crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
993                span: assoc_const.span,
994                assoc_const,
995                var_name: cx.tcx().item_name(var_def_id),
996                var_def_kind: tcx.def_descr(var_def_id),
997                var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
998                ty_note,
999            },
1000        ));
1001    }
1002
1003    let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
1004    Ty::new_error(tcx, guar)
1005}
1006
1007struct GenericParamAndBoundVarCollector<'a, 'tcx> {
1008    cx: &'a dyn HirTyLowerer<'tcx>,
1009    params: FxIndexSet<u32>,
1010    vars: FxIndexSet<DefId>,
1011    depth: ty::DebruijnIndex,
1012}
1013
1014impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
1015    type Result = ControlFlow<ErrorGuaranteed>;
1016
1017    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
1018        &mut self,
1019        binder: &ty::Binder<'tcx, T>,
1020    ) -> Self::Result {
1021        self.depth.shift_in(1);
1022        let result = binder.super_visit_with(self);
1023        self.depth.shift_out(1);
1024        result
1025    }
1026
1027    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
1028        match ty.kind() {
1029            ty::Param(param) => {
1030                self.params.insert(param.index);
1031            }
1032            ty::Bound(db, bt) if *db >= self.depth => {
1033                self.vars.insert(match bt.kind {
1034                    ty::BoundTyKind::Param(def_id) => def_id,
1035                    ty::BoundTyKind::Anon => {
1036                        let reported = self
1037                            .cx
1038                            .dcx()
1039                            .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
1040                        return ControlFlow::Break(reported);
1041                    }
1042                });
1043            }
1044            _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
1045            _ => {}
1046        }
1047        ControlFlow::Continue(())
1048    }
1049
1050    fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
1051        match re.kind() {
1052            ty::ReEarlyParam(param) => {
1053                self.params.insert(param.index);
1054            }
1055            ty::ReBound(db, br) if db >= self.depth => {
1056                self.vars.insert(match br.kind {
1057                    ty::BoundRegionKind::Named(def_id) => def_id,
1058                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1059                        let guar = self
1060                            .cx
1061                            .dcx()
1062                            .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1063                        return ControlFlow::Break(guar);
1064                    }
1065                    ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
1066                });
1067            }
1068            _ => {}
1069        }
1070        ControlFlow::Continue(())
1071    }
1072
1073    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1074        match ct.kind() {
1075            ty::ConstKind::Param(param) => {
1076                self.params.insert(param.index);
1077            }
1078            ty::ConstKind::Bound(db, _) if db >= self.depth => {
1079                let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1080                return ControlFlow::Break(guar);
1081            }
1082            _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1083            _ => {}
1084        }
1085        ControlFlow::Continue(())
1086    }
1087}