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