1mod bounds;
17mod cmse;
18mod dyn_compatibility;
19pub mod errors;
20pub mod generics;
21mod lint;
22
23use std::assert_matches::assert_matches;
24use std::slice;
25
26use rustc_ast::TraitObjectSyntax;
27use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
28use rustc_errors::codes::*;
29use rustc_errors::{
30 Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
31};
32use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
33use rustc_hir::def_id::{DefId, LocalDefId};
34use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
35use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
36use rustc_infer::traits::ObligationCause;
37use rustc_middle::middle::stability::AllowUnstable;
38use rustc_middle::mir::interpret::LitToConstInput;
39use rustc_middle::ty::fold::fold_regions;
40use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
41use rustc_middle::ty::{
42 self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
43 TypeVisitableExt, TypingMode,
44};
45use rustc_middle::{bug, span_bug};
46use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
47use rustc_session::parse::feature_err;
48use rustc_span::edit_distance::find_best_match_for_name;
49use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
50use rustc_trait_selection::infer::InferCtxtExt;
51use rustc_trait_selection::traits::wf::object_region_bounds;
52use rustc_trait_selection::traits::{self, ObligationCtxt};
53use rustc_type_ir::Upcast;
54use tracing::{debug, instrument};
55
56use self::errors::assoc_kind_str;
57use crate::check::check_abi_fn_ptr;
58use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed};
59use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
60use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
61use crate::middle::resolve_bound_vars as rbv;
62use crate::require_c_abi_if_c_variadic;
63
64#[derive(Debug)]
66pub struct GenericPathSegment(pub DefId, pub usize);
67
68#[derive(Copy, Clone, Debug)]
69pub enum PredicateFilter {
70 All,
72
73 SelfOnly,
75
76 SelfTraitThatDefines(Ident),
80
81 SelfAndAssociatedTypeBounds,
85
86 ConstIfConst,
88
89 SelfConstIfConst,
91}
92
93#[derive(Debug)]
94pub enum RegionInferReason<'a> {
95 ExplicitObjectLifetime,
97 ObjectLifetimeDefault,
99 Param(&'a ty::GenericParamDef),
101 RegionPredicate,
102 Reference,
103 OutlivesBound,
104}
105
106pub trait HirTyLowerer<'tcx> {
111 fn tcx(&self) -> TyCtxt<'tcx>;
112
113 fn dcx(&self) -> DiagCtxtHandle<'_>;
114
115 fn item_def_id(&self) -> LocalDefId;
117
118 fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>;
120
121 fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
123
124 fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;
126
127 fn register_trait_ascription_bounds(
128 &self,
129 bounds: Vec<(ty::Clause<'tcx>, Span)>,
130 hir_id: HirId,
131 span: Span,
132 );
133
134 fn probe_ty_param_bounds(
149 &self,
150 span: Span,
151 def_id: LocalDefId,
152 assoc_name: Ident,
153 ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>;
154
155 fn lower_assoc_shared(
168 &self,
169 span: Span,
170 item_def_id: DefId,
171 item_segment: &hir::PathSegment<'tcx>,
172 poly_trait_ref: ty::PolyTraitRef<'tcx>,
173 kind: ty::AssocKind,
174 ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;
175
176 fn lower_fn_sig(
177 &self,
178 decl: &hir::FnDecl<'tcx>,
179 generics: Option<&hir::Generics<'_>>,
180 hir_id: HirId,
181 hir_ty: Option<&hir::Ty<'_>>,
182 ) -> (Vec<Ty<'tcx>>, Ty<'tcx>);
183
184 fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
191
192 fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
194
195 fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
197
198 fn lowerer(&self) -> &dyn HirTyLowerer<'tcx>
203 where
204 Self: Sized,
205 {
206 self
207 }
208}
209
210enum AssocItemQSelf {
214 Trait(DefId),
215 TyParam(LocalDefId, Span),
216 SelfTyAlias,
217}
218
219impl AssocItemQSelf {
220 fn to_string(&self, tcx: TyCtxt<'_>) -> String {
221 match *self {
222 Self::Trait(def_id) => tcx.def_path_str(def_id),
223 Self::TyParam(def_id, _) => tcx.hir_ty_param_name(def_id).to_string(),
224 Self::SelfTyAlias => kw::SelfUpper.to_string(),
225 }
226 }
227}
228
229#[derive(Debug, Clone, Copy)]
236pub enum FeedConstTy<'a, 'tcx> {
237 Param(DefId, &'a [ty::GenericArg<'tcx>]),
245 No,
247}
248
249#[derive(Debug, Clone, Copy)]
250enum LowerAssocMode {
251 Type { permit_variants: bool },
252 Const,
253}
254
255impl LowerAssocMode {
256 fn kind(self) -> ty::AssocKind {
257 match self {
258 LowerAssocMode::Type { .. } => ty::AssocKind::Type,
259 LowerAssocMode::Const => ty::AssocKind::Const,
260 }
261 }
262
263 fn def_kind(self) -> DefKind {
264 match self {
265 LowerAssocMode::Type { .. } => DefKind::AssocTy,
266 LowerAssocMode::Const => DefKind::AssocConst,
267 }
268 }
269
270 fn permit_variants(self) -> bool {
271 match self {
272 LowerAssocMode::Type { permit_variants } => permit_variants,
273 LowerAssocMode::Const => false,
275 }
276 }
277}
278
279#[derive(Debug, Clone, Copy)]
280enum LoweredAssoc<'tcx> {
281 Term(DefId, GenericArgsRef<'tcx>),
282 Variant { adt: Ty<'tcx>, variant_did: DefId },
283}
284
285#[derive(Copy, Clone, PartialEq, Debug)]
295pub enum ExplicitLateBound {
296 Yes,
297 No,
298}
299
300#[derive(Copy, Clone, PartialEq)]
301pub enum IsMethodCall {
302 Yes,
303 No,
304}
305
306#[derive(Copy, Clone, PartialEq)]
309pub(crate) enum GenericArgPosition {
310 Type,
311 Value, MethodCall,
313}
314
315#[derive(Clone, Debug)]
318pub struct GenericArgCountMismatch {
319 pub reported: ErrorGuaranteed,
320 pub invalid_args: Vec<usize>,
322}
323
324#[derive(Clone, Debug)]
327pub struct GenericArgCountResult {
328 pub explicit_late_bound: ExplicitLateBound,
329 pub correct: Result<(), GenericArgCountMismatch>,
330}
331
332pub trait GenericArgsLowerer<'a, 'tcx> {
337 fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
338
339 fn provided_kind(
340 &mut self,
341 preceding_args: &[ty::GenericArg<'tcx>],
342 param: &ty::GenericParamDef,
343 arg: &GenericArg<'tcx>,
344 ) -> ty::GenericArg<'tcx>;
345
346 fn inferred_kind(
347 &mut self,
348 preceding_args: &[ty::GenericArg<'tcx>],
349 param: &ty::GenericParamDef,
350 infer_args: bool,
351 ) -> ty::GenericArg<'tcx>;
352}
353
354impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
355 #[instrument(level = "debug", skip(self), ret)]
357 pub fn lower_lifetime(
358 &self,
359 lifetime: &hir::Lifetime,
360 reason: RegionInferReason<'_>,
361 ) -> ty::Region<'tcx> {
362 if let Some(resolved) = self.tcx().named_bound_var(lifetime.hir_id) {
363 self.lower_resolved_lifetime(resolved)
364 } else {
365 self.re_infer(lifetime.ident.span, reason)
366 }
367 }
368
369 #[instrument(level = "debug", skip(self), ret)]
371 pub fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {
372 let tcx = self.tcx();
373 let lifetime_name = |def_id| tcx.hir_name(tcx.local_def_id_to_hir_id(def_id));
374
375 match resolved {
376 rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,
377
378 rbv::ResolvedArg::LateBound(debruijn, index, def_id) => {
379 let name = lifetime_name(def_id);
380 let br = ty::BoundRegion {
381 var: ty::BoundVar::from_u32(index),
382 kind: ty::BoundRegionKind::Named(def_id.to_def_id(), name),
383 };
384 ty::Region::new_bound(tcx, debruijn, br)
385 }
386
387 rbv::ResolvedArg::EarlyBound(def_id) => {
388 let name = tcx.hir_ty_param_name(def_id);
389 let item_def_id = tcx.hir_ty_param_owner(def_id);
390 let generics = tcx.generics_of(item_def_id);
391 let index = generics.param_def_id_to_index[&def_id.to_def_id()];
392 ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
393 }
394
395 rbv::ResolvedArg::Free(scope, id) => {
396 let name = lifetime_name(id);
397 ty::Region::new_late_param(
398 tcx,
399 scope.to_def_id(),
400 ty::LateParamRegionKind::Named(id.to_def_id(), name),
401 )
402
403 }
405
406 rbv::ResolvedArg::Error(guar) => ty::Region::new_error(tcx, guar),
407 }
408 }
409
410 pub fn lower_generic_args_of_path_segment(
411 &self,
412 span: Span,
413 def_id: DefId,
414 item_segment: &hir::PathSegment<'tcx>,
415 ) -> GenericArgsRef<'tcx> {
416 let (args, _) = self.lower_generic_args_of_path(span, def_id, &[], item_segment, None);
417 if let Some(c) = item_segment.args().constraints.first() {
418 prohibit_assoc_item_constraint(self, c, Some((def_id, item_segment, span)));
419 }
420 args
421 }
422
423 #[instrument(level = "debug", skip(self, span), ret)]
458 fn lower_generic_args_of_path(
459 &self,
460 span: Span,
461 def_id: DefId,
462 parent_args: &[ty::GenericArg<'tcx>],
463 segment: &hir::PathSegment<'tcx>,
464 self_ty: Option<Ty<'tcx>>,
465 ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
466 let tcx = self.tcx();
471 let generics = tcx.generics_of(def_id);
472 debug!(?generics);
473
474 if generics.has_self {
475 if generics.parent.is_some() {
476 assert!(!parent_args.is_empty())
479 } else {
480 assert!(self_ty.is_some());
482 }
483 } else {
484 assert!(self_ty.is_none());
485 }
486
487 let arg_count = check_generic_arg_count(
488 self,
489 def_id,
490 segment,
491 generics,
492 GenericArgPosition::Type,
493 self_ty.is_some(),
494 );
495
496 if generics.is_own_empty() {
501 return (tcx.mk_args(parent_args), arg_count);
502 }
503
504 struct GenericArgsCtxt<'a, 'tcx> {
505 lowerer: &'a dyn HirTyLowerer<'tcx>,
506 def_id: DefId,
507 generic_args: &'a GenericArgs<'tcx>,
508 span: Span,
509 infer_args: bool,
510 incorrect_args: &'a Result<(), GenericArgCountMismatch>,
511 }
512
513 impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> {
514 fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
515 if did == self.def_id {
516 (Some(self.generic_args), self.infer_args)
517 } else {
518 (None, false)
520 }
521 }
522
523 fn provided_kind(
524 &mut self,
525 preceding_args: &[ty::GenericArg<'tcx>],
526 param: &ty::GenericParamDef,
527 arg: &GenericArg<'tcx>,
528 ) -> ty::GenericArg<'tcx> {
529 let tcx = self.lowerer.tcx();
530
531 if let Err(incorrect) = self.incorrect_args {
532 if incorrect.invalid_args.contains(&(param.index as usize)) {
533 return param.to_error(tcx);
534 }
535 }
536
537 let handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
538 if has_default {
539 tcx.check_optional_stability(
540 param.def_id,
541 Some(arg.hir_id()),
542 arg.span(),
543 None,
544 AllowUnstable::No,
545 |_, _| {
546 },
552 );
553 }
554 self.lowerer.lower_ty(ty).into()
555 };
556
557 match (¶m.kind, arg) {
558 (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
559 self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into()
560 }
561 (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
562 handle_ty_args(has_default, ty.as_unambig_ty())
564 }
565 (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
566 handle_ty_args(has_default, &inf.to_ty())
567 }
568 (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
569 .lowerer
570 .lower_const_arg(
572 ct.as_unambig_ct(),
573 FeedConstTy::Param(param.def_id, preceding_args),
574 )
575 .into(),
576 (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
577 self.lowerer.ct_infer(Some(param), inf.span).into()
578 }
579 (kind, arg) => span_bug!(
580 self.span,
581 "mismatched path argument for kind {kind:?}: found arg {arg:?}"
582 ),
583 }
584 }
585
586 fn inferred_kind(
587 &mut self,
588 preceding_args: &[ty::GenericArg<'tcx>],
589 param: &ty::GenericParamDef,
590 infer_args: bool,
591 ) -> ty::GenericArg<'tcx> {
592 let tcx = self.lowerer.tcx();
593
594 if let Err(incorrect) = self.incorrect_args {
595 if incorrect.invalid_args.contains(&(param.index as usize)) {
596 return param.to_error(tcx);
597 }
598 }
599 match param.kind {
600 GenericParamDefKind::Lifetime => {
601 self.lowerer.re_infer(self.span, RegionInferReason::Param(param)).into()
602 }
603 GenericParamDefKind::Type { has_default, .. } => {
604 if !infer_args && has_default {
605 if let Some(prev) =
607 preceding_args.iter().find_map(|arg| match arg.unpack() {
608 GenericArgKind::Type(ty) => ty.error_reported().err(),
609 _ => None,
610 })
611 {
612 return Ty::new_error(tcx, prev).into();
614 }
615 tcx.at(self.span)
616 .type_of(param.def_id)
617 .instantiate(tcx, preceding_args)
618 .into()
619 } else if infer_args {
620 self.lowerer.ty_infer(Some(param), self.span).into()
621 } else {
622 Ty::new_misc_error(tcx).into()
624 }
625 }
626 GenericParamDefKind::Const { has_default, .. } => {
627 let ty = tcx
628 .at(self.span)
629 .type_of(param.def_id)
630 .instantiate(tcx, preceding_args);
631 if let Err(guar) = ty.error_reported() {
632 return ty::Const::new_error(tcx, guar).into();
633 }
634 if !infer_args && has_default {
635 tcx.const_param_default(param.def_id)
636 .instantiate(tcx, preceding_args)
637 .into()
638 } else if infer_args {
639 self.lowerer.ct_infer(Some(param), self.span).into()
640 } else {
641 ty::Const::new_misc_error(tcx).into()
643 }
644 }
645 }
646 }
647 }
648
649 let mut args_ctx = GenericArgsCtxt {
650 lowerer: self,
651 def_id,
652 span,
653 generic_args: segment.args(),
654 infer_args: segment.infer_args,
655 incorrect_args: &arg_count.correct,
656 };
657 let args = lower_generic_args(
658 self,
659 def_id,
660 parent_args,
661 self_ty.is_some(),
662 self_ty,
663 &arg_count,
664 &mut args_ctx,
665 );
666
667 (args, arg_count)
668 }
669
670 #[instrument(level = "debug", skip(self))]
671 pub fn lower_generic_args_of_assoc_item(
672 &self,
673 span: Span,
674 item_def_id: DefId,
675 item_segment: &hir::PathSegment<'tcx>,
676 parent_args: GenericArgsRef<'tcx>,
677 ) -> GenericArgsRef<'tcx> {
678 let (args, _) =
679 self.lower_generic_args_of_path(span, item_def_id, parent_args, item_segment, None);
680 if let Some(c) = item_segment.args().constraints.first() {
681 prohibit_assoc_item_constraint(self, c, Some((item_def_id, item_segment, span)));
682 }
683 args
684 }
685
686 pub fn lower_impl_trait_ref(
690 &self,
691 trait_ref: &hir::TraitRef<'tcx>,
692 self_ty: Ty<'tcx>,
693 ) -> ty::TraitRef<'tcx> {
694 let _ = self.prohibit_generic_args(
695 trait_ref.path.segments.split_last().unwrap().1.iter(),
696 GenericsArgsErrExtend::None,
697 );
698
699 self.lower_mono_trait_ref(
700 trait_ref.path.span,
701 trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
702 self_ty,
703 trait_ref.path.segments.last().unwrap(),
704 true,
705 )
706 }
707
708 #[instrument(level = "debug", skip(self, span, constness, bounds))]
732 pub(crate) fn lower_poly_trait_ref(
733 &self,
734 trait_ref: &hir::TraitRef<'tcx>,
735 span: Span,
736 constness: hir::BoundConstness,
737 polarity: hir::BoundPolarity,
738 self_ty: Ty<'tcx>,
739 bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
740 predicate_filter: PredicateFilter,
741 ) -> GenericArgCountResult {
742 let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
743 let trait_segment = trait_ref.path.segments.last().unwrap();
744
745 let _ = self.prohibit_generic_args(
746 trait_ref.path.segments.split_last().unwrap().1.iter(),
747 GenericsArgsErrExtend::None,
748 );
749 self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
750
751 let (generic_args, arg_count) = self.lower_generic_args_of_path(
752 trait_ref.path.span,
753 trait_def_id,
754 &[],
755 trait_segment,
756 Some(self_ty),
757 );
758
759 let tcx = self.tcx();
760 let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
761 debug!(?bound_vars);
762
763 let poly_trait_ref = ty::Binder::bind_with_vars(
764 ty::TraitRef::new_from_args(tcx, trait_def_id, generic_args),
765 bound_vars,
766 );
767
768 debug!(?poly_trait_ref);
769
770 let polarity = match polarity {
771 rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
772 rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
773 rustc_ast::BoundPolarity::Maybe(_) => {
774 for constraint in trait_segment.args().constraints {
777 let _ = self.lower_assoc_item_constraint(
778 trait_ref.hir_ref_id,
779 poly_trait_ref,
780 constraint,
781 &mut Default::default(),
782 &mut Default::default(),
783 constraint.span,
784 predicate_filter,
785 );
786 }
787 return arg_count;
788 }
789 };
790
791 match predicate_filter {
793 PredicateFilter::All
794 | PredicateFilter::SelfOnly
795 | PredicateFilter::SelfTraitThatDefines(..)
796 | PredicateFilter::SelfAndAssociatedTypeBounds => {
797 let bound = poly_trait_ref.map_bound(|trait_ref| {
798 ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
799 });
800 let bound = (bound.upcast(tcx), span);
801 if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {
803 bounds.insert(0, bound);
804 } else {
805 bounds.push(bound);
806 }
807 }
808 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
809 }
810
811 if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
812 && !self.tcx().is_const_trait(trait_def_id)
813 {
814 let (def_span, suggestion, suggestion_pre) =
815 match (trait_def_id.is_local(), self.tcx().sess.is_nightly_build()) {
816 (true, true) => (
817 None,
818 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
819 if self.tcx().features().const_trait_impl() {
820 ""
821 } else {
822 "enable `#![feature(const_trait_impl)]` in your crate and "
823 },
824 ),
825 (false, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""),
826 };
827 self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
828 span,
829 modifier: constness.as_str(),
830 def_span,
831 trait_name: self.tcx().def_path_str(trait_def_id),
832 suggestion_pre,
833 suggestion,
834 });
835 } else {
836 match predicate_filter {
837 PredicateFilter::SelfTraitThatDefines(..) => {}
839 PredicateFilter::All
840 | PredicateFilter::SelfOnly
841 | PredicateFilter::SelfAndAssociatedTypeBounds => {
842 match constness {
843 hir::BoundConstness::Always(span) => {
844 if polarity == ty::PredicatePolarity::Positive {
845 bounds.push((
846 poly_trait_ref
847 .to_host_effect_clause(tcx, ty::BoundConstness::Const),
848 span,
849 ));
850 }
851 }
852 hir::BoundConstness::Maybe(_) => {
853 }
858 hir::BoundConstness::Never => {}
859 }
860 }
861 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {
868 match constness {
869 hir::BoundConstness::Maybe(span) => {
870 if polarity == ty::PredicatePolarity::Positive {
871 bounds.push((
872 poly_trait_ref
873 .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
874 span,
875 ));
876 }
877 }
878 hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
879 }
880 }
881 }
882 }
883
884 let mut dup_constraints = FxIndexMap::default();
885 for constraint in trait_segment.args().constraints {
886 if polarity != ty::PredicatePolarity::Positive {
890 self.dcx().span_delayed_bug(
891 constraint.span,
892 "negative trait bounds should not have assoc item constraints",
893 );
894 break;
895 }
896
897 let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint(
899 trait_ref.hir_ref_id,
900 poly_trait_ref,
901 constraint,
902 bounds,
903 &mut dup_constraints,
904 constraint.span,
905 predicate_filter,
906 );
907 }
909
910 arg_count
911 }
912
913 fn lower_mono_trait_ref(
917 &self,
918 span: Span,
919 trait_def_id: DefId,
920 self_ty: Ty<'tcx>,
921 trait_segment: &hir::PathSegment<'tcx>,
922 is_impl: bool,
923 ) -> ty::TraitRef<'tcx> {
924 self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
925
926 let (generic_args, _) =
927 self.lower_generic_args_of_path(span, trait_def_id, &[], trait_segment, Some(self_ty));
928 if let Some(c) = trait_segment.args().constraints.first() {
929 prohibit_assoc_item_constraint(self, c, Some((trait_def_id, trait_segment, span)));
930 }
931 ty::TraitRef::new_from_args(self.tcx(), trait_def_id, generic_args)
932 }
933
934 fn probe_trait_that_defines_assoc_item(
935 &self,
936 trait_def_id: DefId,
937 assoc_kind: ty::AssocKind,
938 assoc_name: Ident,
939 ) -> bool {
940 self.tcx()
941 .associated_items(trait_def_id)
942 .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
943 .is_some()
944 }
945
946 fn lower_path_segment(
947 &self,
948 span: Span,
949 did: DefId,
950 item_segment: &hir::PathSegment<'tcx>,
951 ) -> Ty<'tcx> {
952 let tcx = self.tcx();
953 let args = self.lower_generic_args_of_path_segment(span, did, item_segment);
954
955 if let DefKind::TyAlias = tcx.def_kind(did)
956 && tcx.type_alias_is_lazy(did)
957 {
958 let alias_ty = ty::AliasTy::new_from_args(tcx, did, args);
962 Ty::new_alias(tcx, ty::Weak, alias_ty)
963 } else {
964 tcx.at(span).type_of(did).instantiate(tcx, args)
965 }
966 }
967
968 #[instrument(level = "debug", skip_all, ret)]
976 fn probe_single_ty_param_bound_for_assoc_item(
977 &self,
978 ty_param_def_id: LocalDefId,
979 ty_param_span: Span,
980 kind: ty::AssocKind,
981 assoc_name: Ident,
982 span: Span,
983 ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
984 debug!(?ty_param_def_id, ?assoc_name, ?span);
985 let tcx = self.tcx();
986
987 let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name);
988 debug!("predicates={:#?}", predicates);
989
990 self.probe_single_bound_for_assoc_item(
991 || {
992 let trait_refs = predicates
993 .iter_identity_copied()
994 .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
995 traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
996 },
997 AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
998 kind,
999 assoc_name,
1000 span,
1001 None,
1002 )
1003 }
1004
1005 #[instrument(level = "debug", skip(self, all_candidates, qself, constraint), ret)]
1010 fn probe_single_bound_for_assoc_item<I>(
1011 &self,
1012 all_candidates: impl Fn() -> I,
1013 qself: AssocItemQSelf,
1014 assoc_kind: ty::AssocKind,
1015 assoc_name: Ident,
1016 span: Span,
1017 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
1018 ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
1019 where
1020 I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
1021 {
1022 let tcx = self.tcx();
1023
1024 let mut matching_candidates = all_candidates().filter(|r| {
1025 self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_name)
1026 });
1027
1028 let Some(bound) = matching_candidates.next() else {
1029 let reported = self.complain_about_assoc_item_not_found(
1030 all_candidates,
1031 qself,
1032 assoc_kind,
1033 assoc_name,
1034 span,
1035 constraint,
1036 );
1037 return Err(reported);
1038 };
1039 debug!(?bound);
1040
1041 if let Some(bound2) = matching_candidates.next() {
1042 debug!(?bound2);
1043
1044 let assoc_kind_str = errors::assoc_kind_str(assoc_kind);
1045 let qself_str = qself.to_string(tcx);
1046 let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
1047 span,
1048 assoc_kind: assoc_kind_str,
1049 assoc_name,
1050 qself: &qself_str,
1051 });
1052 err.code(
1054 if let Some(constraint) = constraint
1055 && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
1056 {
1057 E0222
1058 } else {
1059 E0221
1060 },
1061 );
1062
1063 let mut where_bounds = vec![];
1066 for bound in [bound, bound2].into_iter().chain(matching_candidates) {
1067 let bound_id = bound.def_id();
1068 let bound_span = tcx
1069 .associated_items(bound_id)
1070 .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id)
1071 .and_then(|item| tcx.hir().span_if_local(item.def_id));
1072
1073 if let Some(bound_span) = bound_span {
1074 err.span_label(
1075 bound_span,
1076 format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),),
1077 );
1078 if let Some(constraint) = constraint {
1079 match constraint.kind {
1080 hir::AssocItemConstraintKind::Equality { term } => {
1081 let term: ty::Term<'_> = match term {
1082 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
1083 hir::Term::Const(ct) => {
1084 self.lower_const_arg(ct, FeedConstTy::No).into()
1085 }
1086 };
1087 if term.references_error() {
1088 continue;
1089 }
1090 where_bounds.push(format!(
1092 " T: {trait}::{assoc_name} = {term}",
1093 trait = bound.print_only_trait_path(),
1094 ));
1095 }
1096 hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
1098 }
1099 } else {
1100 err.span_suggestion_verbose(
1101 span.with_hi(assoc_name.span.lo()),
1102 "use fully-qualified syntax to disambiguate",
1103 format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
1104 Applicability::MaybeIncorrect,
1105 );
1106 }
1107 } else {
1108 err.note(format!(
1109 "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`",
1110 bound.print_only_trait_path(),
1111 ));
1112 }
1113 }
1114 if !where_bounds.is_empty() {
1115 err.help(format!(
1116 "consider introducing a new type parameter `T` and adding `where` constraints:\
1117 \n where\n T: {qself_str},\n{}",
1118 where_bounds.join(",\n"),
1119 ));
1120 let reported = err.emit();
1121 return Err(reported);
1122 }
1123 err.emit();
1124 }
1125
1126 Ok(bound)
1127 }
1128
1129 #[instrument(level = "debug", skip_all, ret)]
1157 pub fn lower_assoc_path_ty(
1158 &self,
1159 hir_ref_id: HirId,
1160 span: Span,
1161 qself_ty: Ty<'tcx>,
1162 qself: &'tcx hir::Ty<'tcx>,
1163 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1164 permit_variants: bool,
1165 ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
1166 let tcx = self.tcx();
1167 match self.lower_assoc_path_shared(
1168 hir_ref_id,
1169 span,
1170 qself_ty,
1171 qself,
1172 assoc_segment,
1173 LowerAssocMode::Type { permit_variants },
1174 )? {
1175 LoweredAssoc::Term(def_id, args) => {
1176 let alias_ty = ty::AliasTy::new_from_args(tcx, def_id, args);
1177 let ty = Ty::new_alias(tcx, alias_ty.kind(tcx), alias_ty);
1178 Ok((ty, tcx.def_kind(def_id), def_id))
1179 }
1180 LoweredAssoc::Variant { adt, variant_did } => Ok((adt, DefKind::Variant, variant_did)),
1181 }
1182 }
1183
1184 #[instrument(level = "debug", skip_all, ret)]
1185 fn lower_assoc_path_const(
1186 &self,
1187 hir_ref_id: HirId,
1188 span: Span,
1189 qself_ty: Ty<'tcx>,
1190 qself: &'tcx hir::Ty<'tcx>,
1191 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1192 ) -> Result<Const<'tcx>, ErrorGuaranteed> {
1193 let tcx = self.tcx();
1194 let (def_id, args) = match self.lower_assoc_path_shared(
1195 hir_ref_id,
1196 span,
1197 qself_ty,
1198 qself,
1199 assoc_segment,
1200 LowerAssocMode::Const,
1201 )? {
1202 LoweredAssoc::Term(def_id, args) => {
1203 if !tcx.associated_item(def_id).is_type_const_capable(tcx) {
1204 let mut err = tcx.dcx().struct_span_err(
1205 span,
1206 "use of trait associated const without `#[type_const]`",
1207 );
1208 err.note("the declaration in the trait must be marked with `#[type_const]`");
1209 return Err(err.emit());
1210 }
1211 (def_id, args)
1212 }
1213 LoweredAssoc::Variant { .. } => {
1216 span_bug!(span, "unexpected variant res for type associated const path")
1217 }
1218 };
1219 Ok(Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)))
1220 }
1221
1222 #[instrument(level = "debug", skip_all, ret)]
1223 fn lower_assoc_path_shared(
1224 &self,
1225 hir_ref_id: HirId,
1226 span: Span,
1227 qself_ty: Ty<'tcx>,
1228 qself: &'tcx hir::Ty<'tcx>,
1229 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1230 mode: LowerAssocMode,
1231 ) -> Result<LoweredAssoc<'tcx>, ErrorGuaranteed> {
1232 debug!(%qself_ty, ?assoc_segment.ident);
1233 let tcx = self.tcx();
1234
1235 let assoc_ident = assoc_segment.ident;
1236
1237 let mut variant_resolution = None;
1239 if let Some(adt_def) = self.probe_adt(span, qself_ty) {
1240 if adt_def.is_enum() {
1241 let variant_def = adt_def
1242 .variants()
1243 .iter()
1244 .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident(tcx), adt_def.did()));
1245 if let Some(variant_def) = variant_def {
1246 if mode.permit_variants() {
1247 tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
1248 let _ = self.prohibit_generic_args(
1249 slice::from_ref(assoc_segment).iter(),
1250 GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
1251 );
1252 return Ok(LoweredAssoc::Variant {
1253 adt: qself_ty,
1254 variant_did: variant_def.def_id,
1255 });
1256 } else {
1257 variant_resolution = Some(variant_def.def_id);
1258 }
1259 }
1260 }
1261
1262 if let Some((did, args)) = self.probe_inherent_assoc_shared(
1264 assoc_segment,
1265 adt_def.did(),
1266 qself_ty,
1267 hir_ref_id,
1268 span,
1269 mode.kind(),
1270 )? {
1271 return Ok(LoweredAssoc::Term(did, args));
1272 }
1273 }
1274
1275 let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1276 path.res
1277 } else {
1278 Res::Err
1279 };
1280
1281 let bound = match (qself_ty.kind(), qself_res) {
1284 (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
1285 let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
1288 self.dcx().span_bug(span, "expected cycle error");
1290 };
1291
1292 self.probe_single_bound_for_assoc_item(
1293 || {
1294 traits::supertraits(
1295 tcx,
1296 ty::Binder::dummy(trait_ref.instantiate_identity()),
1297 )
1298 },
1299 AssocItemQSelf::SelfTyAlias,
1300 mode.kind(),
1301 assoc_ident,
1302 span,
1303 None,
1304 )?
1305 }
1306 (
1307 &ty::Param(_),
1308 Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
1309 ) => self.probe_single_ty_param_bound_for_assoc_item(
1310 param_did.expect_local(),
1311 qself.span,
1312 mode.kind(),
1313 assoc_ident,
1314 span,
1315 )?,
1316 _ => {
1317 let kind_str = assoc_kind_str(mode.kind());
1318 let reported = if variant_resolution.is_some() {
1319 let msg = format!("expected {kind_str}, found variant `{assoc_ident}`");
1321 self.dcx().span_err(span, msg)
1322 } else if qself_ty.is_enum() {
1323 let mut err = self.dcx().create_err(NoVariantNamed {
1324 span: assoc_ident.span,
1325 ident: assoc_ident,
1326 ty: qself_ty,
1327 });
1328
1329 let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
1330 if let Some(variant_name) = find_best_match_for_name(
1331 &adt_def
1332 .variants()
1333 .iter()
1334 .map(|variant| variant.name)
1335 .collect::<Vec<Symbol>>(),
1336 assoc_ident.name,
1337 None,
1338 ) && let Some(variant) =
1339 adt_def.variants().iter().find(|s| s.name == variant_name)
1340 {
1341 let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())];
1342 if let hir::Node::Stmt(&hir::Stmt {
1343 kind: hir::StmtKind::Semi(expr), ..
1344 })
1345 | hir::Node::Expr(expr) = tcx.parent_hir_node(hir_ref_id)
1346 && let hir::ExprKind::Struct(..) = expr.kind
1347 {
1348 match variant.ctor {
1349 None => {
1350 suggestion = vec![(
1352 assoc_ident.span.with_hi(expr.span.hi()),
1353 if variant.fields.is_empty() {
1354 format!("{variant_name} {{}}")
1355 } else {
1356 format!(
1357 "{variant_name} {{ {} }}",
1358 variant
1359 .fields
1360 .iter()
1361 .map(|f| format!("{}: /* value */", f.name))
1362 .collect::<Vec<_>>()
1363 .join(", ")
1364 )
1365 },
1366 )];
1367 }
1368 Some((hir::def::CtorKind::Fn, def_id)) => {
1369 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
1371 let inputs = fn_sig.inputs().skip_binder();
1372 suggestion = vec![(
1373 assoc_ident.span.with_hi(expr.span.hi()),
1374 format!(
1375 "{variant_name}({})",
1376 inputs
1377 .iter()
1378 .map(|i| format!("/* {i} */"))
1379 .collect::<Vec<_>>()
1380 .join(", ")
1381 ),
1382 )];
1383 }
1384 Some((hir::def::CtorKind::Const, _)) => {
1385 suggestion = vec![(
1387 assoc_ident.span.with_hi(expr.span.hi()),
1388 variant_name.to_string(),
1389 )];
1390 }
1391 }
1392 }
1393 err.multipart_suggestion_verbose(
1394 "there is a variant with a similar name",
1395 suggestion,
1396 Applicability::HasPlaceholders,
1397 );
1398 } else {
1399 err.span_label(
1400 assoc_ident.span,
1401 format!("variant not found in `{qself_ty}`"),
1402 );
1403 }
1404
1405 if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
1406 err.span_label(sp, format!("variant `{assoc_ident}` not found here"));
1407 }
1408
1409 err.emit()
1410 } else if let Err(reported) = qself_ty.error_reported() {
1411 reported
1412 } else {
1413 self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;
1414
1415 let traits: Vec<_> =
1416 self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
1417
1418 self.report_ambiguous_assoc(
1420 span,
1421 &[qself_ty.to_string()],
1422 &traits,
1423 assoc_ident.name,
1424 mode.kind(),
1425 )
1426 };
1427 return Err(reported);
1428 }
1429 };
1430
1431 let trait_did = bound.def_id();
1432 let assoc_item = self
1433 .probe_assoc_item(assoc_ident, mode.kind(), hir_ref_id, span, trait_did)
1434 .expect("failed to find associated item");
1435 let (def_id, args) =
1436 self.lower_assoc_shared(span, assoc_item.def_id, assoc_segment, bound, mode.kind())?;
1437 let result = LoweredAssoc::Term(def_id, args);
1438
1439 if let Some(variant_def_id) = variant_resolution {
1440 tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
1441 lint.primary_message("ambiguous associated item");
1442 let mut could_refer_to = |kind: DefKind, def_id, also| {
1443 let note_msg = format!(
1444 "`{}` could{} refer to the {} defined here",
1445 assoc_ident,
1446 also,
1447 tcx.def_kind_descr(kind, def_id)
1448 );
1449 lint.span_note(tcx.def_span(def_id), note_msg);
1450 };
1451
1452 could_refer_to(DefKind::Variant, variant_def_id, "");
1453 could_refer_to(mode.def_kind(), assoc_item.def_id, " also");
1454
1455 lint.span_suggestion(
1456 span,
1457 "use fully-qualified syntax",
1458 format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
1459 Applicability::MachineApplicable,
1460 );
1461 });
1462 }
1463 Ok(result)
1464 }
1465
1466 fn probe_inherent_assoc_shared(
1467 &self,
1468 segment: &hir::PathSegment<'tcx>,
1469 adt_did: DefId,
1470 self_ty: Ty<'tcx>,
1471 block: HirId,
1472 span: Span,
1473 kind: ty::AssocKind,
1474 ) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
1475 let tcx = self.tcx();
1476
1477 if !tcx.features().inherent_associated_types() {
1478 match kind {
1479 ty::AssocKind::Type => return Ok(None),
1486 ty::AssocKind::Const => {
1487 return Err(feature_err(
1491 &tcx.sess,
1492 sym::inherent_associated_types,
1493 span,
1494 "inherent associated types are unstable",
1495 )
1496 .emit());
1497 }
1498 ty::AssocKind::Fn => unreachable!(),
1499 }
1500 }
1501
1502 let name = segment.ident;
1503 let candidates: Vec<_> = tcx
1504 .inherent_impls(adt_did)
1505 .iter()
1506 .filter_map(|&impl_| {
1507 let (item, scope) = self.probe_assoc_item_unchecked(name, kind, block, impl_)?;
1508 Some((impl_, (item.def_id, scope)))
1509 })
1510 .collect();
1511
1512 if candidates.is_empty() {
1513 return Ok(None);
1514 }
1515
1516 let infcx = match self.infcx() {
1523 Some(infcx) => infcx,
1524 None => {
1525 assert!(!self_ty.has_infer());
1526 &tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis())
1527 }
1528 };
1529
1530 let param_env = tcx.param_env(block.owner);
1533
1534 let mut universes = if self_ty.has_escaping_bound_vars() {
1535 vec![None; self_ty.outer_exclusive_binder().as_usize()]
1536 } else {
1537 vec![]
1538 };
1539
1540 let (impl_, (assoc_item, def_scope)) = crate::traits::with_replaced_escaping_bound_vars(
1541 infcx,
1542 &mut universes,
1543 self_ty,
1544 |self_ty| {
1545 self.select_inherent_assoc_candidates(
1546 infcx, name, span, self_ty, param_env, candidates, kind,
1547 )
1548 },
1549 )?;
1550
1551 self.check_assoc_item(assoc_item, name, def_scope, block, span);
1552
1553 let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
1557 let args = self.lower_generic_args_of_assoc_item(span, assoc_item, segment, parent_args);
1558 let args = tcx.mk_args_from_iter(
1559 std::iter::once(ty::GenericArg::from(self_ty))
1560 .chain(args.into_iter().skip(parent_args.len())),
1561 );
1562
1563 Ok(Some((assoc_item, args)))
1564 }
1565
1566 fn select_inherent_assoc_candidates(
1567 &self,
1568 infcx: &InferCtxt<'tcx>,
1569 name: Ident,
1570 span: Span,
1571 self_ty: Ty<'tcx>,
1572 param_env: ParamEnv<'tcx>,
1573 candidates: Vec<(DefId, (DefId, DefId))>,
1574 kind: ty::AssocKind,
1575 ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
1576 let tcx = self.tcx();
1577 let mut fulfillment_errors = Vec::new();
1578
1579 let applicable_candidates: Vec<_> = candidates
1580 .iter()
1581 .copied()
1582 .filter(|&(impl_, _)| {
1583 infcx.probe(|_| {
1584 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
1585 let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
1586
1587 let impl_args = infcx.fresh_args_for_item(span, impl_);
1588 let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
1589 let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
1590
1591 if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
1593 return false;
1594 }
1595
1596 let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
1598 let impl_bounds =
1599 ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
1600 let impl_obligations = traits::predicates_for_generics(
1601 |_, _| ObligationCause::dummy(),
1602 param_env,
1603 impl_bounds,
1604 );
1605 ocx.register_obligations(impl_obligations);
1606
1607 let mut errors = ocx.select_where_possible();
1608 if !errors.is_empty() {
1609 fulfillment_errors.append(&mut errors);
1610 return false;
1611 }
1612
1613 true
1614 })
1615 })
1616 .collect();
1617
1618 match &applicable_candidates[..] {
1619 &[] => Err(self.complain_about_inherent_assoc_not_found(
1620 name,
1621 self_ty,
1622 candidates,
1623 fulfillment_errors,
1624 span,
1625 kind,
1626 )),
1627
1628 &[applicable_candidate] => Ok(applicable_candidate),
1629
1630 &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
1631 name,
1632 applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
1633 span,
1634 )),
1635 }
1636 }
1637
1638 fn probe_assoc_item(
1642 &self,
1643 ident: Ident,
1644 kind: ty::AssocKind,
1645 block: HirId,
1646 span: Span,
1647 scope: DefId,
1648 ) -> Option<ty::AssocItem> {
1649 let (item, scope) = self.probe_assoc_item_unchecked(ident, kind, block, scope)?;
1650 self.check_assoc_item(item.def_id, ident, scope, block, span);
1651 Some(item)
1652 }
1653
1654 fn probe_assoc_item_unchecked(
1659 &self,
1660 ident: Ident,
1661 kind: ty::AssocKind,
1662 block: HirId,
1663 scope: DefId,
1664 ) -> Option<(ty::AssocItem, DefId)> {
1665 let tcx = self.tcx();
1666
1667 let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block);
1668 let item = tcx
1672 .associated_items(scope)
1673 .filter_by_name_unhygienic(ident.name)
1674 .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
1675
1676 Some((*item, def_scope))
1677 }
1678
1679 fn check_assoc_item(
1681 &self,
1682 item_def_id: DefId,
1683 ident: Ident,
1684 scope: DefId,
1685 block: HirId,
1686 span: Span,
1687 ) {
1688 let tcx = self.tcx();
1689
1690 if !tcx.visibility(item_def_id).is_accessible_from(scope, tcx) {
1691 self.dcx().emit_err(crate::errors::AssocItemIsPrivate {
1692 span,
1693 kind: tcx.def_descr(item_def_id),
1694 name: ident,
1695 defined_here_label: tcx.def_span(item_def_id),
1696 });
1697 }
1698
1699 tcx.check_stability(item_def_id, Some(block), span, None);
1700 }
1701
1702 fn probe_traits_that_match_assoc_ty(
1703 &self,
1704 qself_ty: Ty<'tcx>,
1705 assoc_ident: Ident,
1706 ) -> Vec<String> {
1707 let tcx = self.tcx();
1708
1709 let infcx_;
1712 let infcx = if let Some(infcx) = self.infcx() {
1713 infcx
1714 } else {
1715 assert!(!qself_ty.has_infer());
1716 infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
1717 &infcx_
1718 };
1719
1720 tcx.all_traits()
1721 .filter(|trait_def_id| {
1722 tcx.associated_items(*trait_def_id)
1724 .in_definition_order()
1725 .any(|i| {
1726 i.kind.namespace() == Namespace::TypeNS
1727 && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
1728 && matches!(i.kind, ty::AssocKind::Type)
1729 })
1730 && tcx.visibility(*trait_def_id)
1732 .is_accessible_from(self.item_def_id(), tcx)
1733 && tcx.all_impls(*trait_def_id)
1734 .any(|impl_def_id| {
1735 let impl_header = tcx.impl_trait_header(impl_def_id);
1736 impl_header.is_some_and(|header| {
1737 let trait_ref = header.trait_ref.instantiate(
1738 tcx,
1739 infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
1740 );
1741
1742 let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
1743 if value.has_escaping_bound_vars() {
1745 return false;
1746 }
1747 infcx
1748 .can_eq(
1749 ty::ParamEnv::empty(),
1750 trait_ref.self_ty(),
1751 value,
1752 ) && header.polarity != ty::ImplPolarity::Negative
1753 })
1754 })
1755 })
1756 .map(|trait_def_id| tcx.def_path_str(trait_def_id))
1757 .collect()
1758 }
1759
1760 #[instrument(level = "debug", skip_all)]
1762 fn lower_qpath_ty(
1763 &self,
1764 span: Span,
1765 opt_self_ty: Option<Ty<'tcx>>,
1766 item_def_id: DefId,
1767 trait_segment: &hir::PathSegment<'tcx>,
1768 item_segment: &hir::PathSegment<'tcx>,
1769 ) -> Ty<'tcx> {
1770 match self.lower_qpath_shared(
1771 span,
1772 opt_self_ty,
1773 item_def_id,
1774 trait_segment,
1775 item_segment,
1776 ty::AssocKind::Type,
1777 ) {
1778 Ok((item_def_id, item_args)) => {
1779 Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
1780 }
1781 Err(guar) => Ty::new_error(self.tcx(), guar),
1782 }
1783 }
1784
1785 #[instrument(level = "debug", skip_all)]
1787 fn lower_qpath_const(
1788 &self,
1789 span: Span,
1790 opt_self_ty: Option<Ty<'tcx>>,
1791 item_def_id: DefId,
1792 trait_segment: &hir::PathSegment<'tcx>,
1793 item_segment: &hir::PathSegment<'tcx>,
1794 ) -> Const<'tcx> {
1795 match self.lower_qpath_shared(
1796 span,
1797 opt_self_ty,
1798 item_def_id,
1799 trait_segment,
1800 item_segment,
1801 ty::AssocKind::Const,
1802 ) {
1803 Ok((item_def_id, item_args)) => {
1804 let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1805 Const::new_unevaluated(self.tcx(), uv)
1806 }
1807 Err(guar) => Const::new_error(self.tcx(), guar),
1808 }
1809 }
1810
1811 #[instrument(level = "debug", skip_all)]
1812 fn lower_qpath_shared(
1813 &self,
1814 span: Span,
1815 opt_self_ty: Option<Ty<'tcx>>,
1816 item_def_id: DefId,
1817 trait_segment: &hir::PathSegment<'tcx>,
1818 item_segment: &hir::PathSegment<'tcx>,
1819 kind: ty::AssocKind,
1820 ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
1821 let tcx = self.tcx();
1822
1823 let trait_def_id = tcx.parent(item_def_id);
1824 debug!(?trait_def_id);
1825
1826 let Some(self_ty) = opt_self_ty else {
1827 return Err(self.error_missing_qpath_self_ty(trait_def_id, span, item_segment, kind));
1828 };
1829 debug!(?self_ty);
1830
1831 let trait_ref =
1832 self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
1833 debug!(?trait_ref);
1834
1835 let item_args =
1836 self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
1837
1838 Ok((item_def_id, item_args))
1839 }
1840
1841 fn error_missing_qpath_self_ty(
1842 &self,
1843 trait_def_id: DefId,
1844 span: Span,
1845 item_segment: &hir::PathSegment<'tcx>,
1846 kind: ty::AssocKind,
1847 ) -> ErrorGuaranteed {
1848 let tcx = self.tcx();
1849 let path_str = tcx.def_path_str(trait_def_id);
1850
1851 let def_id = self.item_def_id();
1852 debug!(item_def_id = ?def_id);
1853
1854 let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
1856 debug!(?parent_def_id);
1857
1858 let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
1861 let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
1862
1863 let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
1864 vec!["Self".to_string()]
1865 } else {
1866 tcx.all_impls(trait_def_id)
1868 .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
1869 .filter(|header| {
1870 tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
1872 && header.polarity != ty::ImplPolarity::Negative
1873 })
1874 .map(|header| header.trait_ref.instantiate_identity().self_ty())
1875 .filter(|self_ty| !self_ty.has_non_region_param())
1877 .map(|self_ty| tcx.erase_regions(self_ty).to_string())
1878 .collect()
1879 };
1880 self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
1884 }
1885
1886 pub fn prohibit_generic_args<'a>(
1887 &self,
1888 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1889 err_extend: GenericsArgsErrExtend<'a>,
1890 ) -> Result<(), ErrorGuaranteed> {
1891 let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
1892 let mut result = Ok(());
1893 if let Some(_) = args_visitors.clone().next() {
1894 result = Err(self.report_prohibit_generics_error(
1895 segments.clone(),
1896 args_visitors,
1897 err_extend,
1898 ));
1899 }
1900
1901 for segment in segments {
1902 if let Some(c) = segment.args().constraints.first() {
1904 return Err(prohibit_assoc_item_constraint(self, c, None));
1905 }
1906 }
1907
1908 result
1909 }
1910
1911 pub fn probe_generic_path_segments(
1929 &self,
1930 segments: &[hir::PathSegment<'_>],
1931 self_ty: Option<Ty<'tcx>>,
1932 kind: DefKind,
1933 def_id: DefId,
1934 span: Span,
1935 ) -> Vec<GenericPathSegment> {
1936 let tcx = self.tcx();
1982
1983 assert!(!segments.is_empty());
1984 let last = segments.len() - 1;
1985
1986 let mut generic_segments = vec![];
1987
1988 match kind {
1989 DefKind::Ctor(CtorOf::Struct, ..) => {
1991 let generics = tcx.generics_of(def_id);
1994 let generics_def_id = generics.parent.unwrap_or(def_id);
1997 generic_segments.push(GenericPathSegment(generics_def_id, last));
1998 }
1999
2000 DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
2002 let (generics_def_id, index) = if let Some(self_ty) = self_ty {
2003 let adt_def = self.probe_adt(span, self_ty).unwrap();
2004 debug_assert!(adt_def.is_enum());
2005 (adt_def.did(), last)
2006 } else if last >= 1 && segments[last - 1].args.is_some() {
2007 let mut def_id = def_id;
2010
2011 if let DefKind::Ctor(..) = kind {
2013 def_id = tcx.parent(def_id);
2014 }
2015
2016 let enum_def_id = tcx.parent(def_id);
2018 (enum_def_id, last - 1)
2019 } else {
2020 let generics = tcx.generics_of(def_id);
2026 (generics.parent.unwrap_or(def_id), last)
2029 };
2030 generic_segments.push(GenericPathSegment(generics_def_id, index));
2031 }
2032
2033 DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } => {
2035 generic_segments.push(GenericPathSegment(def_id, last));
2036 }
2037
2038 DefKind::AssocFn | DefKind::AssocConst => {
2040 if segments.len() >= 2 {
2041 let generics = tcx.generics_of(def_id);
2042 generic_segments.push(GenericPathSegment(generics.parent.unwrap(), last - 1));
2043 }
2044 generic_segments.push(GenericPathSegment(def_id, last));
2045 }
2046
2047 kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
2048 }
2049
2050 debug!(?generic_segments);
2051
2052 generic_segments
2053 }
2054
2055 #[instrument(level = "debug", skip_all)]
2057 pub fn lower_path(
2058 &self,
2059 opt_self_ty: Option<Ty<'tcx>>,
2060 path: &hir::Path<'tcx>,
2061 hir_id: HirId,
2062 permit_variants: bool,
2063 ) -> Ty<'tcx> {
2064 debug!(?path.res, ?opt_self_ty, ?path.segments);
2065 let tcx = self.tcx();
2066
2067 let span = path.span;
2068 match path.res {
2069 Res::Def(DefKind::OpaqueTy, did) => {
2070 assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
2072 let item_segment = path.segments.split_last().unwrap();
2073 let _ = self
2074 .prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
2075 let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0);
2076 Ty::new_opaque(tcx, did, args)
2077 }
2078 Res::Def(
2079 DefKind::Enum
2080 | DefKind::TyAlias
2081 | DefKind::Struct
2082 | DefKind::Union
2083 | DefKind::ForeignTy,
2084 did,
2085 ) => {
2086 assert_eq!(opt_self_ty, None);
2087 let _ = self.prohibit_generic_args(
2088 path.segments.split_last().unwrap().1.iter(),
2089 GenericsArgsErrExtend::None,
2090 );
2091 self.lower_path_segment(span, did, path.segments.last().unwrap())
2092 }
2093 Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
2094 assert_eq!(opt_self_ty, None);
2097
2098 let generic_segments =
2099 self.probe_generic_path_segments(path.segments, None, kind, def_id, span);
2100 let indices: FxHashSet<_> =
2101 generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect();
2102 let _ = self.prohibit_generic_args(
2103 path.segments.iter().enumerate().filter_map(|(index, seg)| {
2104 if !indices.contains(&index) { Some(seg) } else { None }
2105 }),
2106 GenericsArgsErrExtend::DefVariant(&path.segments),
2107 );
2108
2109 let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
2110 self.lower_path_segment(span, *def_id, &path.segments[*index])
2111 }
2112 Res::Def(DefKind::TyParam, def_id) => {
2113 assert_eq!(opt_self_ty, None);
2114 let _ = self.prohibit_generic_args(
2115 path.segments.iter(),
2116 GenericsArgsErrExtend::Param(def_id),
2117 );
2118 self.lower_ty_param(hir_id)
2119 }
2120 Res::SelfTyParam { .. } => {
2121 assert_eq!(opt_self_ty, None);
2123 let _ = self.prohibit_generic_args(
2124 path.segments.iter(),
2125 if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments {
2126 GenericsArgsErrExtend::SelfTyParam(
2127 ident.span.shrink_to_hi().to(args.span_ext),
2128 )
2129 } else {
2130 GenericsArgsErrExtend::None
2131 },
2132 );
2133 tcx.types.self_param
2134 }
2135 Res::SelfTyAlias { alias_to: def_id, forbid_generic, .. } => {
2136 assert_eq!(opt_self_ty, None);
2138 let ty = tcx.at(span).type_of(def_id).instantiate_identity();
2140 let _ = self.prohibit_generic_args(
2141 path.segments.iter(),
2142 GenericsArgsErrExtend::SelfTyAlias { def_id, span },
2143 );
2144 if forbid_generic && ty.has_param() {
2164 let mut err = self.dcx().struct_span_err(
2165 path.span,
2166 "generic `Self` types are currently not permitted in anonymous constants",
2167 );
2168 if let Some(hir::Node::Item(&hir::Item {
2169 kind: hir::ItemKind::Impl(impl_),
2170 ..
2171 })) = tcx.hir_get_if_local(def_id)
2172 {
2173 err.span_note(impl_.self_ty.span, "not a concrete type");
2174 }
2175 let reported = err.emit();
2176 Ty::new_error(tcx, reported)
2177 } else {
2178 ty
2179 }
2180 }
2181 Res::Def(DefKind::AssocTy, def_id) => {
2182 debug_assert!(path.segments.len() >= 2);
2183 let _ = self.prohibit_generic_args(
2184 path.segments[..path.segments.len() - 2].iter(),
2185 GenericsArgsErrExtend::None,
2186 );
2187 self.lower_qpath_ty(
2188 span,
2189 opt_self_ty,
2190 def_id,
2191 &path.segments[path.segments.len() - 2],
2192 path.segments.last().unwrap(),
2193 )
2194 }
2195 Res::PrimTy(prim_ty) => {
2196 assert_eq!(opt_self_ty, None);
2197 let _ = self.prohibit_generic_args(
2198 path.segments.iter(),
2199 GenericsArgsErrExtend::PrimTy(prim_ty),
2200 );
2201 match prim_ty {
2202 hir::PrimTy::Bool => tcx.types.bool,
2203 hir::PrimTy::Char => tcx.types.char,
2204 hir::PrimTy::Int(it) => Ty::new_int(tcx, ty::int_ty(it)),
2205 hir::PrimTy::Uint(uit) => Ty::new_uint(tcx, ty::uint_ty(uit)),
2206 hir::PrimTy::Float(ft) => Ty::new_float(tcx, ty::float_ty(ft)),
2207 hir::PrimTy::Str => tcx.types.str_,
2208 }
2209 }
2210 Res::Err => {
2211 let e = self
2212 .tcx()
2213 .dcx()
2214 .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
2215 Ty::new_error(tcx, e)
2216 }
2217 Res::Def(..) => {
2218 assert_eq!(
2219 path.segments.get(0).map(|seg| seg.ident.name),
2220 Some(kw::SelfUpper),
2221 "only expected incorrect resolution for `Self`"
2222 );
2223 Ty::new_error(
2224 self.tcx(),
2225 self.dcx().span_delayed_bug(span, "incorrect resolution for `Self`"),
2226 )
2227 }
2228 _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
2229 }
2230 }
2231
2232 pub(crate) fn lower_ty_param(&self, hir_id: HirId) -> Ty<'tcx> {
2237 let tcx = self.tcx();
2238 match tcx.named_bound_var(hir_id) {
2239 Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
2240 let name = tcx.item_name(def_id.to_def_id());
2241 let br = ty::BoundTy {
2242 var: ty::BoundVar::from_u32(index),
2243 kind: ty::BoundTyKind::Param(def_id.to_def_id(), name),
2244 };
2245 Ty::new_bound(tcx, debruijn, br)
2246 }
2247 Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
2248 let item_def_id = tcx.hir_ty_param_owner(def_id);
2249 let generics = tcx.generics_of(item_def_id);
2250 let index = generics.param_def_id_to_index[&def_id.to_def_id()];
2251 Ty::new_param(tcx, index, tcx.hir_ty_param_name(def_id))
2252 }
2253 Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
2254 arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
2255 }
2256 }
2257
2258 pub(crate) fn lower_const_param(&self, param_def_id: DefId, path_hir_id: HirId) -> Const<'tcx> {
2263 let tcx = self.tcx();
2264
2265 match tcx.named_bound_var(path_hir_id) {
2266 Some(rbv::ResolvedArg::EarlyBound(_)) => {
2267 let item_def_id = tcx.parent(param_def_id);
2270 let generics = tcx.generics_of(item_def_id);
2271 let index = generics.param_def_id_to_index[¶m_def_id];
2272 let name = tcx.item_name(param_def_id);
2273 ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
2274 }
2275 Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
2276 ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
2277 }
2278 Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
2279 arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
2280 }
2281 }
2282
2283 #[instrument(skip(self), level = "debug")]
2285 pub fn lower_const_arg(
2286 &self,
2287 const_arg: &hir::ConstArg<'tcx>,
2288 feed: FeedConstTy<'_, 'tcx>,
2289 ) -> Const<'tcx> {
2290 let tcx = self.tcx();
2291
2292 if let FeedConstTy::Param(param_def_id, args) = feed
2293 && let hir::ConstArgKind::Anon(anon) = &const_arg.kind
2294 {
2295 let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
2296
2297 if tcx.features().generic_const_parameter_types()
2306 && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
2307 {
2308 let e = tcx.dcx().span_err(
2309 const_arg.span(),
2310 "anonymous constants with lifetimes in their type are not yet supported",
2311 );
2312 tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
2313 return ty::Const::new_error(tcx, e);
2314 }
2315 if anon_const_type.has_non_region_infer() {
2319 let e = tcx.dcx().span_err(
2320 const_arg.span(),
2321 "anonymous constants with inferred types are not yet supported",
2322 );
2323 tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
2324 return ty::Const::new_error(tcx, e);
2325 }
2326 if anon_const_type.has_non_region_param() {
2329 let e = tcx.dcx().span_err(
2330 const_arg.span(),
2331 "anonymous constants referencing generics are not yet supported",
2332 );
2333 tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
2334 return ty::Const::new_error(tcx, e);
2335 }
2336
2337 tcx.feed_anon_const_type(
2338 anon.def_id,
2339 ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
2340 );
2341 }
2342
2343 let hir_id = const_arg.hir_id;
2344 match const_arg.kind {
2345 hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
2346 debug!(?maybe_qself, ?path);
2347 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
2348 self.lower_const_path_resolved(opt_self_ty, path, hir_id)
2349 }
2350 hir::ConstArgKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
2351 debug!(?qself, ?segment);
2352 let ty = self.lower_ty(qself);
2353 self.lower_assoc_path_const(hir_id, const_arg.span(), ty, qself, segment)
2354 .unwrap_or_else(|guar| Const::new_error(tcx, guar))
2355 }
2356 hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
2357 ty::Const::new_error_with_message(
2358 tcx,
2359 qpath.span(),
2360 format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
2361 )
2362 }
2363 hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon),
2364 hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
2365 }
2366 }
2367
2368 fn lower_const_path_resolved(
2369 &self,
2370 opt_self_ty: Option<Ty<'tcx>>,
2371 path: &hir::Path<'tcx>,
2372 hir_id: HirId,
2373 ) -> Const<'tcx> {
2374 let tcx = self.tcx();
2375 let span = path.span;
2376 match path.res {
2377 Res::Def(DefKind::ConstParam, def_id) => {
2378 assert_eq!(opt_self_ty, None);
2379 let _ = self.prohibit_generic_args(
2380 path.segments.iter(),
2381 GenericsArgsErrExtend::Param(def_id),
2382 );
2383 self.lower_const_param(def_id, hir_id)
2384 }
2385 Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
2386 assert_eq!(opt_self_ty, None);
2387 let _ = self.prohibit_generic_args(
2388 path.segments.split_last().unwrap().1.iter(),
2389 GenericsArgsErrExtend::None,
2390 );
2391 let args = self.lower_generic_args_of_path_segment(
2392 span,
2393 did,
2394 path.segments.last().unwrap(),
2395 );
2396 ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
2397 }
2398 Res::Def(DefKind::AssocConst, did) => {
2399 debug_assert!(path.segments.len() >= 2);
2400 let _ = self.prohibit_generic_args(
2401 path.segments[..path.segments.len() - 2].iter(),
2402 GenericsArgsErrExtend::None,
2403 );
2404 self.lower_qpath_const(
2405 span,
2406 opt_self_ty,
2407 did,
2408 &path.segments[path.segments.len() - 2],
2409 path.segments.last().unwrap(),
2410 )
2411 }
2412 Res::Def(DefKind::Static { .. }, _) => {
2413 span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
2414 }
2415 Res::Def(DefKind::Fn | DefKind::AssocFn, did) => {
2417 self.dcx().span_delayed_bug(span, "function items cannot be used as const args");
2418 let args = self.lower_generic_args_of_path_segment(
2419 span,
2420 did,
2421 path.segments.last().unwrap(),
2422 );
2423 ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
2424 }
2425
2426 res @ (Res::Def(
2429 DefKind::Mod
2430 | DefKind::Enum
2431 | DefKind::Variant
2432 | DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
2433 | DefKind::Struct
2434 | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
2435 | DefKind::OpaqueTy
2436 | DefKind::TyAlias
2437 | DefKind::TraitAlias
2438 | DefKind::AssocTy
2439 | DefKind::Union
2440 | DefKind::Trait
2441 | DefKind::ForeignTy
2442 | DefKind::TyParam
2443 | DefKind::Macro(_)
2444 | DefKind::LifetimeParam
2445 | DefKind::Use
2446 | DefKind::ForeignMod
2447 | DefKind::AnonConst
2448 | DefKind::InlineConst
2449 | DefKind::Field
2450 | DefKind::Impl { .. }
2451 | DefKind::Closure
2452 | DefKind::ExternCrate
2453 | DefKind::GlobalAsm
2454 | DefKind::SyntheticCoroutineBody,
2455 _,
2456 )
2457 | Res::PrimTy(_)
2458 | Res::SelfTyParam { .. }
2459 | Res::SelfTyAlias { .. }
2460 | Res::SelfCtor(_)
2461 | Res::Local(_)
2462 | Res::ToolMod
2463 | Res::NonMacroAttr(_)
2464 | Res::Err) => Const::new_error_with_message(
2465 tcx,
2466 span,
2467 format!("invalid Res {res:?} for const path"),
2468 ),
2469 }
2470 }
2471
2472 #[instrument(skip(self), level = "debug")]
2474 fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> {
2475 let tcx = self.tcx();
2476
2477 let expr = &tcx.hir_body(anon.body).value;
2478 debug!(?expr);
2479
2480 let ty = tcx.type_of(anon.def_id).instantiate_identity();
2484
2485 match self.try_lower_anon_const_lit(ty, expr) {
2486 Some(v) => v,
2487 None => ty::Const::new_unevaluated(
2488 tcx,
2489 ty::UnevaluatedConst {
2490 def: anon.def_id.to_def_id(),
2491 args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()),
2492 },
2493 ),
2494 }
2495 }
2496
2497 #[instrument(skip(self), level = "debug")]
2498 fn try_lower_anon_const_lit(
2499 &self,
2500 ty: Ty<'tcx>,
2501 expr: &'tcx hir::Expr<'tcx>,
2502 ) -> Option<Const<'tcx>> {
2503 let tcx = self.tcx();
2504
2505 let expr = match &expr.kind {
2508 hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
2509 block.expr.as_ref().unwrap()
2510 }
2511 _ => expr,
2512 };
2513
2514 if let hir::ExprKind::Path(hir::QPath::Resolved(
2515 _,
2516 &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
2517 )) = expr.kind
2518 {
2519 span_bug!(
2520 expr.span,
2521 "try_lower_anon_const_lit: received const param which shouldn't be possible"
2522 );
2523 };
2524
2525 let lit_input = match expr.kind {
2526 hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
2527 hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
2528 hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
2529 _ => None,
2530 },
2531 _ => None,
2532 };
2533
2534 lit_input
2535 .filter(|l| !l.ty.has_aliases())
2538 .map(|l| tcx.at(expr.span).lit_to_const(l))
2539 }
2540
2541 fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
2542 let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
2543 match idx {
2544 hir::InferDelegationKind::Input(idx) => delegation_sig[idx],
2545 hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(),
2546 }
2547 }
2548
2549 #[instrument(level = "debug", skip(self), ret)]
2551 pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
2552 let tcx = self.tcx();
2553
2554 let result_ty = match &hir_ty.kind {
2555 hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
2556 hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
2557 hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
2558 hir::TyKind::Ref(region, mt) => {
2559 let r = self.lower_lifetime(region, RegionInferReason::Reference);
2560 debug!(?r);
2561 let t = self.lower_ty(mt.ty);
2562 Ty::new_ref(tcx, r, t, mt.mutbl)
2563 }
2564 hir::TyKind::Never => tcx.types.never,
2565 hir::TyKind::Tup(fields) => {
2566 Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t)))
2567 }
2568 hir::TyKind::BareFn(bf) => {
2569 require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span);
2570
2571 Ty::new_fn_ptr(
2572 tcx,
2573 self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)),
2574 )
2575 }
2576 hir::TyKind::UnsafeBinder(binder) => Ty::new_unsafe_binder(
2577 tcx,
2578 ty::Binder::bind_with_vars(
2579 self.lower_ty(binder.inner_ty),
2580 tcx.late_bound_vars(hir_ty.hir_id),
2581 ),
2582 ),
2583 hir::TyKind::TraitObject(bounds, tagged_ptr) => {
2584 let lifetime = tagged_ptr.pointer();
2585 let repr = tagged_ptr.tag();
2586
2587 if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
2588 Ty::new_error(tcx, guar)
2592 } else {
2593 let repr = match repr {
2594 TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
2595 TraitObjectSyntax::DynStar => ty::DynStar,
2596 };
2597 self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
2598 }
2599 }
2600 hir::TyKind::Path(hir::QPath::Resolved(_, path))
2604 if path.segments.last().and_then(|segment| segment.args).is_some_and(|args| {
2605 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2606 }) =>
2607 {
2608 let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
2609 Ty::new_error(tcx, guar)
2610 }
2611 hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
2612 debug!(?maybe_qself, ?path);
2613 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
2614 self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
2615 }
2616 &hir::TyKind::OpaqueDef(opaque_ty) => {
2617 let in_trait = match opaque_ty.origin {
2621 hir::OpaqueTyOrigin::FnReturn {
2622 in_trait_or_impl: Some(hir::RpitContext::Trait),
2623 ..
2624 }
2625 | hir::OpaqueTyOrigin::AsyncFn {
2626 in_trait_or_impl: Some(hir::RpitContext::Trait),
2627 ..
2628 } => true,
2629 hir::OpaqueTyOrigin::FnReturn {
2630 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
2631 ..
2632 }
2633 | hir::OpaqueTyOrigin::AsyncFn {
2634 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
2635 ..
2636 }
2637 | hir::OpaqueTyOrigin::TyAlias { .. } => false,
2638 };
2639
2640 self.lower_opaque_ty(opaque_ty.def_id, in_trait)
2641 }
2642 hir::TyKind::TraitAscription(hir_bounds) => {
2643 let self_ty = self.ty_infer(None, hir_ty.span);
2646 let mut bounds = Vec::new();
2647 self.lower_bounds(
2648 self_ty,
2649 hir_bounds.iter(),
2650 &mut bounds,
2651 ty::List::empty(),
2652 PredicateFilter::All,
2653 );
2654 self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
2655 self_ty
2656 }
2657 hir::TyKind::Path(hir::QPath::TypeRelative(_, segment))
2661 if segment.args.is_some_and(|args| {
2662 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2663 }) =>
2664 {
2665 let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
2666 Ty::new_error(tcx, guar)
2667 }
2668 hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
2669 debug!(?qself, ?segment);
2670 let ty = self.lower_ty(qself);
2671 self.lower_assoc_path_ty(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false)
2672 .map(|(ty, _, _)| ty)
2673 .unwrap_or_else(|guar| Ty::new_error(tcx, guar))
2674 }
2675 &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
2676 let def_id = tcx.require_lang_item(lang_item, Some(span));
2677 let (args, _) = self.lower_generic_args_of_path(
2678 span,
2679 def_id,
2680 &[],
2681 &hir::PathSegment::invalid(),
2682 None,
2683 );
2684 tcx.at(span).type_of(def_id).instantiate(tcx, args)
2685 }
2686 hir::TyKind::Array(ty, length) => {
2687 let length = self.lower_const_arg(length, FeedConstTy::No);
2688 Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
2689 }
2690 hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(),
2691 hir::TyKind::Infer(()) => {
2692 self.ty_infer(None, hir_ty.span)
2697 }
2698 hir::TyKind::Pat(ty, pat) => {
2699 let ty_span = ty.span;
2700 let ty = self.lower_ty(ty);
2701 let pat_ty = match pat.kind {
2702 hir::TyPatKind::Range(start, end) => {
2703 let (ty, start, end) = match ty.kind() {
2704 ty::Int(_) | ty::Uint(_) | ty::Char => {
2707 let start = self.lower_const_arg(start, FeedConstTy::No);
2708 let end = self.lower_const_arg(end, FeedConstTy::No);
2709 (ty, start, end)
2710 }
2711 _ => {
2712 let guar = self.dcx().span_delayed_bug(
2713 ty_span,
2714 "invalid base type for range pattern",
2715 );
2716 let errc = ty::Const::new_error(tcx, guar);
2717 (Ty::new_error(tcx, guar), errc, errc)
2718 }
2719 };
2720
2721 let pat = tcx.mk_pat(ty::PatternKind::Range { start, end });
2722 Ty::new_pat(tcx, ty, pat)
2723 }
2724 hir::TyPatKind::Err(e) => Ty::new_error(tcx, e),
2725 };
2726 self.record_ty(pat.hir_id, ty, pat.span);
2727 pat_ty
2728 }
2729 hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
2730 };
2731
2732 self.record_ty(hir_ty.hir_id, result_ty, hir_ty.span);
2733 result_ty
2734 }
2735
2736 #[instrument(level = "debug", skip(self), ret)]
2738 fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {
2739 let tcx = self.tcx();
2740
2741 let lifetimes = tcx.opaque_captured_lifetimes(def_id);
2742 debug!(?lifetimes);
2743
2744 let def_id = if in_trait {
2748 tcx.associated_type_for_impl_trait_in_trait(def_id).to_def_id()
2749 } else {
2750 def_id.to_def_id()
2751 };
2752
2753 let generics = tcx.generics_of(def_id);
2754 debug!(?generics);
2755
2756 let offset = generics.count() - lifetimes.len();
2760
2761 let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
2762 if let Some(i) = (param.index as usize).checked_sub(offset) {
2763 let (lifetime, _) = lifetimes[i];
2764 self.lower_resolved_lifetime(lifetime).into()
2765 } else {
2766 tcx.mk_param_from_def(param)
2767 }
2768 });
2769 debug!(?args);
2770
2771 if in_trait {
2772 Ty::new_projection_from_args(tcx, def_id, args)
2773 } else {
2774 Ty::new_opaque(tcx, def_id, args)
2775 }
2776 }
2777
2778 pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
2779 match ty.kind {
2780 hir::TyKind::Infer(()) if let Some(expected_ty) = expected_ty => {
2781 self.record_ty(ty.hir_id, expected_ty, ty.span);
2782 expected_ty
2783 }
2784 _ => self.lower_ty(ty),
2785 }
2786 }
2787
2788 #[instrument(level = "debug", skip(self, hir_id, safety, abi, decl, generics, hir_ty), ret)]
2790 pub fn lower_fn_ty(
2791 &self,
2792 hir_id: HirId,
2793 safety: hir::Safety,
2794 abi: rustc_abi::ExternAbi,
2795 decl: &hir::FnDecl<'tcx>,
2796 generics: Option<&hir::Generics<'_>>,
2797 hir_ty: Option<&hir::Ty<'_>>,
2798 ) -> ty::PolyFnSig<'tcx> {
2799 let tcx = self.tcx();
2800 let bound_vars = tcx.late_bound_vars(hir_id);
2801 debug!(?bound_vars);
2802
2803 let (input_tys, output_ty) = self.lower_fn_sig(decl, generics, hir_id, hir_ty);
2804
2805 debug!(?output_ty);
2806
2807 let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
2808 let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
2809
2810 if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) =
2811 tcx.hir_node(hir_id)
2812 {
2813 check_abi_fn_ptr(tcx, hir_id, *span, bare_fn_ty.abi);
2814 }
2815
2816 cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
2818
2819 if !bare_fn_ty.references_error() {
2820 let inputs = bare_fn_ty.inputs();
2827 let late_bound_in_args =
2828 tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
2829 let output = bare_fn_ty.output();
2830 let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
2831
2832 self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
2833 struct_span_code_err!(
2834 self.dcx(),
2835 decl.output.span(),
2836 E0581,
2837 "return type references {}, which is not constrained by the fn input types",
2838 br_name
2839 )
2840 });
2841 }
2842
2843 bare_fn_ty
2844 }
2845
2846 pub(super) fn suggest_trait_fn_ty_for_impl_fn_infer(
2851 &self,
2852 fn_hir_id: HirId,
2853 arg_idx: Option<usize>,
2854 ) -> Option<Ty<'tcx>> {
2855 let tcx = self.tcx();
2856 let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
2857 tcx.hir_node(fn_hir_id)
2858 else {
2859 return None;
2860 };
2861 let i = tcx.parent_hir_node(fn_hir_id).expect_item().expect_impl();
2862
2863 let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty));
2864
2865 let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
2866 tcx,
2867 *ident,
2868 ty::AssocKind::Fn,
2869 trait_ref.def_id,
2870 )?;
2871
2872 let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(
2873 tcx,
2874 trait_ref.args.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
2875 );
2876 let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
2877
2878 Some(if let Some(arg_idx) = arg_idx {
2879 *fn_sig.inputs().get(arg_idx)?
2880 } else {
2881 fn_sig.output()
2882 })
2883 }
2884
2885 #[instrument(level = "trace", skip(self, generate_err))]
2886 fn validate_late_bound_regions<'cx>(
2887 &'cx self,
2888 constrained_regions: FxIndexSet<ty::BoundRegionKind>,
2889 referenced_regions: FxIndexSet<ty::BoundRegionKind>,
2890 generate_err: impl Fn(&str) -> Diag<'cx>,
2891 ) {
2892 for br in referenced_regions.difference(&constrained_regions) {
2893 let br_name = match *br {
2894 ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
2895 | ty::BoundRegionKind::Anon
2896 | ty::BoundRegionKind::ClosureEnv => "an anonymous lifetime".to_string(),
2897 ty::BoundRegionKind::Named(_, name) => format!("lifetime `{name}`"),
2898 };
2899
2900 let mut err = generate_err(&br_name);
2901
2902 if let ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
2903 | ty::BoundRegionKind::Anon = *br
2904 {
2905 err.note(
2912 "lifetimes appearing in an associated or opaque type are not considered constrained",
2913 );
2914 err.note("consider introducing a named lifetime parameter");
2915 }
2916
2917 err.emit();
2918 }
2919 }
2920
2921 #[instrument(level = "debug", skip(self, span), ret)]
2929 fn compute_object_lifetime_bound(
2930 &self,
2931 span: Span,
2932 existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
2933 ) -> Option<ty::Region<'tcx>> {
2935 let tcx = self.tcx();
2936
2937 let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
2940
2941 if derived_region_bounds.is_empty() {
2944 return None;
2945 }
2946
2947 if derived_region_bounds.iter().any(|r| r.is_static()) {
2950 return Some(tcx.lifetimes.re_static);
2951 }
2952
2953 let r = derived_region_bounds[0];
2957 if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
2958 self.dcx().emit_err(AmbiguousLifetimeBound { span });
2959 }
2960 Some(r)
2961 }
2962}