rustc_hir_analysis/hir_ty_lowering/
bounds.rs

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