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, HirId};
10use rustc_middle::bug;
11use rustc_middle::ty::{
12 self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
13 TypeVisitableExt, TypeVisitor, Upcast,
14};
15use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, 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
26impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27 pub(crate) fn add_default_traits(
28 &self,
29 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
30 self_ty: Ty<'tcx>,
31 hir_bounds: &[hir::GenericBound<'tcx>],
32 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
33 span: Span,
34 ) {
35 self.add_default_traits_with_filter(
36 bounds,
37 self_ty,
38 hir_bounds,
39 self_ty_where_predicates,
40 span,
41 |_| true,
42 );
43 }
44
45 fn requires_default_supertraits(
85 &self,
86 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
87 hir_generics: &'tcx hir::Generics<'tcx>,
88 ) -> bool {
89 struct TraitInfoCollector;
90
91 impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
92 type Result = ControlFlow<()>;
93
94 fn visit_assoc_item_constraint(
95 &mut self,
96 _constraint: &'tcx hir::AssocItemConstraint<'tcx>,
97 ) -> Self::Result {
98 ControlFlow::Break(())
99 }
100
101 fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
102 if matches!(
103 &t.kind,
104 hir::TyKind::Path(hir::QPath::Resolved(
105 _,
106 hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
107 ))
108 ) {
109 return ControlFlow::Break(());
110 }
111 hir::intravisit::walk_ty(self, t)
112 }
113 }
114
115 let mut found = false;
116 for bound in hir_bounds {
117 found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
118 }
119 found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
120 found
121 }
122
123 pub(crate) fn add_default_trait_item_bounds(
127 &self,
128 trait_item: &hir::TraitItem<'tcx>,
129 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
130 ) {
131 let tcx = self.tcx();
132 if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
133 return;
134 }
135
136 let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
137 let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
138 unreachable!();
139 };
140
141 let (trait_generics, trait_bounds) = match parent_trait.kind {
142 hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits),
143 hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
144 _ => unreachable!(),
145 };
146
147 if !self.requires_default_supertraits(trait_bounds, trait_generics) {
148 let self_ty_where_predicates = (parent, trait_item.generics.predicates);
149 self.add_default_traits_with_filter(
150 bounds,
151 tcx.types.self_param,
152 &[],
153 Some(self_ty_where_predicates),
154 trait_item.span,
155 |tr| tr != hir::LangItem::Sized,
156 );
157 }
158 }
159
160 pub(crate) fn add_default_super_traits(
163 &self,
164 trait_def_id: LocalDefId,
165 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
166 hir_bounds: &'tcx [hir::GenericBound<'tcx>],
167 hir_generics: &'tcx hir::Generics<'tcx>,
168 span: Span,
169 ) {
170 if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
171 return;
172 }
173
174 assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
175 if self.requires_default_supertraits(hir_bounds, hir_generics) {
176 let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
177 self.add_default_traits_with_filter(
178 bounds,
179 self.tcx().types.self_param,
180 hir_bounds,
181 Some(self_ty_where_predicates),
182 span,
183 |default_trait| default_trait != hir::LangItem::Sized,
184 );
185 }
186 }
187
188 pub(crate) fn add_default_traits_with_filter(
189 &self,
190 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
191 self_ty: Ty<'tcx>,
192 hir_bounds: &[hir::GenericBound<'tcx>],
193 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
194 span: Span,
195 f: impl Fn(hir::LangItem) -> bool,
196 ) {
197 self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each(
198 |default_trait| {
199 self.add_default_trait(
200 *default_trait,
201 bounds,
202 self_ty,
203 hir_bounds,
204 self_ty_where_predicates,
205 span,
206 );
207 },
208 );
209 }
210
211 pub(crate) fn add_default_trait(
215 &self,
216 trait_: hir::LangItem,
217 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
218 self_ty: Ty<'tcx>,
219 hir_bounds: &[hir::GenericBound<'tcx>],
220 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
221 span: Span,
222 ) {
223 let trait_id = self.tcx().lang_items().get(trait_);
224 if let Some(trait_id) = trait_id
225 && self.do_not_provide_default_trait_bound(
226 trait_id,
227 hir_bounds,
228 self_ty_where_predicates,
229 )
230 {
231 let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]);
234 bounds.insert(0, (trait_ref.upcast(self.tcx()), span));
236 }
237 }
238
239 fn do_not_provide_default_trait_bound<'a>(
240 &self,
241 trait_def_id: DefId,
242 hir_bounds: &'a [hir::GenericBound<'tcx>],
243 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
244 ) -> bool {
245 let tcx = self.tcx();
246 let mut seen_negative_bound = false;
247 let mut seen_positive_bound = false;
248
249 let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
251 let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| {
252 for hir_bound in hir_bounds {
253 let hir::GenericBound::Trait(ptr) = hir_bound else {
254 continue;
255 };
256 match ptr.modifiers.polarity {
257 hir::BoundPolarity::Maybe(_) => unbounds.push(ptr),
258 hir::BoundPolarity::Negative(_) => {
259 if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
260 seen_negative_bound = true;
261 }
262 }
263 hir::BoundPolarity::Positive => {
264 if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
265 seen_positive_bound = true;
266 }
267 }
268 }
269 }
270 };
271 search_bounds(hir_bounds);
272 if let Some((self_ty, where_clause)) = self_ty_where_predicates {
273 for clause in where_clause {
274 if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
275 && pred.is_param_bound(self_ty.to_def_id())
276 {
277 search_bounds(pred.bounds);
278 }
279 }
280 }
281
282 let mut unique_bounds = FxIndexSet::default();
283 let mut seen_repeat = false;
284 for unbound in &unbounds {
285 if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
286 seen_repeat |= !unique_bounds.insert(unbound_def_id);
287 }
288 }
289 if unbounds.len() > 1 {
290 let err = errors::MultipleRelaxedDefaultBounds {
291 spans: unbounds.iter().map(|ptr| ptr.span).collect(),
292 };
293 if seen_repeat {
294 self.dcx().emit_err(err);
295 } else if !tcx.features().more_maybe_bounds() {
296 self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
297 };
298 }
299
300 let mut seen_unbound = false;
301 for unbound in unbounds {
302 let unbound_def_id = unbound.trait_ref.trait_def_id();
303 if unbound_def_id == Some(trait_def_id) {
304 seen_unbound = true;
305 }
306 let emit_relax_err = || {
307 let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
308 true => "`?Sized` and `experimental_default_bounds`",
309 false => "`?Sized`",
310 };
311 tcx.dcx().span_err(
313 unbound.span,
314 format!(
315 "relaxing a default bound only does something for {}; \
316 all other traits are not bound by default",
317 unbound_traits
318 ),
319 );
320 };
321 match unbound_def_id {
322 Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(),
323 None => emit_relax_err(),
324 _ => {}
325 }
326 }
327
328 !(seen_unbound || seen_negative_bound || seen_positive_bound)
329 }
330
331 #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
353 pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
354 &self,
355 param_ty: Ty<'tcx>,
356 hir_bounds: I,
357 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
358 bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
359 predicate_filter: PredicateFilter,
360 ) where
361 'tcx: 'hir,
362 {
363 for hir_bound in hir_bounds {
364 if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
367 if let Some(trait_ref) = hir_bound.trait_ref()
368 && let Some(trait_did) = trait_ref.trait_def_id()
369 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident)
370 {
371 } else {
373 continue;
374 }
375 }
376
377 match hir_bound {
378 hir::GenericBound::Trait(poly_trait_ref) => {
379 let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
380 let _ = self.lower_poly_trait_ref(
381 &poly_trait_ref.trait_ref,
382 poly_trait_ref.span,
383 constness,
384 polarity,
385 param_ty,
386 bounds,
387 predicate_filter,
388 );
389 }
390 hir::GenericBound::Outlives(lifetime) => {
391 if matches!(
393 predicate_filter,
394 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
395 ) {
396 continue;
397 }
398
399 let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
400 let bound = ty::Binder::bind_with_vars(
401 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
402 bound_vars,
403 );
404 bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
405 }
406 hir::GenericBound::Use(..) => {
407 }
409 }
410 }
411 }
412
413 #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
422 pub(super) fn lower_assoc_item_constraint(
423 &self,
424 hir_ref_id: hir::HirId,
425 trait_ref: ty::PolyTraitRef<'tcx>,
426 constraint: &hir::AssocItemConstraint<'tcx>,
427 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
428 duplicates: &mut FxIndexMap<DefId, Span>,
429 path_span: Span,
430 predicate_filter: PredicateFilter,
431 ) -> Result<(), ErrorGuaranteed> {
432 let tcx = self.tcx();
433
434 let assoc_tag = if constraint.gen_args.parenthesized
435 == hir::GenericArgsParentheses::ReturnTypeNotation
436 {
437 ty::AssocTag::Fn
438 } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
439 constraint.kind
440 {
441 ty::AssocTag::Const
442 } else {
443 ty::AssocTag::Type
444 };
445
446 let candidate = if self.probe_trait_that_defines_assoc_item(
455 trait_ref.def_id(),
456 assoc_tag,
457 constraint.ident,
458 ) {
459 trait_ref
461 } else {
462 self.probe_single_bound_for_assoc_item(
465 || traits::supertraits(tcx, trait_ref),
466 AssocItemQSelf::Trait(trait_ref.def_id()),
467 assoc_tag,
468 constraint.ident,
469 path_span,
470 Some(constraint),
471 )?
472 };
473
474 let assoc_item = self
475 .probe_assoc_item(
476 constraint.ident,
477 assoc_tag,
478 hir_ref_id,
479 constraint.span,
480 candidate.def_id(),
481 )
482 .expect("failed to find associated item");
483
484 duplicates
485 .entry(assoc_item.def_id)
486 .and_modify(|prev_span| {
487 self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
488 span: constraint.span,
489 prev_span: *prev_span,
490 item_name: constraint.ident,
491 def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
492 });
493 })
494 .or_insert(constraint.span);
495
496 let projection_term = if let ty::AssocTag::Fn = assoc_tag {
497 let bound_vars = tcx.late_bound_vars(constraint.hir_id);
498 ty::Binder::bind_with_vars(
499 self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
500 bound_vars,
501 )
502 } else {
503 let alias_term = candidate.map_bound(|trait_ref| {
507 let item_segment = hir::PathSegment {
508 ident: constraint.ident,
509 hir_id: constraint.hir_id,
510 res: Res::Err,
511 args: Some(constraint.gen_args),
512 infer_args: false,
513 };
514
515 let alias_args = self.lower_generic_args_of_assoc_item(
516 path_span,
517 assoc_item.def_id,
518 &item_segment,
519 trait_ref.args,
520 );
521 debug!(?alias_args);
522
523 ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
524 });
525
526 if let Some(const_arg) = constraint.ct() {
528 if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
529 let ty = alias_term
530 .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
531 let ty = check_assoc_const_binding_type(
532 self,
533 constraint.ident,
534 ty,
535 constraint.hir_id,
536 );
537 tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
538 }
539 }
540
541 alias_term
542 };
543
544 match constraint.kind {
545 hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
546 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
547 span: constraint.span,
548 }));
549 }
550 hir::AssocItemConstraintKind::Equality { term } => {
553 let term = match term {
554 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
555 hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
556 };
557
558 let late_bound_in_projection_ty =
566 tcx.collect_constrained_late_bound_regions(projection_term);
567 let late_bound_in_term =
568 tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
569 debug!(?late_bound_in_projection_ty);
570 debug!(?late_bound_in_term);
571
572 self.validate_late_bound_regions(
578 late_bound_in_projection_ty,
579 late_bound_in_term,
580 |br_name| {
581 struct_span_code_err!(
582 self.dcx(),
583 constraint.span,
584 E0582,
585 "binding for associated type `{}` references {}, \
586 which does not appear in the trait input types",
587 constraint.ident,
588 br_name
589 )
590 },
591 );
592
593 match predicate_filter {
594 PredicateFilter::All
595 | PredicateFilter::SelfOnly
596 | PredicateFilter::SelfAndAssociatedTypeBounds => {
597 let bound = projection_term.map_bound(|projection_term| {
598 ty::ClauseKind::Projection(ty::ProjectionPredicate {
599 projection_term,
600 term,
601 })
602 });
603 bounds.push((bound.upcast(tcx), constraint.span));
604 }
605 PredicateFilter::SelfTraitThatDefines(_) => {}
607 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
609 }
610 }
611 hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
614 match predicate_filter {
615 PredicateFilter::All
616 | PredicateFilter::SelfAndAssociatedTypeBounds
617 | PredicateFilter::ConstIfConst => {
618 let projection_ty = projection_term
619 .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
620 let param_ty =
623 Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
624 self.lower_bounds(
625 param_ty,
626 hir_bounds,
627 bounds,
628 projection_ty.bound_vars(),
629 predicate_filter,
630 );
631 }
632 PredicateFilter::SelfOnly
633 | PredicateFilter::SelfTraitThatDefines(_)
634 | PredicateFilter::SelfConstIfConst => {}
635 }
636 }
637 }
638 Ok(())
639 }
640
641 pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
644 let hir::TyKind::Path(qpath) = hir_ty.kind else {
645 return self.lower_ty(hir_ty);
646 };
647
648 let tcx = self.tcx();
649 match qpath {
650 hir::QPath::Resolved(opt_self_ty, path)
651 if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
652 && item_segment.args.is_some_and(|args| {
653 matches!(
654 args.parenthesized,
655 hir::GenericArgsParentheses::ReturnTypeNotation
656 )
657 }) =>
658 {
659 let _ =
661 self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
662
663 let item_def_id = match path.res {
664 Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
665 Res::Err => {
666 return Ty::new_error_with_message(
667 tcx,
668 hir_ty.span,
669 "failed to resolve RTN",
670 );
671 }
672 _ => bug!("only expected method resolution for fully qualified RTN"),
673 };
674 let trait_def_id = tcx.parent(item_def_id);
675
676 let Some(self_ty) = opt_self_ty else {
678 let guar = self.error_missing_qpath_self_ty(
679 trait_def_id,
680 hir_ty.span,
681 item_segment,
682 ty::AssocTag::Type,
683 );
684 return Ty::new_error(tcx, guar);
685 };
686 let self_ty = self.lower_ty(self_ty);
687
688 let trait_ref = self.lower_mono_trait_ref(
689 hir_ty.span,
690 trait_def_id,
691 self_ty,
692 trait_segment,
693 false,
694 );
695
696 let candidate =
709 ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
710
711 match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
712 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
713 Err(guar) => Ty::new_error(tcx, guar),
714 }
715 }
716 hir::QPath::TypeRelative(qself, item_segment)
717 if item_segment.args.is_some_and(|args| {
718 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
719 }) =>
720 {
721 match self
722 .resolve_type_relative_return_type_notation(
723 qself,
724 item_segment,
725 hir_ty.hir_id,
726 hir_ty.span,
727 )
728 .and_then(|(candidate, item_def_id)| {
729 self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span)
730 }) {
731 Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
732 Err(guar) => Ty::new_error(tcx, guar),
733 }
734 }
735 _ => self.lower_ty(hir_ty),
736 }
737 }
738
739 fn resolve_type_relative_return_type_notation(
742 &self,
743 qself: &'tcx hir::Ty<'tcx>,
744 item_segment: &'tcx hir::PathSegment<'tcx>,
745 qpath_hir_id: HirId,
746 span: Span,
747 ) -> Result<(ty::PolyTraitRef<'tcx>, DefId), ErrorGuaranteed> {
748 let tcx = self.tcx();
749 let qself_ty = self.lower_ty(qself);
750 let assoc_ident = item_segment.ident;
751 let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
752 path.res
753 } else {
754 Res::Err
755 };
756
757 let bound = match (qself_ty.kind(), qself_res) {
758 (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
759 let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
762 self.dcx().span_bug(span, "expected cycle error");
764 };
765
766 self.probe_single_bound_for_assoc_item(
767 || {
768 traits::supertraits(
769 tcx,
770 ty::Binder::dummy(trait_ref.instantiate_identity()),
771 )
772 },
773 AssocItemQSelf::SelfTyAlias,
774 ty::AssocTag::Fn,
775 assoc_ident,
776 span,
777 None,
778 )?
779 }
780 (
781 &ty::Param(_),
782 Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
783 ) => self.probe_single_ty_param_bound_for_assoc_item(
784 param_did.expect_local(),
785 qself.span,
786 ty::AssocTag::Fn,
787 assoc_ident,
788 span,
789 )?,
790 _ => {
791 if let Err(reported) = qself_ty.error_reported() {
792 return Err(reported);
793 } else {
794 let err = struct_span_code_err!(
796 self.dcx(),
797 span,
798 E0223,
799 "ambiguous associated function"
800 );
801 return Err(err.emit());
802 }
803 }
804 };
805
806 if bound.has_bound_vars() {
813 return Err(self.tcx().dcx().emit_err(
814 errors::AssociatedItemTraitUninferredGenericParams {
815 span,
816 inferred_sugg: Some(span.with_hi(item_segment.ident.span.lo())),
817 bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder(),),
818 mpart_sugg: None,
819 what: "function",
820 },
821 ));
822 }
823
824 let trait_def_id = bound.def_id();
825 let assoc_ty = self
826 .probe_assoc_item(assoc_ident, ty::AssocTag::Fn, qpath_hir_id, span, trait_def_id)
827 .expect("failed to find associated type");
828
829 Ok((bound, assoc_ty.def_id))
830 }
831
832 fn lower_return_type_notation_ty(
837 &self,
838 candidate: ty::PolyTraitRef<'tcx>,
839 item_def_id: DefId,
840 path_span: Span,
841 ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
842 let tcx = self.tcx();
843 let mut emitted_bad_param_err = None;
844 let mut num_bound_vars = candidate.bound_vars().len();
847 let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
848 let arg = match param.kind {
849 ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
850 tcx,
851 ty::INNERMOST,
852 ty::BoundRegion {
853 var: ty::BoundVar::from_usize(num_bound_vars),
854 kind: ty::BoundRegionKind::Named(param.def_id, param.name),
855 },
856 )
857 .into(),
858 ty::GenericParamDefKind::Type { .. } => {
859 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
860 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
861 span: path_span,
862 param_span: tcx.def_span(param.def_id),
863 })
864 });
865 Ty::new_error(tcx, guar).into()
866 }
867 ty::GenericParamDefKind::Const { .. } => {
868 let guar = *emitted_bad_param_err.get_or_insert_with(|| {
869 self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
870 span: path_span,
871 param_span: tcx.def_span(param.def_id),
872 })
873 });
874 ty::Const::new_error(tcx, guar).into()
875 }
876 };
877 num_bound_vars += 1;
878 arg
879 });
880
881 let output = tcx.fn_sig(item_def_id).skip_binder().output();
884 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
885 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
886 {
887 alias_ty
888 } else {
889 return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
890 span: path_span,
891 ty: tcx.liberate_late_bound_regions(item_def_id, output),
892 fn_span: tcx.hir_span_if_local(item_def_id),
893 note: (),
894 }));
895 };
896
897 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
902 Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
903 }
904}
905
906fn check_assoc_const_binding_type<'tcx>(
918 cx: &dyn HirTyLowerer<'tcx>,
919 assoc_const: Ident,
920 ty: ty::Binder<'tcx, Ty<'tcx>>,
921 hir_id: hir::HirId,
922) -> Ty<'tcx> {
923 let ty = ty.skip_binder();
930 if !ty.has_param() && !ty.has_escaping_bound_vars() {
931 return ty;
932 }
933
934 let mut collector = GenericParamAndBoundVarCollector {
935 cx,
936 params: Default::default(),
937 vars: Default::default(),
938 depth: ty::INNERMOST,
939 };
940 let mut guar = ty.visit_with(&mut collector).break_value();
941
942 let tcx = cx.tcx();
943 let ty_note = ty
944 .make_suggestable(tcx, false, None)
945 .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
946
947 let enclosing_item_owner_id = tcx
948 .hir_parent_owner_iter(hir_id)
949 .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
950 .unwrap();
951 let generics = tcx.generics_of(enclosing_item_owner_id);
952 for index in collector.params {
953 let param = generics.param_at(index as _, tcx);
954 let is_self_param = param.name == kw::SelfUpper;
955 guar.get_or_insert(cx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
956 span: assoc_const.span,
957 assoc_const,
958 param_name: param.name,
959 param_def_kind: tcx.def_descr(param.def_id),
960 param_category: if is_self_param {
961 "self"
962 } else if param.kind.is_synthetic() {
963 "synthetic"
964 } else {
965 "normal"
966 },
967 param_defined_here_label:
968 (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
969 ty_note,
970 }));
971 }
972 for (var_def_id, var_name) in collector.vars {
973 guar.get_or_insert(cx.dcx().emit_err(
974 crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
975 span: assoc_const.span,
976 assoc_const,
977 var_name,
978 var_def_kind: tcx.def_descr(var_def_id),
979 var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
980 ty_note,
981 },
982 ));
983 }
984
985 let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
986 Ty::new_error(tcx, guar)
987}
988
989struct GenericParamAndBoundVarCollector<'a, 'tcx> {
990 cx: &'a dyn HirTyLowerer<'tcx>,
991 params: FxIndexSet<u32>,
992 vars: FxIndexSet<(DefId, Symbol)>,
993 depth: ty::DebruijnIndex,
994}
995
996impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
997 type Result = ControlFlow<ErrorGuaranteed>;
998
999 fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
1000 &mut self,
1001 binder: &ty::Binder<'tcx, T>,
1002 ) -> Self::Result {
1003 self.depth.shift_in(1);
1004 let result = binder.super_visit_with(self);
1005 self.depth.shift_out(1);
1006 result
1007 }
1008
1009 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
1010 match ty.kind() {
1011 ty::Param(param) => {
1012 self.params.insert(param.index);
1013 }
1014 ty::Bound(db, bt) if *db >= self.depth => {
1015 self.vars.insert(match bt.kind {
1016 ty::BoundTyKind::Param(def_id, name) => (def_id, name),
1017 ty::BoundTyKind::Anon => {
1018 let reported = self
1019 .cx
1020 .dcx()
1021 .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
1022 return ControlFlow::Break(reported);
1023 }
1024 });
1025 }
1026 _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
1027 _ => {}
1028 }
1029 ControlFlow::Continue(())
1030 }
1031
1032 fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
1033 match re.kind() {
1034 ty::ReEarlyParam(param) => {
1035 self.params.insert(param.index);
1036 }
1037 ty::ReBound(db, br) if db >= self.depth => {
1038 self.vars.insert(match br.kind {
1039 ty::BoundRegionKind::Named(def_id, name) => (def_id, name),
1040 ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
1041 let guar = self
1042 .cx
1043 .dcx()
1044 .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
1045 return ControlFlow::Break(guar);
1046 }
1047 });
1048 }
1049 _ => {}
1050 }
1051 ControlFlow::Continue(())
1052 }
1053
1054 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
1055 match ct.kind() {
1056 ty::ConstKind::Param(param) => {
1057 self.params.insert(param.index);
1058 }
1059 ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
1060 let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
1061 return ControlFlow::Break(guar);
1062 }
1063 _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
1064 _ => {}
1065 }
1066 ControlFlow::Continue(())
1067 }
1068}