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