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::PolyTraitRef;
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
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 crate::errors;
21use crate::hir_ty_lowering::{
22    AssocItemQSelf, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
23    OverlappingAsssocItemConstraints, 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    context: ImpliedBoundsContext<'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 ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
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    context: ImpliedBoundsContext<'tcx>,
91) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
92    let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
93    search_bounds_for(hir_bounds, context, |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    context: ImpliedBoundsContext<'tcx>,
104    target_did: DefId,
105) -> CollectedBound {
106    let mut collect_into = CollectedBound::default();
107    search_bounds_for(hir_bounds, context, |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    context: ImpliedBoundsContext<'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, context, sized_did);
129
130    let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
131    let meta_sized = collect_bounds(hir_bounds, context, 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, context, 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_implicit_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        context: ImpliedBoundsContext<'tcx>,
168        span: Span,
169    ) {
170        let tcx = self.tcx();
171
172        // Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
173        if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
174            return;
175        }
176
177        let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
178        let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
179
180        // If adding sizedness bounds to a trait, then there are some relevant early exits
181        match context {
182            ImpliedBoundsContext::TraitDef(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            }
194            ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
195                // Report invalid relaxed bounds.
196                // FIXME: Since we only call this validation function here in this function, we only
197                //        fully validate relaxed bounds in contexts where we perform
198                //        "sized elaboration". In most cases that doesn't matter because we *usually*
199                //        reject such relaxed bounds outright during AST lowering.
200                //        However, this can easily get out of sync! Ideally, we would perform this step
201                //        where we are guaranteed to catch *all* bounds like in
202                //        `Self::lower_poly_trait_ref`. List of concrete issues:
203                //        FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
204                //                                  bounds, trait alias bounds, assoc type bounds (ATB)!
205                let bounds = collect_relaxed_bounds(hir_bounds, context);
206                self.reject_duplicate_relaxed_bounds(bounds);
207            }
208        }
209
210        let collected = collect_sizedness_bounds(tcx, hir_bounds, context, 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            match context {
221                ImpliedBoundsContext::TraitDef(..) => {
222                    // If there are no explicit sizedness bounds on a trait then add a default
223                    // `MetaSized` supertrait.
224                    add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
225                }
226                ImpliedBoundsContext::TyParam(..)
227                | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
228                    // If there are no explicit sizedness bounds on a parameter then add a default
229                    // `Sized` bound.
230                    let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
231                    add_trait_bound(tcx, bounds, self_ty, sized_did, span);
232                }
233            }
234        }
235    }
236
237    pub(crate) fn add_default_traits(
238        &self,
239        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
240        self_ty: Ty<'tcx>,
241        hir_bounds: &[hir::GenericBound<'tcx>],
242        context: ImpliedBoundsContext<'tcx>,
243        span: Span,
244    ) {
245        self.tcx().default_traits().iter().for_each(|default_trait| {
246            self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
247        });
248    }
249
250    /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate.
251    ///
252    /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
253    pub(crate) fn add_default_trait(
254        &self,
255        trait_: hir::LangItem,
256        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
257        self_ty: Ty<'tcx>,
258        hir_bounds: &[hir::GenericBound<'tcx>],
259        context: ImpliedBoundsContext<'tcx>,
260        span: Span,
261    ) {
262        let tcx = self.tcx();
263
264        // Supertraits for auto trait are unsound according to the unstable book:
265        // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits
266        if let ImpliedBoundsContext::TraitDef(trait_did) = context
267            && self.tcx().trait_is_auto(trait_did.into())
268        {
269            return;
270        }
271
272        if let Some(trait_did) = tcx.lang_items().get(trait_)
273            && self.should_add_default_traits(trait_did, hir_bounds, context)
274        {
275            add_trait_bound(tcx, bounds, self_ty, trait_did, span);
276        }
277    }
278
279    /// Returns `true` if default trait bound should be added.
280    fn should_add_default_traits<'a>(
281        &self,
282        trait_def_id: DefId,
283        hir_bounds: &'a [hir::GenericBound<'tcx>],
284        context: ImpliedBoundsContext<'tcx>,
285    ) -> bool {
286        let collected = collect_bounds(hir_bounds, context, trait_def_id);
287        !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
288    }
289
290    fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
291        let tcx = self.tcx();
292
293        let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
294
295        for bound in &relaxed_bounds {
296            if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
297                grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
298            }
299        }
300
301        for (trait_def_id, spans) in grouped_bounds {
302            if spans.len() > 1 {
303                let name = tcx.item_name(trait_def_id);
304                self.dcx()
305                    .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
306                    .with_code(E0203)
307                    .emit();
308            }
309        }
310    }
311
312    pub(crate) fn require_bound_to_relax_default_trait(
313        &self,
314        trait_ref: hir::TraitRef<'_>,
315        span: Span,
316    ) {
317        let tcx = self.tcx();
318
319        if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
320            && (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id))
321        {
322            return;
323        }
324
325        self.dcx().span_err(
326            span,
327            if tcx.sess.opts.unstable_opts.experimental_default_bounds
328                || tcx.features().more_maybe_bounds()
329            {
330                "bound modifier `?` can only be applied to default traits"
331            } else {
332                "bound modifier `?` can only be applied to `Sized`"
333            },
334        );
335    }
336
337    /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
338    ///
339    /// ### Examples
340    ///
341    /// ```ignore (illustrative)
342    /// fn foo<T>() where for<'a> T: Trait<'a> + Copy {}
343    /// //                ^^^^^^^ ^  ^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
344    /// //                |       |
345    /// //                |       `param_ty`, in ty form
346    /// //                `bound_vars`, in ty form
347    ///
348    /// fn bar<T>() where T: for<'a> Trait<'a> + Copy {} // no overarching `bound_vars` here!
349    /// //                ^  ^^^^^^^^^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
350    /// //                |
351    /// //                `param_ty`, in ty form
352    /// ```
353    ///
354    /// ### A Note on Binders
355    ///
356    /// There is an implied binder around `param_ty` and `hir_bounds`.
357    /// See `lower_poly_trait_ref` for more details.
358    #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
359    pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
360        &self,
361        param_ty: Ty<'tcx>,
362        hir_bounds: I,
363        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
364        bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
365        predicate_filter: PredicateFilter,
366        overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
367    ) where
368        'tcx: 'hir,
369    {
370        for hir_bound in hir_bounds {
371            // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
372            // we skip over any traits that don't define the given associated type.
373            if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
374                if let Some(trait_ref) = hir_bound.trait_ref()
375                    && let Some(trait_did) = trait_ref.trait_def_id()
376                    && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
377                {
378                    // Okay
379                } else {
380                    continue;
381                }
382            }
383
384            match hir_bound {
385                hir::GenericBound::Trait(poly_trait_ref) => {
386                    let _ = self.lower_poly_trait_ref(
387                        poly_trait_ref,
388                        param_ty,
389                        bounds,
390                        predicate_filter,
391                        overlapping_assoc_constraints,
392                    );
393                }
394                hir::GenericBound::Outlives(lifetime) => {
395                    // `ConstIfConst` is only interested in `[const]` bounds.
396                    if matches!(
397                        predicate_filter,
398                        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
399                    ) {
400                        continue;
401                    }
402
403                    let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
404                    let bound = ty::Binder::bind_with_vars(
405                        ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
406                        bound_vars,
407                    );
408                    bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
409                }
410                hir::GenericBound::Use(..) => {
411                    // We don't actually lower `use` into the type layer.
412                }
413            }
414        }
415    }
416
417    /// Lower an associated item constraint from the HIR into `bounds`.
418    ///
419    /// ### A Note on Binders
420    ///
421    /// Given something like `T: for<'a> Iterator<Item = &'a u32>`,
422    /// the `trait_ref` here will be `for<'a> T: Iterator`.
423    /// The `constraint` data however is from *inside* the binder
424    /// (e.g., `&'a u32`) and hence may reference bound regions.
425    #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
426    pub(super) fn lower_assoc_item_constraint(
427        &self,
428        hir_ref_id: hir::HirId,
429        trait_ref: ty::PolyTraitRef<'tcx>,
430        constraint: &hir::AssocItemConstraint<'tcx>,
431        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
432        duplicates: Option<&mut FxIndexMap<DefId, Span>>,
433        path_span: Span,
434        predicate_filter: PredicateFilter,
435    ) -> Result<(), ErrorGuaranteed> {
436        let tcx = self.tcx();
437
438        let assoc_tag = if constraint.gen_args.parenthesized
439            == hir::GenericArgsParentheses::ReturnTypeNotation
440        {
441            ty::AssocTag::Fn
442        } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
443            constraint.kind
444        {
445            ty::AssocTag::Const
446        } else {
447            ty::AssocTag::Type
448        };
449
450        // Given something like `U: Trait<T = X>`, we want to produce a predicate like
451        // `<U as Trait>::T = X`.
452        // This is somewhat subtle in the event that `T` is defined in a supertrait of `Trait`,
453        // because in that case we need to upcast. I.e., we want to produce
454        // `<B as SuperTrait<i32>>::T == X` for `B: SubTrait<T = X>` where
455        //
456        //     trait SubTrait: SuperTrait<i32> {}
457        //     trait SuperTrait<A> { type T; }
458        let candidate = if self.probe_trait_that_defines_assoc_item(
459            trait_ref.def_id(),
460            assoc_tag,
461            constraint.ident,
462        ) {
463            // Simple case: The assoc item is defined in the current trait.
464            trait_ref
465        } else {
466            // Otherwise, we have to walk through the supertraits to find
467            // one that does define it.
468            self.probe_single_bound_for_assoc_item(
469                || traits::supertraits(tcx, trait_ref),
470                AssocItemQSelf::Trait(trait_ref.def_id()),
471                assoc_tag,
472                constraint.ident,
473                path_span,
474                Some(constraint),
475            )?
476        };
477
478        let assoc_item = self
479            .probe_assoc_item(
480                constraint.ident,
481                assoc_tag,
482                hir_ref_id,
483                constraint.span,
484                candidate.def_id(),
485            )
486            .expect("failed to find associated item");
487
488        if let Some(duplicates) = duplicates {
489            duplicates
490                .entry(assoc_item.def_id)
491                .and_modify(|prev_span| {
492                    self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
493                        span: constraint.span,
494                        prev_span: *prev_span,
495                        item_name: constraint.ident,
496                        def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
497                    });
498                })
499                .or_insert(constraint.span);
500        }
501
502        let projection_term = if let ty::AssocTag::Fn = assoc_tag {
503            let bound_vars = tcx.late_bound_vars(constraint.hir_id);
504            ty::Binder::bind_with_vars(
505                self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
506                bound_vars,
507            )
508        } else {
509            // Create the generic arguments for the associated type or constant by joining the
510            // parent arguments (the arguments of the trait) and the own arguments (the ones of
511            // the associated item itself) and construct an alias type using them.
512            let alias_term = candidate.map_bound(|trait_ref| {
513                let item_segment = hir::PathSegment {
514                    ident: constraint.ident,
515                    hir_id: constraint.hir_id,
516                    res: Res::Err,
517                    args: Some(constraint.gen_args),
518                    infer_args: false,
519                };
520
521                let alias_args = self.lower_generic_args_of_assoc_item(
522                    path_span,
523                    assoc_item.def_id,
524                    &item_segment,
525                    trait_ref.args,
526                );
527                debug!(?alias_args);
528
529                ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
530            });
531
532            // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
533            if let Some(const_arg) = constraint.ct()
534                && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
535            {
536                let ty = alias_term
537                    .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
538                let ty =
539                    check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
540                tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
541            }
542
543            alias_term
544        };
545
546        match constraint.kind {
547            hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
548                return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
549                    span: constraint.span,
550                }));
551            }
552            // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>`
553            // to a projection predicate: `<T as Iterator>::Item = u32`.
554            hir::AssocItemConstraintKind::Equality { term } => {
555                let term = match term {
556                    hir::Term::Ty(ty) => self.lower_ty(ty).into(),
557                    hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
558                };
559
560                // Find any late-bound regions declared in `ty` that are not
561                // declared in the trait-ref or assoc_item. These are not well-formed.
562                //
563                // Example:
564                //
565                //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
566                //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
567                let late_bound_in_projection_ty =
568                    tcx.collect_constrained_late_bound_regions(projection_term);
569                let late_bound_in_term =
570                    tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
571                debug!(?late_bound_in_projection_ty);
572                debug!(?late_bound_in_term);
573
574                // FIXME: point at the type params that don't have appropriate lifetimes:
575                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
576                //                         ----  ----     ^^^^^^^
577                // NOTE(associated_const_equality): This error should be impossible to trigger
578                //                                  with associated const equality constraints.
579                self.validate_late_bound_regions(
580                    late_bound_in_projection_ty,
581                    late_bound_in_term,
582                    |br_name| {
583                        struct_span_code_err!(
584                            self.dcx(),
585                            constraint.span,
586                            E0582,
587                            "binding for associated type `{}` references {}, \
588                             which does not appear in the trait input types",
589                            constraint.ident,
590                            br_name
591                        )
592                    },
593                );
594
595                match predicate_filter {
596                    PredicateFilter::All
597                    | PredicateFilter::SelfOnly
598                    | PredicateFilter::SelfAndAssociatedTypeBounds => {
599                        let bound = projection_term.map_bound(|projection_term| {
600                            ty::ClauseKind::Projection(ty::ProjectionPredicate {
601                                projection_term,
602                                term,
603                            })
604                        });
605                        bounds.push((bound.upcast(tcx), constraint.span));
606                    }
607                    // SelfTraitThatDefines is only interested in trait predicates.
608                    PredicateFilter::SelfTraitThatDefines(_) => {}
609                    // `ConstIfConst` is only interested in `[const]` bounds.
610                    PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
611                }
612            }
613            // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
614            // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
615            hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
616                match predicate_filter {
617                    PredicateFilter::All
618                    | PredicateFilter::SelfAndAssociatedTypeBounds
619                    | PredicateFilter::ConstIfConst => {
620                        let projection_ty = projection_term
621                            .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
622                        // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
623                        // parameter to have a skipped binder.
624                        let param_ty =
625                            Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
626                        self.lower_bounds(
627                            param_ty,
628                            hir_bounds,
629                            bounds,
630                            projection_ty.bound_vars(),
631                            predicate_filter,
632                            OverlappingAsssocItemConstraints::Allowed,
633                        );
634                    }
635                    PredicateFilter::SelfOnly
636                    | PredicateFilter::SelfTraitThatDefines(_)
637                    | PredicateFilter::SelfConstIfConst => {}
638                }
639            }
640        }
641        Ok(())
642    }
643
644    /// Lower a type, possibly specially handling the type if it's a return type notation
645    /// which we otherwise deny in other positions.
646    pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
647        let hir::TyKind::Path(qpath) = hir_ty.kind else {
648            return self.lower_ty(hir_ty);
649        };
650
651        let tcx = self.tcx();
652        match qpath {
653            hir::QPath::Resolved(opt_self_ty, path)
654                if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
655                    && item_segment.args.is_some_and(|args| {
656                        matches!(
657                            args.parenthesized,
658                            hir::GenericArgsParentheses::ReturnTypeNotation
659                        )
660                    }) =>
661            {
662                // We don't allow generics on the module segments.
663                let _ =
664                    self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
665
666                let item_def_id = match path.res {
667                    Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
668                    Res::Err => {
669                        return Ty::new_error_with_message(
670                            tcx,
671                            hir_ty.span,
672                            "failed to resolve RTN",
673                        );
674                    }
675                    _ => bug!("only expected method resolution for fully qualified RTN"),
676                };
677                let trait_def_id = tcx.parent(item_def_id);
678
679                // Good error for `where Trait::method(..): Send`.
680                let Some(self_ty) = opt_self_ty else {
681                    let guar = self.report_missing_self_ty_for_resolved_path(
682                        trait_def_id,
683                        hir_ty.span,
684                        item_segment,
685                        ty::AssocTag::Type,
686                    );
687                    return Ty::new_error(tcx, guar);
688                };
689                let self_ty = self.lower_ty(self_ty);
690
691                let trait_ref = self.lower_mono_trait_ref(
692                    hir_ty.span,
693                    trait_def_id,
694                    self_ty,
695                    trait_segment,
696                    false,
697                );
698
699                // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
700                // in `resolve_bound_vars`, we stash the explicit bound vars of the where
701                // clause onto the item segment of the RTN type. This allows us to know
702                // how many bound vars are *not* coming from the signature of the function
703                // from lowering RTN itself.
704                //
705                // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
706                // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
707                // parent) will include `'a` AND all the early- and late-bound vars of the
708                // method. But when lowering the RTN type, we just want the list of vars
709                // we used to resolve the trait ref. We explicitly stored those back onto
710                // the item segment, since there's no other good place to put them.
711                let candidate =
712                    ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
713
714                match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
715                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
716                    Err(guar) => Ty::new_error(tcx, guar),
717                }
718            }
719            hir::QPath::TypeRelative(hir_self_ty, segment)
720                if segment.args.is_some_and(|args| {
721                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
722                }) =>
723            {
724                let self_ty = self.lower_ty(hir_self_ty);
725                let (item_def_id, bound) = match self.resolve_type_relative_path(
726                    self_ty,
727                    hir_self_ty,
728                    ty::AssocTag::Fn,
729                    segment,
730                    hir_ty.hir_id,
731                    hir_ty.span,
732                    None,
733                ) {
734                    Ok(result) => result,
735                    Err(guar) => return Ty::new_error(tcx, guar),
736                };
737
738                // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
739                // which may happen via a higher-ranked where clause or supertrait.
740                // This is the same restrictions as associated types; even though we could
741                // support it, it just makes things a lot more difficult to support in
742                // `resolve_bound_vars`, since we'd need to introduce those as elided
743                // bound vars on the where clause too.
744                if bound.has_bound_vars() {
745                    return Ty::new_error(
746                        tcx,
747                        self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
748                            span: hir_ty.span,
749                            inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
750                            bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
751                            mpart_sugg: None,
752                            what: tcx.def_descr(item_def_id),
753                        }),
754                    );
755                }
756
757                match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
758                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
759                    Err(guar) => Ty::new_error(tcx, guar),
760                }
761            }
762            _ => self.lower_ty(hir_ty),
763        }
764    }
765
766    /// Do the common parts of lowering an RTN type. This involves extending the
767    /// candidate binder to include all of the early- and late-bound vars that are
768    /// defined on the function itself, and constructing a projection to the RPITIT
769    /// return type of that function.
770    fn lower_return_type_notation_ty(
771        &self,
772        candidate: ty::PolyTraitRef<'tcx>,
773        item_def_id: DefId,
774        path_span: Span,
775    ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
776        let tcx = self.tcx();
777        let mut emitted_bad_param_err = None;
778        // If we have an method return type bound, then we need to instantiate
779        // the method's early bound params with suitable late-bound params.
780        let mut num_bound_vars = candidate.bound_vars().len();
781        let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
782            let arg = match param.kind {
783                ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
784                    tcx,
785                    ty::INNERMOST,
786                    ty::BoundRegion {
787                        var: ty::BoundVar::from_usize(num_bound_vars),
788                        kind: ty::BoundRegionKind::Named(param.def_id),
789                    },
790                )
791                .into(),
792                ty::GenericParamDefKind::Type { .. } => {
793                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
794                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
795                            span: path_span,
796                            param_span: tcx.def_span(param.def_id),
797                        })
798                    });
799                    Ty::new_error(tcx, guar).into()
800                }
801                ty::GenericParamDefKind::Const { .. } => {
802                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
803                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
804                            span: path_span,
805                            param_span: tcx.def_span(param.def_id),
806                        })
807                    });
808                    ty::Const::new_error(tcx, guar).into()
809                }
810            };
811            num_bound_vars += 1;
812            arg
813        });
814
815        // Next, we need to check that the return-type notation is being used on
816        // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
817        let output = tcx.fn_sig(item_def_id).skip_binder().output();
818        let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
819            && tcx.is_impl_trait_in_trait(alias_ty.def_id)
820        {
821            alias_ty
822        } else {
823            return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
824                span: path_span,
825                ty: tcx.liberate_late_bound_regions(item_def_id, output),
826                fn_span: tcx.hir_span_if_local(item_def_id),
827                note: (),
828            }));
829        };
830
831        // Finally, move the fn return type's bound vars over to account for the early bound
832        // params (and trait ref's late bound params). This logic is very similar to
833        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
834        // and it's no coincidence why.
835        let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
836        Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
837    }
838}
839
840/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
841///
842/// FIXME(const_generics): This is a temporary and semi-artificial restriction until the
843/// arrival of *generic const generics*[^1].
844///
845/// It might actually be possible that we can already support early-bound generic params
846/// in such types if we just lifted some more checks in other places, too, for example
847/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
848/// probably gate this behind another feature flag.
849///
850/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
851fn check_assoc_const_binding_type<'tcx>(
852    cx: &dyn HirTyLowerer<'tcx>,
853    assoc_const: Ident,
854    ty: ty::Binder<'tcx, Ty<'tcx>>,
855    hir_id: hir::HirId,
856) -> Ty<'tcx> {
857    // We can't perform the checks for early-bound params during name resolution unlike E0770
858    // because this information depends on *type* resolution.
859    // We can't perform these checks in `resolve_bound_vars` either for the same reason.
860    // Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
861    // resolved type of `Trait::C` in order to know if it references `'a` or not.
862
863    let ty = ty.skip_binder();
864    if !ty.has_param() && !ty.has_escaping_bound_vars() {
865        return ty;
866    }
867
868    let mut collector = GenericParamAndBoundVarCollector {
869        cx,
870        params: Default::default(),
871        vars: Default::default(),
872        depth: ty::INNERMOST,
873    };
874    let mut guar = ty.visit_with(&mut collector).break_value();
875
876    let tcx = cx.tcx();
877    let ty_note = ty
878        .make_suggestable(tcx, false, None)
879        .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
880
881    let enclosing_item_owner_id = tcx
882        .hir_parent_owner_iter(hir_id)
883        .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
884        .unwrap();
885    let generics = tcx.generics_of(enclosing_item_owner_id);
886    for index in collector.params {
887        let param = generics.param_at(index as _, tcx);
888        let is_self_param = param.name == kw::SelfUpper;
889        guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
890            span: assoc_const.span,
891            assoc_const,
892            param_name: param.name,
893            param_def_kind: tcx.def_descr(param.def_id),
894            param_category: if is_self_param {
895                "self"
896            } else if param.kind.is_synthetic() {
897                "synthetic"
898            } else {
899                "normal"
900            },
901            param_defined_here_label:
902                (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
903            ty_note,
904        }));
905    }
906    for var_def_id in collector.vars {
907        guar.get_or_insert(cx.dcx().emit_err(
908            crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
909                span: assoc_const.span,
910                assoc_const,
911                var_name: cx.tcx().item_name(var_def_id),
912                var_def_kind: tcx.def_descr(var_def_id),
913                var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
914                ty_note,
915            },
916        ));
917    }
918
919    let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
920    Ty::new_error(tcx, guar)
921}
922
923struct GenericParamAndBoundVarCollector<'a, 'tcx> {
924    cx: &'a dyn HirTyLowerer<'tcx>,
925    params: FxIndexSet<u32>,
926    vars: FxIndexSet<DefId>,
927    depth: ty::DebruijnIndex,
928}
929
930impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
931    type Result = ControlFlow<ErrorGuaranteed>;
932
933    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
934        &mut self,
935        binder: &ty::Binder<'tcx, T>,
936    ) -> Self::Result {
937        self.depth.shift_in(1);
938        let result = binder.super_visit_with(self);
939        self.depth.shift_out(1);
940        result
941    }
942
943    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
944        match ty.kind() {
945            ty::Param(param) => {
946                self.params.insert(param.index);
947            }
948            ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
949                self.vars.insert(match bt.kind {
950                    ty::BoundTyKind::Param(def_id) => def_id,
951                    ty::BoundTyKind::Anon => {
952                        let reported = self
953                            .cx
954                            .dcx()
955                            .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
956                        return ControlFlow::Break(reported);
957                    }
958                });
959            }
960            _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
961            _ => {}
962        }
963        ControlFlow::Continue(())
964    }
965
966    fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
967        match re.kind() {
968            ty::ReEarlyParam(param) => {
969                self.params.insert(param.index);
970            }
971            ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
972                self.vars.insert(match br.kind {
973                    ty::BoundRegionKind::Named(def_id) => def_id,
974                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
975                        let guar = self
976                            .cx
977                            .dcx()
978                            .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
979                        return ControlFlow::Break(guar);
980                    }
981                    ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
982                });
983            }
984            _ => {}
985        }
986        ControlFlow::Continue(())
987    }
988
989    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
990        match ct.kind() {
991            ty::ConstKind::Param(param) => {
992                self.params.insert(param.index);
993            }
994            ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
995                let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
996                return ControlFlow::Break(guar);
997            }
998            _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
999            _ => {}
1000        }
1001        ControlFlow::Continue(())
1002    }
1003}