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