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::def::{DefKind, Res};
8use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
9use rustc_hir::{AmbigArg, PolyTraitRef};
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 super::errors::GenericsArgsErrExtend;
21use crate::errors;
22use crate::hir_ty_lowering::{
23 AssocItemQSelf, FeedConstTy, HirTyLowerer, 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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'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 Some((self_ty, where_clause)) = self_ty_where_predicates {
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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
91) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
92 let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
93 search_bounds_for(hir_bounds, self_ty_where_predicates, |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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
104 target_did: DefId,
105) -> CollectedBound {
106 let mut collect_into = CollectedBound::default();
107 search_bounds_for(hir_bounds, self_ty_where_predicates, |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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'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, self_ty_where_predicates, sized_did);
129
130 let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
131 let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, 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, self_ty_where_predicates, 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_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 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
168 trait_did: Option<LocalDefId>,
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 if let Some(trait_did) = 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 } else {
194 let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
207 self.check_and_report_invalid_relaxed_bounds(bounds);
208 }
209
210 let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, 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 if trait_did.is_some() {
221 add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
224 } else {
225 let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
228 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
229 }
230 }
231 }
232
233 fn requires_default_supertraits(
273 &self,
274 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
275 hir_generics: &'tcx hir::Generics<'tcx>,
276 ) -> bool {
277 struct TraitInfoCollector;
278
279 impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
280 type Result = ControlFlow<()>;
281
282 fn visit_assoc_item_constraint(
283 &mut self,
284 _constraint: &'tcx hir::AssocItemConstraint<'tcx>,
285 ) -> Self::Result {
286 ControlFlow::Break(())
287 }
288
289 fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
290 if matches!(
291 &t.kind,
292 hir::TyKind::Path(hir::QPath::Resolved(
293 _,
294 hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
295 ))
296 ) {
297 return ControlFlow::Break(());
298 }
299 hir::intravisit::walk_ty(self, t)
300 }
301 }
302
303 let mut found = false;
304 for bound in hir_bounds {
305 found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
306 }
307 found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
308 found
309 }
310
311 pub(crate) fn add_default_trait_item_bounds(
315 &self,
316 trait_item: &hir::TraitItem<'tcx>,
317 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
318 ) {
319 let tcx = self.tcx();
320 if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
321 return;
322 }
323
324 let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
325 let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
326 unreachable!();
327 };
328
329 let (trait_generics, trait_bounds) = match parent_trait.kind {
330 hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
331 hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
332 _ => unreachable!(),
333 };
334
335 if !self.requires_default_supertraits(trait_bounds, trait_generics) {
336 let self_ty_where_predicates = (parent, trait_item.generics.predicates);
337 self.add_default_traits(
338 bounds,
339 tcx.types.self_param,
340 &[],
341 Some(self_ty_where_predicates),
342 trait_item.span,
343 );
344 }
345 }
346
347 pub(crate) fn add_default_super_traits(
350 &self,
351 trait_def_id: LocalDefId,
352 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
353 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
354 hir_generics: &'tcx hir::Generics<'tcx>,
355 span: Span,
356 ) {
357 if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
358 return;
359 }
360
361 assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
362 if self.requires_default_supertraits(hir_bounds, hir_generics) {
363 let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
364 self.add_default_traits(
365 bounds,
366 self.tcx().types.self_param,
367 hir_bounds,
368 Some(self_ty_where_predicates),
369 span,
370 );
371 }
372 }
373
374 pub(crate) fn add_default_traits(
375 &self,
376 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
377 self_ty: Ty<'tcx>,
378 hir_bounds: &[hir::GenericBound<'tcx>],
379 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
380 span: Span,
381 ) {
382 self.tcx().default_traits().iter().for_each(|default_trait| {
383 self.add_default_trait(
384 *default_trait,
385 bounds,
386 self_ty,
387 hir_bounds,
388 self_ty_where_predicates,
389 span,
390 );
391 });
392 }
393
394 pub(crate) fn add_default_trait(
398 &self,
399 trait_: hir::LangItem,
400 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
401 self_ty: Ty<'tcx>,
402 hir_bounds: &[hir::GenericBound<'tcx>],
403 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
404 span: Span,
405 ) {
406 let tcx = self.tcx();
407 let trait_id = tcx.lang_items().get(trait_);
408 if let Some(trait_id) = trait_id
409 && self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
410 {
411 add_trait_bound(tcx, bounds, self_ty, trait_id, span);
412 }
413 }
414
415 fn should_add_default_traits<'a>(
417 &self,
418 trait_def_id: DefId,
419 hir_bounds: &'a [hir::GenericBound<'tcx>],
420 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
421 ) -> bool {
422 let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
423 !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
424 }
425
426 #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
448 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
449 &self,
450 param_ty: Ty<'tcx>,
451 hir_bounds: I,
452 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
453 bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
454 predicate_filter: PredicateFilter,
455 ) where
456 'tcx: 'hir,
457 {
458 for hir_bound in hir_bounds {
459 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
462 if let Some(trait_ref) = hir_bound.trait_ref()
463 && let Some(trait_did) = trait_ref.trait_def_id()
464 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
465 {
466 } else {
468 continue;
469 }
470 }
471
472 match hir_bound {
473 hir::GenericBound::Trait(poly_trait_ref) => {
474 let _ = self.lower_poly_trait_ref(
475 poly_trait_ref,
476 param_ty,
477 bounds,
478 predicate_filter,
479 );
480 }
481 hir::GenericBound::Outlives(lifetime) => {
482 if matches!(
484 predicate_filter,
485 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
486 ) {
487 continue;
488 }
489
490 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
491 let bound = ty::Binder::bind_with_vars(
492 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
493 bound_vars,
494 );
495 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
496 }
497 hir::GenericBound::Use(..) => {
498 }
500 }
501 }
502 }
503
504 #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
513 pub(super) fn lower_assoc_item_constraint(
514 &self,
515 hir_ref_id: hir::HirId,
516 trait_ref: ty::PolyTraitRef<'tcx>,
517 constraint: &hir::AssocItemConstraint<'tcx>,
518 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
519 duplicates: &mut FxIndexMap<DefId, Span>,
520 path_span: Span,
521 predicate_filter: PredicateFilter,
522 ) -> Result<(), ErrorGuaranteed> {
523 let tcx = self.tcx();
524
525 let assoc_tag = if constraint.gen_args.parenthesized
526 == hir::GenericArgsParentheses::ReturnTypeNotation
527 {
528 ty::AssocTag::Fn
529 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
530 constraint.kind
531 {
532 ty::AssocTag::Const
533 } else {
534 ty::AssocTag::Type
535 };
536
537 let candidate = if self.probe_trait_that_defines_assoc_item(
546 trait_ref.def_id(),
547 assoc_tag,
548 constraint.ident,
549 ) {
550 trait_ref
552 } else {
553 self.probe_single_bound_for_assoc_item(
556 || traits::supertraits(tcx, trait_ref),
557 AssocItemQSelf::Trait(trait_ref.def_id()),
558 assoc_tag,
559 constraint.ident,
560 path_span,
561 Some(constraint),
562 )?
563 };
564
565 let assoc_item = self
566 .probe_assoc_item(
567 constraint.ident,
568 assoc_tag,
569 hir_ref_id,
570 constraint.span,
571 candidate.def_id(),
572 )
573 .expect("failed to find associated item");
574
575 duplicates
576 .entry(assoc_item.def_id)
577 .and_modify(|prev_span| {
578 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
579 span: constraint.span,
580 prev_span: *prev_span,
581 item_name: constraint.ident,
582 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
583 });
584 })
585 .or_insert(constraint.span);
586
587 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
588 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
589 ty::Binder::bind_with_vars(
590 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
591 bound_vars,
592 )
593 } else {
594 let alias_term = candidate.map_bound(|trait_ref| {
598 let item_segment = hir::PathSegment {
599 ident: constraint.ident,
600 hir_id: constraint.hir_id,
601 res: Res::Err,
602 args: Some(constraint.gen_args),
603 infer_args: false,
604 };
605
606 let alias_args = self.lower_generic_args_of_assoc_item(
607 path_span,
608 assoc_item.def_id,
609 &item_segment,
610 trait_ref.args,
611 );
612 debug!(?alias_args);
613
614 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
615 });
616
617 if let Some(const_arg) = constraint.ct()
619 && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
620 {
621 let ty = alias_term
622 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
623 let ty =
624 check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
625 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
626 }
627
628 alias_term
629 };
630
631 match constraint.kind {
632 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
633 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
634 span: constraint.span,
635 }));
636 }
637 hir::AssocItemConstraintKind::Equality { term } => {
640 let term = match term {
641 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
642 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
643 };
644
645 let late_bound_in_projection_ty =
653 tcx.collect_constrained_late_bound_regions(projection_term);
654 let late_bound_in_term =
655 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
656 debug!(?late_bound_in_projection_ty);
657 debug!(?late_bound_in_term);
658
659 self.validate_late_bound_regions(
665 late_bound_in_projection_ty,
666 late_bound_in_term,
667 |br_name| {
668 struct_span_code_err!(
669 self.dcx(),
670 constraint.span,
671 E0582,
672 "binding for associated type `{}` references {}, \
673 which does not appear in the trait input types",
674 constraint.ident,
675 br_name
676 )
677 },
678 );
679
680 match predicate_filter {
681 PredicateFilter::All
682 | PredicateFilter::SelfOnly
683 | PredicateFilter::SelfAndAssociatedTypeBounds => {
684 let bound = projection_term.map_bound(|projection_term| {
685 ty::ClauseKind::Projection(ty::ProjectionPredicate {
686 projection_term,
687 term,
688 })
689 });
690 bounds.push((bound.upcast(tcx), constraint.span));
691 }
692 PredicateFilter::SelfTraitThatDefines(_) => {}
694 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
696 }
697 }
698 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
701 match predicate_filter {
702 PredicateFilter::All
703 | PredicateFilter::SelfAndAssociatedTypeBounds
704 | PredicateFilter::ConstIfConst => {
705 let projection_ty = projection_term
706 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
707 let param_ty =
710 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
711 self.lower_bounds(
712 param_ty,
713 hir_bounds,
714 bounds,
715 projection_ty.bound_vars(),
716 predicate_filter,
717 );
718 }
719 PredicateFilter::SelfOnly
720 | PredicateFilter::SelfTraitThatDefines(_)
721 | PredicateFilter::SelfConstIfConst => {}
722 }
723 }
724 }
725 Ok(())
726 }
727
728 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
731 let hir::TyKind::Path(qpath) = hir_ty.kind else {
732 return self.lower_ty(hir_ty);
733 };
734
735 let tcx = self.tcx();
736 match qpath {
737 hir::QPath::Resolved(opt_self_ty, path)
738 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
739 && item_segment.args.is_some_and(|args| {
740 matches!(
741 args.parenthesized,
742 hir::GenericArgsParentheses::ReturnTypeNotation
743 )
744 }) =>
745 {
746 let _ =
748 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
749
750 let item_def_id = match path.res {
751 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
752 Res::Err => {
753 return Ty::new_error_with_message(
754 tcx,
755 hir_ty.span,
756 "failed to resolve RTN",
757 );
758 }
759 _ => bug!("only expected method resolution for fully qualified RTN"),
760 };
761 let trait_def_id = tcx.parent(item_def_id);
762
763 let Some(self_ty) = opt_self_ty else {
765 let guar = self.report_missing_self_ty_for_resolved_path(
766 trait_def_id,
767 hir_ty.span,
768 item_segment,
769 ty::AssocTag::Type,
770 );
771 return Ty::new_error(tcx, guar);
772 };
773 let self_ty = self.lower_ty(self_ty);
774
775 let trait_ref = self.lower_mono_trait_ref(
776 hir_ty.span,
777 trait_def_id,
778 self_ty,
779 trait_segment,
780 false,
781 );
782
783 let candidate =
796 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
797
798 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
799 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
800 Err(guar) => Ty::new_error(tcx, guar),
801 }
802 }
803 hir::QPath::TypeRelative(hir_self_ty, segment)
804 if segment.args.is_some_and(|args| {
805 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
806 }) =>
807 {
808 let self_ty = self.lower_ty(hir_self_ty);
809 let (item_def_id, bound) = match self.resolve_type_relative_path(
810 self_ty,
811 hir_self_ty,
812 ty::AssocTag::Fn,
813 segment,
814 hir_ty.hir_id,
815 hir_ty.span,
816 None,
817 ) {
818 Ok(result) => result,
819 Err(guar) => return Ty::new_error(tcx, guar),
820 };
821
822 if bound.has_bound_vars() {
829 return Ty::new_error(
830 tcx,
831 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
832 span: hir_ty.span,
833 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
834 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
835 mpart_sugg: None,
836 what: tcx.def_descr(item_def_id),
837 }),
838 );
839 }
840
841 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
842 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
843 Err(guar) => Ty::new_error(tcx, guar),
844 }
845 }
846 _ => self.lower_ty(hir_ty),
847 }
848 }
849
850 fn lower_return_type_notation_ty(
855 &self,
856 candidate: ty::PolyTraitRef<'tcx>,
857 item_def_id: DefId,
858 path_span: Span,
859 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
860 let tcx = self.tcx();
861 let mut emitted_bad_param_err = None;
862 let mut num_bound_vars = candidate.bound_vars().len();
865 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
866 let arg = match param.kind {
867 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
868 tcx,
869 ty::INNERMOST,
870 ty::BoundRegion {
871 var: ty::BoundVar::from_usize(num_bound_vars),
872 kind: ty::BoundRegionKind::Named(param.def_id),
873 },
874 )
875 .into(),
876 ty::GenericParamDefKind::Type { .. } => {
877 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
878 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
879 span: path_span,
880 param_span: tcx.def_span(param.def_id),
881 })
882 });
883 Ty::new_error(tcx, guar).into()
884 }
885 ty::GenericParamDefKind::Const { .. } => {
886 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
887 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
888 span: path_span,
889 param_span: tcx.def_span(param.def_id),
890 })
891 });
892 ty::Const::new_error(tcx, guar).into()
893 }
894 };
895 num_bound_vars += 1;
896 arg
897 });
898
899 let output = tcx.fn_sig(item_def_id).skip_binder().output();
902 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
903 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
904 {
905 alias_ty
906 } else {
907 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
908 span: path_span,
909 ty: tcx.liberate_late_bound_regions(item_def_id, output),
910 fn_span: tcx.hir_span_if_local(item_def_id),
911 note: (),
912 }));
913 };
914
915 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
920 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
921 }
922}
923
924fn check_assoc_const_binding_type<'tcx>(
936 cx: &dyn HirTyLowerer<'tcx>,
937 assoc_const: Ident,
938 ty: ty::Binder<'tcx, Ty<'tcx>>,
939 hir_id: hir::HirId,
940) -> Ty<'tcx> {
941 let ty = ty.skip_binder();
948 if !ty.has_param() && !ty.has_escaping_bound_vars() {
949 return ty;
950 }
951
952 let mut collector = GenericParamAndBoundVarCollector {
953 cx,
954 params: Default::default(),
955 vars: Default::default(),
956 depth: ty::INNERMOST,
957 };
958 let mut guar = ty.visit_with(&mut collector).break_value();
959
960 let tcx = cx.tcx();
961 let ty_note = ty
962 .make_suggestable(tcx, false, None)
963 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
964
965 let enclosing_item_owner_id = tcx
966 .hir_parent_owner_iter(hir_id)
967 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
968 .unwrap();
969 let generics = tcx.generics_of(enclosing_item_owner_id);
970 for index in collector.params {
971 let param = generics.param_at(index as _, tcx);
972 let is_self_param = param.name == kw::SelfUpper;
973 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
974 span: assoc_const.span,
975 assoc_const,
976 param_name: param.name,
977 param_def_kind: tcx.def_descr(param.def_id),
978 param_category: if is_self_param {
979 "self"
980 } else if param.kind.is_synthetic() {
981 "synthetic"
982 } else {
983 "normal"
984 },
985 param_defined_here_label:
986 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
987 ty_note,
988 }));
989 }
990 for var_def_id in collector.vars {
991 guar.get_or_insert(cx.dcx().emit_err(
992 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
993 span: assoc_const.span,
994 assoc_const,
995 var_name: cx.tcx().item_name(var_def_id),
996 var_def_kind: tcx.def_descr(var_def_id),
997 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
998 ty_note,
999 },
1000 ));
1001 }
1002
1003 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
1004 Ty::new_error(tcx, guar)
1005}
1006
1007struct GenericParamAndBoundVarCollector<'a, 'tcx> {
1008 cx: &'a dyn HirTyLowerer<'tcx>,
1009 params: FxIndexSet<u32>,
1010 vars: FxIndexSet<DefId>,
1011 depth: ty::DebruijnIndex,
1012}
1013
1014impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
1015 type Result = ControlFlow<ErrorGuaranteed>;
1016
1017 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
1018 &mut self,
1019 binder: &ty::Binder<'tcx, T>,
1020 ) -> Self::Result {
1021 self.depth.shift_in(1);
1022 let result = binder.super_visit_with(self);
1023 self.depth.shift_out(1);
1024 result
1025 }
1026
1027 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
1028 match ty.kind() {
1029 ty::Param(param) => {
1030 self.params.insert(param.index);
1031 }
1032 ty::Bound(db, bt) if *db >= self.depth => {
1033 self.vars.insert(match bt.kind {
1034 ty::BoundTyKind::Param(def_id) => def_id,
1035 ty::BoundTyKind::Anon => {
1036 let reported = self
1037 .cx
1038 .dcx()
1039 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
1040 return ControlFlow::Break(reported);
1041 }
1042 });
1043 }
1044 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
1045 _ => {}
1046 }
1047 ControlFlow::Continue(())
1048 }
1049
1050 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
1051 match re.kind() {
1052 ty::ReEarlyParam(param) => {
1053 self.params.insert(param.index);
1054 }
1055 ty::ReBound(db, br) if db >= self.depth => {
1056 self.vars.insert(match br.kind {
1057 ty::BoundRegionKind::Named(def_id) => def_id,
1058 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1059 let guar = self
1060 .cx
1061 .dcx()
1062 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1063 return ControlFlow::Break(guar);
1064 }
1065 ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
1066 });
1067 }
1068 _ => {}
1069 }
1070 ControlFlow::Continue(())
1071 }
1072
1073 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1074 match ct.kind() {
1075 ty::ConstKind::Param(param) => {
1076 self.params.insert(param.index);
1077 }
1078 ty::ConstKind::Bound(db, _) if db >= self.depth => {
1079 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1080 return ControlFlow::Break(guar);
1081 }
1082 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1083 _ => {}
1084 }
1085 ControlFlow::Continue(())
1086 }
1087}