1use rustc_data_structures::sorted_map::SortedIndexMultiMap;
2use rustc_hir as hir;
3use rustc_hir::def::{DefKind, Namespace};
4use rustc_hir::def_id::DefId;
5use rustc_macros::{Decodable, Encodable, HashStable};
6use rustc_span::{Ident, Symbol};
7
8use super::{TyCtxt, Visibility};
9use crate::ty;
10
11#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
12pub enum AssocItemContainer {
13 Trait,
14 Impl,
15}
16
17#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)]
19pub struct AssocItem {
20 pub def_id: DefId,
21 pub name: Symbol,
22 pub kind: AssocKind,
23 pub container: AssocItemContainer,
24
25 pub trait_item_def_id: Option<DefId>,
28
29 pub fn_has_self_parameter: bool,
32
33 pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
37}
38
39impl AssocItem {
40 pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
41 Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
42 }
43
44 pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
50 tcx.defaultness(self.def_id)
51 }
52
53 #[inline]
54 pub fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility<DefId> {
55 tcx.visibility(self.def_id)
56 }
57
58 #[inline]
59 pub fn container_id(&self, tcx: TyCtxt<'_>) -> DefId {
60 tcx.parent(self.def_id)
61 }
62
63 #[inline]
64 pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
65 match self.container {
66 AssocItemContainer::Impl => None,
67 AssocItemContainer::Trait => Some(tcx.parent(self.def_id)),
68 }
69 }
70
71 #[inline]
72 pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
73 match self.container {
74 AssocItemContainer::Impl => Some(tcx.parent(self.def_id)),
75 AssocItemContainer::Trait => None,
76 }
77 }
78
79 pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
80 match self.kind {
81 ty::AssocKind::Fn => {
82 tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
87 }
88 ty::AssocKind::Type => format!("type {};", self.name),
89 ty::AssocKind::Const => {
90 format!(
91 "const {}: {:?};",
92 self.name,
93 tcx.type_of(self.def_id).instantiate_identity()
94 )
95 }
96 }
97 }
98
99 pub fn descr(&self) -> &'static str {
100 match self.kind {
101 ty::AssocKind::Const => "const",
102 ty::AssocKind::Fn if self.fn_has_self_parameter => "method",
103 ty::AssocKind::Fn => "associated function",
104 ty::AssocKind::Type => "type",
105 }
106 }
107
108 pub fn is_impl_trait_in_trait(&self) -> bool {
109 self.opt_rpitit_info.is_some()
110 }
111}
112
113#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
114pub enum AssocKind {
115 Const,
116 Fn,
117 Type,
118}
119
120impl AssocKind {
121 pub fn namespace(&self) -> Namespace {
122 match *self {
123 ty::AssocKind::Type => Namespace::TypeNS,
124 ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
125 }
126 }
127
128 pub fn as_def_kind(&self) -> DefKind {
129 match self {
130 AssocKind::Const => DefKind::AssocConst,
131 AssocKind::Fn => DefKind::AssocFn,
132 AssocKind::Type => DefKind::AssocTy,
133 }
134 }
135}
136
137impl std::fmt::Display for AssocKind {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 match self {
140 AssocKind::Fn => write!(f, "method"),
141 AssocKind::Const => write!(f, "associated const"),
142 AssocKind::Type => write!(f, "associated type"),
143 }
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, HashStable)]
153pub struct AssocItems {
154 items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
155}
156
157impl AssocItems {
158 pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
160 let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
161 AssocItems { items }
162 }
163
164 pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
169 self.items.iter().map(|(_, v)| v)
170 }
171
172 pub fn len(&self) -> usize {
173 self.items.len()
174 }
175
176 pub fn filter_by_name_unhygienic(
178 &self,
179 name: Symbol,
180 ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
181 self.items.get_by_key(name)
182 }
183
184 pub fn find_by_name_and_kind(
186 &self,
187 tcx: TyCtxt<'_>,
188 ident: Ident,
189 kind: AssocKind,
190 parent_def_id: DefId,
191 ) -> Option<&ty::AssocItem> {
192 self.filter_by_name_unhygienic(ident.name)
193 .filter(|item| item.kind == kind)
194 .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
195 }
196
197 pub fn find_by_name_and_kinds(
199 &self,
200 tcx: TyCtxt<'_>,
201 ident: Ident,
202 kinds: &[AssocKind],
204 parent_def_id: DefId,
205 ) -> Option<&ty::AssocItem> {
206 kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id))
207 }
208
209 pub fn find_by_name_and_namespace(
211 &self,
212 tcx: TyCtxt<'_>,
213 ident: Ident,
214 ns: Namespace,
215 parent_def_id: DefId,
216 ) -> Option<&ty::AssocItem> {
217 self.filter_by_name_unhygienic(ident.name)
218 .filter(|item| item.kind.namespace() == ns)
219 .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
220 }
221}