rustc_hir_analysis/hir_ty_lowering/
bounds.rs

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