]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/assoc.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / assoc.rs
CommitLineData
6a06907d
XL
1pub use self::AssocItemContainer::*;
2
3use crate::ty;
4use rustc_data_structures::sorted_map::SortedIndexMultiMap;
5use rustc_hir as hir;
6use rustc_hir::def::{DefKind, Namespace};
7use rustc_hir::def_id::DefId;
8use rustc_span::symbol::{Ident, Symbol};
9
10use super::{TyCtxt, Visibility};
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
13pub enum AssocItemContainer {
14 TraitContainer(DefId),
15 ImplContainer(DefId),
16}
17
18impl AssocItemContainer {
94222f64
XL
19 pub fn impl_def_id(&self) -> Option<DefId> {
20 match *self {
21 ImplContainer(id) => Some(id),
22 _ => None,
23 }
24 }
25
6a06907d
XL
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
5099ac24 43/// Information about an associated item
6a06907d
XL
44#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
45pub struct AssocItem {
46 pub def_id: DefId,
5099ac24 47 pub name: Symbol,
6a06907d
XL
48 pub kind: AssocKind,
49 pub vis: Visibility,
50 pub defaultness: hir::Defaultness,
51 pub container: AssocItemContainer,
52
5099ac24
FG
53 /// If this is an item in an impl of a trait then this is the `DefId` of
54 /// the associated item on the trait that this implements.
55 pub trait_item_def_id: Option<DefId>,
56
6a06907d
XL
57 /// Whether this is a method with an explicit self
58 /// as its first parameter, allowing method calls.
59 pub fn_has_self_parameter: bool,
60}
61
62impl AssocItem {
5099ac24
FG
63 pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
64 Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
65 }
66
6a06907d
XL
67 pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
68 match self.kind {
69 ty::AssocKind::Fn => {
70 // We skip the binder here because the binder would deanonymize all
71 // late-bound regions, and we don't want method signatures to show up
72 // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
73 // regions just fine, showing `fn(&MyType)`.
74 tcx.fn_sig(self.def_id).skip_binder().to_string()
75 }
5099ac24 76 ty::AssocKind::Type => format!("type {};", self.name),
6a06907d 77 ty::AssocKind::Const => {
5099ac24 78 format!("const {}: {:?};", self.name, tcx.type_of(self.def_id))
6a06907d
XL
79 }
80 }
81 }
82}
83
84#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
85pub enum AssocKind {
86 Const,
87 Fn,
88 Type,
89}
90
91impl AssocKind {
92 pub fn namespace(&self) -> Namespace {
93 match *self {
94 ty::AssocKind::Type => Namespace::TypeNS,
95 ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
96 }
97 }
98
99 pub fn as_def_kind(&self) -> DefKind {
100 match self {
101 AssocKind::Const => DefKind::AssocConst,
102 AssocKind::Fn => DefKind::AssocFn,
103 AssocKind::Type => DefKind::AssocTy,
104 }
105 }
106}
107
108/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
109///
110/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
111/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
112/// done only on items with the same name.
113#[derive(Debug, Clone, PartialEq, HashStable)]
cdc7bbd5 114pub struct AssocItems<'tcx> {
6a06907d
XL
115 pub(super) items: SortedIndexMultiMap<u32, Symbol, &'tcx ty::AssocItem>,
116}
117
cdc7bbd5 118impl<'tcx> AssocItems<'tcx> {
6a06907d
XL
119 /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
120 pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self {
5099ac24 121 let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
cdc7bbd5 122 AssocItems { items }
6a06907d
XL
123 }
124
125 /// Returns a slice of associated items in the order they were defined.
126 ///
127 /// New code should avoid relying on definition order. If you need a particular associated item
128 /// for a known trait, make that trait a lang item instead of indexing this array.
129 pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
130 self.items.iter().map(|(_, v)| *v)
131 }
132
133 pub fn len(&self) -> usize {
134 self.items.len()
135 }
136
137 /// Returns an iterator over all associated items with the given name, ignoring hygiene.
138 pub fn filter_by_name_unhygienic(
139 &self,
140 name: Symbol,
141 ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
136023e0 142 self.items.get_by_key(name).copied()
6a06907d
XL
143 }
144
6a06907d
XL
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)
5099ac24
FG
155 .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
156 }
157
158 /// Returns the associated item with the given name and any of `AssocKind`, if one exists.
159 pub fn find_by_name_and_kinds(
160 &self,
161 tcx: TyCtxt<'_>,
162 ident: Ident,
163 // Sorted in order of what kinds to look at
164 kinds: &[AssocKind],
165 parent_def_id: DefId,
166 ) -> Option<&ty::AssocItem> {
167 kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id))
6a06907d
XL
168 }
169
170 /// Returns the associated item with the given name in the given `Namespace`, if one exists.
171 pub fn find_by_name_and_namespace(
172 &self,
173 tcx: TyCtxt<'_>,
174 ident: Ident,
175 ns: Namespace,
176 parent_def_id: DefId,
177 ) -> Option<&ty::AssocItem> {
178 self.filter_by_name_unhygienic(ident.name)
179 .filter(|item| item.kind.namespace() == ns)
5099ac24 180 .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
6a06907d
XL
181 }
182}