1use std::assert_matches::assert_matches;
2use std::ops::ControlFlow;
3
4use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
5use rustc_errors::codes::*;
6use rustc_errors::struct_span_code_err;
7use rustc_hir as hir;
8use rustc_hir::PolyTraitRef;
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
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 super::errors::GenericsArgsErrExtend;
22use crate::errors;
23use crate::hir_ty_lowering::{
24 AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
25};
26
27#[derive(Debug, 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(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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'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 Some((self_ty, where_clause)) = self_ty_where_predicates {
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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
92) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
93 let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
94 search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
95 if 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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
105 target_did: DefId,
106) -> CollectedBound {
107 let mut collect_into = CollectedBound::default();
108 search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
109 if !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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'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, self_ty_where_predicates, sized_did);
130
131 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
132 let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, 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, self_ty_where_predicates, 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_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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
169 trait_did: Option<LocalDefId>,
170 span: Span,
171 ) {
172 let tcx = self.tcx();
173
174 if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
176 return;
177 }
178
179 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
180 let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
181
182 if let Some(trait_did) = 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 } else {
195 let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
208 self.check_and_report_invalid_relaxed_bounds(bounds);
209 }
210
211 let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, 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 if trait_did.is_some() {
222 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
225 } else {
226 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
229 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
230 }
231 }
232 }
233
234 pub(crate) fn add_default_super_traits(
236 &self,
237 trait_def_id: LocalDefId,
238 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
239 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
240 hir_generics: &'tcx hir::Generics<'tcx>,
241 span: Span,
242 ) {
243 assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);
244
245 if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
248 return;
249 }
250
251 self.add_default_traits(
252 bounds,
253 self.tcx().types.self_param,
254 hir_bounds,
255 Some((trait_def_id, hir_generics.predicates)),
256 span,
257 );
258 }
259
260 pub(crate) fn add_default_traits(
261 &self,
262 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
263 self_ty: Ty<'tcx>,
264 hir_bounds: &[hir::GenericBound<'tcx>],
265 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
266 span: Span,
267 ) {
268 self.tcx().default_traits().iter().for_each(|default_trait| {
269 self.add_default_trait(
270 *default_trait,
271 bounds,
272 self_ty,
273 hir_bounds,
274 self_ty_where_predicates,
275 span,
276 );
277 });
278 }
279
280 pub(crate) fn add_default_trait(
284 &self,
285 trait_: hir::LangItem,
286 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
287 self_ty: Ty<'tcx>,
288 hir_bounds: &[hir::GenericBound<'tcx>],
289 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
290 span: Span,
291 ) {
292 let tcx = self.tcx();
293 let trait_id = tcx.lang_items().get(trait_);
294 if let Some(trait_id) = trait_id
295 && self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
296 {
297 add_trait_bound(tcx, bounds, self_ty, trait_id, span);
298 }
299 }
300
301 fn should_add_default_traits<'a>(
303 &self,
304 trait_def_id: DefId,
305 hir_bounds: &'a [hir::GenericBound<'tcx>],
306 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
307 ) -> bool {
308 let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
309 !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
310 }
311
312 #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
334 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
335 &self,
336 param_ty: Ty<'tcx>,
337 hir_bounds: I,
338 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
339 bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
340 predicate_filter: PredicateFilter,
341 ) where
342 'tcx: 'hir,
343 {
344 for hir_bound in hir_bounds {
345 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
348 if let Some(trait_ref) = hir_bound.trait_ref()
349 && let Some(trait_did) = trait_ref.trait_def_id()
350 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
351 {
352 } else {
354 continue;
355 }
356 }
357
358 match hir_bound {
359 hir::GenericBound::Trait(poly_trait_ref) => {
360 let _ = self.lower_poly_trait_ref(
361 poly_trait_ref,
362 param_ty,
363 bounds,
364 predicate_filter,
365 );
366 }
367 hir::GenericBound::Outlives(lifetime) => {
368 if matches!(
370 predicate_filter,
371 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
372 ) {
373 continue;
374 }
375
376 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
377 let bound = ty::Binder::bind_with_vars(
378 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
379 bound_vars,
380 );
381 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
382 }
383 hir::GenericBound::Use(..) => {
384 }
386 }
387 }
388 }
389
390 #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
399 pub(super) fn lower_assoc_item_constraint(
400 &self,
401 hir_ref_id: hir::HirId,
402 trait_ref: ty::PolyTraitRef<'tcx>,
403 constraint: &hir::AssocItemConstraint<'tcx>,
404 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
405 duplicates: &mut FxIndexMap<DefId, Span>,
406 path_span: Span,
407 predicate_filter: PredicateFilter,
408 ) -> Result<(), ErrorGuaranteed> {
409 let tcx = self.tcx();
410
411 let assoc_tag = if constraint.gen_args.parenthesized
412 == hir::GenericArgsParentheses::ReturnTypeNotation
413 {
414 ty::AssocTag::Fn
415 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
416 constraint.kind
417 {
418 ty::AssocTag::Const
419 } else {
420 ty::AssocTag::Type
421 };
422
423 let candidate = if self.probe_trait_that_defines_assoc_item(
432 trait_ref.def_id(),
433 assoc_tag,
434 constraint.ident,
435 ) {
436 trait_ref
438 } else {
439 self.probe_single_bound_for_assoc_item(
442 || traits::supertraits(tcx, trait_ref),
443 AssocItemQSelf::Trait(trait_ref.def_id()),
444 assoc_tag,
445 constraint.ident,
446 path_span,
447 Some(constraint),
448 )?
449 };
450
451 let assoc_item = self
452 .probe_assoc_item(
453 constraint.ident,
454 assoc_tag,
455 hir_ref_id,
456 constraint.span,
457 candidate.def_id(),
458 )
459 .expect("failed to find associated item");
460
461 duplicates
462 .entry(assoc_item.def_id)
463 .and_modify(|prev_span| {
464 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
465 span: constraint.span,
466 prev_span: *prev_span,
467 item_name: constraint.ident,
468 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
469 });
470 })
471 .or_insert(constraint.span);
472
473 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
474 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
475 ty::Binder::bind_with_vars(
476 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
477 bound_vars,
478 )
479 } else {
480 let alias_term = candidate.map_bound(|trait_ref| {
484 let item_segment = hir::PathSegment {
485 ident: constraint.ident,
486 hir_id: constraint.hir_id,
487 res: Res::Err,
488 args: Some(constraint.gen_args),
489 infer_args: false,
490 };
491
492 let alias_args = self.lower_generic_args_of_assoc_item(
493 path_span,
494 assoc_item.def_id,
495 &item_segment,
496 trait_ref.args,
497 );
498 debug!(?alias_args);
499
500 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
501 });
502
503 if let Some(const_arg) = constraint.ct()
505 && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
506 {
507 let ty = alias_term
508 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
509 let ty =
510 check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
511 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
512 }
513
514 alias_term
515 };
516
517 match constraint.kind {
518 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
519 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
520 span: constraint.span,
521 }));
522 }
523 hir::AssocItemConstraintKind::Equality { term } => {
526 let term = match term {
527 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
528 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
529 };
530
531 let late_bound_in_projection_ty =
539 tcx.collect_constrained_late_bound_regions(projection_term);
540 let late_bound_in_term =
541 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
542 debug!(?late_bound_in_projection_ty);
543 debug!(?late_bound_in_term);
544
545 self.validate_late_bound_regions(
551 late_bound_in_projection_ty,
552 late_bound_in_term,
553 |br_name| {
554 struct_span_code_err!(
555 self.dcx(),
556 constraint.span,
557 E0582,
558 "binding for associated type `{}` references {}, \
559 which does not appear in the trait input types",
560 constraint.ident,
561 br_name
562 )
563 },
564 );
565
566 match predicate_filter {
567 PredicateFilter::All
568 | PredicateFilter::SelfOnly
569 | PredicateFilter::SelfAndAssociatedTypeBounds => {
570 let bound = projection_term.map_bound(|projection_term| {
571 ty::ClauseKind::Projection(ty::ProjectionPredicate {
572 projection_term,
573 term,
574 })
575 });
576 bounds.push((bound.upcast(tcx), constraint.span));
577 }
578 PredicateFilter::SelfTraitThatDefines(_) => {}
580 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
582 }
583 }
584 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
587 match predicate_filter {
588 PredicateFilter::All
589 | PredicateFilter::SelfAndAssociatedTypeBounds
590 | PredicateFilter::ConstIfConst => {
591 let projection_ty = projection_term
592 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
593 let param_ty =
596 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
597 self.lower_bounds(
598 param_ty,
599 hir_bounds,
600 bounds,
601 projection_ty.bound_vars(),
602 predicate_filter,
603 );
604 }
605 PredicateFilter::SelfOnly
606 | PredicateFilter::SelfTraitThatDefines(_)
607 | PredicateFilter::SelfConstIfConst => {}
608 }
609 }
610 }
611 Ok(())
612 }
613
614 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
617 let hir::TyKind::Path(qpath) = hir_ty.kind else {
618 return self.lower_ty(hir_ty);
619 };
620
621 let tcx = self.tcx();
622 match qpath {
623 hir::QPath::Resolved(opt_self_ty, path)
624 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
625 && item_segment.args.is_some_and(|args| {
626 matches!(
627 args.parenthesized,
628 hir::GenericArgsParentheses::ReturnTypeNotation
629 )
630 }) =>
631 {
632 let _ =
634 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
635
636 let item_def_id = match path.res {
637 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
638 Res::Err => {
639 return Ty::new_error_with_message(
640 tcx,
641 hir_ty.span,
642 "failed to resolve RTN",
643 );
644 }
645 _ => bug!("only expected method resolution for fully qualified RTN"),
646 };
647 let trait_def_id = tcx.parent(item_def_id);
648
649 let Some(self_ty) = opt_self_ty else {
651 let guar = self.report_missing_self_ty_for_resolved_path(
652 trait_def_id,
653 hir_ty.span,
654 item_segment,
655 ty::AssocTag::Type,
656 );
657 return Ty::new_error(tcx, guar);
658 };
659 let self_ty = self.lower_ty(self_ty);
660
661 let trait_ref = self.lower_mono_trait_ref(
662 hir_ty.span,
663 trait_def_id,
664 self_ty,
665 trait_segment,
666 false,
667 );
668
669 let candidate =
682 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
683
684 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
685 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
686 Err(guar) => Ty::new_error(tcx, guar),
687 }
688 }
689 hir::QPath::TypeRelative(hir_self_ty, segment)
690 if segment.args.is_some_and(|args| {
691 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
692 }) =>
693 {
694 let self_ty = self.lower_ty(hir_self_ty);
695 let (item_def_id, bound) = match self.resolve_type_relative_path(
696 self_ty,
697 hir_self_ty,
698 ty::AssocTag::Fn,
699 segment,
700 hir_ty.hir_id,
701 hir_ty.span,
702 None,
703 ) {
704 Ok(result) => result,
705 Err(guar) => return Ty::new_error(tcx, guar),
706 };
707
708 if bound.has_bound_vars() {
715 return Ty::new_error(
716 tcx,
717 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
718 span: hir_ty.span,
719 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
720 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
721 mpart_sugg: None,
722 what: tcx.def_descr(item_def_id),
723 }),
724 );
725 }
726
727 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
728 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
729 Err(guar) => Ty::new_error(tcx, guar),
730 }
731 }
732 _ => self.lower_ty(hir_ty),
733 }
734 }
735
736 fn lower_return_type_notation_ty(
741 &self,
742 candidate: ty::PolyTraitRef<'tcx>,
743 item_def_id: DefId,
744 path_span: Span,
745 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
746 let tcx = self.tcx();
747 let mut emitted_bad_param_err = None;
748 let mut num_bound_vars = candidate.bound_vars().len();
751 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
752 let arg = match param.kind {
753 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
754 tcx,
755 ty::INNERMOST,
756 ty::BoundRegion {
757 var: ty::BoundVar::from_usize(num_bound_vars),
758 kind: ty::BoundRegionKind::Named(param.def_id),
759 },
760 )
761 .into(),
762 ty::GenericParamDefKind::Type { .. } => {
763 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
764 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
765 span: path_span,
766 param_span: tcx.def_span(param.def_id),
767 })
768 });
769 Ty::new_error(tcx, guar).into()
770 }
771 ty::GenericParamDefKind::Const { .. } => {
772 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
773 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
774 span: path_span,
775 param_span: tcx.def_span(param.def_id),
776 })
777 });
778 ty::Const::new_error(tcx, guar).into()
779 }
780 };
781 num_bound_vars += 1;
782 arg
783 });
784
785 let output = tcx.fn_sig(item_def_id).skip_binder().output();
788 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
789 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
790 {
791 alias_ty
792 } else {
793 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
794 span: path_span,
795 ty: tcx.liberate_late_bound_regions(item_def_id, output),
796 fn_span: tcx.hir_span_if_local(item_def_id),
797 note: (),
798 }));
799 };
800
801 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
806 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
807 }
808}
809
810fn check_assoc_const_binding_type<'tcx>(
822 cx: &dyn HirTyLowerer<'tcx>,
823 assoc_const: Ident,
824 ty: ty::Binder<'tcx, Ty<'tcx>>,
825 hir_id: hir::HirId,
826) -> Ty<'tcx> {
827 let ty = ty.skip_binder();
834 if !ty.has_param() && !ty.has_escaping_bound_vars() {
835 return ty;
836 }
837
838 let mut collector = GenericParamAndBoundVarCollector {
839 cx,
840 params: Default::default(),
841 vars: Default::default(),
842 depth: ty::INNERMOST,
843 };
844 let mut guar = ty.visit_with(&mut collector).break_value();
845
846 let tcx = cx.tcx();
847 let ty_note = ty
848 .make_suggestable(tcx, false, None)
849 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
850
851 let enclosing_item_owner_id = tcx
852 .hir_parent_owner_iter(hir_id)
853 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
854 .unwrap();
855 let generics = tcx.generics_of(enclosing_item_owner_id);
856 for index in collector.params {
857 let param = generics.param_at(index as _, tcx);
858 let is_self_param = param.name == kw::SelfUpper;
859 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
860 span: assoc_const.span,
861 assoc_const,
862 param_name: param.name,
863 param_def_kind: tcx.def_descr(param.def_id),
864 param_category: if is_self_param {
865 "self"
866 } else if param.kind.is_synthetic() {
867 "synthetic"
868 } else {
869 "normal"
870 },
871 param_defined_here_label:
872 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
873 ty_note,
874 }));
875 }
876 for var_def_id in collector.vars {
877 guar.get_or_insert(cx.dcx().emit_err(
878 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
879 span: assoc_const.span,
880 assoc_const,
881 var_name: cx.tcx().item_name(var_def_id),
882 var_def_kind: tcx.def_descr(var_def_id),
883 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
884 ty_note,
885 },
886 ));
887 }
888
889 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
890 Ty::new_error(tcx, guar)
891}
892
893struct GenericParamAndBoundVarCollector<'a, 'tcx> {
894 cx: &'a dyn HirTyLowerer<'tcx>,
895 params: FxIndexSet<u32>,
896 vars: FxIndexSet<DefId>,
897 depth: ty::DebruijnIndex,
898}
899
900impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
901 type Result = ControlFlow<ErrorGuaranteed>;
902
903 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
904 &mut self,
905 binder: &ty::Binder<'tcx, T>,
906 ) -> Self::Result {
907 self.depth.shift_in(1);
908 let result = binder.super_visit_with(self);
909 self.depth.shift_out(1);
910 result
911 }
912
913 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
914 match ty.kind() {
915 ty::Param(param) => {
916 self.params.insert(param.index);
917 }
918 ty::Bound(db, bt) if *db >= self.depth => {
919 self.vars.insert(match bt.kind {
920 ty::BoundTyKind::Param(def_id) => def_id,
921 ty::BoundTyKind::Anon => {
922 let reported = self
923 .cx
924 .dcx()
925 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
926 return ControlFlow::Break(reported);
927 }
928 });
929 }
930 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
931 _ => {}
932 }
933 ControlFlow::Continue(())
934 }
935
936 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
937 match re.kind() {
938 ty::ReEarlyParam(param) => {
939 self.params.insert(param.index);
940 }
941 ty::ReBound(db, br) if db >= self.depth => {
942 self.vars.insert(match br.kind {
943 ty::BoundRegionKind::Named(def_id) => def_id,
944 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
945 let guar = self
946 .cx
947 .dcx()
948 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
949 return ControlFlow::Break(guar);
950 }
951 ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
952 });
953 }
954 _ => {}
955 }
956 ControlFlow::Continue(())
957 }
958
959 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
960 match ct.kind() {
961 ty::ConstKind::Param(param) => {
962 self.params.insert(param.index);
963 }
964 ty::ConstKind::Bound(db, _) if db >= self.depth => {
965 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
966 return ControlFlow::Break(guar);
967 }
968 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
969 _ => {}
970 }
971 ControlFlow::Continue(())
972 }
973}