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 if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
622 let ty = alias_term
623 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
624 let ty = check_assoc_const_binding_type(
625 self,
626 constraint.ident,
627 ty,
628 constraint.hir_id,
629 );
630 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
631 }
632 }
633
634 alias_term
635 };
636
637 match constraint.kind {
638 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
639 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
640 span: constraint.span,
641 }));
642 }
643 hir::AssocItemConstraintKind::Equality { term } => {
646 let term = match term {
647 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
648 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
649 };
650
651 let late_bound_in_projection_ty =
659 tcx.collect_constrained_late_bound_regions(projection_term);
660 let late_bound_in_term =
661 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
662 debug!(?late_bound_in_projection_ty);
663 debug!(?late_bound_in_term);
664
665 self.validate_late_bound_regions(
671 late_bound_in_projection_ty,
672 late_bound_in_term,
673 |br_name| {
674 struct_span_code_err!(
675 self.dcx(),
676 constraint.span,
677 E0582,
678 "binding for associated type `{}` references {}, \
679 which does not appear in the trait input types",
680 constraint.ident,
681 br_name
682 )
683 },
684 );
685
686 match predicate_filter {
687 PredicateFilter::All
688 | PredicateFilter::SelfOnly
689 | PredicateFilter::SelfAndAssociatedTypeBounds => {
690 let bound = projection_term.map_bound(|projection_term| {
691 ty::ClauseKind::Projection(ty::ProjectionPredicate {
692 projection_term,
693 term,
694 })
695 });
696 bounds.push((bound.upcast(tcx), constraint.span));
697 }
698 PredicateFilter::SelfTraitThatDefines(_) => {}
700 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
702 }
703 }
704 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
707 match predicate_filter {
708 PredicateFilter::All
709 | PredicateFilter::SelfAndAssociatedTypeBounds
710 | PredicateFilter::ConstIfConst => {
711 let projection_ty = projection_term
712 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
713 let param_ty =
716 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
717 self.lower_bounds(
718 param_ty,
719 hir_bounds,
720 bounds,
721 projection_ty.bound_vars(),
722 predicate_filter,
723 );
724 }
725 PredicateFilter::SelfOnly
726 | PredicateFilter::SelfTraitThatDefines(_)
727 | PredicateFilter::SelfConstIfConst => {}
728 }
729 }
730 }
731 Ok(())
732 }
733
734 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
737 let hir::TyKind::Path(qpath) = hir_ty.kind else {
738 return self.lower_ty(hir_ty);
739 };
740
741 let tcx = self.tcx();
742 match qpath {
743 hir::QPath::Resolved(opt_self_ty, path)
744 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
745 && item_segment.args.is_some_and(|args| {
746 matches!(
747 args.parenthesized,
748 hir::GenericArgsParentheses::ReturnTypeNotation
749 )
750 }) =>
751 {
752 let _ =
754 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
755
756 let item_def_id = match path.res {
757 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
758 Res::Err => {
759 return Ty::new_error_with_message(
760 tcx,
761 hir_ty.span,
762 "failed to resolve RTN",
763 );
764 }
765 _ => bug!("only expected method resolution for fully qualified RTN"),
766 };
767 let trait_def_id = tcx.parent(item_def_id);
768
769 let Some(self_ty) = opt_self_ty else {
771 let guar = self.report_missing_self_ty_for_resolved_path(
772 trait_def_id,
773 hir_ty.span,
774 item_segment,
775 ty::AssocTag::Type,
776 );
777 return Ty::new_error(tcx, guar);
778 };
779 let self_ty = self.lower_ty(self_ty);
780
781 let trait_ref = self.lower_mono_trait_ref(
782 hir_ty.span,
783 trait_def_id,
784 self_ty,
785 trait_segment,
786 false,
787 );
788
789 let candidate =
802 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
803
804 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
805 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
806 Err(guar) => Ty::new_error(tcx, guar),
807 }
808 }
809 hir::QPath::TypeRelative(hir_self_ty, segment)
810 if segment.args.is_some_and(|args| {
811 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
812 }) =>
813 {
814 let self_ty = self.lower_ty(hir_self_ty);
815 let (item_def_id, bound) = match self.resolve_type_relative_path(
816 self_ty,
817 hir_self_ty,
818 ty::AssocTag::Fn,
819 segment,
820 hir_ty.hir_id,
821 hir_ty.span,
822 None,
823 ) {
824 Ok(result) => result,
825 Err(guar) => return Ty::new_error(tcx, guar),
826 };
827
828 if bound.has_bound_vars() {
835 return Ty::new_error(
836 tcx,
837 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
838 span: hir_ty.span,
839 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
840 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
841 mpart_sugg: None,
842 what: tcx.def_descr(item_def_id),
843 }),
844 );
845 }
846
847 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
848 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
849 Err(guar) => Ty::new_error(tcx, guar),
850 }
851 }
852 _ => self.lower_ty(hir_ty),
853 }
854 }
855
856 fn lower_return_type_notation_ty(
861 &self,
862 candidate: ty::PolyTraitRef<'tcx>,
863 item_def_id: DefId,
864 path_span: Span,
865 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
866 let tcx = self.tcx();
867 let mut emitted_bad_param_err = None;
868 let mut num_bound_vars = candidate.bound_vars().len();
871 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
872 let arg = match param.kind {
873 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
874 tcx,
875 ty::INNERMOST,
876 ty::BoundRegion {
877 var: ty::BoundVar::from_usize(num_bound_vars),
878 kind: ty::BoundRegionKind::Named(param.def_id),
879 },
880 )
881 .into(),
882 ty::GenericParamDefKind::Type { .. } => {
883 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
884 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
885 span: path_span,
886 param_span: tcx.def_span(param.def_id),
887 })
888 });
889 Ty::new_error(tcx, guar).into()
890 }
891 ty::GenericParamDefKind::Const { .. } => {
892 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
893 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
894 span: path_span,
895 param_span: tcx.def_span(param.def_id),
896 })
897 });
898 ty::Const::new_error(tcx, guar).into()
899 }
900 };
901 num_bound_vars += 1;
902 arg
903 });
904
905 let output = tcx.fn_sig(item_def_id).skip_binder().output();
908 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
909 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
910 {
911 alias_ty
912 } else {
913 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
914 span: path_span,
915 ty: tcx.liberate_late_bound_regions(item_def_id, output),
916 fn_span: tcx.hir_span_if_local(item_def_id),
917 note: (),
918 }));
919 };
920
921 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
926 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
927 }
928}
929
930fn check_assoc_const_binding_type<'tcx>(
942 cx: &dyn HirTyLowerer<'tcx>,
943 assoc_const: Ident,
944 ty: ty::Binder<'tcx, Ty<'tcx>>,
945 hir_id: hir::HirId,
946) -> Ty<'tcx> {
947 let ty = ty.skip_binder();
954 if !ty.has_param() && !ty.has_escaping_bound_vars() {
955 return ty;
956 }
957
958 let mut collector = GenericParamAndBoundVarCollector {
959 cx,
960 params: Default::default(),
961 vars: Default::default(),
962 depth: ty::INNERMOST,
963 };
964 let mut guar = ty.visit_with(&mut collector).break_value();
965
966 let tcx = cx.tcx();
967 let ty_note = ty
968 .make_suggestable(tcx, false, None)
969 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
970
971 let enclosing_item_owner_id = tcx
972 .hir_parent_owner_iter(hir_id)
973 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
974 .unwrap();
975 let generics = tcx.generics_of(enclosing_item_owner_id);
976 for index in collector.params {
977 let param = generics.param_at(index as _, tcx);
978 let is_self_param = param.name == kw::SelfUpper;
979 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
980 span: assoc_const.span,
981 assoc_const,
982 param_name: param.name,
983 param_def_kind: tcx.def_descr(param.def_id),
984 param_category: if is_self_param {
985 "self"
986 } else if param.kind.is_synthetic() {
987 "synthetic"
988 } else {
989 "normal"
990 },
991 param_defined_here_label:
992 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
993 ty_note,
994 }));
995 }
996 for var_def_id in collector.vars {
997 guar.get_or_insert(cx.dcx().emit_err(
998 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
999 span: assoc_const.span,
1000 assoc_const,
1001 var_name: cx.tcx().item_name(var_def_id),
1002 var_def_kind: tcx.def_descr(var_def_id),
1003 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
1004 ty_note,
1005 },
1006 ));
1007 }
1008
1009 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
1010 Ty::new_error(tcx, guar)
1011}
1012
1013struct GenericParamAndBoundVarCollector<'a, 'tcx> {
1014 cx: &'a dyn HirTyLowerer<'tcx>,
1015 params: FxIndexSet<u32>,
1016 vars: FxIndexSet<DefId>,
1017 depth: ty::DebruijnIndex,
1018}
1019
1020impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
1021 type Result = ControlFlow<ErrorGuaranteed>;
1022
1023 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
1024 &mut self,
1025 binder: &ty::Binder<'tcx, T>,
1026 ) -> Self::Result {
1027 self.depth.shift_in(1);
1028 let result = binder.super_visit_with(self);
1029 self.depth.shift_out(1);
1030 result
1031 }
1032
1033 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
1034 match ty.kind() {
1035 ty::Param(param) => {
1036 self.params.insert(param.index);
1037 }
1038 ty::Bound(db, bt) if *db >= self.depth => {
1039 self.vars.insert(match bt.kind {
1040 ty::BoundTyKind::Param(def_id) => def_id,
1041 ty::BoundTyKind::Anon => {
1042 let reported = self
1043 .cx
1044 .dcx()
1045 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
1046 return ControlFlow::Break(reported);
1047 }
1048 });
1049 }
1050 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
1051 _ => {}
1052 }
1053 ControlFlow::Continue(())
1054 }
1055
1056 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
1057 match re.kind() {
1058 ty::ReEarlyParam(param) => {
1059 self.params.insert(param.index);
1060 }
1061 ty::ReBound(db, br) if db >= self.depth => {
1062 self.vars.insert(match br.kind {
1063 ty::BoundRegionKind::Named(def_id) => def_id,
1064 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1065 let guar = self
1066 .cx
1067 .dcx()
1068 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1069 return ControlFlow::Break(guar);
1070 }
1071 ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
1072 });
1073 }
1074 _ => {}
1075 }
1076 ControlFlow::Continue(())
1077 }
1078
1079 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1080 match ct.kind() {
1081 ty::ConstKind::Param(param) => {
1082 self.params.insert(param.index);
1083 }
1084 ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
1085 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1086 return ControlFlow::Break(guar);
1087 }
1088 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1089 _ => {}
1090 }
1091 ControlFlow::Continue(())
1092 }
1093}