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, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
24 OverlappingAsssocItemConstraints, 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 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 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 !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, 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 #[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>,
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 #[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 let alias_term = 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 if let Some(const_arg) = constraint.ct()
535 && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
536 {
537 let ty = alias_term
538 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
539 let ty =
540 check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
541 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
542 }
543
544 alias_term
545 };
546
547 match constraint.kind {
548 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
549 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
550 span: constraint.span,
551 }));
552 }
553 hir::AssocItemConstraintKind::Equality { term } => {
556 let term = match term {
557 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
558 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
559 };
560
561 let late_bound_in_projection_ty =
569 tcx.collect_constrained_late_bound_regions(projection_term);
570 let late_bound_in_term =
571 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
572 debug!(?late_bound_in_projection_ty);
573 debug!(?late_bound_in_term);
574
575 self.validate_late_bound_regions(
581 late_bound_in_projection_ty,
582 late_bound_in_term,
583 |br_name| {
584 struct_span_code_err!(
585 self.dcx(),
586 constraint.span,
587 E0582,
588 "binding for associated type `{}` references {}, \
589 which does not appear in the trait input types",
590 constraint.ident,
591 br_name
592 )
593 },
594 );
595
596 match predicate_filter {
597 PredicateFilter::All
598 | PredicateFilter::SelfOnly
599 | PredicateFilter::SelfAndAssociatedTypeBounds => {
600 let bound = projection_term.map_bound(|projection_term| {
601 ty::ClauseKind::Projection(ty::ProjectionPredicate {
602 projection_term,
603 term,
604 })
605 });
606
607 if let ty::AssocTag::Const = assoc_tag
608 && !find_attr!(
609 self.tcx().get_all_attrs(assoc_item.def_id),
610 AttributeKind::TypeConst(_)
611 )
612 {
613 if tcx.features().min_generic_const_args()
614 || tcx.features().associated_const_equality()
615 {
616 let mut err = self.dcx().struct_span_err(
617 constraint.span,
618 "use of trait associated const without `#[type_const]`",
619 );
620 err.note("the declaration in the trait must be marked with `#[type_const]`");
621 return Err(err.emit());
622 } else {
623 let err = self.dcx().span_delayed_bug(
624 constraint.span,
625 "use of trait associated const without `#[type_const]`",
626 );
627 return Err(err);
628 }
629 } else {
630 bounds.push((bound.upcast(tcx), constraint.span));
631 }
632 }
633 PredicateFilter::SelfTraitThatDefines(_) => {}
635 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
637 }
638 }
639 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
642 match predicate_filter {
643 PredicateFilter::All
644 | PredicateFilter::SelfAndAssociatedTypeBounds
645 | PredicateFilter::ConstIfConst => {
646 let projection_ty = projection_term
647 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
648 let param_ty =
651 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
652 self.lower_bounds(
653 param_ty,
654 hir_bounds,
655 bounds,
656 projection_ty.bound_vars(),
657 predicate_filter,
658 OverlappingAsssocItemConstraints::Allowed,
659 );
660 }
661 PredicateFilter::SelfOnly
662 | PredicateFilter::SelfTraitThatDefines(_)
663 | PredicateFilter::SelfConstIfConst => {}
664 }
665 }
666 }
667 Ok(())
668 }
669
670 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
673 let hir::TyKind::Path(qpath) = hir_ty.kind else {
674 return self.lower_ty(hir_ty);
675 };
676
677 let tcx = self.tcx();
678 match qpath {
679 hir::QPath::Resolved(opt_self_ty, path)
680 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
681 && item_segment.args.is_some_and(|args| {
682 matches!(
683 args.parenthesized,
684 hir::GenericArgsParentheses::ReturnTypeNotation
685 )
686 }) =>
687 {
688 let _ =
690 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
691
692 let item_def_id = match path.res {
693 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
694 Res::Err => {
695 return Ty::new_error_with_message(
696 tcx,
697 hir_ty.span,
698 "failed to resolve RTN",
699 );
700 }
701 _ => bug!("only expected method resolution for fully qualified RTN"),
702 };
703 let trait_def_id = tcx.parent(item_def_id);
704
705 let Some(self_ty) = opt_self_ty else {
707 let guar = self.report_missing_self_ty_for_resolved_path(
708 trait_def_id,
709 hir_ty.span,
710 item_segment,
711 ty::AssocTag::Type,
712 );
713 return Ty::new_error(tcx, guar);
714 };
715 let self_ty = self.lower_ty(self_ty);
716
717 let trait_ref = self.lower_mono_trait_ref(
718 hir_ty.span,
719 trait_def_id,
720 self_ty,
721 trait_segment,
722 false,
723 );
724
725 let candidate =
738 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
739
740 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
741 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
742 Err(guar) => Ty::new_error(tcx, guar),
743 }
744 }
745 hir::QPath::TypeRelative(hir_self_ty, segment)
746 if segment.args.is_some_and(|args| {
747 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
748 }) =>
749 {
750 let self_ty = self.lower_ty(hir_self_ty);
751 let (item_def_id, bound) = match self.resolve_type_relative_path(
752 self_ty,
753 hir_self_ty,
754 ty::AssocTag::Fn,
755 segment,
756 hir_ty.hir_id,
757 hir_ty.span,
758 None,
759 ) {
760 Ok(result) => result,
761 Err(guar) => return Ty::new_error(tcx, guar),
762 };
763
764 if bound.has_bound_vars() {
771 return Ty::new_error(
772 tcx,
773 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
774 span: hir_ty.span,
775 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
776 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
777 mpart_sugg: None,
778 what: tcx.def_descr(item_def_id),
779 }),
780 );
781 }
782
783 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
784 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
785 Err(guar) => Ty::new_error(tcx, guar),
786 }
787 }
788 _ => self.lower_ty(hir_ty),
789 }
790 }
791
792 fn lower_return_type_notation_ty(
797 &self,
798 candidate: ty::PolyTraitRef<'tcx>,
799 item_def_id: DefId,
800 path_span: Span,
801 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
802 let tcx = self.tcx();
803 let mut emitted_bad_param_err = None;
804 let mut num_bound_vars = candidate.bound_vars().len();
807 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
808 let arg = match param.kind {
809 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
810 tcx,
811 ty::INNERMOST,
812 ty::BoundRegion {
813 var: ty::BoundVar::from_usize(num_bound_vars),
814 kind: ty::BoundRegionKind::Named(param.def_id),
815 },
816 )
817 .into(),
818 ty::GenericParamDefKind::Type { .. } => {
819 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
820 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
821 span: path_span,
822 param_span: tcx.def_span(param.def_id),
823 })
824 });
825 Ty::new_error(tcx, guar).into()
826 }
827 ty::GenericParamDefKind::Const { .. } => {
828 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
829 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
830 span: path_span,
831 param_span: tcx.def_span(param.def_id),
832 })
833 });
834 ty::Const::new_error(tcx, guar).into()
835 }
836 };
837 num_bound_vars += 1;
838 arg
839 });
840
841 let output = tcx.fn_sig(item_def_id).skip_binder().output();
844 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
845 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
846 {
847 alias_ty
848 } else {
849 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
850 span: path_span,
851 ty: tcx.liberate_late_bound_regions(item_def_id, output),
852 fn_span: tcx.hir_span_if_local(item_def_id),
853 note: (),
854 }));
855 };
856
857 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
862 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
863 }
864}
865
866fn check_assoc_const_binding_type<'tcx>(
878 cx: &dyn HirTyLowerer<'tcx>,
879 assoc_const: Ident,
880 ty: ty::Binder<'tcx, Ty<'tcx>>,
881 hir_id: hir::HirId,
882) -> Ty<'tcx> {
883 let ty = ty.skip_binder();
890 if !ty.has_param() && !ty.has_escaping_bound_vars() {
891 return ty;
892 }
893
894 let mut collector = GenericParamAndBoundVarCollector {
895 cx,
896 params: Default::default(),
897 vars: Default::default(),
898 depth: ty::INNERMOST,
899 };
900 let mut guar = ty.visit_with(&mut collector).break_value();
901
902 let tcx = cx.tcx();
903 let ty_note = ty
904 .make_suggestable(tcx, false, None)
905 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
906
907 let enclosing_item_owner_id = tcx
908 .hir_parent_owner_iter(hir_id)
909 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
910 .unwrap();
911 let generics = tcx.generics_of(enclosing_item_owner_id);
912 for index in collector.params {
913 let param = generics.param_at(index as _, tcx);
914 let is_self_param = param.name == kw::SelfUpper;
915 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
916 span: assoc_const.span,
917 assoc_const,
918 param_name: param.name,
919 param_def_kind: tcx.def_descr(param.def_id),
920 param_category: if is_self_param {
921 "self"
922 } else if param.kind.is_synthetic() {
923 "synthetic"
924 } else {
925 "normal"
926 },
927 param_defined_here_label:
928 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
929 ty_note,
930 }));
931 }
932 for var_def_id in collector.vars {
933 guar.get_or_insert(cx.dcx().emit_err(
934 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
935 span: assoc_const.span,
936 assoc_const,
937 var_name: cx.tcx().item_name(var_def_id),
938 var_def_kind: tcx.def_descr(var_def_id),
939 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
940 ty_note,
941 },
942 ));
943 }
944
945 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
946 Ty::new_error(tcx, guar)
947}
948
949struct GenericParamAndBoundVarCollector<'a, 'tcx> {
950 cx: &'a dyn HirTyLowerer<'tcx>,
951 params: FxIndexSet<u32>,
952 vars: FxIndexSet<DefId>,
953 depth: ty::DebruijnIndex,
954}
955
956impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
957 type Result = ControlFlow<ErrorGuaranteed>;
958
959 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
960 &mut self,
961 binder: &ty::Binder<'tcx, T>,
962 ) -> Self::Result {
963 self.depth.shift_in(1);
964 let result = binder.super_visit_with(self);
965 self.depth.shift_out(1);
966 result
967 }
968
969 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
970 match ty.kind() {
971 ty::Param(param) => {
972 self.params.insert(param.index);
973 }
974 ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
975 self.vars.insert(match bt.kind {
976 ty::BoundTyKind::Param(def_id) => def_id,
977 ty::BoundTyKind::Anon => {
978 let reported = self
979 .cx
980 .dcx()
981 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
982 return ControlFlow::Break(reported);
983 }
984 });
985 }
986 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
987 _ => {}
988 }
989 ControlFlow::Continue(())
990 }
991
992 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
993 match re.kind() {
994 ty::ReEarlyParam(param) => {
995 self.params.insert(param.index);
996 }
997 ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
998 self.vars.insert(match br.kind {
999 ty::BoundRegionKind::Named(def_id) => def_id,
1000 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1001 let guar = self
1002 .cx
1003 .dcx()
1004 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1005 return ControlFlow::Break(guar);
1006 }
1007 ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
1008 });
1009 }
1010 _ => {}
1011 }
1012 ControlFlow::Continue(())
1013 }
1014
1015 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1016 match ct.kind() {
1017 ty::ConstKind::Param(param) => {
1018 self.params.insert(param.index);
1019 }
1020 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
1021 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1022 return ControlFlow::Break(guar);
1023 }
1024 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1025 _ => {}
1026 }
1027 ControlFlow::Continue(())
1028 }
1029}