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