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