]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/assoc.rs
VxWorks does provide sigemptyset and sigaddset
[rust.git] / compiler / rustc_middle / src / ty / assoc.rs
1 pub use self::AssocItemContainer::*;
2
3 use crate::ty;
4 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
5 use rustc_hir as hir;
6 use rustc_hir::def::{DefKind, Namespace};
7 use rustc_hir::def_id::DefId;
8 use rustc_span::symbol::{Ident, Symbol};
9
10 use super::{TyCtxt, Visibility};
11
12 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
13 pub enum AssocItemContainer {
14     TraitContainer(DefId),
15     ImplContainer(DefId),
16 }
17
18 impl AssocItemContainer {
19     /// Asserts that this is the `DefId` of an associated item declared
20     /// in a trait, and returns the trait `DefId`.
21     pub fn assert_trait(&self) -> DefId {
22         match *self {
23             TraitContainer(id) => id,
24             _ => bug!("associated item has wrong container type: {:?}", self),
25         }
26     }
27
28     pub fn id(&self) -> DefId {
29         match *self {
30             TraitContainer(id) => id,
31             ImplContainer(id) => id,
32         }
33     }
34 }
35
36 #[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
37 pub struct AssocItem {
38     pub def_id: DefId,
39     #[stable_hasher(project(name))]
40     pub ident: Ident,
41     pub kind: AssocKind,
42     pub vis: Visibility,
43     pub defaultness: hir::Defaultness,
44     pub container: AssocItemContainer,
45
46     /// Whether this is a method with an explicit self
47     /// as its first parameter, allowing method calls.
48     pub fn_has_self_parameter: bool,
49 }
50
51 impl AssocItem {
52     pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
53         match self.kind {
54             ty::AssocKind::Fn => {
55                 // We skip the binder here because the binder would deanonymize all
56                 // late-bound regions, and we don't want method signatures to show up
57                 // `as for<'r> fn(&'r MyType)`.  Pretty-printing handles late-bound
58                 // regions just fine, showing `fn(&MyType)`.
59                 tcx.fn_sig(self.def_id).skip_binder().to_string()
60             }
61             ty::AssocKind::Type => format!("type {};", self.ident),
62             ty::AssocKind::Const => {
63                 format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id))
64             }
65         }
66     }
67 }
68
69 #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
70 pub enum AssocKind {
71     Const,
72     Fn,
73     Type,
74 }
75
76 impl AssocKind {
77     pub fn namespace(&self) -> Namespace {
78         match *self {
79             ty::AssocKind::Type => Namespace::TypeNS,
80             ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
81         }
82     }
83
84     pub fn as_def_kind(&self) -> DefKind {
85         match self {
86             AssocKind::Const => DefKind::AssocConst,
87             AssocKind::Fn => DefKind::AssocFn,
88             AssocKind::Type => DefKind::AssocTy,
89         }
90     }
91 }
92
93 /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
94 ///
95 /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
96 /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
97 /// done only on items with the same name.
98 #[derive(Debug, Clone, PartialEq, HashStable)]
99 pub struct AssocItems<'tcx> {
100     pub(super) items: SortedIndexMultiMap<u32, Symbol, &'tcx ty::AssocItem>,
101 }
102
103 impl<'tcx> AssocItems<'tcx> {
104     /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
105     pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self {
106         let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect();
107         AssocItems { items }
108     }
109
110     /// Returns a slice of associated items in the order they were defined.
111     ///
112     /// New code should avoid relying on definition order. If you need a particular associated item
113     /// for a known trait, make that trait a lang item instead of indexing this array.
114     pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
115         self.items.iter().map(|(_, v)| *v)
116     }
117
118     pub fn len(&self) -> usize {
119         self.items.len()
120     }
121
122     /// Returns an iterator over all associated items with the given name, ignoring hygiene.
123     pub fn filter_by_name_unhygienic(
124         &self,
125         name: Symbol,
126     ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
127         self.items.get_by_key(&name).copied()
128     }
129
130     /// Returns an iterator over all associated items with the given name.
131     ///
132     /// Multiple items may have the same name if they are in different `Namespace`s. For example,
133     /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*`
134     /// methods below if you know which item you are looking for.
135     pub fn filter_by_name(
136         &'a self,
137         tcx: TyCtxt<'a>,
138         ident: Ident,
139         parent_def_id: DefId,
140     ) -> impl 'a + Iterator<Item = &'a ty::AssocItem> {
141         self.filter_by_name_unhygienic(ident.name)
142             .filter(move |item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
143     }
144
145     /// Returns the associated item with the given name and `AssocKind`, if one exists.
146     pub fn find_by_name_and_kind(
147         &self,
148         tcx: TyCtxt<'_>,
149         ident: Ident,
150         kind: AssocKind,
151         parent_def_id: DefId,
152     ) -> Option<&ty::AssocItem> {
153         self.filter_by_name_unhygienic(ident.name)
154             .filter(|item| item.kind == kind)
155             .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
156     }
157
158     /// Returns the associated item with the given name in the given `Namespace`, if one exists.
159     pub fn find_by_name_and_namespace(
160         &self,
161         tcx: TyCtxt<'_>,
162         ident: Ident,
163         ns: Namespace,
164         parent_def_id: DefId,
165     ) -> Option<&ty::AssocItem> {
166         self.filter_by_name_unhygienic(ident.name)
167             .filter(|item| item.kind.namespace() == ns)
168             .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
169     }
170 }