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