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, OverlappingAsssocItemConstraints, PredicateFilter,
25 RegionInferReason,
26};
27
28#[derive(Debug, Default)]
29struct CollectedBound {
30 positive: bool,
32 maybe: bool,
34 negative: bool,
36}
37
38impl CollectedBound {
39 fn any(&self) -> bool {
41 self.positive || self.maybe || self.negative
42 }
43}
44
45#[derive(Debug)]
46struct CollectedSizednessBounds {
47 sized: CollectedBound,
49 meta_sized: CollectedBound,
51 pointee_sized: CollectedBound,
53}
54
55impl CollectedSizednessBounds {
56 fn any(&self) -> bool {
59 self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
60 }
61}
62
63fn search_bounds_for<'tcx>(
64 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
65 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
66 mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
67) {
68 let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
69 for hir_bound in hir_bounds {
70 let hir::GenericBound::Trait(ptr) = hir_bound else {
71 continue;
72 };
73
74 f(ptr)
75 }
76 };
77
78 search_bounds(hir_bounds);
79 if let Some((self_ty, where_clause)) = self_ty_where_predicates {
80 for clause in where_clause {
81 if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
82 && pred.is_param_bound(self_ty.to_def_id())
83 {
84 search_bounds(pred.bounds);
85 }
86 }
87 }
88}
89
90fn collect_relaxed_bounds<'tcx>(
91 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
92 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
93) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
94 let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
95 search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
96 if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
97 relaxed_bounds.push(ptr);
98 }
99 });
100 relaxed_bounds
101}
102
103fn collect_bounds<'a, 'tcx>(
104 hir_bounds: &'a [hir::GenericBound<'tcx>],
105 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
106 target_did: DefId,
107) -> CollectedBound {
108 let mut collect_into = CollectedBound::default();
109 search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
110 if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
111 return;
112 }
113
114 match ptr.modifiers.polarity {
115 hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
116 hir::BoundPolarity::Negative(_) => collect_into.negative = true,
117 hir::BoundPolarity::Positive => collect_into.positive = true,
118 }
119 });
120 collect_into
121}
122
123fn collect_sizedness_bounds<'tcx>(
124 tcx: TyCtxt<'tcx>,
125 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
126 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
127 span: Span,
128) -> CollectedSizednessBounds {
129 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
130 let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
131
132 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
133 let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
134
135 let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
136 let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
137
138 CollectedSizednessBounds { sized, meta_sized, pointee_sized }
139}
140
141fn add_trait_bound<'tcx>(
143 tcx: TyCtxt<'tcx>,
144 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
145 self_ty: Ty<'tcx>,
146 did: DefId,
147 span: Span,
148) {
149 let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
150 bounds.insert(0, (trait_ref.upcast(tcx), span));
153}
154
155impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
156 pub(crate) fn add_sizedness_bounds(
165 &self,
166 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
167 self_ty: Ty<'tcx>,
168 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
169 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
170 trait_did: Option<LocalDefId>,
171 span: Span,
172 ) {
173 let tcx = self.tcx();
174
175 if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
177 return;
178 }
179
180 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
181 let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
182
183 if let Some(trait_did) = trait_did {
185 let trait_did = trait_did.to_def_id();
186 if trait_did == pointee_sized_did {
188 return;
189 }
190 if tcx.trait_is_auto(trait_did) {
193 return;
194 }
195 } else {
196 let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
209 self.check_and_report_invalid_relaxed_bounds(bounds);
210 }
211
212 let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
213 if (collected.sized.maybe || collected.sized.negative)
214 && !collected.sized.positive
215 && !collected.meta_sized.any()
216 && !collected.pointee_sized.any()
217 {
218 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
221 } else if !collected.any() {
222 if trait_did.is_some() {
223 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
226 } else {
227 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
230 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
231 }
232 }
233 }
234
235 pub(crate) fn add_default_super_traits(
237 &self,
238 trait_def_id: LocalDefId,
239 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
240 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
241 hir_generics: &'tcx hir::Generics<'tcx>,
242 span: Span,
243 ) {
244 assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);
245
246 if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
249 return;
250 }
251
252 self.add_default_traits(
253 bounds,
254 self.tcx().types.self_param,
255 hir_bounds,
256 Some((trait_def_id, hir_generics.predicates)),
257 span,
258 );
259 }
260
261 pub(crate) fn add_default_traits(
262 &self,
263 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
264 self_ty: Ty<'tcx>,
265 hir_bounds: &[hir::GenericBound<'tcx>],
266 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
267 span: Span,
268 ) {
269 self.tcx().default_traits().iter().for_each(|default_trait| {
270 self.add_default_trait(
271 *default_trait,
272 bounds,
273 self_ty,
274 hir_bounds,
275 self_ty_where_predicates,
276 span,
277 );
278 });
279 }
280
281 pub(crate) fn add_default_trait(
285 &self,
286 trait_: hir::LangItem,
287 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
288 self_ty: Ty<'tcx>,
289 hir_bounds: &[hir::GenericBound<'tcx>],
290 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
291 span: Span,
292 ) {
293 let tcx = self.tcx();
294 let trait_id = tcx.lang_items().get(trait_);
295 if let Some(trait_id) = trait_id
296 && self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
297 {
298 add_trait_bound(tcx, bounds, self_ty, trait_id, span);
299 }
300 }
301
302 fn should_add_default_traits<'a>(
304 &self,
305 trait_def_id: DefId,
306 hir_bounds: &'a [hir::GenericBound<'tcx>],
307 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
308 ) -> bool {
309 let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
310 !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
311 }
312
313 #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
335 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
336 &self,
337 param_ty: Ty<'tcx>,
338 hir_bounds: I,
339 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
340 bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
341 predicate_filter: PredicateFilter,
342 overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
343 ) where
344 'tcx: 'hir,
345 {
346 for hir_bound in hir_bounds {
347 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
350 if let Some(trait_ref) = hir_bound.trait_ref()
351 && let Some(trait_did) = trait_ref.trait_def_id()
352 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
353 {
354 } else {
356 continue;
357 }
358 }
359
360 match hir_bound {
361 hir::GenericBound::Trait(poly_trait_ref) => {
362 let _ = self.lower_poly_trait_ref(
363 poly_trait_ref,
364 param_ty,
365 bounds,
366 predicate_filter,
367 overlapping_assoc_constraints,
368 );
369 }
370 hir::GenericBound::Outlives(lifetime) => {
371 if matches!(
373 predicate_filter,
374 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
375 ) {
376 continue;
377 }
378
379 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
380 let bound = ty::Binder::bind_with_vars(
381 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
382 bound_vars,
383 );
384 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
385 }
386 hir::GenericBound::Use(..) => {
387 }
389 }
390 }
391 }
392
393 #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
402 pub(super) fn lower_assoc_item_constraint(
403 &self,
404 hir_ref_id: hir::HirId,
405 trait_ref: ty::PolyTraitRef<'tcx>,
406 constraint: &hir::AssocItemConstraint<'tcx>,
407 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
408 duplicates: Option<&mut FxIndexMap<DefId, Span>>,
409 path_span: Span,
410 predicate_filter: PredicateFilter,
411 ) -> Result<(), ErrorGuaranteed> {
412 let tcx = self.tcx();
413
414 let assoc_tag = if constraint.gen_args.parenthesized
415 == hir::GenericArgsParentheses::ReturnTypeNotation
416 {
417 ty::AssocTag::Fn
418 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
419 constraint.kind
420 {
421 ty::AssocTag::Const
422 } else {
423 ty::AssocTag::Type
424 };
425
426 let candidate = if self.probe_trait_that_defines_assoc_item(
435 trait_ref.def_id(),
436 assoc_tag,
437 constraint.ident,
438 ) {
439 trait_ref
441 } else {
442 self.probe_single_bound_for_assoc_item(
445 || traits::supertraits(tcx, trait_ref),
446 AssocItemQSelf::Trait(trait_ref.def_id()),
447 assoc_tag,
448 constraint.ident,
449 path_span,
450 Some(constraint),
451 )?
452 };
453
454 let assoc_item = self
455 .probe_assoc_item(
456 constraint.ident,
457 assoc_tag,
458 hir_ref_id,
459 constraint.span,
460 candidate.def_id(),
461 )
462 .expect("failed to find associated item");
463
464 if let Some(duplicates) = duplicates {
465 duplicates
466 .entry(assoc_item.def_id)
467 .and_modify(|prev_span| {
468 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
469 span: constraint.span,
470 prev_span: *prev_span,
471 item_name: constraint.ident,
472 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
473 });
474 })
475 .or_insert(constraint.span);
476 }
477
478 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
479 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
480 ty::Binder::bind_with_vars(
481 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
482 bound_vars,
483 )
484 } else {
485 let alias_term = candidate.map_bound(|trait_ref| {
489 let item_segment = hir::PathSegment {
490 ident: constraint.ident,
491 hir_id: constraint.hir_id,
492 res: Res::Err,
493 args: Some(constraint.gen_args),
494 infer_args: false,
495 };
496
497 let alias_args = self.lower_generic_args_of_assoc_item(
498 path_span,
499 assoc_item.def_id,
500 &item_segment,
501 trait_ref.args,
502 );
503 debug!(?alias_args);
504
505 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
506 });
507
508 if let Some(const_arg) = constraint.ct()
510 && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
511 {
512 let ty = alias_term
513 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
514 let ty =
515 check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
516 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
517 }
518
519 alias_term
520 };
521
522 match constraint.kind {
523 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
524 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
525 span: constraint.span,
526 }));
527 }
528 hir::AssocItemConstraintKind::Equality { term } => {
531 let term = match term {
532 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
533 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
534 };
535
536 let late_bound_in_projection_ty =
544 tcx.collect_constrained_late_bound_regions(projection_term);
545 let late_bound_in_term =
546 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
547 debug!(?late_bound_in_projection_ty);
548 debug!(?late_bound_in_term);
549
550 self.validate_late_bound_regions(
556 late_bound_in_projection_ty,
557 late_bound_in_term,
558 |br_name| {
559 struct_span_code_err!(
560 self.dcx(),
561 constraint.span,
562 E0582,
563 "binding for associated type `{}` references {}, \
564 which does not appear in the trait input types",
565 constraint.ident,
566 br_name
567 )
568 },
569 );
570
571 match predicate_filter {
572 PredicateFilter::All
573 | PredicateFilter::SelfOnly
574 | PredicateFilter::SelfAndAssociatedTypeBounds => {
575 let bound = projection_term.map_bound(|projection_term| {
576 ty::ClauseKind::Projection(ty::ProjectionPredicate {
577 projection_term,
578 term,
579 })
580 });
581 bounds.push((bound.upcast(tcx), constraint.span));
582 }
583 PredicateFilter::SelfTraitThatDefines(_) => {}
585 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
587 }
588 }
589 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
592 match predicate_filter {
593 PredicateFilter::All
594 | PredicateFilter::SelfAndAssociatedTypeBounds
595 | PredicateFilter::ConstIfConst => {
596 let projection_ty = projection_term
597 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
598 let param_ty =
601 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
602 self.lower_bounds(
603 param_ty,
604 hir_bounds,
605 bounds,
606 projection_ty.bound_vars(),
607 predicate_filter,
608 OverlappingAsssocItemConstraints::Allowed,
609 );
610 }
611 PredicateFilter::SelfOnly
612 | PredicateFilter::SelfTraitThatDefines(_)
613 | PredicateFilter::SelfConstIfConst => {}
614 }
615 }
616 }
617 Ok(())
618 }
619
620 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
623 let hir::TyKind::Path(qpath) = hir_ty.kind else {
624 return self.lower_ty(hir_ty);
625 };
626
627 let tcx = self.tcx();
628 match qpath {
629 hir::QPath::Resolved(opt_self_ty, path)
630 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
631 && item_segment.args.is_some_and(|args| {
632 matches!(
633 args.parenthesized,
634 hir::GenericArgsParentheses::ReturnTypeNotation
635 )
636 }) =>
637 {
638 let _ =
640 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
641
642 let item_def_id = match path.res {
643 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
644 Res::Err => {
645 return Ty::new_error_with_message(
646 tcx,
647 hir_ty.span,
648 "failed to resolve RTN",
649 );
650 }
651 _ => bug!("only expected method resolution for fully qualified RTN"),
652 };
653 let trait_def_id = tcx.parent(item_def_id);
654
655 let Some(self_ty) = opt_self_ty else {
657 let guar = self.report_missing_self_ty_for_resolved_path(
658 trait_def_id,
659 hir_ty.span,
660 item_segment,
661 ty::AssocTag::Type,
662 );
663 return Ty::new_error(tcx, guar);
664 };
665 let self_ty = self.lower_ty(self_ty);
666
667 let trait_ref = self.lower_mono_trait_ref(
668 hir_ty.span,
669 trait_def_id,
670 self_ty,
671 trait_segment,
672 false,
673 );
674
675 let candidate =
688 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
689
690 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
691 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
692 Err(guar) => Ty::new_error(tcx, guar),
693 }
694 }
695 hir::QPath::TypeRelative(hir_self_ty, segment)
696 if segment.args.is_some_and(|args| {
697 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
698 }) =>
699 {
700 let self_ty = self.lower_ty(hir_self_ty);
701 let (item_def_id, bound) = match self.resolve_type_relative_path(
702 self_ty,
703 hir_self_ty,
704 ty::AssocTag::Fn,
705 segment,
706 hir_ty.hir_id,
707 hir_ty.span,
708 None,
709 ) {
710 Ok(result) => result,
711 Err(guar) => return Ty::new_error(tcx, guar),
712 };
713
714 if bound.has_bound_vars() {
721 return Ty::new_error(
722 tcx,
723 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
724 span: hir_ty.span,
725 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
726 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
727 mpart_sugg: None,
728 what: tcx.def_descr(item_def_id),
729 }),
730 );
731 }
732
733 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
734 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
735 Err(guar) => Ty::new_error(tcx, guar),
736 }
737 }
738 _ => self.lower_ty(hir_ty),
739 }
740 }
741
742 fn lower_return_type_notation_ty(
747 &self,
748 candidate: ty::PolyTraitRef<'tcx>,
749 item_def_id: DefId,
750 path_span: Span,
751 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
752 let tcx = self.tcx();
753 let mut emitted_bad_param_err = None;
754 let mut num_bound_vars = candidate.bound_vars().len();
757 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
758 let arg = match param.kind {
759 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
760 tcx,
761 ty::INNERMOST,
762 ty::BoundRegion {
763 var: ty::BoundVar::from_usize(num_bound_vars),
764 kind: ty::BoundRegionKind::Named(param.def_id),
765 },
766 )
767 .into(),
768 ty::GenericParamDefKind::Type { .. } => {
769 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
770 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
771 span: path_span,
772 param_span: tcx.def_span(param.def_id),
773 })
774 });
775 Ty::new_error(tcx, guar).into()
776 }
777 ty::GenericParamDefKind::Const { .. } => {
778 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
779 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
780 span: path_span,
781 param_span: tcx.def_span(param.def_id),
782 })
783 });
784 ty::Const::new_error(tcx, guar).into()
785 }
786 };
787 num_bound_vars += 1;
788 arg
789 });
790
791 let output = tcx.fn_sig(item_def_id).skip_binder().output();
794 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
795 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
796 {
797 alias_ty
798 } else {
799 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
800 span: path_span,
801 ty: tcx.liberate_late_bound_regions(item_def_id, output),
802 fn_span: tcx.hir_span_if_local(item_def_id),
803 note: (),
804 }));
805 };
806
807 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
812 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
813 }
814}
815
816fn check_assoc_const_binding_type<'tcx>(
828 cx: &dyn HirTyLowerer<'tcx>,
829 assoc_const: Ident,
830 ty: ty::Binder<'tcx, Ty<'tcx>>,
831 hir_id: hir::HirId,
832) -> Ty<'tcx> {
833 let ty = ty.skip_binder();
840 if !ty.has_param() && !ty.has_escaping_bound_vars() {
841 return ty;
842 }
843
844 let mut collector = GenericParamAndBoundVarCollector {
845 cx,
846 params: Default::default(),
847 vars: Default::default(),
848 depth: ty::INNERMOST,
849 };
850 let mut guar = ty.visit_with(&mut collector).break_value();
851
852 let tcx = cx.tcx();
853 let ty_note = ty
854 .make_suggestable(tcx, false, None)
855 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
856
857 let enclosing_item_owner_id = tcx
858 .hir_parent_owner_iter(hir_id)
859 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
860 .unwrap();
861 let generics = tcx.generics_of(enclosing_item_owner_id);
862 for index in collector.params {
863 let param = generics.param_at(index as _, tcx);
864 let is_self_param = param.name == kw::SelfUpper;
865 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
866 span: assoc_const.span,
867 assoc_const,
868 param_name: param.name,
869 param_def_kind: tcx.def_descr(param.def_id),
870 param_category: if is_self_param {
871 "self"
872 } else if param.kind.is_synthetic() {
873 "synthetic"
874 } else {
875 "normal"
876 },
877 param_defined_here_label:
878 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
879 ty_note,
880 }));
881 }
882 for var_def_id in collector.vars {
883 guar.get_or_insert(cx.dcx().emit_err(
884 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
885 span: assoc_const.span,
886 assoc_const,
887 var_name: cx.tcx().item_name(var_def_id),
888 var_def_kind: tcx.def_descr(var_def_id),
889 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
890 ty_note,
891 },
892 ));
893 }
894
895 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
896 Ty::new_error(tcx, guar)
897}
898
899struct GenericParamAndBoundVarCollector<'a, 'tcx> {
900 cx: &'a dyn HirTyLowerer<'tcx>,
901 params: FxIndexSet<u32>,
902 vars: FxIndexSet<DefId>,
903 depth: ty::DebruijnIndex,
904}
905
906impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
907 type Result = ControlFlow<ErrorGuaranteed>;
908
909 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
910 &mut self,
911 binder: &ty::Binder<'tcx, T>,
912 ) -> Self::Result {
913 self.depth.shift_in(1);
914 let result = binder.super_visit_with(self);
915 self.depth.shift_out(1);
916 result
917 }
918
919 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
920 match ty.kind() {
921 ty::Param(param) => {
922 self.params.insert(param.index);
923 }
924 ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
925 self.vars.insert(match bt.kind {
926 ty::BoundTyKind::Param(def_id) => def_id,
927 ty::BoundTyKind::Anon => {
928 let reported = self
929 .cx
930 .dcx()
931 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
932 return ControlFlow::Break(reported);
933 }
934 });
935 }
936 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
937 _ => {}
938 }
939 ControlFlow::Continue(())
940 }
941
942 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
943 match re.kind() {
944 ty::ReEarlyParam(param) => {
945 self.params.insert(param.index);
946 }
947 ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
948 self.vars.insert(match br.kind {
949 ty::BoundRegionKind::Named(def_id) => def_id,
950 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
951 let guar = self
952 .cx
953 .dcx()
954 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
955 return ControlFlow::Break(guar);
956 }
957 ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
958 });
959 }
960 _ => {}
961 }
962 ControlFlow::Continue(())
963 }
964
965 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
966 match ct.kind() {
967 ty::ConstKind::Param(param) => {
968 self.params.insert(param.index);
969 }
970 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
971 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
972 return ControlFlow::Break(guar);
973 }
974 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
975 _ => {}
976 }
977 ControlFlow::Continue(())
978 }
979}