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::{DefId, LocalDefId};
9use rustc_hir::{AmbigArg, LangItem, 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, Symbol, kw};
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_unbounds<'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 unbounds: 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 unbounds.push(ptr);
96 }
97 });
98 unbounds
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(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(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(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 should_skip_sizedness_bound<'hir>(
162 &self,
163 bound: &'hir hir::GenericBound<'tcx>,
164 ) -> bool {
165 bound
166 .trait_ref()
167 .and_then(|tr| tr.trait_def_id())
168 .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
169 .unwrap_or(false)
170 }
171
172 pub(crate) fn add_sizedness_bounds(
181 &self,
182 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
183 self_ty: Ty<'tcx>,
184 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
185 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
186 trait_did: Option<LocalDefId>,
187 span: Span,
188 ) {
189 let tcx = self.tcx();
190
191 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
192 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
193
194 if let Some(trait_did) = trait_did {
196 let trait_did = trait_did.to_def_id();
197 if trait_did == pointee_sized_did {
199 return;
200 }
201 if tcx.trait_is_auto(trait_did) {
204 return;
205 }
206 } else {
207 let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
209 self.check_and_report_invalid_unbounds_on_param(unbounds);
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(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.do_not_provide_default_trait_bound(
412 trait_id,
413 hir_bounds,
414 self_ty_where_predicates,
415 )
416 {
417 add_trait_bound(tcx, bounds, self_ty, trait_id, span);
418 }
419 }
420
421 fn do_not_provide_default_trait_bound<'a>(
422 &self,
423 trait_def_id: DefId,
424 hir_bounds: &'a [hir::GenericBound<'tcx>],
425 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
426 ) -> bool {
427 let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
428 !collected.any()
429 }
430
431 #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
453 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
454 &self,
455 param_ty: Ty<'tcx>,
456 hir_bounds: I,
457 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
458 bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
459 predicate_filter: PredicateFilter,
460 ) where
461 'tcx: 'hir,
462 {
463 for hir_bound in hir_bounds {
464 if self.should_skip_sizedness_bound(hir_bound) {
465 continue;
466 }
467
468 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
471 if let Some(trait_ref) = hir_bound.trait_ref()
472 && let Some(trait_did) = trait_ref.trait_def_id()
473 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
474 {
475 } else {
477 continue;
478 }
479 }
480
481 match hir_bound {
482 hir::GenericBound::Trait(poly_trait_ref) => {
483 let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
484 let _ = self.lower_poly_trait_ref(
485 &poly_trait_ref.trait_ref,
486 poly_trait_ref.span,
487 constness,
488 polarity,
489 param_ty,
490 bounds,
491 predicate_filter,
492 );
493 }
494 hir::GenericBound::Outlives(lifetime) => {
495 if matches!(
497 predicate_filter,
498 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
499 ) {
500 continue;
501 }
502
503 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
504 let bound = ty::Binder::bind_with_vars(
505 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
506 bound_vars,
507 );
508 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
509 }
510 hir::GenericBound::Use(..) => {
511 }
513 }
514 }
515 }
516
517 #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
526 pub(super) fn lower_assoc_item_constraint(
527 &self,
528 hir_ref_id: hir::HirId,
529 trait_ref: ty::PolyTraitRef<'tcx>,
530 constraint: &hir::AssocItemConstraint<'tcx>,
531 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
532 duplicates: &mut FxIndexMap<DefId, Span>,
533 path_span: Span,
534 predicate_filter: PredicateFilter,
535 ) -> Result<(), ErrorGuaranteed> {
536 let tcx = self.tcx();
537
538 let assoc_tag = if constraint.gen_args.parenthesized
539 == hir::GenericArgsParentheses::ReturnTypeNotation
540 {
541 ty::AssocTag::Fn
542 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
543 constraint.kind
544 {
545 ty::AssocTag::Const
546 } else {
547 ty::AssocTag::Type
548 };
549
550 let candidate = if self.probe_trait_that_defines_assoc_item(
559 trait_ref.def_id(),
560 assoc_tag,
561 constraint.ident,
562 ) {
563 trait_ref
565 } else {
566 self.probe_single_bound_for_assoc_item(
569 || traits::supertraits(tcx, trait_ref),
570 AssocItemQSelf::Trait(trait_ref.def_id()),
571 assoc_tag,
572 constraint.ident,
573 path_span,
574 Some(constraint),
575 )?
576 };
577
578 let assoc_item = self
579 .probe_assoc_item(
580 constraint.ident,
581 assoc_tag,
582 hir_ref_id,
583 constraint.span,
584 candidate.def_id(),
585 )
586 .expect("failed to find associated item");
587
588 duplicates
589 .entry(assoc_item.def_id)
590 .and_modify(|prev_span| {
591 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
592 span: constraint.span,
593 prev_span: *prev_span,
594 item_name: constraint.ident,
595 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
596 });
597 })
598 .or_insert(constraint.span);
599
600 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
601 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
602 ty::Binder::bind_with_vars(
603 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
604 bound_vars,
605 )
606 } else {
607 let alias_term = candidate.map_bound(|trait_ref| {
611 let item_segment = hir::PathSegment {
612 ident: constraint.ident,
613 hir_id: constraint.hir_id,
614 res: Res::Err,
615 args: Some(constraint.gen_args),
616 infer_args: false,
617 };
618
619 let alias_args = self.lower_generic_args_of_assoc_item(
620 path_span,
621 assoc_item.def_id,
622 &item_segment,
623 trait_ref.args,
624 );
625 debug!(?alias_args);
626
627 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
628 });
629
630 if let Some(const_arg) = constraint.ct() {
632 if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
633 let ty = alias_term
634 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
635 let ty = check_assoc_const_binding_type(
636 self,
637 constraint.ident,
638 ty,
639 constraint.hir_id,
640 );
641 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
642 }
643 }
644
645 alias_term
646 };
647
648 match constraint.kind {
649 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
650 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
651 span: constraint.span,
652 }));
653 }
654 hir::AssocItemConstraintKind::Equality { term } => {
657 let term = match term {
658 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
659 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
660 };
661
662 let late_bound_in_projection_ty =
670 tcx.collect_constrained_late_bound_regions(projection_term);
671 let late_bound_in_term =
672 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
673 debug!(?late_bound_in_projection_ty);
674 debug!(?late_bound_in_term);
675
676 self.validate_late_bound_regions(
682 late_bound_in_projection_ty,
683 late_bound_in_term,
684 |br_name| {
685 struct_span_code_err!(
686 self.dcx(),
687 constraint.span,
688 E0582,
689 "binding for associated type `{}` references {}, \
690 which does not appear in the trait input types",
691 constraint.ident,
692 br_name
693 )
694 },
695 );
696
697 match predicate_filter {
698 PredicateFilter::All
699 | PredicateFilter::SelfOnly
700 | PredicateFilter::SelfAndAssociatedTypeBounds => {
701 let bound = projection_term.map_bound(|projection_term| {
702 ty::ClauseKind::Projection(ty::ProjectionPredicate {
703 projection_term,
704 term,
705 })
706 });
707 bounds.push((bound.upcast(tcx), constraint.span));
708 }
709 PredicateFilter::SelfTraitThatDefines(_) => {}
711 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
713 }
714 }
715 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
718 match predicate_filter {
719 PredicateFilter::All
720 | PredicateFilter::SelfAndAssociatedTypeBounds
721 | PredicateFilter::ConstIfConst => {
722 let projection_ty = projection_term
723 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
724 let param_ty =
727 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
728 self.lower_bounds(
729 param_ty,
730 hir_bounds,
731 bounds,
732 projection_ty.bound_vars(),
733 predicate_filter,
734 );
735 }
736 PredicateFilter::SelfOnly
737 | PredicateFilter::SelfTraitThatDefines(_)
738 | PredicateFilter::SelfConstIfConst => {}
739 }
740 }
741 }
742 Ok(())
743 }
744
745 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
748 let hir::TyKind::Path(qpath) = hir_ty.kind else {
749 return self.lower_ty(hir_ty);
750 };
751
752 let tcx = self.tcx();
753 match qpath {
754 hir::QPath::Resolved(opt_self_ty, path)
755 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
756 && item_segment.args.is_some_and(|args| {
757 matches!(
758 args.parenthesized,
759 hir::GenericArgsParentheses::ReturnTypeNotation
760 )
761 }) =>
762 {
763 let _ =
765 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
766
767 let item_def_id = match path.res {
768 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
769 Res::Err => {
770 return Ty::new_error_with_message(
771 tcx,
772 hir_ty.span,
773 "failed to resolve RTN",
774 );
775 }
776 _ => bug!("only expected method resolution for fully qualified RTN"),
777 };
778 let trait_def_id = tcx.parent(item_def_id);
779
780 let Some(self_ty) = opt_self_ty else {
782 let guar = self.report_missing_self_ty_for_resolved_path(
783 trait_def_id,
784 hir_ty.span,
785 item_segment,
786 ty::AssocTag::Type,
787 );
788 return Ty::new_error(tcx, guar);
789 };
790 let self_ty = self.lower_ty(self_ty);
791
792 let trait_ref = self.lower_mono_trait_ref(
793 hir_ty.span,
794 trait_def_id,
795 self_ty,
796 trait_segment,
797 false,
798 );
799
800 let candidate =
813 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
814
815 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
816 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
817 Err(guar) => Ty::new_error(tcx, guar),
818 }
819 }
820 hir::QPath::TypeRelative(hir_self_ty, segment)
821 if segment.args.is_some_and(|args| {
822 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
823 }) =>
824 {
825 let self_ty = self.lower_ty(hir_self_ty);
826 let (item_def_id, bound) = match self.resolve_type_relative_path(
827 self_ty,
828 hir_self_ty,
829 ty::AssocTag::Fn,
830 segment,
831 hir_ty.hir_id,
832 hir_ty.span,
833 None,
834 ) {
835 Ok(result) => result,
836 Err(guar) => return Ty::new_error(tcx, guar),
837 };
838
839 if bound.has_bound_vars() {
846 return Ty::new_error(
847 tcx,
848 self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
849 span: hir_ty.span,
850 inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
851 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
852 mpart_sugg: None,
853 what: tcx.def_descr(item_def_id),
854 }),
855 );
856 }
857
858 match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
859 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
860 Err(guar) => Ty::new_error(tcx, guar),
861 }
862 }
863 _ => self.lower_ty(hir_ty),
864 }
865 }
866
867 fn lower_return_type_notation_ty(
872 &self,
873 candidate: ty::PolyTraitRef<'tcx>,
874 item_def_id: DefId,
875 path_span: Span,
876 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
877 let tcx = self.tcx();
878 let mut emitted_bad_param_err = None;
879 let mut num_bound_vars = candidate.bound_vars().len();
882 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
883 let arg = match param.kind {
884 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
885 tcx,
886 ty::INNERMOST,
887 ty::BoundRegion {
888 var: ty::BoundVar::from_usize(num_bound_vars),
889 kind: ty::BoundRegionKind::Named(param.def_id, param.name),
890 },
891 )
892 .into(),
893 ty::GenericParamDefKind::Type { .. } => {
894 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
895 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
896 span: path_span,
897 param_span: tcx.def_span(param.def_id),
898 })
899 });
900 Ty::new_error(tcx, guar).into()
901 }
902 ty::GenericParamDefKind::Const { .. } => {
903 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
904 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
905 span: path_span,
906 param_span: tcx.def_span(param.def_id),
907 })
908 });
909 ty::Const::new_error(tcx, guar).into()
910 }
911 };
912 num_bound_vars += 1;
913 arg
914 });
915
916 let output = tcx.fn_sig(item_def_id).skip_binder().output();
919 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
920 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
921 {
922 alias_ty
923 } else {
924 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
925 span: path_span,
926 ty: tcx.liberate_late_bound_regions(item_def_id, output),
927 fn_span: tcx.hir_span_if_local(item_def_id),
928 note: (),
929 }));
930 };
931
932 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
937 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
938 }
939}
940
941fn check_assoc_const_binding_type<'tcx>(
953 cx: &dyn HirTyLowerer<'tcx>,
954 assoc_const: Ident,
955 ty: ty::Binder<'tcx, Ty<'tcx>>,
956 hir_id: hir::HirId,
957) -> Ty<'tcx> {
958 let ty = ty.skip_binder();
965 if !ty.has_param() && !ty.has_escaping_bound_vars() {
966 return ty;
967 }
968
969 let mut collector = GenericParamAndBoundVarCollector {
970 cx,
971 params: Default::default(),
972 vars: Default::default(),
973 depth: ty::INNERMOST,
974 };
975 let mut guar = ty.visit_with(&mut collector).break_value();
976
977 let tcx = cx.tcx();
978 let ty_note = ty
979 .make_suggestable(tcx, false, None)
980 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
981
982 let enclosing_item_owner_id = tcx
983 .hir_parent_owner_iter(hir_id)
984 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
985 .unwrap();
986 let generics = tcx.generics_of(enclosing_item_owner_id);
987 for index in collector.params {
988 let param = generics.param_at(index as _, tcx);
989 let is_self_param = param.name == kw::SelfUpper;
990 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
991 span: assoc_const.span,
992 assoc_const,
993 param_name: param.name,
994 param_def_kind: tcx.def_descr(param.def_id),
995 param_category: if is_self_param {
996 "self"
997 } else if param.kind.is_synthetic() {
998 "synthetic"
999 } else {
1000 "normal"
1001 },
1002 param_defined_here_label:
1003 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
1004 ty_note,
1005 }));
1006 }
1007 for (var_def_id, var_name) in collector.vars {
1008 guar.get_or_insert(cx.dcx().emit_err(
1009 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
1010 span: assoc_const.span,
1011 assoc_const,
1012 var_name,
1013 var_def_kind: tcx.def_descr(var_def_id),
1014 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
1015 ty_note,
1016 },
1017 ));
1018 }
1019
1020 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
1021 Ty::new_error(tcx, guar)
1022}
1023
1024struct GenericParamAndBoundVarCollector<'a, 'tcx> {
1025 cx: &'a dyn HirTyLowerer<'tcx>,
1026 params: FxIndexSet<u32>,
1027 vars: FxIndexSet<(DefId, Symbol)>,
1028 depth: ty::DebruijnIndex,
1029}
1030
1031impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
1032 type Result = ControlFlow<ErrorGuaranteed>;
1033
1034 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
1035 &mut self,
1036 binder: &ty::Binder<'tcx, T>,
1037 ) -> Self::Result {
1038 self.depth.shift_in(1);
1039 let result = binder.super_visit_with(self);
1040 self.depth.shift_out(1);
1041 result
1042 }
1043
1044 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
1045 match ty.kind() {
1046 ty::Param(param) => {
1047 self.params.insert(param.index);
1048 }
1049 ty::Bound(db, bt) if *db >= self.depth => {
1050 self.vars.insert(match bt.kind {
1051 ty::BoundTyKind::Param(def_id, name) => (def_id, name),
1052 ty::BoundTyKind::Anon => {
1053 let reported = self
1054 .cx
1055 .dcx()
1056 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
1057 return ControlFlow::Break(reported);
1058 }
1059 });
1060 }
1061 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
1062 _ => {}
1063 }
1064 ControlFlow::Continue(())
1065 }
1066
1067 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
1068 match re.kind() {
1069 ty::ReEarlyParam(param) => {
1070 self.params.insert(param.index);
1071 }
1072 ty::ReBound(db, br) if db >= self.depth => {
1073 self.vars.insert(match br.kind {
1074 ty::BoundRegionKind::Named(def_id, name) => (def_id, name),
1075 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1076 let guar = self
1077 .cx
1078 .dcx()
1079 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1080 return ControlFlow::Break(guar);
1081 }
1082 });
1083 }
1084 _ => {}
1085 }
1086 ControlFlow::Continue(())
1087 }
1088
1089 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1090 match ct.kind() {
1091 ty::ConstKind::Param(param) => {
1092 self.params.insert(param.index);
1093 }
1094 ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
1095 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1096 return ControlFlow::Break(guar);
1097 }
1098 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1099 _ => {}
1100 }
1101 ControlFlow::Continue(())
1102 }
1103}