1use std::ops::ControlFlow;
2
3use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
4use rustc_errors::codes::*;
5use rustc_errors::struct_span_code_err;
6use rustc_hir as hir;
7use rustc_hir::attrs::lang_items::LangItem;
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::DefId;
10use rustc_hir::{PolyTraitRef, find_attr};
11use rustc_middle::ty::{
12 self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
13 TypeVisitor, Upcast,
14};
15use rustc_span::{ErrorGuaranteed, Ident, Span, bug, kw};
16use rustc_trait_selection::traits;
17use tracing::{debug, instrument};
18
19use crate::diagnostics;
20use crate::hir_ty_lowering::{
21 AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
22 OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
23};
24
25#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CollectedBound {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"CollectedBound", "positive", &self.positive, "maybe",
&self.maybe, "negative", &&self.negative)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for CollectedBound {
#[inline]
fn default() -> CollectedBound {
CollectedBound {
positive: ::core::default::Default::default(),
maybe: ::core::default::Default::default(),
negative: ::core::default::Default::default(),
}
}
}Default)]
26struct CollectedBound {
27 positive: Option<Span>,
29 maybe: Option<Span>,
31 negative: Option<Span>,
33}
34
35impl CollectedBound {
36 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 sized: CollectedBound,
46 meta_sized: CollectedBound,
48 pointee_sized: CollectedBound,
50}
51
52impl CollectedSizednessBounds {
53 fn any(&self) -> bool {
56 self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
57 }
58}
59
60fn search_bounds_for<'tcx>(
61 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
62 context: ImpliedBoundsContext<'tcx>,
63 mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
64) {
65 let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
66 for hir_bound in hir_bounds {
67 let hir::GenericBound::Trait(ptr) = hir_bound else {
68 continue;
69 };
70
71 f(ptr)
72 }
73 };
74
75 search_bounds(hir_bounds);
76 if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
77 for clause in where_clause {
78 if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
79 && pred.is_param_bound(self_ty.to_def_id())
80 {
81 search_bounds(pred.bounds);
82 }
83 }
84 }
85}
86
87fn collect_bounds<'a, 'tcx>(
88 hir_bounds: &'a [hir::GenericBound<'tcx>],
89 context: ImpliedBoundsContext<'tcx>,
90 target_did: DefId,
91) -> CollectedBound {
92 let mut collect_into = CollectedBound::default();
93 search_bounds_for(hir_bounds, context, |ptr| {
94 if !#[allow(non_exhaustive_omitted_patterns)] match ptr.trait_ref.path.res {
Res::Def(DefKind::Trait, did) if did == target_did => true,
_ => false,
}matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
95 return;
96 }
97
98 match ptr.modifiers.polarity {
99 hir::BoundPolarity::Maybe(_) => collect_into.maybe = Some(ptr.span),
100 hir::BoundPolarity::Negative(_) => collect_into.negative = Some(ptr.span),
101 hir::BoundPolarity::Positive => collect_into.positive = Some(ptr.span),
102 }
103 });
104 collect_into
105}
106
107fn collect_sizedness_bounds<'tcx>(
108 tcx: TyCtxt<'tcx>,
109 hir_bounds: &[hir::GenericBound<'_>],
110 context: ImpliedBoundsContext<'tcx>,
111 span: Span,
112) -> CollectedSizednessBounds {
113 let sized_did = tcx.require_lang_item(LangItem::Sized, span);
114 let sized = collect_bounds(hir_bounds, context, sized_did);
115
116 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
117 let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
118
119 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
120 let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
121
122 CollectedSizednessBounds { sized, meta_sized, pointee_sized }
123}
124
125fn add_trait_bound<'tcx>(
127 tcx: TyCtxt<'tcx>,
128 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
129 self_ty: Ty<'tcx>,
130 did: DefId,
131 span: Span,
132) {
133 let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
134 bounds.insert(0, (trait_ref.upcast(tcx), span));
137}
138
139impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
140 pub(crate) fn add_implicit_sizedness_bounds(
149 &self,
150 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
151 self_ty: Ty<'tcx>,
152 hir_bounds: &[hir::GenericBound<'_>],
153 context: ImpliedBoundsContext<'tcx>,
154 span: Span,
155 ) {
156 let tcx = self.tcx();
157
158 if {
'done:
{
for i in tcx.hir_krate_attrs() {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcNoImplicitBounds) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()find_attr!(tcx, crate, RustcNoImplicitBounds) {
160 return;
161 }
162
163 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
164 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
165
166 match context {
168 ImpliedBoundsContext::TraitDef(trait_did) => {
169 let trait_did = trait_did.to_def_id();
170 if trait_did == pointee_sized_did {
172 return;
173 }
174 if tcx.trait_is_auto(trait_did) {
177 return;
178 }
179 }
180 ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
181 }
182 }
183 let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
184 if let Some(span) = collected.sized.maybe.or(collected.sized.negative)
185 && collected.sized.positive.is_none()
186 && !collected.meta_sized.any()
187 && !collected.pointee_sized.any()
188 {
189 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
192 } else if !collected.any() {
193 match context {
194 ImpliedBoundsContext::TraitDef(..) => {
195 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
198 }
199 ImpliedBoundsContext::TyParam(..)
200 | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
201 let sized_did = tcx.require_lang_item(LangItem::Sized, span);
204 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
205 }
206 }
207 }
208 }
209
210 pub(crate) fn add_default_traits(
211 &self,
212 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
213 self_ty: Ty<'tcx>,
214 hir_bounds: &[hir::GenericBound<'_>],
215 context: ImpliedBoundsContext<'tcx>,
216 span: Span,
217 ) {
218 self.tcx().default_traits().iter().for_each(|default_trait| {
219 self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
220 });
221 }
222
223 pub(crate) fn add_default_trait(
227 &self,
228 trait_: LangItem,
229 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
230 self_ty: Ty<'tcx>,
231 hir_bounds: &[hir::GenericBound<'_>],
232 context: ImpliedBoundsContext<'tcx>,
233 span: Span,
234 ) {
235 let tcx = self.tcx();
236
237 if let ImpliedBoundsContext::TraitDef(trait_did) = context
240 && self.tcx().trait_is_auto(trait_did.into())
241 {
242 return;
243 }
244
245 if let Some(trait_did) = tcx.lang_items().get(trait_)
246 && self.should_add_default_traits(trait_did, hir_bounds, context)
247 {
248 add_trait_bound(tcx, bounds, self_ty, trait_did, span);
249 }
250 }
251
252 fn should_add_default_traits(
254 &self,
255 trait_def_id: DefId,
256 hir_bounds: &[hir::GenericBound<'_>],
257 context: ImpliedBoundsContext<'tcx>,
258 ) -> bool {
259 let collected = collect_bounds(hir_bounds, context, trait_def_id);
260 !{
'done:
{
for i in self.tcx().hir_krate_attrs() {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcNoImplicitBounds) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any()
261 }
262
263 pub(crate) fn require_bound_to_relax_default_trait(
264 &self,
265 trait_ref: hir::TraitRef<'_>,
266 span: Span,
267 ) {
268 let tcx = self.tcx();
269
270 if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
271 && (tcx.is_lang_item(def_id, LangItem::Sized) || tcx.is_default_trait(def_id))
272 {
273 return;
274 }
275
276 self.dcx().span_err(
277 span,
278 if tcx.sess.opts.unstable_opts.experimental_default_bounds
279 || tcx.features().more_maybe_bounds()
280 {
281 "bound modifier `?` can only be applied to default traits"
282 } else {
283 "bound modifier `?` can only be applied to `Sized`"
284 },
285 );
286 }
287
288 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("lower_bounds",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(309u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("param_ty")
}> =
::tracing::__macro_support::FieldName::new("param_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bound_vars")
}> =
::tracing::__macro_support::FieldName::new("bound_vars");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("predicate_filter")
}> =
::tracing::__macro_support::FieldName::new("predicate_filter");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("overlapping_assoc_constraints")
}> =
::tracing::__macro_support::FieldName::new("overlapping_assoc_constraints");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(¶m_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bound_vars)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&predicate_filter)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&overlapping_assoc_constraints)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
for hir_bound in hir_bounds {
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) =
predicate_filter {
if let Some(trait_ref) = hir_bound.trait_ref() &&
let Some(trait_did) = trait_ref.trait_def_id() &&
self.tcx().trait_may_define_assoc_item(trait_did,
assoc_ident) {} else { continue; }
}
match hir_bound {
hir::GenericBound::Trait(poly_trait_ref) => {
let _ =
self.lower_poly_trait_ref(poly_trait_ref, param_ty, bounds,
predicate_filter, overlapping_assoc_constraints);
}
hir::GenericBound::Outlives(lifetime) => {
if #[allow(non_exhaustive_omitted_patterns)] match predicate_filter
{
PredicateFilter::ConstIfConst |
PredicateFilter::SelfConstIfConst => true,
_ => false,
} {
continue;
}
let region =
self.lower_lifetime(lifetime,
RegionInferReason::OutlivesBound);
let bound =
ty::Binder::bind_with_vars(ty::ClauseKind::TypeOutlives(ty::OutlivesClause(param_ty,
region)), bound_vars);
bounds.push((bound.upcast(self.tcx()),
lifetime.ident.span));
}
hir::GenericBound::Use(..) => {}
}
}
}
}
}#[instrument(level = "debug", skip(self, hir_bounds, bounds))]
310 pub(crate) fn lower_bounds<'a, I: IntoIterator<Item = &'a hir::GenericBound<'a>>>(
311 &self,
312 param_ty: Ty<'tcx>,
313 hir_bounds: I,
314 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
315 bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
316 predicate_filter: PredicateFilter,
317 overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
318 ) {
319 for hir_bound in hir_bounds {
320 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
323 if let Some(trait_ref) = hir_bound.trait_ref()
324 && let Some(trait_did) = trait_ref.trait_def_id()
325 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
326 {
327 } else {
329 continue;
330 }
331 }
332
333 match hir_bound {
334 hir::GenericBound::Trait(poly_trait_ref) => {
335 let _ = self.lower_poly_trait_ref(
336 poly_trait_ref,
337 param_ty,
338 bounds,
339 predicate_filter,
340 overlapping_assoc_constraints,
341 );
342 }
343 hir::GenericBound::Outlives(lifetime) => {
344 if matches!(
346 predicate_filter,
347 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
348 ) {
349 continue;
350 }
351
352 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
353 let bound = ty::Binder::bind_with_vars(
354 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(param_ty, region)),
355 bound_vars,
356 );
357 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
358 }
359 hir::GenericBound::Use(..) => {
360 }
362 }
363 }
364 }
365
366 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("lower_assoc_item_constraint",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(374u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("hir_ref_id")
}> =
::tracing::__macro_support::FieldName::new("hir_ref_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_ref")
}> =
::tracing::__macro_support::FieldName::new("trait_ref");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("constraint")
}> =
::tracing::__macro_support::FieldName::new("constraint");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("predicate_filter")
}> =
::tracing::__macro_support::FieldName::new("predicate_filter");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&hir_ref_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_ref)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&constraint)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&predicate_filter)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Result<(), ErrorGuaranteed> =
loop {};
return __tracing_attr_fake_return;
}
{
let tcx = self.tcx();
let assoc_tag =
if constraint.gen_args.parenthesized ==
hir::GenericArgsParentheses::ReturnTypeNotation {
ty::AssocTag::Fn
} else if let hir::AssocItemConstraintKind::Equality {
term: hir::Term::Const(_) } = constraint.kind {
ty::AssocTag::Const
} else { ty::AssocTag::Type };
let candidate =
if self.probe_trait_that_defines_assoc_item(trait_ref.def_id(),
assoc_tag, constraint.ident) {
trait_ref
} else {
self.probe_single_bound_for_assoc_item(||
traits::supertraits(tcx, trait_ref),
AssocItemQSelf::Trait(trait_ref.def_id()), assoc_tag,
constraint.ident, path_span, Some(constraint))?
};
let assoc_item =
self.probe_assoc_item(constraint.ident, assoc_tag, hir_ref_id,
constraint.span,
candidate.def_id()).expect("failed to find associated item");
if let Some(duplicates) = duplicates {
duplicates.entry(assoc_item.def_id).and_modify(|prev_span|
{
self.dcx().emit_err(diagnostics::ValueOfAssociatedStructAlreadySpecified {
span: constraint.span,
prev_span: *prev_span,
item_name: constraint.ident,
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
});
}).or_insert(constraint.span);
}
let projection_term =
if let ty::AssocTag::Fn = assoc_tag {
let bound_vars = tcx.late_bound_vars(constraint.hir_id);
ty::Binder::bind_with_vars(self.lower_return_type_notation_ty(candidate,
assoc_item.def_id, path_span)?.into(), bound_vars)
} else {
candidate.map_bound(|trait_ref|
{
let item_segment =
hir::PathSegment {
ident: constraint.ident,
hir_id: constraint.hir_id,
res: Res::Err,
args: Some(constraint.gen_args),
infer_args: false,
delegation_child_segment: false,
};
let alias_args =
self.lower_generic_args_of_assoc_item(path_span,
assoc_item.def_id, &item_segment, trait_ref.args);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:477",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(477u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("alias_args")
}> =
::tracing::__macro_support::FieldName::new("alias_args");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&alias_args)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
ty::AliasTerm::new_from_def_id(tcx, assoc_item.def_id,
alias_args, ty::AliasConstInherentArgsKind::WithSelf)
})
};
match constraint.kind {
hir::AssocItemConstraintKind::Equality { .. } if
let ty::AssocTag::Fn = assoc_tag => {
return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationEqualityBound {
span: constraint.span,
}));
}
hir::AssocItemConstraintKind::Equality { term } => {
let term =
match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => {
let ty =
projection_term.map_bound(|alias|
alias.expect_ct().type_of(tcx).skip_norm_wip());
let ty =
check_assoc_const_binding_type(self, constraint.ident, ty,
constraint.hir_id);
self.lower_const_arg(ct, ty).into()
}
};
let late_bound_in_projection_ty =
tcx.collect_constrained_late_bound_regions(projection_term);
let late_bound_in_term =
tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:524",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(524u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("late_bound_in_projection_ty")
}> =
::tracing::__macro_support::FieldName::new("late_bound_in_projection_ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&late_bound_in_projection_ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:525",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(525u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::bounds"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("late_bound_in_term")
}> =
::tracing::__macro_support::FieldName::new("late_bound_in_term");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&late_bound_in_term)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.validate_late_bound_regions(late_bound_in_projection_ty,
late_bound_in_term,
|br_name|
{
{
self.dcx().struct_span_err(constraint.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("binding for associated type `{0}` references {1}, which does not appear in the trait input types",
constraint.ident, br_name))
})).with_code(E0582)
}
});
match predicate_filter {
PredicateFilter::All | PredicateFilter::SelfOnly |
PredicateFilter::SelfAndAssociatedTypeBounds => {
let bound =
projection_term.map_bound(|projection_term|
{
ty::ClauseKind::Projection(ty::ProjectionClause {
projection_term,
term,
})
});
if let ty::AssocTag::Const = assoc_tag &&
!self.tcx().is_direct_const(assoc_item.def_id) &&
!tcx.features().generic_const_args() {
if tcx.features().min_generic_const_args() {
let err =
self.dcx().struct_span_err(constraint.span,
"use of trait associated const not defined as `#[rustc_always_gca]`");
return Err(err.emit());
} else {
let err =
self.dcx().span_delayed_bug(constraint.span,
"use of trait associated const defined as `#[rustc_always_gca]`");
return Err(err);
}
}
bounds.push((bound.upcast(tcx), constraint.span));
}
PredicateFilter::SelfTraitThatDefines(_) => {}
PredicateFilter::ConstIfConst |
PredicateFilter::SelfConstIfConst => {}
}
}
hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } =>
{
match predicate_filter {
PredicateFilter::All |
PredicateFilter::SelfAndAssociatedTypeBounds |
PredicateFilter::ConstIfConst => {
let projection_ty =
projection_term.map_bound(|projection_term|
projection_term.expect_ty());
let param_ty =
Ty::new_alias(tcx, ty::IsRigid::No,
projection_ty.skip_binder());
self.lower_bounds(param_ty, hir_bounds, bounds,
projection_ty.bound_vars(), predicate_filter,
OverlappingAsssocItemConstraints::Allowed);
}
PredicateFilter::SelfOnly |
PredicateFilter::SelfTraitThatDefines(_) |
PredicateFilter::SelfConstIfConst => {}
}
}
}
Ok(())
}
}
}#[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
375 pub(super) fn lower_assoc_item_constraint(
376 &self,
377 hir_ref_id: hir::HirId,
378 trait_ref: ty::PolyTraitRef<'tcx>,
379 constraint: &hir::AssocItemConstraint<'_>,
380 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
381 duplicates: Option<&mut FxIndexMap<DefId, Span>>,
382 path_span: Span,
383 predicate_filter: PredicateFilter,
384 ) -> Result<(), ErrorGuaranteed> {
385 let tcx = self.tcx();
386
387 let assoc_tag = if constraint.gen_args.parenthesized
388 == hir::GenericArgsParentheses::ReturnTypeNotation
389 {
390 ty::AssocTag::Fn
391 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
392 constraint.kind
393 {
394 ty::AssocTag::Const
395 } else {
396 ty::AssocTag::Type
397 };
398
399 let candidate = if self.probe_trait_that_defines_assoc_item(
408 trait_ref.def_id(),
409 assoc_tag,
410 constraint.ident,
411 ) {
412 trait_ref
414 } else {
415 self.probe_single_bound_for_assoc_item(
418 || traits::supertraits(tcx, trait_ref),
419 AssocItemQSelf::Trait(trait_ref.def_id()),
420 assoc_tag,
421 constraint.ident,
422 path_span,
423 Some(constraint),
424 )?
425 };
426
427 let assoc_item = self
428 .probe_assoc_item(
429 constraint.ident,
430 assoc_tag,
431 hir_ref_id,
432 constraint.span,
433 candidate.def_id(),
434 )
435 .expect("failed to find associated item");
436
437 if let Some(duplicates) = duplicates {
438 duplicates
439 .entry(assoc_item.def_id)
440 .and_modify(|prev_span| {
441 self.dcx().emit_err(diagnostics::ValueOfAssociatedStructAlreadySpecified {
442 span: constraint.span,
443 prev_span: *prev_span,
444 item_name: constraint.ident,
445 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
446 });
447 })
448 .or_insert(constraint.span);
449 }
450
451 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
452 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
453 ty::Binder::bind_with_vars(
454 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
455 bound_vars,
456 )
457 } else {
458 candidate.map_bound(|trait_ref| {
462 let item_segment = hir::PathSegment {
463 ident: constraint.ident,
464 hir_id: constraint.hir_id,
465 res: Res::Err,
466 args: Some(constraint.gen_args),
467 infer_args: false,
468 delegation_child_segment: false,
469 };
470
471 let alias_args = self.lower_generic_args_of_assoc_item(
472 path_span,
473 assoc_item.def_id,
474 &item_segment,
475 trait_ref.args,
476 );
477 debug!(?alias_args);
478
479 ty::AliasTerm::new_from_def_id(
480 tcx,
481 assoc_item.def_id,
482 alias_args,
483 ty::AliasConstInherentArgsKind::WithSelf,
484 )
485 })
486 };
487
488 match constraint.kind {
489 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
490 return Err(self.dcx().emit_err(
491 crate::diagnostics::ReturnTypeNotationEqualityBound { span: constraint.span },
492 ));
493 }
494 hir::AssocItemConstraintKind::Equality { term } => {
497 let term = match term {
498 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
499 hir::Term::Const(ct) => {
500 let ty = projection_term
501 .map_bound(|alias| alias.expect_ct().type_of(tcx).skip_norm_wip());
502 let ty = check_assoc_const_binding_type(
503 self,
504 constraint.ident,
505 ty,
506 constraint.hir_id,
507 );
508
509 self.lower_const_arg(ct, ty).into()
510 }
511 };
512
513 let late_bound_in_projection_ty =
521 tcx.collect_constrained_late_bound_regions(projection_term);
522 let late_bound_in_term =
523 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
524 debug!(?late_bound_in_projection_ty);
525 debug!(?late_bound_in_term);
526
527 self.validate_late_bound_regions(
532 late_bound_in_projection_ty,
533 late_bound_in_term,
534 |br_name| {
535 struct_span_code_err!(
536 self.dcx(),
537 constraint.span,
538 E0582,
539 "binding for associated type `{}` references {}, \
540 which does not appear in the trait input types",
541 constraint.ident,
542 br_name
543 )
544 },
545 );
546
547 match predicate_filter {
548 PredicateFilter::All
549 | PredicateFilter::SelfOnly
550 | PredicateFilter::SelfAndAssociatedTypeBounds => {
551 let bound = projection_term.map_bound(|projection_term| {
552 ty::ClauseKind::Projection(ty::ProjectionClause {
553 projection_term,
554 term,
555 })
556 });
557
558 if let ty::AssocTag::Const = assoc_tag
559 && !self.tcx().is_direct_const(assoc_item.def_id)
560 && !tcx.features().generic_const_args()
561 {
562 if tcx.features().min_generic_const_args() {
563 let err = self.dcx().struct_span_err(
564 constraint.span,
565 "use of trait associated const not defined as `#[rustc_always_gca]`",
566 );
567 return Err(err.emit());
568 } else {
569 let err = self.dcx().span_delayed_bug(
570 constraint.span,
571 "use of trait associated const defined as `#[rustc_always_gca]`",
572 );
573 return Err(err);
574 }
575 }
576
577 bounds.push((bound.upcast(tcx), constraint.span));
578 }
579 PredicateFilter::SelfTraitThatDefines(_) => {}
581 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
583 }
584 }
585 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
588 match predicate_filter {
589 PredicateFilter::All
590 | PredicateFilter::SelfAndAssociatedTypeBounds
591 | PredicateFilter::ConstIfConst => {
592 let projection_ty = projection_term
593 .map_bound(|projection_term| projection_term.expect_ty());
594 let param_ty =
597 Ty::new_alias(tcx, ty::IsRigid::No, projection_ty.skip_binder());
598 self.lower_bounds(
599 param_ty,
600 hir_bounds,
601 bounds,
602 projection_ty.bound_vars(),
603 predicate_filter,
604 OverlappingAsssocItemConstraints::Allowed,
605 );
606 }
607 PredicateFilter::SelfOnly
608 | PredicateFilter::SelfTraitThatDefines(_)
609 | PredicateFilter::SelfConstIfConst => {}
610 }
611 }
612 }
613 Ok(())
614 }
615
616 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
619 let hir::TyKind::Path(qpath) = hir_ty.kind else {
620 return self.lower_ty(hir_ty);
621 };
622
623 let tcx = self.tcx();
624 match qpath {
625 hir::QPath::Resolved(opt_self_ty, path)
626 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
627 && item_segment.args.is_some_and(|args| {
628 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(
629 args.parenthesized,
630 hir::GenericArgsParentheses::ReturnTypeNotation
631 )
632 }) =>
633 {
634 let _ =
636 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
637
638 let item_def_id = match path.res {
639 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
640 Res::Err => {
641 return Ty::new_error_with_message(
642 tcx,
643 hir_ty.span,
644 "failed to resolve RTN",
645 );
646 }
647 _ => bug_impl(None,
format_args!("only expected method resolution for fully qualified RTN"),
Location::caller())bug!("only expected method resolution for fully qualified RTN"),
648 };
649 let trait_def_id = tcx.parent(item_def_id);
650
651 let Some(self_ty) = opt_self_ty else {
653 let guar = self.report_missing_self_ty_for_resolved_path(
654 trait_def_id,
655 hir_ty.span,
656 item_segment,
657 ty::AssocTag::Type,
658 );
659 return Ty::new_error(tcx, guar);
660 };
661 let self_ty = self.lower_ty(self_ty);
662
663 let trait_ref = self.lower_mono_trait_ref(
664 hir_ty.span,
665 trait_def_id,
666 self_ty,
667 trait_segment,
668 false,
669 );
670
671 let candidate =
684 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
685
686 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
687 Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
688 Err(guar) => Ty::new_error(tcx, guar),
689 }
690 }
691 hir::QPath::TypeRelative(hir_self_ty, segment)
692 if segment.args.is_some_and(|args| {
693 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
694 }) =>
695 {
696 let self_ty = self.lower_ty(hir_self_ty);
697 let (item_def_id, bound) = match self.resolve_type_relative_path(
698 self_ty,
699 hir_self_ty,
700 ty::AssocTag::Fn,
701 segment,
702 hir_ty.hir_id,
703 hir_ty.span,
704 None,
705 ) {
706 Ok(result) => result,
707 Err(guar) => return Ty::new_error(tcx, guar),
708 };
709
710 if bound.has_bound_vars() {
717 return Ty::new_error(
718 tcx,
719 self.dcx().emit_err(
720 diagnostics::AssociatedItemTraitUninferredGenericParams {
721 span: hir_ty.span,
722 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
723 bound: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
tcx.anonymize_bound_vars(bound).skip_binder()))
})format!(
724 "{}::",
725 tcx.anonymize_bound_vars(bound).skip_binder()
726 ),
727 mpart_sugg: None,
728 what: tcx.def_descr(item_def_id),
729 },
730 ),
731 );
732 }
733
734 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
735 Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
736 Err(guar) => Ty::new_error(tcx, guar),
737 }
738 }
739 _ => self.lower_ty(hir_ty),
740 }
741 }
742
743 fn lower_return_type_notation_ty(
748 &self,
749 candidate: ty::PolyTraitRef<'tcx>,
750 item_def_id: DefId,
751 path_span: Span,
752 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
753 let tcx = self.tcx();
754 let mut emitted_bad_param_err = None;
755 let mut num_bound_vars = candidate.bound_vars().len();
758 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
759 let arg = match param.kind {
760 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
761 tcx,
762 ty::INNERMOST,
763 ty::BoundRegion {
764 var: ty::BoundVar::from_usize(num_bound_vars),
765 kind: ty::BoundRegionKind::Named(param.def_id),
766 },
767 )
768 .into(),
769 ty::GenericParamDefKind::Type { .. } => {
770 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
771 self.dcx().emit_err(
772 crate::diagnostics::ReturnTypeNotationIllegalParam::Type {
773 span: path_span,
774 param_span: tcx.def_span(param.def_id),
775 },
776 )
777 });
778 Ty::new_error(tcx, guar).into()
779 }
780 ty::GenericParamDefKind::Const { .. } => {
781 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
782 self.dcx().emit_err(
783 crate::diagnostics::ReturnTypeNotationIllegalParam::Const {
784 span: path_span,
785 param_span: tcx.def_span(param.def_id),
786 },
787 )
788 });
789 ty::Const::new_error(tcx, guar).into()
790 }
791 };
792 num_bound_vars += 1;
793 arg
794 });
795
796 let output = tcx.fn_sig(item_def_id).skip_binder().output();
799 let output = if let ty::Alias(_, alias_ty) = *output.skip_binder().kind()
800 && let ty::AliasTy { kind: ty::Projection { def_id: projection_def_id }, .. } = alias_ty
801 && tcx.is_impl_trait_in_trait(projection_def_id)
802 {
803 alias_ty
804 } else {
805 return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationOnNonRpitit {
806 span: path_span,
807 ty: tcx.liberate_late_bound_regions(item_def_id, output),
808 fn_span: tcx.hir_span_if_local(item_def_id),
809 note: (),
810 }));
811 };
812
813 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
818 Ok(ty::EarlyBinder::bind(tcx, shifted_output).instantiate(tcx, args).skip_norm_wip())
819 }
820}
821
822pub(crate) fn check_assoc_const_binding_type<'tcx>(
834 cx: &dyn HirTyLowerer<'tcx>,
835 assoc_const: Ident,
836 ty: ty::Binder<'tcx, Ty<'tcx>>,
837 hir_id: hir::HirId,
838) -> Ty<'tcx> {
839 let ty = ty.skip_binder();
846 if !ty.has_param() && !ty.has_escaping_bound_vars() {
847 return ty;
848 }
849
850 let mut collector = GenericParamAndBoundVarCollector {
851 cx,
852 params: Default::default(),
853 vars: Default::default(),
854 depth: ty::INNERMOST,
855 };
856 let mut guar = ty.visit_with(&mut collector).break_value();
857
858 let tcx = cx.tcx();
859 let ty_note = ty
860 .make_suggestable(tcx, false, None)
861 .map(|ty| crate::diagnostics::TyOfAssocConstBindingNote { assoc_const, ty });
862
863 let enclosing_item_owner_id = tcx
864 .hir_parent_owner_iter(hir_id)
865 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
866 .unwrap();
867 let generics = tcx.generics_of(enclosing_item_owner_id);
868 for index in collector.params {
869 let param = generics.param_at(index as _, tcx);
870 let is_self_param = param.name == kw::SelfUpper;
871 guar.get_or_insert(cx.dcx().emit_err(crate::diagnostics::ParamInTyOfAssocConstBinding {
872 span: assoc_const.span,
873 assoc_const,
874 param_name: param.name,
875 param_def_kind: tcx.def_descr(param.def_id),
876 param_category: if is_self_param {
877 "self"
878 } else if param.kind.is_synthetic() {
879 "synthetic"
880 } else {
881 "normal"
882 },
883 param_defined_here_label:
884 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
885 ty_note,
886 }));
887 }
888 for var_def_id in collector.vars {
889 guar.get_or_insert(cx.dcx().emit_err(
890 crate::diagnostics::EscapingBoundVarInTyOfAssocConstBinding {
891 span: assoc_const.span,
892 assoc_const,
893 var_name: cx.tcx().item_name(var_def_id),
894 var_def_kind: tcx.def_descr(var_def_id),
895 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
896 ty_note,
897 },
898 ));
899 }
900
901 let guar = guar.unwrap_or_else(|| bug_impl(None, format_args!("failed to find gen params or bound vars in ty"),
Location::caller())bug!("failed to find gen params or bound vars in ty"));
902 Ty::new_error(tcx, guar)
903}
904
905struct GenericParamAndBoundVarCollector<'a, 'tcx> {
906 cx: &'a dyn HirTyLowerer<'tcx>,
907 params: FxIndexSet<u32>,
908 vars: FxIndexSet<DefId>,
909 depth: ty::DebruijnIndex,
910}
911
912impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
913 type Result = ControlFlow<ErrorGuaranteed>;
914
915 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
916 &mut self,
917 binder: &ty::Binder<'tcx, T>,
918 ) -> Self::Result {
919 self.depth.shift_in(1);
920 let result = binder.super_visit_with(self);
921 self.depth.shift_out(1);
922 result
923 }
924
925 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
926 match ty.kind() {
927 ty::Param(param) => {
928 self.params.insert(param.index);
929 }
930 ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
931 self.vars.insert(match bt.kind {
932 ty::BoundTyKind::Param(def_id) => def_id,
933 ty::BoundTyKind::Anon => {
934 let reported = self
935 .cx
936 .dcx()
937 .delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected anon bound ty: {0:?}",
bt.var))
})format!("unexpected anon bound ty: {:?}", bt.var));
938 return ControlFlow::Break(reported);
939 }
940 });
941 }
942 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
943 _ => {}
944 }
945 ControlFlow::Continue(())
946 }
947
948 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
949 match re.kind() {
950 ty::ReEarlyParam(param) => {
951 self.params.insert(param.index);
952 }
953 ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
954 self.vars.insert(match br.kind {
955 ty::BoundRegionKind::Named(def_id) => def_id,
956 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
957 let guar = self
958 .cx
959 .dcx()
960 .delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected bound region kind: {0:?}",
br.kind))
})format!("unexpected bound region kind: {:?}", br.kind));
961 return ControlFlow::Break(guar);
962 }
963 ty::BoundRegionKind::NamedForPrinting(_) => {
964 bug_impl(None, format_args!("only used for pretty printing"),
Location::caller())bug!("only used for pretty printing")
965 }
966 });
967 }
968 _ => {}
969 }
970 ControlFlow::Continue(())
971 }
972
973 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
974 match ct.kind() {
975 ty::ConstKind::Param(param) => {
976 self.params.insert(param.index);
977 }
978 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
979 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
980 return ControlFlow::Break(guar);
981 }
982 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
983 _ => {}
984 }
985 ControlFlow::Continue(())
986 }
987}