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::{ErrorGuaranteed, Ident, Span, kw};
16use rustc_trait_selection::traits;
17use smallvec::SmallVec;
18use tracing::{debug, instrument};
19
20use crate::errors;
21use crate::hir_ty_lowering::{
22 AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
23 OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
24};
25
26#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CollectedBound {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"CollectedBound", "positive", &self.positive, "maybe",
&self.maybe, "negative", &&self.negative)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for CollectedBound {
#[inline]
fn default() -> CollectedBound {
CollectedBound {
positive: ::core::default::Default::default(),
maybe: ::core::default::Default::default(),
negative: ::core::default::Default::default(),
}
}
}Default)]
27struct CollectedBound {
28 positive: bool,
30 maybe: bool,
32 negative: bool,
34}
35
36impl CollectedBound {
37 fn any(&self) -> bool {
39 self.positive || self.maybe || self.negative
40 }
41}
42
43#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CollectedSizednessBounds {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"CollectedSizednessBounds", "sized", &self.sized, "meta_sized",
&self.meta_sized, "pointee_sized", &&self.pointee_sized)
}
}Debug)]
44struct CollectedSizednessBounds {
45 sized: CollectedBound,
47 meta_sized: CollectedBound,
49 pointee_sized: CollectedBound,
51}
52
53impl CollectedSizednessBounds {
54 fn any(&self) -> bool {
57 self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
58 }
59}
60
61fn search_bounds_for<'tcx>(
62 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
63 context: ImpliedBoundsContext<'tcx>,
64 mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
65) {
66 let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
67 for hir_bound in hir_bounds {
68 let hir::GenericBound::Trait(ptr) = hir_bound else {
69 continue;
70 };
71
72 f(ptr)
73 }
74 };
75
76 search_bounds(hir_bounds);
77 if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
78 for clause in where_clause {
79 if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
80 && pred.is_param_bound(self_ty.to_def_id())
81 {
82 search_bounds(pred.bounds);
83 }
84 }
85 }
86}
87
88fn collect_relaxed_bounds<'tcx>(
89 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
90 context: ImpliedBoundsContext<'tcx>,
91) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
92 let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
93 search_bounds_for(hir_bounds, context, |ptr| {
94 if #[allow(non_exhaustive_omitted_patterns)] match ptr.modifiers.polarity {
hir::BoundPolarity::Maybe(_) => true,
_ => false,
}matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
95 relaxed_bounds.push(ptr);
96 }
97 });
98 relaxed_bounds
99}
100
101fn collect_bounds<'a, 'tcx>(
102 hir_bounds: &'a [hir::GenericBound<'tcx>],
103 context: ImpliedBoundsContext<'tcx>,
104 target_did: DefId,
105) -> CollectedBound {
106 let mut collect_into = CollectedBound::default();
107 search_bounds_for(hir_bounds, context, |ptr| {
108 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) {
109 return;
110 }
111
112 match ptr.modifiers.polarity {
113 hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
114 hir::BoundPolarity::Negative(_) => collect_into.negative = true,
115 hir::BoundPolarity::Positive => collect_into.positive = true,
116 }
117 });
118 collect_into
119}
120
121fn collect_sizedness_bounds<'tcx>(
122 tcx: TyCtxt<'tcx>,
123 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
124 context: ImpliedBoundsContext<'tcx>,
125 span: Span,
126) -> CollectedSizednessBounds {
127 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
128 let sized = collect_bounds(hir_bounds, context, sized_did);
129
130 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
131 let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
132
133 let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
134 let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
135
136 CollectedSizednessBounds { sized, meta_sized, pointee_sized }
137}
138
139fn add_trait_bound<'tcx>(
141 tcx: TyCtxt<'tcx>,
142 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
143 self_ty: Ty<'tcx>,
144 did: DefId,
145 span: Span,
146) {
147 let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
148 bounds.insert(0, (trait_ref.upcast(tcx), span));
151}
152
153impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
154 pub(crate) fn add_implicit_sizedness_bounds(
163 &self,
164 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
165 self_ty: Ty<'tcx>,
166 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
167 context: ImpliedBoundsContext<'tcx>,
168 span: Span,
169 ) {
170 let tcx = self.tcx();
171
172 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) {
174 return;
175 }
176
177 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
178 let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
179
180 match context {
182 ImpliedBoundsContext::TraitDef(trait_did) => {
183 let trait_did = trait_did.to_def_id();
184 if trait_did == pointee_sized_did {
186 return;
187 }
188 if tcx.trait_is_auto(trait_did) {
191 return;
192 }
193 }
194 ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
195 let bounds = collect_relaxed_bounds(hir_bounds, context);
206 self.reject_duplicate_relaxed_bounds(bounds);
207 }
208 }
209
210 let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
211 if (collected.sized.maybe || collected.sized.negative)
212 && !collected.sized.positive
213 && !collected.meta_sized.any()
214 && !collected.pointee_sized.any()
215 {
216 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
219 } else if !collected.any() {
220 match context {
221 ImpliedBoundsContext::TraitDef(..) => {
222 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
225 }
226 ImpliedBoundsContext::TyParam(..)
227 | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
228 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
231 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
232 }
233 }
234 }
235 }
236
237 pub(crate) fn add_default_traits(
238 &self,
239 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
240 self_ty: Ty<'tcx>,
241 hir_bounds: &[hir::GenericBound<'tcx>],
242 context: ImpliedBoundsContext<'tcx>,
243 span: Span,
244 ) {
245 self.tcx().default_traits().iter().for_each(|default_trait| {
246 self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
247 });
248 }
249
250 pub(crate) fn add_default_trait(
254 &self,
255 trait_: hir::LangItem,
256 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
257 self_ty: Ty<'tcx>,
258 hir_bounds: &[hir::GenericBound<'tcx>],
259 context: ImpliedBoundsContext<'tcx>,
260 span: Span,
261 ) {
262 let tcx = self.tcx();
263
264 if let ImpliedBoundsContext::TraitDef(trait_did) = context
267 && self.tcx().trait_is_auto(trait_did.into())
268 {
269 return;
270 }
271
272 if let Some(trait_did) = tcx.lang_items().get(trait_)
273 && self.should_add_default_traits(trait_did, hir_bounds, context)
274 {
275 add_trait_bound(tcx, bounds, self_ty, trait_did, span);
276 }
277 }
278
279 fn should_add_default_traits<'a>(
281 &self,
282 trait_def_id: DefId,
283 hir_bounds: &'a [hir::GenericBound<'tcx>],
284 context: ImpliedBoundsContext<'tcx>,
285 ) -> bool {
286 let collected = collect_bounds(hir_bounds, context, trait_def_id);
287 !{
'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()
288 }
289
290 fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
291 let tcx = self.tcx();
292
293 let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
294
295 for bound in &relaxed_bounds {
296 if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
297 grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
298 }
299 }
300
301 for (trait_def_id, spans) in grouped_bounds {
302 if spans.len() > 1 {
303 let name = tcx.item_name(trait_def_id);
304 self.dcx()
305 .struct_span_err(spans, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("duplicate relaxed `{0}` bounds",
name))
})format!("duplicate relaxed `{name}` bounds"))
306 .with_code(E0203)
307 .emit();
308 }
309 }
310 }
311
312 pub(crate) fn require_bound_to_relax_default_trait(
313 &self,
314 trait_ref: hir::TraitRef<'_>,
315 span: Span,
316 ) {
317 let tcx = self.tcx();
318
319 if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
320 && (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id))
321 {
322 return;
323 }
324
325 self.dcx().span_err(
326 span,
327 if tcx.sess.opts.unstable_opts.experimental_default_bounds
328 || tcx.features().more_maybe_bounds()
329 {
330 "bound modifier `?` can only be applied to default traits"
331 } else {
332 "bound modifier `?` can only be applied to `Sized`"
333 },
334 );
335 }
336
337 #[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(358u32),
::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(¶m_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))]
359 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
360 &self,
361 param_ty: Ty<'tcx>,
362 hir_bounds: I,
363 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
364 bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
365 predicate_filter: PredicateFilter,
366 overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
367 ) where
368 'tcx: 'hir,
369 {
370 for hir_bound in hir_bounds {
371 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
374 if let Some(trait_ref) = hir_bound.trait_ref()
375 && let Some(trait_did) = trait_ref.trait_def_id()
376 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
377 {
378 } else {
380 continue;
381 }
382 }
383
384 match hir_bound {
385 hir::GenericBound::Trait(poly_trait_ref) => {
386 let _ = self.lower_poly_trait_ref(
387 poly_trait_ref,
388 param_ty,
389 bounds,
390 predicate_filter,
391 overlapping_assoc_constraints,
392 );
393 }
394 hir::GenericBound::Outlives(lifetime) => {
395 if matches!(
397 predicate_filter,
398 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
399 ) {
400 continue;
401 }
402
403 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
404 let bound = ty::Binder::bind_with_vars(
405 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
406 bound_vars,
407 );
408 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
409 }
410 hir::GenericBound::Use(..) => {
411 }
413 }
414 }
415 }
416
417 #[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(425u32),
::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(errors::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:527",
"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(527u32),
::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_args(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::errors::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|
{ tcx.type_of(alias.def_id).instantiate(tcx, alias.args) });
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:570",
"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(570u32),
::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:571",
"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(571u32),
::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(self.tcx()));
let param_ty =
Ty::new_alias(tcx, ty::Projection,
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))]
426 pub(super) fn lower_assoc_item_constraint(
427 &self,
428 hir_ref_id: hir::HirId,
429 trait_ref: ty::PolyTraitRef<'tcx>,
430 constraint: &hir::AssocItemConstraint<'tcx>,
431 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
432 duplicates: Option<&mut FxIndexMap<DefId, Span>>,
433 path_span: Span,
434 predicate_filter: PredicateFilter,
435 ) -> Result<(), ErrorGuaranteed> {
436 let tcx = self.tcx();
437
438 let assoc_tag = if constraint.gen_args.parenthesized
439 == hir::GenericArgsParentheses::ReturnTypeNotation
440 {
441 ty::AssocTag::Fn
442 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
443 constraint.kind
444 {
445 ty::AssocTag::Const
446 } else {
447 ty::AssocTag::Type
448 };
449
450 let candidate = if self.probe_trait_that_defines_assoc_item(
459 trait_ref.def_id(),
460 assoc_tag,
461 constraint.ident,
462 ) {
463 trait_ref
465 } else {
466 self.probe_single_bound_for_assoc_item(
469 || traits::supertraits(tcx, trait_ref),
470 AssocItemQSelf::Trait(trait_ref.def_id()),
471 assoc_tag,
472 constraint.ident,
473 path_span,
474 Some(constraint),
475 )?
476 };
477
478 let assoc_item = self
479 .probe_assoc_item(
480 constraint.ident,
481 assoc_tag,
482 hir_ref_id,
483 constraint.span,
484 candidate.def_id(),
485 )
486 .expect("failed to find associated item");
487
488 if let Some(duplicates) = duplicates {
489 duplicates
490 .entry(assoc_item.def_id)
491 .and_modify(|prev_span| {
492 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
493 span: constraint.span,
494 prev_span: *prev_span,
495 item_name: constraint.ident,
496 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
497 });
498 })
499 .or_insert(constraint.span);
500 }
501
502 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
503 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
504 ty::Binder::bind_with_vars(
505 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
506 bound_vars,
507 )
508 } else {
509 candidate.map_bound(|trait_ref| {
513 let item_segment = hir::PathSegment {
514 ident: constraint.ident,
515 hir_id: constraint.hir_id,
516 res: Res::Err,
517 args: Some(constraint.gen_args),
518 infer_args: false,
519 };
520
521 let alias_args = self.lower_generic_args_of_assoc_item(
522 path_span,
523 assoc_item.def_id,
524 &item_segment,
525 trait_ref.args,
526 );
527 debug!(?alias_args);
528
529 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
530 })
531 };
532
533 match constraint.kind {
534 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
535 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
536 span: constraint.span,
537 }));
538 }
539 hir::AssocItemConstraintKind::Equality { term } => {
542 let term = match term {
543 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
544 hir::Term::Const(ct) => {
545 let ty = projection_term.map_bound(|alias| {
546 tcx.type_of(alias.def_id).instantiate(tcx, alias.args)
547 });
548 let ty = check_assoc_const_binding_type(
549 self,
550 constraint.ident,
551 ty,
552 constraint.hir_id,
553 );
554
555 self.lower_const_arg(ct, ty).into()
556 }
557 };
558
559 let late_bound_in_projection_ty =
567 tcx.collect_constrained_late_bound_regions(projection_term);
568 let late_bound_in_term =
569 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
570 debug!(?late_bound_in_projection_ty);
571 debug!(?late_bound_in_term);
572
573 self.validate_late_bound_regions(
578 late_bound_in_projection_ty,
579 late_bound_in_term,
580 |br_name| {
581 struct_span_code_err!(
582 self.dcx(),
583 constraint.span,
584 E0582,
585 "binding for associated type `{}` references {}, \
586 which does not appear in the trait input types",
587 constraint.ident,
588 br_name
589 )
590 },
591 );
592
593 match predicate_filter {
594 PredicateFilter::All
595 | PredicateFilter::SelfOnly
596 | PredicateFilter::SelfAndAssociatedTypeBounds => {
597 let bound = projection_term.map_bound(|projection_term| {
598 ty::ClauseKind::Projection(ty::ProjectionPredicate {
599 projection_term,
600 term,
601 })
602 });
603
604 if let ty::AssocTag::Const = assoc_tag
605 && !self.tcx().is_type_const(assoc_item.def_id)
606 {
607 if tcx.features().min_generic_const_args() {
608 let mut err = self.dcx().struct_span_err(
609 constraint.span,
610 "use of trait associated const not defined as `type const`",
611 );
612 err.note("the declaration in the trait must begin with `type const` not just `const` alone");
613 return Err(err.emit());
614 } else {
615 let err = self.dcx().span_delayed_bug(
616 constraint.span,
617 "use of trait associated const defined as `type const`",
618 );
619 return Err(err);
620 }
621 } else {
622 bounds.push((bound.upcast(tcx), constraint.span));
623 }
624 }
625 PredicateFilter::SelfTraitThatDefines(_) => {}
627 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
629 }
630 }
631 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
634 match predicate_filter {
635 PredicateFilter::All
636 | PredicateFilter::SelfAndAssociatedTypeBounds
637 | PredicateFilter::ConstIfConst => {
638 let projection_ty = projection_term
639 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
640 let param_ty =
643 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
644 self.lower_bounds(
645 param_ty,
646 hir_bounds,
647 bounds,
648 projection_ty.bound_vars(),
649 predicate_filter,
650 OverlappingAsssocItemConstraints::Allowed,
651 );
652 }
653 PredicateFilter::SelfOnly
654 | PredicateFilter::SelfTraitThatDefines(_)
655 | PredicateFilter::SelfConstIfConst => {}
656 }
657 }
658 }
659 Ok(())
660 }
661
662 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
665 let hir::TyKind::Path(qpath) = hir_ty.kind else {
666 return self.lower_ty(hir_ty);
667 };
668
669 let tcx = self.tcx();
670 match qpath {
671 hir::QPath::Resolved(opt_self_ty, path)
672 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
673 && item_segment.args.is_some_and(|args| {
674 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(
675 args.parenthesized,
676 hir::GenericArgsParentheses::ReturnTypeNotation
677 )
678 }) =>
679 {
680 let _ =
682 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
683
684 let item_def_id = match path.res {
685 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
686 Res::Err => {
687 return Ty::new_error_with_message(
688 tcx,
689 hir_ty.span,
690 "failed to resolve RTN",
691 );
692 }
693 _ => ::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"),
694 };
695 let trait_def_id = tcx.parent(item_def_id);
696
697 let Some(self_ty) = opt_self_ty else {
699 let guar = self.report_missing_self_ty_for_resolved_path(
700 trait_def_id,
701 hir_ty.span,
702 item_segment,
703 ty::AssocTag::Type,
704 );
705 return Ty::new_error(tcx, guar);
706 };
707 let self_ty = self.lower_ty(self_ty);
708
709 let trait_ref = self.lower_mono_trait_ref(
710 hir_ty.span,
711 trait_def_id,
712 self_ty,
713 trait_segment,
714 false,
715 );
716
717 let candidate =
730 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
731
732 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
733 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
734 Err(guar) => Ty::new_error(tcx, guar),
735 }
736 }
737 hir::QPath::TypeRelative(hir_self_ty, segment)
738 if segment.args.is_some_and(|args| {
739 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
740 }) =>
741 {
742 let self_ty = self.lower_ty(hir_self_ty);
743 let (item_def_id, bound) = match self.resolve_type_relative_path(
744 self_ty,
745 hir_self_ty,
746 ty::AssocTag::Fn,
747 segment,
748 hir_ty.hir_id,
749 hir_ty.span,
750 None,
751 ) {
752 Ok(result) => result,
753 Err(guar) => return Ty::new_error(tcx, guar),
754 };
755
756 if bound.has_bound_vars() {
763 return Ty::new_error(
764 tcx,
765 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
766 span: hir_ty.span,
767 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
768 bound: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
tcx.anonymize_bound_vars(bound).skip_binder()))
})format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
769 mpart_sugg: None,
770 what: tcx.def_descr(item_def_id),
771 }),
772 );
773 }
774
775 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
776 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
777 Err(guar) => Ty::new_error(tcx, guar),
778 }
779 }
780 _ => self.lower_ty(hir_ty),
781 }
782 }
783
784 fn lower_return_type_notation_ty(
789 &self,
790 candidate: ty::PolyTraitRef<'tcx>,
791 item_def_id: DefId,
792 path_span: Span,
793 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
794 let tcx = self.tcx();
795 let mut emitted_bad_param_err = None;
796 let mut num_bound_vars = candidate.bound_vars().len();
799 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
800 let arg = match param.kind {
801 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
802 tcx,
803 ty::INNERMOST,
804 ty::BoundRegion {
805 var: ty::BoundVar::from_usize(num_bound_vars),
806 kind: ty::BoundRegionKind::Named(param.def_id),
807 },
808 )
809 .into(),
810 ty::GenericParamDefKind::Type { .. } => {
811 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
812 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
813 span: path_span,
814 param_span: tcx.def_span(param.def_id),
815 })
816 });
817 Ty::new_error(tcx, guar).into()
818 }
819 ty::GenericParamDefKind::Const { .. } => {
820 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
821 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
822 span: path_span,
823 param_span: tcx.def_span(param.def_id),
824 })
825 });
826 ty::Const::new_error(tcx, guar).into()
827 }
828 };
829 num_bound_vars += 1;
830 arg
831 });
832
833 let output = tcx.fn_sig(item_def_id).skip_binder().output();
836 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
837 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
838 {
839 alias_ty
840 } else {
841 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
842 span: path_span,
843 ty: tcx.liberate_late_bound_regions(item_def_id, output),
844 fn_span: tcx.hir_span_if_local(item_def_id),
845 note: (),
846 }));
847 };
848
849 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
854 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
855 }
856}
857
858pub(crate) fn check_assoc_const_binding_type<'tcx>(
870 cx: &dyn HirTyLowerer<'tcx>,
871 assoc_const: Ident,
872 ty: ty::Binder<'tcx, Ty<'tcx>>,
873 hir_id: hir::HirId,
874) -> Ty<'tcx> {
875 let ty = ty.skip_binder();
882 if !ty.has_param() && !ty.has_escaping_bound_vars() {
883 return ty;
884 }
885
886 let mut collector = GenericParamAndBoundVarCollector {
887 cx,
888 params: Default::default(),
889 vars: Default::default(),
890 depth: ty::INNERMOST,
891 };
892 let mut guar = ty.visit_with(&mut collector).break_value();
893
894 let tcx = cx.tcx();
895 let ty_note = ty
896 .make_suggestable(tcx, false, None)
897 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
898
899 let enclosing_item_owner_id = tcx
900 .hir_parent_owner_iter(hir_id)
901 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
902 .unwrap();
903 let generics = tcx.generics_of(enclosing_item_owner_id);
904 for index in collector.params {
905 let param = generics.param_at(index as _, tcx);
906 let is_self_param = param.name == kw::SelfUpper;
907 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
908 span: assoc_const.span,
909 assoc_const,
910 param_name: param.name,
911 param_def_kind: tcx.def_descr(param.def_id),
912 param_category: if is_self_param {
913 "self"
914 } else if param.kind.is_synthetic() {
915 "synthetic"
916 } else {
917 "normal"
918 },
919 param_defined_here_label:
920 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
921 ty_note,
922 }));
923 }
924 for var_def_id in collector.vars {
925 guar.get_or_insert(cx.dcx().emit_err(
926 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
927 span: assoc_const.span,
928 assoc_const,
929 var_name: cx.tcx().item_name(var_def_id),
930 var_def_kind: tcx.def_descr(var_def_id),
931 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
932 ty_note,
933 },
934 ));
935 }
936
937 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"));
938 Ty::new_error(tcx, guar)
939}
940
941struct GenericParamAndBoundVarCollector<'a, 'tcx> {
942 cx: &'a dyn HirTyLowerer<'tcx>,
943 params: FxIndexSet<u32>,
944 vars: FxIndexSet<DefId>,
945 depth: ty::DebruijnIndex,
946}
947
948impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
949 type Result = ControlFlow<ErrorGuaranteed>;
950
951 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
952 &mut self,
953 binder: &ty::Binder<'tcx, T>,
954 ) -> Self::Result {
955 self.depth.shift_in(1);
956 let result = binder.super_visit_with(self);
957 self.depth.shift_out(1);
958 result
959 }
960
961 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
962 match ty.kind() {
963 ty::Param(param) => {
964 self.params.insert(param.index);
965 }
966 ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
967 self.vars.insert(match bt.kind {
968 ty::BoundTyKind::Param(def_id) => def_id,
969 ty::BoundTyKind::Anon => {
970 let reported = self
971 .cx
972 .dcx()
973 .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));
974 return ControlFlow::Break(reported);
975 }
976 });
977 }
978 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
979 _ => {}
980 }
981 ControlFlow::Continue(())
982 }
983
984 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
985 match re.kind() {
986 ty::ReEarlyParam(param) => {
987 self.params.insert(param.index);
988 }
989 ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
990 self.vars.insert(match br.kind {
991 ty::BoundRegionKind::Named(def_id) => def_id,
992 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
993 let guar = self
994 .cx
995 .dcx()
996 .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));
997 return ControlFlow::Break(guar);
998 }
999 ty::BoundRegionKind::NamedForPrinting(_) => {
1000 ::rustc_middle::util::bug::bug_fmt(format_args!("only used for pretty printing"))bug!("only used for pretty printing")
1001 }
1002 });
1003 }
1004 _ => {}
1005 }
1006 ControlFlow::Continue(())
1007 }
1008
1009 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1010 match ct.kind() {
1011 ty::ConstKind::Param(param) => {
1012 self.params.insert(param.index);
1013 }
1014 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
1015 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1016 return ControlFlow::Break(guar);
1017 }
1018 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1019 _ => {}
1020 }
1021 ControlFlow::Continue(())
1022 }
1023}