1use std::ops::ControlFlow;
2
3use rustc_attr_ir::find_attr;
4use rustc_attr_ir::lang_items::LangItem;
5use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
6use rustc_errors::codes::*;
7use rustc_errors::struct_span_code_err;
8use rustc_hir as hir;
9use rustc_hir::PolyTraitRef;
10use rustc_hir::def::{DefKind, Res};
11use rustc_hir::def_id::DefId;
12use rustc_middle::ty::{
13 self as ty, IncludeSizedImplicitBounds, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable,
14 TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast,
15};
16use rustc_span::{ErrorGuaranteed, Ident, Span, bug, kw};
17use rustc_trait_selection::traits;
18use tracing::{debug, instrument};
19
20use crate::diagnostics;
21use crate::hir_ty_lowering::{
22 AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
23 OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
24};
25
26#[derive(#[automatically_derived]impl ::core::fmt::Debug for CollectedBound {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"CollectedBound positive maybe negative", &self.positive,
&self.maybe, &&self.negative)
}
}Debug, #[automatically_derived]impl ::core::default::Default for CollectedBound {
#[inline]
fn default() -> Self {
CollectedBound {
positive: ::core::default::Default::default(),
maybe: ::core::default::Default::default(),
negative: ::core::default::Default::default(),
}
}
}Default)]
27struct CollectedBound {
28 positive: Option<Span>,
30 maybe: Option<Span>,
32 negative: Option<Span>,
34}
35
36impl CollectedBound {
37 fn any(&self) -> bool {
39 self.positive.is_some() || self.maybe.is_some() || self.negative.is_some()
40 }
41}
42
43#[derive(#[automatically_derived]impl ::core::fmt::Debug for CollectedSizednessBounds {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"CollectedSizednessBounds sized meta_sized pointee_sized",
&self.sized, &self.meta_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_bounds<'a, 'tcx>(
89 hir_bounds: &'a [hir::GenericBound<'tcx>],
90 context: ImpliedBoundsContext<'tcx>,
91 target_did: DefId,
92) -> CollectedBound {
93 let mut collect_into = CollectedBound::default();
94 search_bounds_for(hir_bounds, context, |ptr| {
95 if !#[allow(non_exhaustive_omitted_patterns)] match ptr.trait_ref.path.res {
Res::Def(DefKind::Trait, did) if did == target_did => true,
_ => false,
}matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
96 return;
97 }
98
99 match ptr.modifiers.polarity {
100 hir::BoundPolarity::Maybe(_) => collect_into.maybe = Some(ptr.span),
101 hir::BoundPolarity::Negative(_) => collect_into.negative = Some(ptr.span),
102 hir::BoundPolarity::Positive => collect_into.positive = Some(ptr.span),
103 }
104 });
105 collect_into
106}
107
108fn collect_sizedness_bounds<'tcx>(
109 tcx: TyCtxt<'tcx>,
110 hir_bounds: &[hir::GenericBound<'_>],
111 context: ImpliedBoundsContext<'tcx>,
112 span: Span,
113) -> CollectedSizednessBounds {
114 let sized_did = tcx.require_lang_item(LangItem::Sized, span);
115 let sized = collect_bounds(hir_bounds, context, sized_did);
116
117 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
118 let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
119
120 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
121 let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
122
123 CollectedSizednessBounds { sized, meta_sized, pointee_sized }
124}
125
126fn add_trait_bound<'tcx>(
128 tcx: TyCtxt<'tcx>,
129 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
130 self_ty: Ty<'tcx>,
131 did: DefId,
132 span: Span,
133) {
134 let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
135 bounds.insert(0, (trait_ref.upcast(tcx), span));
138}
139
140impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
141 pub(crate) fn add_implicit_bounds(
143 &self,
144 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
145 self_ty: Ty<'tcx>,
146 hir_bounds: &[hir::GenericBound<'_>],
147 context: ImpliedBoundsContext<'tcx>,
148 span: Span,
149 include_sized: IncludeSizedImplicitBounds,
151 ) {
152 if {
'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::Tool(..) |
::rustc_attr_ir::Attribute::DeriveHelper(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()find_attr!(self.tcx(), crate, RustcNoImplicitBounds) {
154 return;
155 }
156
157 self.add_default_traits(bounds, self_ty, hir_bounds, context, span);
158
159 if let IncludeSizedImplicitBounds::Yes = include_sized {
160 self.add_implicit_sizedness_bounds(bounds, self_ty, hir_bounds, context, span);
161 }
162 }
163
164 fn add_implicit_sizedness_bounds(
173 &self,
174 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
175 self_ty: Ty<'tcx>,
176 hir_bounds: &[hir::GenericBound<'_>],
177 context: ImpliedBoundsContext<'tcx>,
178 span: Span,
179 ) {
180 let tcx = self.tcx();
181
182 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
183 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
184
185 match context {
187 ImpliedBoundsContext::TraitDef(trait_did) => {
188 let trait_did = trait_did.to_def_id();
189 if trait_did == pointee_sized_did {
191 return;
192 }
193 if tcx.trait_is_auto(trait_did) {
196 return;
197 }
198 }
199 ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
200 }
201 }
202 let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
203 if let Some(span) = collected.sized.maybe.or(collected.sized.negative)
204 && collected.sized.positive.is_none()
205 && !collected.meta_sized.any()
206 && !collected.pointee_sized.any()
207 {
208 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
211 } else if !collected.any() {
212 match context {
213 ImpliedBoundsContext::TraitDef(..) => {
214 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
217 }
218 ImpliedBoundsContext::TyParam(..)
219 | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
220 let sized_did = tcx.require_lang_item(LangItem::Sized, span);
223 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
224 }
225 }
226 }
227 }
228
229 fn add_default_traits(
230 &self,
231 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
232 self_ty: Ty<'tcx>,
233 hir_bounds: &[hir::GenericBound<'_>],
234 context: ImpliedBoundsContext<'tcx>,
235 span: Span,
236 ) {
237 self.tcx().default_traits().iter().for_each(|default_trait| {
238 self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
239 });
240 }
241
242 fn add_default_trait(
246 &self,
247 trait_: LangItem,
248 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
249 self_ty: Ty<'tcx>,
250 hir_bounds: &[hir::GenericBound<'_>],
251 context: ImpliedBoundsContext<'tcx>,
252 span: Span,
253 ) {
254 let tcx = self.tcx();
255
256 if let ImpliedBoundsContext::TraitDef(trait_did) = context
259 && self.tcx().trait_is_auto(trait_did.into())
260 {
261 return;
262 }
263
264 if let Some(trait_did) = tcx.lang_items().get(trait_)
265 && !collect_bounds(hir_bounds, context, trait_did).any()
266 {
267 add_trait_bound(tcx, bounds, self_ty, trait_did, span);
268 }
269 }
270
271 pub(crate) fn require_bound_to_relax_default_trait(
272 &self,
273 trait_ref: hir::TraitRef<'_>,
274 span: Span,
275 ) {
276 let tcx = self.tcx();
277
278 if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
279 && (tcx.is_lang_item(def_id, LangItem::Sized)
280 || tcx.is_implicit_trait(def_id, IncludeSizedImplicitBounds::No))
281 {
282 return;
283 }
284
285 self.dcx().span_err(
286 span,
287 if tcx.sess.opts.unstable_opts.experimental_default_bounds
288 || tcx.features().more_maybe_bounds()
289 {
290 "bound modifier `?` can only be applied to default traits"
291 } else {
292 "bound modifier `?` can only be applied to `Sized`"
293 },
294 );
295 }
296
297 {}
#[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/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(318u32),
::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))]
319 pub(crate) fn lower_bounds<'a, I: IntoIterator<Item = &'a hir::GenericBound<'a>>>(
320 &self,
321 param_ty: Ty<'tcx>,
322 hir_bounds: I,
323 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
324 bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
325 predicate_filter: PredicateFilter,
326 overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
327 ) {
328 for hir_bound in hir_bounds {
329 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
332 if let Some(trait_ref) = hir_bound.trait_ref()
333 && let Some(trait_did) = trait_ref.trait_def_id()
334 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
335 {
336 } else {
338 continue;
339 }
340 }
341
342 match hir_bound {
343 hir::GenericBound::Trait(poly_trait_ref) => {
344 let _ = self.lower_poly_trait_ref(
345 poly_trait_ref,
346 param_ty,
347 bounds,
348 predicate_filter,
349 overlapping_assoc_constraints,
350 );
351 }
352 hir::GenericBound::Outlives(lifetime) => {
353 if matches!(
355 predicate_filter,
356 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
357 ) {
358 continue;
359 }
360
361 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
362 let bound = ty::Binder::bind_with_vars(
363 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(param_ty, region)),
364 bound_vars,
365 );
366 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
367 }
368 hir::GenericBound::Use(..) => {
369 }
371 }
372 }
373 }
374
375 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("lower_assoc_item_constraint",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(383u32),
::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/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:486",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(486u32),
::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 { ; }
};
let kind =
if let ty::AssocTag::Const = assoc_tag {
ty::AliasTermKind::ProjectionConst {
def_id: assoc_item.def_id,
}
} else {
ty::AliasTermKind::ProjectionTy {
def_id: assoc_item.def_id,
}
};
ty::AliasTerm::new_from_args(tcx, kind, alias_args)
})
};
match constraint.kind {
hir::AssocItemConstraintKind::Equality { .. } if
let ty::AssocTag::Fn = assoc_tag => {
return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationEqualityBound {
span: constraint.span,
}));
}
hir::AssocItemConstraintKind::Equality { term } => {
let term =
match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => {
let ty =
projection_term.map_bound(|alias|
alias.expect_ct().type_of(tcx).skip_norm_wip());
let ty =
check_assoc_const_binding_type(self, constraint.ident, ty,
constraint.hir_id);
self.lower_const_arg(ct, ty).into()
}
};
let late_bound_in_projection_ty =
tcx.collect_constrained_late_bound_regions(projection_term);
let late_bound_in_term =
tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:533",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(533u32),
::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/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs:534",
"rustc_hir_analysis::hir_ty_lowering::bounds",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs"),
::tracing_core::__macro_support::Option::Some(534u32),
::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().gca_const_items() {
if tcx.features().gca_min_const_items() {
let err =
self.dcx().struct_span_err(constraint.span,
"use of trait associated const not defined as `#[rustc_always_gca]`");
return Err(err.emit_err());
} 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))]
384 pub(super) fn lower_assoc_item_constraint(
385 &self,
386 hir_ref_id: hir::HirId,
387 trait_ref: ty::PolyTraitRef<'tcx>,
388 constraint: &hir::AssocItemConstraint<'_>,
389 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
390 duplicates: Option<&mut FxIndexMap<DefId, Span>>,
391 path_span: Span,
392 predicate_filter: PredicateFilter,
393 ) -> Result<(), ErrorGuaranteed> {
394 let tcx = self.tcx();
395
396 let assoc_tag = if constraint.gen_args.parenthesized
397 == hir::GenericArgsParentheses::ReturnTypeNotation
398 {
399 ty::AssocTag::Fn
400 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
401 constraint.kind
402 {
403 ty::AssocTag::Const
404 } else {
405 ty::AssocTag::Type
406 };
407
408 let candidate = if self.probe_trait_that_defines_assoc_item(
417 trait_ref.def_id(),
418 assoc_tag,
419 constraint.ident,
420 ) {
421 trait_ref
423 } else {
424 self.probe_single_bound_for_assoc_item(
427 || traits::supertraits(tcx, trait_ref),
428 AssocItemQSelf::Trait(trait_ref.def_id()),
429 assoc_tag,
430 constraint.ident,
431 path_span,
432 Some(constraint),
433 )?
434 };
435
436 let assoc_item = self
437 .probe_assoc_item(
438 constraint.ident,
439 assoc_tag,
440 hir_ref_id,
441 constraint.span,
442 candidate.def_id(),
443 )
444 .expect("failed to find associated item");
445
446 if let Some(duplicates) = duplicates {
447 duplicates
448 .entry(assoc_item.def_id)
449 .and_modify(|prev_span| {
450 self.dcx().emit_err(diagnostics::ValueOfAssociatedStructAlreadySpecified {
451 span: constraint.span,
452 prev_span: *prev_span,
453 item_name: constraint.ident,
454 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
455 });
456 })
457 .or_insert(constraint.span);
458 }
459
460 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
461 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
462 ty::Binder::bind_with_vars(
463 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
464 bound_vars,
465 )
466 } else {
467 candidate.map_bound(|trait_ref| {
471 let item_segment = hir::PathSegment {
472 ident: constraint.ident,
473 hir_id: constraint.hir_id,
474 res: Res::Err,
475 args: Some(constraint.gen_args),
476 infer_args: false,
477 delegation_child_segment: false,
478 };
479
480 let alias_args = self.lower_generic_args_of_assoc_item(
481 path_span,
482 assoc_item.def_id,
483 &item_segment,
484 trait_ref.args,
485 );
486 debug!(?alias_args);
487
488 let kind = if let ty::AssocTag::Const = assoc_tag {
489 ty::AliasTermKind::ProjectionConst { def_id: assoc_item.def_id }
490 } else {
491 ty::AliasTermKind::ProjectionTy { def_id: assoc_item.def_id }
492 };
493 ty::AliasTerm::new_from_args(tcx, kind, alias_args)
494 })
495 };
496
497 match constraint.kind {
498 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
499 return Err(self.dcx().emit_err(
500 crate::diagnostics::ReturnTypeNotationEqualityBound { span: constraint.span },
501 ));
502 }
503 hir::AssocItemConstraintKind::Equality { term } => {
506 let term = match term {
507 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
508 hir::Term::Const(ct) => {
509 let ty = projection_term
510 .map_bound(|alias| alias.expect_ct().type_of(tcx).skip_norm_wip());
511 let ty = check_assoc_const_binding_type(
512 self,
513 constraint.ident,
514 ty,
515 constraint.hir_id,
516 );
517
518 self.lower_const_arg(ct, ty).into()
519 }
520 };
521
522 let late_bound_in_projection_ty =
530 tcx.collect_constrained_late_bound_regions(projection_term);
531 let late_bound_in_term =
532 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
533 debug!(?late_bound_in_projection_ty);
534 debug!(?late_bound_in_term);
535
536 self.validate_late_bound_regions(
541 late_bound_in_projection_ty,
542 late_bound_in_term,
543 |br_name| {
544 struct_span_code_err!(
545 self.dcx(),
546 constraint.span,
547 E0582,
548 "binding for associated type `{}` references {}, \
549 which does not appear in the trait input types",
550 constraint.ident,
551 br_name
552 )
553 },
554 );
555
556 match predicate_filter {
557 PredicateFilter::All
558 | PredicateFilter::SelfOnly
559 | PredicateFilter::SelfAndAssociatedTypeBounds => {
560 let bound = projection_term.map_bound(|projection_term| {
561 ty::ClauseKind::Projection(ty::ProjectionClause {
562 projection_term,
563 term,
564 })
565 });
566
567 if let ty::AssocTag::Const = assoc_tag
568 && !self.tcx().is_direct_const(assoc_item.def_id)
569 && !tcx.features().gca_const_items()
570 {
571 if tcx.features().gca_min_const_items() {
572 let err = self.dcx().struct_span_err(
573 constraint.span,
574 "use of trait associated const not defined as `#[rustc_always_gca]`",
575 );
576 return Err(err.emit_err());
577 } else {
578 let err = self.dcx().span_delayed_bug(
579 constraint.span,
580 "use of trait associated const defined as `#[rustc_always_gca]`",
581 );
582 return Err(err);
583 }
584 }
585
586 bounds.push((bound.upcast(tcx), constraint.span));
587 }
588 PredicateFilter::SelfTraitThatDefines(_) => {}
590 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
592 }
593 }
594 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
597 match predicate_filter {
598 PredicateFilter::All
599 | PredicateFilter::SelfAndAssociatedTypeBounds
600 | PredicateFilter::ConstIfConst => {
601 let projection_ty = projection_term
602 .map_bound(|projection_term| projection_term.expect_ty());
603 let param_ty =
606 Ty::new_alias(tcx, ty::IsRigid::No, projection_ty.skip_binder());
607 self.lower_bounds(
608 param_ty,
609 hir_bounds,
610 bounds,
611 projection_ty.bound_vars(),
612 predicate_filter,
613 OverlappingAsssocItemConstraints::Allowed,
614 );
615 }
616 PredicateFilter::SelfOnly
617 | PredicateFilter::SelfTraitThatDefines(_)
618 | PredicateFilter::SelfConstIfConst => {}
619 }
620 }
621 }
622 Ok(())
623 }
624
625 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
628 let hir::TyKind::Path(qpath) = hir_ty.kind else {
629 return self.lower_ty(hir_ty);
630 };
631
632 let tcx = self.tcx();
633 match qpath {
634 hir::QPath::Resolved(opt_self_ty, path)
635 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
636 && item_segment.args.is_some_and(|args| {
637 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(
638 args.parenthesized,
639 hir::GenericArgsParentheses::ReturnTypeNotation
640 )
641 }) =>
642 {
643 let _ =
645 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
646
647 let item_def_id = match path.res {
648 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
649 Res::Err => {
650 return Ty::new_error_with_message(
651 tcx,
652 hir_ty.span,
653 "failed to resolve RTN",
654 );
655 }
656 _ => ::rustc_span::macros::bug_impl(None,
format_args!("only expected method resolution for fully qualified RTN"),
Location::caller())bug!("only expected method resolution for fully qualified RTN"),
657 };
658 let trait_def_id = tcx.parent(item_def_id);
659
660 let Some(self_ty) = opt_self_ty else {
662 let guar = self.report_missing_self_ty_for_resolved_path(
663 trait_def_id,
664 hir_ty.span,
665 item_segment,
666 ty::AssocTag::Type,
667 );
668 return Ty::new_error(tcx, guar);
669 };
670 let self_ty = self.lower_ty(self_ty);
671
672 let trait_ref = self.lower_mono_trait_ref(
673 hir_ty.span,
674 trait_def_id,
675 self_ty,
676 trait_segment,
677 false,
678 );
679
680 let candidate =
693 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
694
695 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
696 Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
697 Err(guar) => Ty::new_error(tcx, guar),
698 }
699 }
700 hir::QPath::TypeRelative(hir_self_ty, segment)
701 if segment.args.is_some_and(|args| {
702 #[allow(non_exhaustive_omitted_patterns)] match args.parenthesized {
hir::GenericArgsParentheses::ReturnTypeNotation => true,
_ => false,
}matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
703 }) =>
704 {
705 let self_ty = self.lower_ty(hir_self_ty);
706 let (item_def_id, bound) = match self.resolve_type_relative_path(
707 self_ty,
708 hir_self_ty,
709 ty::AssocTag::Fn,
710 segment,
711 hir_ty.hir_id,
712 hir_ty.span,
713 None,
714 ) {
715 Ok(result) => result,
716 Err(guar) => return Ty::new_error(tcx, guar),
717 };
718
719 if bound.has_bound_vars() {
726 return Ty::new_error(
727 tcx,
728 self.dcx().emit_err(
729 diagnostics::AssociatedItemTraitUninferredGenericParams {
730 span: hir_ty.span,
731 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
732 bound: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
tcx.anonymize_bound_vars(bound).skip_binder()))
})format!(
733 "{}::",
734 tcx.anonymize_bound_vars(bound).skip_binder()
735 ),
736 mpart_sugg: None,
737 what: tcx.def_descr(item_def_id),
738 },
739 ),
740 );
741 }
742
743 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
744 Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty),
745 Err(guar) => Ty::new_error(tcx, guar),
746 }
747 }
748 _ => self.lower_ty(hir_ty),
749 }
750 }
751
752 fn lower_return_type_notation_ty(
757 &self,
758 candidate: ty::PolyTraitRef<'tcx>,
759 item_def_id: DefId,
760 path_span: Span,
761 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
762 let tcx = self.tcx();
763 let mut emitted_bad_param_err = None;
764 let mut num_bound_vars = candidate.bound_vars().len();
767 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
768 let arg = match param.kind {
769 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
770 tcx,
771 ty::INNERMOST,
772 ty::BoundRegion {
773 var: ty::BoundVar::from_usize(num_bound_vars),
774 kind: ty::BoundRegionKind::Named(param.def_id),
775 },
776 )
777 .into(),
778 ty::GenericParamDefKind::Type { .. } => {
779 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
780 self.dcx().emit_err(
781 crate::diagnostics::ReturnTypeNotationIllegalParam::Type {
782 span: path_span,
783 param_span: tcx.def_span(param.def_id),
784 },
785 )
786 });
787 Ty::new_error(tcx, guar).into()
788 }
789 ty::GenericParamDefKind::Const { .. } => {
790 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
791 self.dcx().emit_err(
792 crate::diagnostics::ReturnTypeNotationIllegalParam::Const {
793 span: path_span,
794 param_span: tcx.def_span(param.def_id),
795 },
796 )
797 });
798 ty::Const::new_error(tcx, guar).into()
799 }
800 };
801 num_bound_vars += 1;
802 arg
803 });
804
805 let output = tcx.fn_sig(item_def_id).skip_binder().output();
808 let output = if let ty::Alias(_, alias_ty) = *output.skip_binder().kind()
809 && let ty::AliasTy { kind: ty::Projection { def_id: projection_def_id }, .. } = alias_ty
810 && tcx.is_impl_trait_in_trait(projection_def_id)
811 {
812 alias_ty
813 } else {
814 return Err(self.dcx().emit_err(crate::diagnostics::ReturnTypeNotationOnNonRpitit {
815 span: path_span,
816 ty: tcx.liberate_late_bound_regions(item_def_id, output),
817 fn_span: tcx.hir_span_if_local(item_def_id),
818 note: (),
819 }));
820 };
821
822 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
827 Ok(ty::EarlyBinder::bind(tcx, shifted_output).instantiate(tcx, args).skip_norm_wip())
828 }
829}
830
831pub(crate) fn check_assoc_const_binding_type<'tcx>(
843 cx: &dyn HirTyLowerer<'tcx>,
844 assoc_const: Ident,
845 ty: ty::Binder<'tcx, Ty<'tcx>>,
846 hir_id: hir::HirId,
847) -> Ty<'tcx> {
848 let ty = ty.skip_binder();
855 if !ty.has_param() && !ty.has_escaping_bound_vars() {
856 return ty;
857 }
858
859 let mut collector = GenericParamAndBoundVarCollector {
860 cx,
861 params: Default::default(),
862 vars: Default::default(),
863 depth: ty::INNERMOST,
864 };
865 let mut guar = ty.visit_with(&mut collector).break_value();
866
867 let tcx = cx.tcx();
868 let ty_note = ty
869 .make_suggestable(tcx, false, None)
870 .map(|ty| crate::diagnostics::TyOfAssocConstBindingNote { assoc_const, ty });
871
872 let enclosing_item_owner_id = tcx
873 .hir_parent_owner_iter(hir_id)
874 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
875 .unwrap();
876 let generics = tcx.generics_of(enclosing_item_owner_id);
877 for index in collector.params {
878 let param = generics.param_at(index as _, tcx);
879 let is_self_param = param.name == kw::SelfUpper;
880 guar.get_or_insert(cx.dcx().emit_err(crate::diagnostics::ParamInTyOfAssocConstBinding {
881 span: assoc_const.span,
882 assoc_const,
883 param_name: param.name,
884 param_def_kind: tcx.def_descr(param.def_id),
885 param_category: if is_self_param {
886 "self"
887 } else if param.kind.is_synthetic() {
888 "synthetic"
889 } else {
890 "normal"
891 },
892 param_defined_here_label:
893 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
894 ty_note,
895 }));
896 }
897 for var_def_id in collector.vars {
898 guar.get_or_insert(cx.dcx().emit_err(
899 crate::diagnostics::EscapingBoundVarInTyOfAssocConstBinding {
900 span: assoc_const.span,
901 assoc_const,
902 var_name: cx.tcx().item_name(var_def_id),
903 var_def_kind: tcx.def_descr(var_def_id),
904 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
905 ty_note,
906 },
907 ));
908 }
909
910 let guar = guar.unwrap_or_else(|| ::rustc_span::macros::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"));
911 Ty::new_error(tcx, guar)
912}
913
914struct GenericParamAndBoundVarCollector<'a, 'tcx> {
915 cx: &'a dyn HirTyLowerer<'tcx>,
916 params: FxIndexSet<u32>,
917 vars: FxIndexSet<DefId>,
918 depth: ty::DebruijnIndex,
919}
920
921impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
922 type Result = ControlFlow<ErrorGuaranteed>;
923
924 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
925 &mut self,
926 binder: &ty::Binder<'tcx, T>,
927 ) -> Self::Result {
928 self.depth.shift_in(1);
929 let result = binder.super_visit_with(self);
930 self.depth.shift_out(1);
931 result
932 }
933
934 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
935 match ty.kind() {
936 ty::Param(param) => {
937 self.params.insert(param.index);
938 }
939 ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
940 self.vars.insert(match bt.kind {
941 ty::BoundTyKind::Param(def_id) => def_id,
942 ty::BoundTyKind::Anon => {
943 let reported = self
944 .cx
945 .dcx()
946 .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));
947 return ControlFlow::Break(reported);
948 }
949 });
950 }
951 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
952 _ => {}
953 }
954 ControlFlow::Continue(())
955 }
956
957 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
958 match re.kind() {
959 ty::ReEarlyParam(param) => {
960 self.params.insert(param.index);
961 }
962 ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
963 self.vars.insert(match br.kind {
964 ty::BoundRegionKind::Named(def_id) => def_id,
965 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
966 let guar = self
967 .cx
968 .dcx()
969 .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));
970 return ControlFlow::Break(guar);
971 }
972 ty::BoundRegionKind::NamedForPrinting(_) => {
973 ::rustc_span::macros::bug_impl(None,
format_args!("only used for pretty printing"), Location::caller())bug!("only used for pretty printing")
974 }
975 });
976 }
977 _ => {}
978 }
979 ControlFlow::Continue(())
980 }
981
982 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
983 match ct.kind() {
984 ty::ConstKind::Param(param) => {
985 self.params.insert(param.index);
986 }
987 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
988 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
989 return ControlFlow::Break(guar);
990 }
991 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
992 _ => {}
993 }
994 ControlFlow::Continue(())
995 }
996}