]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | use rustc_data_structures::fx::FxHashMap; |
2 | use rustc_hir as hir; | |
064997fb | 3 | use rustc_hir::def_id::DefId; |
5099ac24 FG |
4 | use rustc_middle::ty::{self, TyCtxt}; |
5 | ||
6 | pub 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 | ||
16 | fn 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 | ||
30 | fn 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 | ||
35 | fn 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 |
42 | fn 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 | 77 | fn 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 | 95 | fn 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 | } |