1 use rustc_data_structures::fx::FxHashMap;
3 use rustc_hir::def_id::DefId;
4 use rustc_middle::ty::{self, TyCtxt};
6 pub fn provide(providers: &mut ty::query::Providers) {
7 *providers = ty::query::Providers {
9 associated_item_def_ids,
11 impl_item_implementor_ids,
17 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
18 let item = tcx.hir().expect_item(def_id.expect_local());
20 hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
21 trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
23 hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
24 impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()),
26 hir::ItemKind::TraitAlias(..) => &[],
27 _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
31 fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
32 let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
33 ty::AssocItems::new(items)
36 fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
37 tcx.associated_items(impl_id)
38 .in_definition_order()
39 .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
43 /// If the given `DefId` describes an item belonging to a trait,
44 /// returns the `DefId` of the trait that the trait item belongs to;
45 /// otherwise, returns `None`.
46 fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
47 tcx.opt_associated_item(def_id).and_then(|associated_item| associated_item.trait_container(tcx))
50 fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
51 let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
52 let parent_def_id = tcx.hir().get_parent_item(id);
53 let parent_item = tcx.hir().expect_item(parent_def_id);
54 match parent_item.kind {
55 hir::ItemKind::Impl(ref impl_) => {
56 if let Some(impl_item_ref) =
57 impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id)
59 let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
60 debug_assert_eq!(assoc_item.def_id, def_id);
65 hir::ItemKind::Trait(.., ref trait_item_refs) => {
66 if let Some(trait_item_ref) =
67 trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id)
69 let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
70 debug_assert_eq!(assoc_item.def_id, def_id);
80 "unexpected parent of trait or impl item or item not found: {:?}",
85 fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
86 let def_id = trait_item_ref.id.def_id;
87 let (kind, has_self) = match trait_item_ref.kind {
88 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
89 hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
90 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
94 name: trait_item_ref.ident.name,
96 def_id: def_id.to_def_id(),
97 trait_item_def_id: Some(def_id.to_def_id()),
98 container: ty::TraitContainer,
99 fn_has_self_parameter: has_self,
103 fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
104 let def_id = impl_item_ref.id.def_id;
105 let (kind, has_self) = match impl_item_ref.kind {
106 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
107 hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
108 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
112 name: impl_item_ref.ident.name,
114 def_id: def_id.to_def_id(),
115 trait_item_def_id: impl_item_ref.trait_item_def_id,
116 container: ty::ImplContainer,
117 fn_has_self_parameter: has_self,