]>
git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/ty/assoc.rs
1 pub use self::AssocItemContainer
::*;
4 use rustc_data_structures
::sorted_map
::SortedIndexMultiMap
;
6 use rustc_hir
::def
::{DefKind, Namespace}
;
7 use rustc_hir
::def_id
::DefId
;
8 use rustc_span
::symbol
::{Ident, Symbol}
;
10 use super::{TyCtxt, Visibility}
;
12 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
13 pub enum AssocItemContainer
{
14 TraitContainer(DefId
),
18 impl AssocItemContainer
{
19 pub fn impl_def_id(&self) -> Option
<DefId
> {
21 ImplContainer(id
) => Some(id
),
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
{
30 TraitContainer(id
) => id
,
31 _
=> bug
!("associated item has wrong container type: {:?}", self),
35 pub fn id(&self) -> DefId
{
37 TraitContainer(id
) => id
,
38 ImplContainer(id
) => id
,
43 /// Information about an associated item
44 #[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)]
45 pub struct AssocItem
{
50 pub defaultness
: hir
::Defaultness
,
51 pub container
: AssocItemContainer
,
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
>,
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
,
63 pub fn ident(&self, tcx
: TyCtxt
<'_
>) -> Ident
{
64 Ident
::new(self.name
, tcx
.def_ident_span(self.def_id
).unwrap())
67 pub fn signature(&self, tcx
: TyCtxt
<'_
>) -> String
{
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()
76 ty
::AssocKind
::Type
=> format
!("type {};", self.name
),
77 ty
::AssocKind
::Const
=> {
78 format
!("const {}: {:?};", self.name
, tcx
.type_of(self.def_id
))
84 #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
92 pub fn namespace(&self) -> Namespace
{
94 ty
::AssocKind
::Type
=> Namespace
::TypeNS
,
95 ty
::AssocKind
::Const
| ty
::AssocKind
::Fn
=> Namespace
::ValueNS
,
99 pub fn as_def_kind(&self) -> DefKind
{
101 AssocKind
::Const
=> DefKind
::AssocConst
,
102 AssocKind
::Fn
=> DefKind
::AssocFn
,
103 AssocKind
::Type
=> DefKind
::AssocTy
,
108 /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
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)]
114 pub struct AssocItems
<'tcx
> {
115 pub(super) items
: SortedIndexMultiMap
<u32, Symbol
, &'tcx ty
::AssocItem
>,
118 impl<'tcx
> AssocItems
<'tcx
> {
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 {
121 let items
= items_in_def_order
.into_iter().map(|item
| (item
.name
, item
)).collect();
125 /// Returns a slice of associated items in the order they were defined.
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
)
133 pub fn len(&self) -> usize {
137 /// Returns an iterator over all associated items with the given name, ignoring hygiene.
138 pub fn filter_by_name_unhygienic(
141 ) -> impl '_
+ Iterator
<Item
= &ty
::AssocItem
> {
142 self.items
.get_by_key(name
).copied()
145 /// Returns the associated item with the given name and `AssocKind`, if one exists.
146 pub fn find_by_name_and_kind(
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(tcx
), parent_def_id
))
158 /// Returns the associated item with the given name and any of `AssocKind`, if one exists.
159 pub fn find_by_name_and_kinds(
163 // Sorted in order of what kinds to look at
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
))
170 /// Returns the associated item with the given name in the given `Namespace`, if one exists.
171 pub fn find_by_name_and_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
)
180 .find(|item
| tcx
.hygienic_eq(ident
, item
.ident(tcx
), parent_def_id
))