]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_ty_utils/src/assoc.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_ty_utils / src / assoc.rs
CommitLineData
5099ac24
FG
1use rustc_data_structures::fx::FxHashMap;
2use rustc_hir as hir;
064997fb 3use rustc_hir::def_id::DefId;
5099ac24
FG
4use rustc_middle::ty::{self, TyCtxt};
5
6pub fn provide(providers: &mut ty::query::Providers) {
7 *providers = ty::query::Providers {
8 associated_item,
9 associated_item_def_ids,
10 associated_items,
11 impl_item_implementor_ids,
5099ac24
FG
12 ..*providers
13 };
14}
15
16fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
17 let item = tcx.hir().expect_item(def_id.expect_local());
18 match item.kind {
19 hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
20 trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
21 ),
22 hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
23 impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()),
24 ),
25 hir::ItemKind::TraitAlias(..) => &[],
26 _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
27 }
28}
29
30fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
31 let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
32 ty::AssocItems::new(items)
33}
34
35fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
36 tcx.associated_items(impl_id)
37 .in_definition_order()
38 .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
39 .collect()
40}
41
5099ac24
FG
42fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
43 let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
44 let parent_def_id = tcx.hir().get_parent_item(id);
45 let parent_item = tcx.hir().expect_item(parent_def_id);
46 match parent_item.kind {
47 hir::ItemKind::Impl(ref impl_) => {
48 if let Some(impl_item_ref) =
49 impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id)
50 {
064997fb 51 let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
5099ac24
FG
52 debug_assert_eq!(assoc_item.def_id, def_id);
53 return assoc_item;
54 }
55 }
56
57 hir::ItemKind::Trait(.., ref trait_item_refs) => {
58 if let Some(trait_item_ref) =
59 trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id)
60 {
064997fb 61 let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
5099ac24
FG
62 debug_assert_eq!(assoc_item.def_id, def_id);
63 return assoc_item;
64 }
65 }
66
67 _ => {}
68 }
69
70 span_bug!(
71 parent_item.span,
72 "unexpected parent of trait or impl item or item not found: {:?}",
73 parent_item.kind
74 )
75}
76
064997fb 77fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
5099ac24
FG
78 let def_id = trait_item_ref.id.def_id;
79 let (kind, has_self) = match trait_item_ref.kind {
80 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
81 hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
82 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
83 };
84
85 ty::AssocItem {
86 name: trait_item_ref.ident.name,
87 kind,
5099ac24
FG
88 def_id: def_id.to_def_id(),
89 trait_item_def_id: Some(def_id.to_def_id()),
064997fb 90 container: ty::TraitContainer,
5099ac24
FG
91 fn_has_self_parameter: has_self,
92 }
93}
94
064997fb 95fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
5099ac24
FG
96 let def_id = impl_item_ref.id.def_id;
97 let (kind, has_self) = match impl_item_ref.kind {
98 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
99 hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
100 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
101 };
102
103 ty::AssocItem {
104 name: impl_item_ref.ident.name,
105 kind,
5099ac24
FG
106 def_id: def_id.to_def_id(),
107 trait_item_def_id: impl_item_ref.trait_item_def_id,
064997fb 108 container: ty::ImplContainer,
5099ac24
FG
109 fn_has_self_parameter: has_self,
110 }
111}