Skip to main content

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::attrs::lang_items::LangItem;
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::DefId;
10use rustc_hir::{PolyTraitRef, find_attr};
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};
17use rustc_trait_selection::traits;
18use tracing::{debug, instrument};
19
20use crate::diagnostics;
21use crate::hir_ty_lowering::{
22    AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
23    OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
24};
25
26#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CollectedBound {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "CollectedBound", "positive", &self.positive, "maybe",
            &self.maybe, "negative", &&self.negative)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for CollectedBound {
    #[inline]
    fn default() -> CollectedBound {
        CollectedBound {
            positive: ::core::default::Default::default(),
            maybe: ::core::default::Default::default(),
            negative: ::core::default::Default::default(),
        }
    }
}Default)]
27struct CollectedBound {
28    /// `Trait`
29    positive: Option<Span>,
30    /// `?Trait`
31    maybe: Option<Span>,
32    /// `!Trait`
33    negative: Option<Span>,
34}
35
36impl CollectedBound {
37    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered.
38    fn any(&self) -> bool {
39        self.positive.is_some() || self.maybe.is_some() || self.negative.is_some()
40    }
41}
42
43#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CollectedSizednessBounds {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "CollectedSizednessBounds", "sized", &self.sized, "meta_sized",
            &self.meta_sized, "pointee_sized", &&self.pointee_sized)
    }
}Debug)]
44struct CollectedSizednessBounds {
45    // Collected `Sized` bounds
46    sized: CollectedBound,
47    // Collected `MetaSized` bounds
48    meta_sized: CollectedBound,
49    // Collected `PointeeSized` bounds
50    pointee_sized: CollectedBound,
51}
52
53impl CollectedSizednessBounds {
54    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered for `Sized`,
55    /// `MetaSized` or `PointeeSized`.
56    fn any(&self) -> bool {
57        self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
58    }
59}
60
61fn search_bounds_for<'tcx>(
62    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
63    context: ImpliedBoundsContext<'tcx>,
64    mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
65) {
66    let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
67        for hir_bound in hir_bounds {
68            let hir::GenericBound::Trait(ptr) = hir_bound else {
69                continue;
70            };
71
72            f(ptr)
73        }
74    };
75
76    search_bounds(hir_bounds);
77    if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
78        for clause in where_clause {
79            if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
80                && pred.is_param_bound(self_ty.to_def_id())
81            {
82                search_bounds(pred.bounds);
83            }
84        }
85    }
86}
87
88fn collect_bounds<'a, 'tcx>(
89    hir_bounds: &'a [hir::GenericBound<'tcx>],
90    context: ImpliedBoundsContext<'tcx>,
91    target_did: DefId,
92) -> CollectedBound {
93    let mut collect_into = CollectedBound::default();
94    search_bounds_for(hir_bounds, context, |ptr| {
95        if !#[allow(non_exhaustive_omitted_patterns)] match ptr.trait_ref.path.res {
    Res::Def(DefKind::Trait, did) if did == target_did => true,
    _ => false,
}matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
96            return;
97        }
98
99        match ptr.modifiers.polarity {
100            hir::BoundPolarity::Maybe(_) => collect_into.maybe = Some(ptr.span),
101            hir::BoundPolarity::Negative(_) => collect_into.negative = Some(ptr.span),
102            hir::BoundPolarity::Positive => collect_into.positive = Some(ptr.span),
103        }
104    });
105    collect_into
106}
107
108fn collect_sizedness_bounds<'tcx>(
109    tcx: TyCtxt<'tcx>,
110    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
111    context: ImpliedBoundsContext<'tcx>,
112    span: Span,
113) -> CollectedSizednessBounds {
114    let sized_did = tcx.require_lang_item(LangItem::Sized, span);
115    let sized = collect_bounds(hir_bounds, context, sized_did);
116
117    let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
118    let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
119
120    let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
121    let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
122
123    CollectedSizednessBounds { sized, meta_sized, pointee_sized }
124}
125
126/// Add a trait bound for `did`.
127fn add_trait_bound<'tcx>(
128    tcx: TyCtxt<'tcx>,
129    bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
130    self_ty: Ty<'tcx>,
131    did: DefId,
132    span: Span,
133) {
134    let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
135    // Preferable to put sizedness obligations first, since we report better errors for `Sized`
136    // ambiguity.
137    bounds.insert(0, (trait_ref.upcast(tcx), span));
138}
139
140impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
141    /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
142    ///
143    /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
144    ///   sizedness bounds are present.
145    /// - On traits and trait aliases, add default `MetaSized` supertrait if no explicit sizedness
146    ///   bounds are present.
147    /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if
148    ///   a `?Sized` bound is present.
149    pub(crate) fn add_implicit_sizedness_bounds(
150        &self,
151        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
152        self_ty: Ty<'tcx>,
153        hir_bounds: &'tcx [hir::GenericBound<'tcx>],
154        context: ImpliedBoundsContext<'tcx>,
155        span: Span,
156    ) {
157        let tcx = self.tcx();
158
159        // Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
160        if {
        'done:
            {
            for i in tcx.hir_krate_attrs() {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(RustcNoImplicitBounds) =>
                        {
                        break 'done Some(());
                    }
                    ::rustc_attr_ir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }.is_some()find_attr!(tcx, crate, RustcNoImplicitBounds) {
161            return;
162        }
163
164        let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
165        let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
166
167        // If adding sizedness bounds to a trait, then there are some relevant early exits
168        match context {
169            ImpliedBoundsContext::TraitDef(trait_did) => {
170                let trait_did = trait_did.to_def_id();
171                // Never add a default supertrait to `PointeeSized`.
172                if trait_did == pointee_sized_did {
173                    return;
174                }
175                // Don't add default sizedness supertraits to auto traits because it isn't possible to
176                // relax an automatically added supertrait on the defn itself.
177                if tcx.trait_is_auto(trait_did) {
178                    return;
179                }
180            }
181            ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
182            }
183        }
184        let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
185        if let Some(span) = collected.sized.maybe.or(collected.sized.negative)
186            && collected.sized.positive.is_none()
187            && !collected.meta_sized.any()
188            && !collected.pointee_sized.any()
189        {
190            // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any
191            // other explicit ones) - this can happen for trait aliases as well as bounds.
192            add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
193        } else if !collected.any() {
194            match context {
195                ImpliedBoundsContext::TraitDef(..) => {
196                    // If there are no explicit sizedness bounds on a trait then add a default
197                    // `MetaSized` supertrait.
198                    add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
199                }
200                ImpliedBoundsContext::TyParam(..)
201                | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
202                    // If there are no explicit sizedness bounds on a parameter then add a default
203                    // `Sized` bound.
204                    let sized_did = tcx.require_lang_item(LangItem::Sized, span);
205                    add_trait_bound(tcx, bounds, self_ty, sized_did, span);
206                }
207            }
208        }
209    }
210
211    pub(crate) fn add_default_traits(
212        &self,
213        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
214        self_ty: Ty<'tcx>,
215        hir_bounds: &[hir::GenericBound<'tcx>],
216        context: ImpliedBoundsContext<'tcx>,
217        span: Span,
218    ) {
219        self.tcx().default_traits().iter().for_each(|default_trait| {
220            self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
221        });
222    }
223
224    /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate.
225    ///
226    /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
227    pub(crate) fn add_default_trait(
228        &self,
229        trait_: LangItem,
230        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
231        self_ty: Ty<'tcx>,
232        hir_bounds: &[hir::GenericBound<'tcx>],
233        context: ImpliedBoundsContext<'tcx>,
234        span: Span,
235    ) {
236        let tcx = self.tcx();
237
238        // Supertraits for auto trait are unsound according to the unstable book:
239        // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits
240        if let ImpliedBoundsContext::TraitDef(trait_did) = context
241            && self.tcx().trait_is_auto(trait_did.into())
242        {
243            return;
244        }
245
246        if let Some(trait_did) = tcx.lang_items().get(trait_)
247            && self.should_add_default_traits(trait_did, hir_bounds, context)
248        {
249            add_trait_bound(tcx, bounds, self_ty, trait_did, span);
250        }
251    }
252
253    /// Returns `true` if default trait bound should be added.
254    fn should_add_default_traits<'a>(
255        &self,
256        trait_def_id: DefId,
257        hir_bounds: &'a [hir::GenericBound<'tcx>],
258        context: ImpliedBoundsContext<'tcx>,
259    ) -> bool {
260        let collected = collect_bounds(hir_bounds, context, trait_def_id);
261        !{
        'done:
            {
            for i in self.tcx().hir_krate_attrs() {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(RustcNoImplicitBounds) =>
                        {
                        break 'done Some(());
                    }
                    ::rustc_attr_ir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }.is_some()find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any()
262    }
263
264    pub(crate) fn require_bound_to_relax_default_trait(
265        &self,
266        trait_ref: hir::TraitRef<'_>,
267        span: Span,
268    ) {
269        let tcx = self.tcx();
270
271        if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
272            && (tcx.is_lang_item(def_id, LangItem::Sized) || tcx.is_default_trait(def_id))
273        {
274            return;
275        }
276
277        self.dcx().span_err(
278            span,
279            if tcx.sess.opts.unstable_opts.experimental_default_bounds
280                || tcx.features().more_maybe_bounds()
281            {
282                "bound modifier `?` can only be applied to default traits"
283            } else {
284                "bound modifier `?` can only be applied to `Sized`"
285            },
286        );
287    }
288
289    /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
290    ///
291    /// ### Examples
292    ///
293    /// ```ignore (illustrative)
294    /// fn foo<T>() where for<'a> T: Trait<'a> + Copy {}
295    /// //                ^^^^^^^ ^  ^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
296    /// //                |       |
297    /// //                |       `param_ty`, in ty form
298    /// //                `bound_vars`, in ty form
299    ///
300    /// fn bar<T>() where T: for<'a> Trait<'a> + Copy {} // no overarching `bound_vars` here!
301    /// //                ^  ^^^^^^^^^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
302    /// //                |
303    /// //                `param_ty`, in ty form
304    /// ```
305    ///
306    /// ### A Note on Binders
307    ///
308    /// There is an implied binder around `param_ty` and `hir_bounds`.
309    /// See `lower_poly_trait_ref` for more details.
310    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("lower_bounds",
                                    "rustc_hir_analysis::hir_ty_lowering::bounds",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
                                    ::tracing_core::__macro_support::Option::Some(310u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("param_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("param_ty");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("bound_vars")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("bound_vars");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("predicate_filter")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("predicate_filter");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("overlapping_assoc_constraints")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("overlapping_assoc_constraints");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param_ty)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bound_vars)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&predicate_filter)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&overlapping_assoc_constraints)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            for hir_bound in hir_bounds {
                if let PredicateFilter::SelfTraitThatDefines(assoc_ident) =
                        predicate_filter {
                    if let Some(trait_ref) = hir_bound.trait_ref() &&
                                let Some(trait_did) = trait_ref.trait_def_id() &&
                            self.tcx().trait_may_define_assoc_item(trait_did,
                                assoc_ident) {} else { continue; }
                }
                match hir_bound {
                    hir::GenericBound::Trait(poly_trait_ref) => {
                        let _ =
                            self.lower_poly_trait_ref(poly_trait_ref, param_ty, bounds,
                                predicate_filter, overlapping_assoc_constraints);
                    }
                    hir::GenericBound::Outlives(lifetime) => {
                        if #[allow(non_exhaustive_omitted_patterns)] match predicate_filter
                                {
                                PredicateFilter::ConstIfConst |
                                    PredicateFilter::SelfConstIfConst => true,
                                _ => false,
                            } {
                            continue;
                        }
                        let region =
                            self.lower_lifetime(lifetime,
                                RegionInferReason::OutlivesBound);
                        let bound =
                            ty::Binder::bind_with_vars(ty::ClauseKind::TypeOutlives(ty::OutlivesClause(param_ty,
                                        region)), bound_vars);
                        bounds.push((bound.upcast(self.tcx()),
                                lifetime.ident.span));
                    }
                    hir::GenericBound::Use(..) => {}
                }
            }
        }
    }
}#[instrument(level = "debug", skip(self, hir_bounds, bounds))]
311    pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
312        &self,
313        param_ty: Ty<'tcx>,
314        hir_bounds: I,
315        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
316        bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
317        predicate_filter: PredicateFilter,
318        overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
319    ) where
320        'tcx: 'hir,
321    {
322        for hir_bound in hir_bounds {
323            // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
324            // we skip over any traits that don't define the given associated type.
325            if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
326                if let Some(trait_ref) = hir_bound.trait_ref()
327                    && let Some(trait_did) = trait_ref.trait_def_id()
328                    && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
329                {
330                    // Okay
331                } else {
332                    continue;
333                }
334            }
335
336            match hir_bound {
337                hir::GenericBound::Trait(poly_trait_ref) => {
338                    let _ = self.lower_poly_trait_ref(
339                        poly_trait_ref,
340                        param_ty,
341                        bounds,
342                        predicate_filter,
343                        overlapping_assoc_constraints,
344                    );
345                }
346                hir::GenericBound::Outlives(lifetime) => {
347                    // `ConstIfConst` is only interested in `[const]` bounds.
348                    if matches!(
349                        predicate_filter,
350                        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
351                    ) {
352                        continue;
353                    }
354
355                    let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
356                    let bound = ty::Binder::bind_with_vars(
357                        ty::ClauseKind::TypeOutlives(ty::OutlivesClause(param_ty, region)),
358                        bound_vars,
359                    );
360                    bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
361                }
362                hir::GenericBound::Use(..) => {
363                    // We don't actually lower `use` into the type layer.
364                }
365            }
366        }
367    }
368
369    /// Lower an associated item constraint from the HIR into `bounds`.
370    ///
371    /// ### A Note on Binders
372    ///
373    /// Given something like `T: for<'a> Iterator<Item = &'a u32>`,
374    /// the `trait_ref` here will be `for<'a> T: Iterator`.
375    /// The `constraint` data however is from *inside* the binder
376    /// (e.g., `&'a u32`) and hence may reference bound regions.
377    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("lower_assoc_item_constraint",
                                    "rustc_hir_analysis::hir_ty_lowering::bounds",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
                                    ::tracing_core::__macro_support::Option::Some(377u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("hir_ref_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("hir_ref_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_ref")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_ref");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("constraint")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("constraint");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("predicate_filter")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("predicate_filter");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&hir_ref_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_ref)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&constraint)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&predicate_filter)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<(), ErrorGuaranteed> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = self.tcx();
            let assoc_tag =
                if constraint.gen_args.parenthesized ==
                        hir::GenericArgsParentheses::ReturnTypeNotation {
                    ty::AssocTag::Fn
                } else if let hir::AssocItemConstraintKind::Equality {
                        term: hir::Term::Const(_) } = constraint.kind {
                    ty::AssocTag::Const
                } else { ty::AssocTag::Type };
            let candidate =
                if self.probe_trait_that_defines_assoc_item(trait_ref.def_id(),
                        assoc_tag, constraint.ident) {
                    trait_ref
                } else {
                    self.probe_single_bound_for_assoc_item(||
                                traits::supertraits(tcx, trait_ref),
                            AssocItemQSelf::Trait(trait_ref.def_id()), assoc_tag,
                            constraint.ident, path_span, Some(constraint))?
                };
            let assoc_item =
                self.probe_assoc_item(constraint.ident, assoc_tag, hir_ref_id,
                        constraint.span,
                        candidate.def_id()).expect("failed to find associated item");
            if let Some(duplicates) = duplicates {
                duplicates.entry(assoc_item.def_id).and_modify(|prev_span|
                            {
                                self.dcx().emit_err(diagnostics::ValueOfAssociatedStructAlreadySpecified {
                                        span: constraint.span,
                                        prev_span: *prev_span,
                                        item_name: constraint.ident,
                                        def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
                                    });
                            }).or_insert(constraint.span);
            }
            let projection_term =
                if let ty::AssocTag::Fn = assoc_tag {
                    let bound_vars = tcx.late_bound_vars(constraint.hir_id);
                    ty::Binder::bind_with_vars(self.lower_return_type_notation_ty(candidate,
                                    assoc_item.def_id, path_span)?.into(), bound_vars)
                } else {
                    candidate.map_bound(|trait_ref|
                            {
                                let item_segment =
                                    hir::PathSegment {
                                        ident: constraint.ident,
                                        hir_id: constraint.hir_id,
                                        res: Res::Err,
                                        args: Some(constraint.gen_args),
                                        infer_args: false,
                                        delegation_child_segment: false,
                                    };
                                let alias_args =
                                    self.lower_generic_args_of_assoc_item(path_span,
                                        assoc_item.def_id, &item_segment, trait_ref.args);
                                {
                                    use ::tracing::__macro_support::Callsite as _;
                                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                        {
                                            static META: ::tracing::Metadata<'static> =
                                                {
                                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:480",
                                                        "rustc_hir_analysis::hir_ty_lowering::bounds",
                                                        ::tracing::Level::DEBUG,
                                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
                                                        ::tracing_core::__macro_support::Option::Some(480u32),
                                                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
                                                        ::tracing_core::field::FieldSet::new(&[{
                                                                            const NAME:
                                                                                ::tracing::__macro_support::FieldName<{
                                                                                    ::tracing::__macro_support::FieldName::len("alias_args")
                                                                                }> =
                                                                                ::tracing::__macro_support::FieldName::new("alias_args");
                                                                            NAME.as_str()
                                                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                        ::tracing::metadata::Kind::EVENT)
                                                };
                                            ::tracing::callsite::DefaultCallsite::new(&META)
                                        };
                                    let enabled =
                                        ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::LevelFilter::current() &&
                                            {
                                                let interest = __CALLSITE.interest();
                                                !interest.is_never() &&
                                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                        interest)
                                            };
                                    if enabled {
                                        (|value_set: ::tracing::field::ValueSet|
                                                    {
                                                        let meta = __CALLSITE.metadata();
                                                        ::tracing::Event::dispatch(meta, &value_set);
                                                        ;
                                                    })({
                                                #[allow(unused_imports)]
                                                use ::tracing::field::{debug, display, Value};
                                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&alias_args)
                                                                            as &dyn ::tracing::field::Value))])
                                            });
                                    } else { ; }
                                };
                                ty::AliasTerm::new_from_def_id(tcx, assoc_item.def_id,
                                    alias_args)
                            })
                };
            match constraint.kind {
                hir::AssocItemConstraintKind::Equality { .. } if
                    let ty::AssocTag::Fn = assoc_tag => {
                    return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationEqualityBound {
                                    span: constraint.span,
                                }));
                }
                hir::AssocItemConstraintKind::Equality { term } => {
                    let term =
                        match term {
                            hir::Term::Ty(ty) => self.lower_ty(ty).into(),
                            hir::Term::Const(ct) => {
                                let ty =
                                    projection_term.map_bound(|alias|
                                            alias.expect_ct().type_of(tcx).skip_norm_wip());
                                let ty =
                                    check_assoc_const_binding_type(self, constraint.ident, ty,
                                        constraint.hir_id);
                                self.lower_const_arg(ct, ty).into()
                            }
                        };
                    let late_bound_in_projection_ty =
                        tcx.collect_constrained_late_bound_regions(projection_term);
                    let late_bound_in_term =
                        tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:522",
                                            "rustc_hir_analysis::hir_ty_lowering::bounds",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
                                            ::tracing_core::__macro_support::Option::Some(522u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
                                            ::tracing_core::field::FieldSet::new(&[{
                                                                const NAME:
                                                                    ::tracing::__macro_support::FieldName<{
                                                                        ::tracing::__macro_support::FieldName::len("late_bound_in_projection_ty")
                                                                    }> =
                                                                    ::tracing::__macro_support::FieldName::new("late_bound_in_projection_ty");
                                                                NAME.as_str()
                                                            }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&late_bound_in_projection_ty)
                                                                as &dyn ::tracing::field::Value))])
                                });
                        } else { ; }
                    };
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:523",
                                            "rustc_hir_analysis::hir_ty_lowering::bounds",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
                                            ::tracing_core::__macro_support::Option::Some(523u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
                                            ::tracing_core::field::FieldSet::new(&[{
                                                                const NAME:
                                                                    ::tracing::__macro_support::FieldName<{
                                                                        ::tracing::__macro_support::FieldName::len("late_bound_in_term")
                                                                    }> =
                                                                    ::tracing::__macro_support::FieldName::new("late_bound_in_term");
                                                                NAME.as_str()
                                                            }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&late_bound_in_term)
                                                                as &dyn ::tracing::field::Value))])
                                });
                        } else { ; }
                    };
                    self.validate_late_bound_regions(late_bound_in_projection_ty,
                        late_bound_in_term,
                        |br_name|
                            {
                                {
                                    self.dcx().struct_span_err(constraint.span,
                                            ::alloc::__export::must_use({
                                                    ::alloc::fmt::format(format_args!("binding for associated type `{0}` references {1}, which does not appear in the trait input types",
                                                            constraint.ident, br_name))
                                                })).with_code(E0582)
                                }
                            });
                    match predicate_filter {
                        PredicateFilter::All | PredicateFilter::SelfOnly |
                            PredicateFilter::SelfAndAssociatedTypeBounds => {
                            let bound =
                                projection_term.map_bound(|projection_term|
                                        {
                                            ty::ClauseKind::Projection(ty::ProjectionPredicate {
                                                    projection_term,
                                                    term,
                                                })
                                        });
                            if let ty::AssocTag::Const = assoc_tag &&
                                        !self.tcx().is_type_const(assoc_item.def_id) &&
                                    !tcx.features().generic_const_args() {
                                if tcx.features().min_generic_const_args() {
                                    let mut err =
                                        self.dcx().struct_span_err(constraint.span,
                                            "use of trait associated const not defined as `type const`");
                                    err.note("the declaration in the trait must begin with `type const` not just `const` alone");
                                    return Err(err.emit());
                                } else {
                                    let err =
                                        self.dcx().span_delayed_bug(constraint.span,
                                            "use of trait associated const defined as `type const`");
                                    return Err(err);
                                }
                            }
                            bounds.push((bound.upcast(tcx), constraint.span));
                        }
                        PredicateFilter::SelfTraitThatDefines(_) => {}
                        PredicateFilter::ConstIfConst |
                            PredicateFilter::SelfConstIfConst => {}
                    }
                }
                hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } =>
                    {
                    match predicate_filter {
                        PredicateFilter::All |
                            PredicateFilter::SelfAndAssociatedTypeBounds |
                            PredicateFilter::ConstIfConst => {
                            let projection_ty =
                                projection_term.map_bound(|projection_term|
                                        projection_term.expect_ty());
                            let param_ty =
                                Ty::new_alias(tcx, ty::IsRigid::No,
                                    projection_ty.skip_binder());
                            self.lower_bounds(param_ty, hir_bounds, bounds,
                                projection_ty.bound_vars(), predicate_filter,
                                OverlappingAsssocItemConstraints::Allowed);
                        }
                        PredicateFilter::SelfOnly |
                            PredicateFilter::SelfTraitThatDefines(_) |
                            PredicateFilter::SelfConstIfConst => {}
                    }
                }
            }
            Ok(())
        }
    }
}#[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
378    pub(super) fn lower_assoc_item_constraint(
379        &self,
380        hir_ref_id: hir::HirId,
381        trait_ref: ty::PolyTraitRef<'tcx>,
382        constraint: &hir::AssocItemConstraint<'tcx>,
383        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
384        duplicates: Option<&mut FxIndexMap<DefId, Span>>,
385        path_span: Span,
386        predicate_filter: PredicateFilter,
387    ) -> Result<(), ErrorGuaranteed> {
388        let tcx = self.tcx();
389
390        let assoc_tag = if constraint.gen_args.parenthesized
391            == hir::GenericArgsParentheses::ReturnTypeNotation
392        {
393            ty::AssocTag::Fn
394        } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
395            constraint.kind
396        {
397            ty::AssocTag::Const
398        } else {
399            ty::AssocTag::Type
400        };
401
402        // Given something like `U: Trait<T = X>`, we want to produce a predicate like
403        // `<U as Trait>::T = X`.
404        // This is somewhat subtle in the event that `T` is defined in a supertrait of `Trait`,
405        // because in that case we need to upcast. I.e., we want to produce
406        // `<B as SuperTrait<i32>>::T == X` for `B: SubTrait<T = X>` where
407        //
408        //     trait SubTrait: SuperTrait<i32> {}
409        //     trait SuperTrait<A> { type T; }
410        let candidate = if self.probe_trait_that_defines_assoc_item(
411            trait_ref.def_id(),
412            assoc_tag,
413            constraint.ident,
414        ) {
415            // Simple case: The assoc item is defined in the current trait.
416            trait_ref
417        } else {
418            // Otherwise, we have to walk through the supertraits to find
419            // one that does define it.
420            self.probe_single_bound_for_assoc_item(
421                || traits::supertraits(tcx, trait_ref),
422                AssocItemQSelf::Trait(trait_ref.def_id()),
423                assoc_tag,
424                constraint.ident,
425                path_span,
426                Some(constraint),
427            )?
428        };
429
430        let assoc_item = self
431            .probe_assoc_item(
432                constraint.ident,
433                assoc_tag,
434                hir_ref_id,
435                constraint.span,
436                candidate.def_id(),
437            )
438            .expect("failed to find associated item");
439
440        if let Some(duplicates) = duplicates {
441            duplicates
442                .entry(assoc_item.def_id)
443                .and_modify(|prev_span| {
444                    self.dcx().emit_err(diagnostics::ValueOfAssociatedStructAlreadySpecified {
445                        span: constraint.span,
446                        prev_span: *prev_span,
447                        item_name: constraint.ident,
448                        def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
449                    });
450                })
451                .or_insert(constraint.span);
452        }
453
454        let projection_term = if let ty::AssocTag::Fn = assoc_tag {
455            let bound_vars = tcx.late_bound_vars(constraint.hir_id);
456            ty::Binder::bind_with_vars(
457                self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
458                bound_vars,
459            )
460        } else {
461            // Create the generic arguments for the associated type or constant by joining the
462            // parent arguments (the arguments of the trait) and the own arguments (the ones of
463            // the associated item itself) and construct an alias type using them.
464            candidate.map_bound(|trait_ref| {
465                let item_segment = hir::PathSegment {
466                    ident: constraint.ident,
467                    hir_id: constraint.hir_id,
468                    res: Res::Err,
469                    args: Some(constraint.gen_args),
470                    infer_args: false,
471                    delegation_child_segment: false,
472                };
473
474                let alias_args = self.lower_generic_args_of_assoc_item(
475                    path_span,
476                    assoc_item.def_id,
477                    &item_segment,
478                    trait_ref.args,
479                );
480                debug!(?alias_args);
481
482                ty::AliasTerm::new_from_def_id(tcx, assoc_item.def_id, alias_args)
483            })
484        };
485
486        match constraint.kind {
487            hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
488                return Err(self.dcx().emit_err(
489                    crate::diagnostics::ReturnTypeNotationEqualityBound { span: constraint.span },
490                ));
491            }
492            // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>`
493            // to a projection predicate: `<T as Iterator>::Item = u32`.
494            hir::AssocItemConstraintKind::Equality { term } => {
495                let term = match term {
496                    hir::Term::Ty(ty) => self.lower_ty(ty).into(),
497                    hir::Term::Const(ct) => {
498                        let ty = projection_term
499                            .map_bound(|alias| alias.expect_ct().type_of(tcx).skip_norm_wip());
500                        let ty = check_assoc_const_binding_type(
501                            self,
502                            constraint.ident,
503                            ty,
504                            constraint.hir_id,
505                        );
506
507                        self.lower_const_arg(ct, ty).into()
508                    }
509                };
510
511                // Find any late-bound regions declared in `ty` that are not
512                // declared in the trait-ref or assoc_item. These are not well-formed.
513                //
514                // Example:
515                //
516                //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
517                //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
518                let late_bound_in_projection_ty =
519                    tcx.collect_constrained_late_bound_regions(projection_term);
520                let late_bound_in_term =
521                    tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
522                debug!(?late_bound_in_projection_ty);
523                debug!(?late_bound_in_term);
524
525                // FIXME: point at the type params that don't have appropriate lifetimes:
526                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
527                //                         ----  ----     ^^^^^^^
528                // NOTE(mgca): This error should be impossible to trigger with assoc const bindings.
529                self.validate_late_bound_regions(
530                    late_bound_in_projection_ty,
531                    late_bound_in_term,
532                    |br_name| {
533                        struct_span_code_err!(
534                            self.dcx(),
535                            constraint.span,
536                            E0582,
537                            "binding for associated type `{}` references {}, \
538                             which does not appear in the trait input types",
539                            constraint.ident,
540                            br_name
541                        )
542                    },
543                );
544
545                match predicate_filter {
546                    PredicateFilter::All
547                    | PredicateFilter::SelfOnly
548                    | PredicateFilter::SelfAndAssociatedTypeBounds => {
549                        let bound = projection_term.map_bound(|projection_term| {
550                            ty::ClauseKind::Projection(ty::ProjectionPredicate {
551                                projection_term,
552                                term,
553                            })
554                        });
555
556                        if let ty::AssocTag::Const = assoc_tag
557                            && !self.tcx().is_type_const(assoc_item.def_id)
558                            && !tcx.features().generic_const_args()
559                        {
560                            if tcx.features().min_generic_const_args() {
561                                let mut err = self.dcx().struct_span_err(
562                                    constraint.span,
563                                    "use of trait associated const not defined as `type const`",
564                                );
565                                err.note(
566                                    "the declaration in the trait must begin with `type const` not just `const` alone",
567                                );
568                                return Err(err.emit());
569                            } else {
570                                let err = self.dcx().span_delayed_bug(
571                                    constraint.span,
572                                    "use of trait associated const defined as `type const`",
573                                );
574                                return Err(err);
575                            }
576                        }
577
578                        bounds.push((bound.upcast(tcx), constraint.span));
579                    }
580                    // SelfTraitThatDefines is only interested in trait predicates.
581                    PredicateFilter::SelfTraitThatDefines(_) => {}
582                    // `ConstIfConst` is only interested in `[const]` bounds.
583                    PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
584                }
585            }
586            // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
587            // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
588            hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
589                match predicate_filter {
590                    PredicateFilter::All
591                    | PredicateFilter::SelfAndAssociatedTypeBounds
592                    | PredicateFilter::ConstIfConst => {
593                        let projection_ty = projection_term
594                            .map_bound(|projection_term| projection_term.expect_ty());
595                        // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
596                        // parameter to have a skipped binder.
597                        let param_ty =
598                            Ty::new_alias(tcx, ty::IsRigid::No, projection_ty.skip_binder());
599                        self.lower_bounds(
600                            param_ty,
601                            hir_bounds,
602                            bounds,
603                            projection_ty.bound_vars(),
604                            predicate_filter,
605                            OverlappingAsssocItemConstraints::Allowed,
606                        );
607                    }
608                    PredicateFilter::SelfOnly
609                    | PredicateFilter::SelfTraitThatDefines(_)
610                    | PredicateFilter::SelfConstIfConst => {}
611                }
612            }
613        }
614        Ok(())
615    }
616
617    /// Lower a type, possibly specially handling the type if it's a return type notation
618    /// which we otherwise deny in other positions.
619    pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
620        let hir::TyKind::Path(qpath) = hir_ty.kind else {
621            return self.lower_ty(hir_ty);
622        };
623
624        let tcx = self.tcx();
625        match qpath {
626            hir::QPath::Resolved(opt_self_ty, path)
627                if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
628                    && item_segment.args.is_some_and(|args| {
629                        #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
    hir::GenericArgsParentheses::ReturnTypeNotation => true,
    _ => false,
}matches!(
630                            args.parenthesized,
631                            hir::GenericArgsParentheses::ReturnTypeNotation
632                        )
633                    }) =>
634            {
635                // We don't allow generics on the module segments.
636                let _ =
637                    self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
638
639                let item_def_id = match path.res {
640                    Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
641                    Res::Err => {
642                        return Ty::new_error_with_message(
643                            tcx,
644                            hir_ty.span,
645                            "failed to resolve RTN",
646                        );
647                    }
648                    _ => ::rustc_middle::util::bug::bug_fmt(format_args!("only expected method resolution for fully qualified RTN"))bug!("only expected method resolution for fully qualified RTN"),
649                };
650                let trait_def_id = tcx.parent(item_def_id);
651
652                // Good error for `where Trait::method(..): Send`.
653                let Some(self_ty) = opt_self_ty else {
654                    let guar = self.report_missing_self_ty_for_resolved_path(
655                        trait_def_id,
656                        hir_ty.span,
657                        item_segment,
658                        ty::AssocTag::Type,
659                    );
660                    return Ty::new_error(tcx, guar);
661                };
662                let self_ty = self.lower_ty(self_ty);
663
664                let trait_ref = self.lower_mono_trait_ref(
665                    hir_ty.span,
666                    trait_def_id,
667                    self_ty,
668                    trait_segment,
669                    false,
670                );
671
672                // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
673                // in `resolve_bound_vars`, we stash the explicit bound vars of the where
674                // clause onto the item segment of the RTN type. This allows us to know
675                // how many bound vars are *not* coming from the signature of the function
676                // from lowering RTN itself.
677                //
678                // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
679                // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
680                // parent) will include `'a` AND all the early- and late-bound vars of the
681                // method. But when lowering the RTN type, we just want the list of vars
682                // we used to resolve the trait ref. We explicitly stored those back onto
683                // the item segment, since there's no other good place to put them.
684                let candidate =
685                    ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
686
687                match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
688                    Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
689                    Err(guar) => Ty::new_error(tcx, guar),
690                }
691            }
692            hir::QPath::TypeRelative(hir_self_ty, segment)
693                if segment.args.is_some_and(|args| {
694                    #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
    hir::GenericArgsParentheses::ReturnTypeNotation => true,
    _ => false,
}matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
695                }) =>
696            {
697                let self_ty = self.lower_ty(hir_self_ty);
698                let (item_def_id, bound) = match self.resolve_type_relative_path(
699                    self_ty,
700                    hir_self_ty,
701                    ty::AssocTag::Fn,
702                    segment,
703                    hir_ty.hir_id,
704                    hir_ty.span,
705                    None,
706                ) {
707                    Ok(result) => result,
708                    Err(guar) => return Ty::new_error(tcx, guar),
709                };
710
711                // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
712                // which may happen via a higher-ranked where clause or supertrait.
713                // This is the same restrictions as associated types; even though we could
714                // support it, it just makes things a lot more difficult to support in
715                // `resolve_bound_vars`, since we'd need to introduce those as elided
716                // bound vars on the where clause too.
717                if bound.has_bound_vars() {
718                    return Ty::new_error(
719                        tcx,
720                        self.dcx().emit_err(
721                            diagnostics::AssociatedItemTraitUninferredGenericParams {
722                                span: hir_ty.span,
723                                inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
724                                bound: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::",
                tcx.anonymize_bound_vars(bound).skip_binder()))
    })format!(
725                                    "{}::",
726                                    tcx.anonymize_bound_vars(bound).skip_binder()
727                                ),
728                                mpart_sugg: None,
729                                what: tcx.def_descr(item_def_id),
730                            },
731                        ),
732                    );
733                }
734
735                match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
736                    Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
737                    Err(guar) => Ty::new_error(tcx, guar),
738                }
739            }
740            _ => self.lower_ty(hir_ty),
741        }
742    }
743
744    /// Do the common parts of lowering an RTN type. This involves extending the
745    /// candidate binder to include all of the early- and late-bound vars that are
746    /// defined on the function itself, and constructing a projection to the RPITIT
747    /// return type of that function.
748    fn lower_return_type_notation_ty(
749        &self,
750        candidate: ty::PolyTraitRef<'tcx>,
751        item_def_id: DefId,
752        path_span: Span,
753    ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
754        let tcx = self.tcx();
755        let mut emitted_bad_param_err = None;
756        // If we have an method return type bound, then we need to instantiate
757        // the method's early bound params with suitable late-bound params.
758        let mut num_bound_vars = candidate.bound_vars().len();
759        let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
760            let arg = match param.kind {
761                ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
762                    tcx,
763                    ty::INNERMOST,
764                    ty::BoundRegion {
765                        var: ty::BoundVar::from_usize(num_bound_vars),
766                        kind: ty::BoundRegionKind::Named(param.def_id),
767                    },
768                )
769                .into(),
770                ty::GenericParamDefKind::Type { .. } => {
771                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
772                        self.dcx().emit_err(
773                            crate::diagnostics::ReturnTypeNotationIllegalParam::Type {
774                                span: path_span,
775                                param_span: tcx.def_span(param.def_id),
776                            },
777                        )
778                    });
779                    Ty::new_error(tcx, guar).into()
780                }
781                ty::GenericParamDefKind::Const { .. } => {
782                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
783                        self.dcx().emit_err(
784                            crate::diagnostics::ReturnTypeNotationIllegalParam::Const {
785                                span: path_span,
786                                param_span: tcx.def_span(param.def_id),
787                            },
788                        )
789                    });
790                    ty::Const::new_error(tcx, guar).into()
791                }
792            };
793            num_bound_vars += 1;
794            arg
795        });
796
797        // Next, we need to check that the return-type notation is being used on
798        // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
799        let output = tcx.fn_sig(item_def_id).skip_binder().output();
800        let output = if let ty::Alias(_, alias_ty) = *output.skip_binder().kind()
801            && let ty::AliasTy { kind: ty::Projection { def_id: projection_def_id }, .. } = alias_ty
802            && tcx.is_impl_trait_in_trait(projection_def_id)
803        {
804            alias_ty
805        } else {
806            return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationOnNonRpitit {
807                span: path_span,
808                ty: tcx.liberate_late_bound_regions(item_def_id, output),
809                fn_span: tcx.hir_span_if_local(item_def_id),
810                note: (),
811            }));
812        };
813
814        // Finally, move the fn return type's bound vars over to account for the early bound
815        // params (and trait ref's late bound params). This logic is very similar to
816        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
817        // and it's no coincidence why.
818        let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
819        Ok(ty::EarlyBinder::bind(tcx, shifted_output).instantiate(tcx, args).skip_norm_wip())
820    }
821}
822
823/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
824///
825/// FIXME(const_generics): This is a temporary and semi-artificial restriction until the
826/// arrival of *generic const generics*[^1].
827///
828/// It might actually be possible that we can already support early-bound generic params
829/// in such types if we just lifted some more checks in other places, too, for example
830/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
831/// probably gate this behind another feature flag.
832///
833/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
834pub(crate) fn check_assoc_const_binding_type<'tcx>(
835    cx: &dyn HirTyLowerer<'tcx>,
836    assoc_const: Ident,
837    ty: ty::Binder<'tcx, Ty<'tcx>>,
838    hir_id: hir::HirId,
839) -> Ty<'tcx> {
840    // We can't perform the checks for early-bound params during name resolution unlike E0770
841    // because this information depends on *type* resolution.
842    // We can't perform these checks in `resolve_bound_vars` either for the same reason.
843    // Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
844    // resolved type of `Trait::C` in order to know if it references `'a` or not.
845
846    let ty = ty.skip_binder();
847    if !ty.has_param() && !ty.has_escaping_bound_vars() {
848        return ty;
849    }
850
851    let mut collector = GenericParamAndBoundVarCollector {
852        cx,
853        params: Default::default(),
854        vars: Default::default(),
855        depth: ty::INNERMOST,
856    };
857    let mut guar = ty.visit_with(&mut collector).break_value();
858
859    let tcx = cx.tcx();
860    let ty_note = ty
861        .make_suggestable(tcx, false, None)
862        .map(|ty| crate::diagnostics::TyOfAssocConstBindingNote { assoc_const, ty });
863
864    let enclosing_item_owner_id = tcx
865        .hir_parent_owner_iter(hir_id)
866        .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
867        .unwrap();
868    let generics = tcx.generics_of(enclosing_item_owner_id);
869    for index in collector.params {
870        let param = generics.param_at(index as _, tcx);
871        let is_self_param = param.name == kw::SelfUpper;
872        guar.get_or_insert(cx.dcx().emit_err(crate::diagnostics::ParamInTyOfAssocConstBinding {
873            span: assoc_const.span,
874            assoc_const,
875            param_name: param.name,
876            param_def_kind: tcx.def_descr(param.def_id),
877            param_category: if is_self_param {
878                "self"
879            } else if param.kind.is_synthetic() {
880                "synthetic"
881            } else {
882                "normal"
883            },
884            param_defined_here_label:
885                (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
886            ty_note,
887        }));
888    }
889    for var_def_id in collector.vars {
890        guar.get_or_insert(cx.dcx().emit_err(
891            crate::diagnostics::EscapingBoundVarInTyOfAssocConstBinding {
892                span: assoc_const.span,
893                assoc_const,
894                var_name: cx.tcx().item_name(var_def_id),
895                var_def_kind: tcx.def_descr(var_def_id),
896                var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
897                ty_note,
898            },
899        ));
900    }
901
902    let guar = guar.unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("failed to find gen params or bound vars in ty"))bug!("failed to find gen params or bound vars in ty"));
903    Ty::new_error(tcx, guar)
904}
905
906struct GenericParamAndBoundVarCollector<'a, 'tcx> {
907    cx: &'a dyn HirTyLowerer<'tcx>,
908    params: FxIndexSet<u32>,
909    vars: FxIndexSet<DefId>,
910    depth: ty::DebruijnIndex,
911}
912
913impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
914    type Result = ControlFlow<ErrorGuaranteed>;
915
916    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
917        &mut self,
918        binder: &ty::Binder<'tcx, T>,
919    ) -> Self::Result {
920        self.depth.shift_in(1);
921        let result = binder.super_visit_with(self);
922        self.depth.shift_out(1);
923        result
924    }
925
926    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
927        match ty.kind() {
928            ty::Param(param) => {
929                self.params.insert(param.index);
930            }
931            ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
932                self.vars.insert(match bt.kind {
933                    ty::BoundTyKind::Param(def_id) => def_id,
934                    ty::BoundTyKind::Anon => {
935                        let reported = self
936                            .cx
937                            .dcx()
938                            .delayed_bug(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unexpected anon bound ty: {0:?}",
                bt.var))
    })format!("unexpected anon bound ty: {:?}", bt.var));
939                        return ControlFlow::Break(reported);
940                    }
941                });
942            }
943            _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
944            _ => {}
945        }
946        ControlFlow::Continue(())
947    }
948
949    fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
950        match re.kind() {
951            ty::ReEarlyParam(param) => {
952                self.params.insert(param.index);
953            }
954            ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
955                self.vars.insert(match br.kind {
956                    ty::BoundRegionKind::Named(def_id) => def_id,
957                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
958                        let guar = self
959                            .cx
960                            .dcx()
961                            .delayed_bug(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unexpected bound region kind: {0:?}",
                br.kind))
    })format!("unexpected bound region kind: {:?}", br.kind));
962                        return ControlFlow::Break(guar);
963                    }
964                    ty::BoundRegionKind::NamedForPrinting(_) => {
965                        ::rustc_middle::util::bug::bug_fmt(format_args!("only used for pretty printing"))bug!("only used for pretty printing")
966                    }
967                });
968            }
969            _ => {}
970        }
971        ControlFlow::Continue(())
972    }
973
974    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
975        match ct.kind() {
976            ty::ConstKind::Param(param) => {
977                self.params.insert(param.index);
978            }
979            ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
980                let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
981                return ControlFlow::Break(guar);
982            }
983            _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
984            _ => {}
985        }
986        ControlFlow::Continue(())
987    }
988}