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