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