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