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