Skip to main content

rustc_middle/ty/
assoc.rs

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, StableHash};
6use rustc_span::def_id::ModId;
7use rustc_span::{ErrorGuaranteed, Ident, Symbol};
8
9use super::{TyCtxt, Visibility};
10use crate::ty;
11
12#[derive(#[automatically_derived]
impl ::core::clone::Clone for AssocContainer {
    #[inline]
    fn clone(&self) -> AssocContainer {
        let _:
                ::core::clone::AssertParamIsClone<Result<DefId,
                ErrorGuaranteed>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AssocContainer { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocContainer {
    #[inline]
    fn eq(&self, other: &AssocContainer) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AssocContainer::TraitImpl(__self_0),
                    AssocContainer::TraitImpl(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AssocContainer {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Result<DefId, ErrorGuaranteed>>;
    }
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for AssocContainer {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AssocContainer::Trait =>
                ::core::fmt::Formatter::write_str(f, "Trait"),
            AssocContainer::InherentImpl =>
                ::core::fmt::Formatter::write_str(f, "InherentImpl"),
            AssocContainer::TraitImpl(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "TraitImpl", &__self_0),
        }
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            AssocContainer {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    AssocContainer::Trait => {}
                    AssocContainer::InherentImpl => {}
                    AssocContainer::TraitImpl(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::hash::Hash for AssocContainer {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            AssocContainer::TraitImpl(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AssocContainer {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AssocContainer::Trait => { 0usize }
                        AssocContainer::InherentImpl => { 1usize }
                        AssocContainer::TraitImpl(ref __binding_0) => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AssocContainer::Trait => {}
                    AssocContainer::InherentImpl => {}
                    AssocContainer::TraitImpl(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AssocContainer {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AssocContainer::Trait }
                    1usize => { AssocContainer::InherentImpl }
                    2usize => {
                        AssocContainer::TraitImpl(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AssocContainer`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
13pub enum AssocContainer {
14    Trait,
15    InherentImpl,
16    /// The `DefId` points to the trait item being implemented.
17    TraitImpl(Result<DefId, ErrorGuaranteed>),
18}
19
20/// Information about an associated item
21#[derive(#[automatically_derived]
impl ::core::marker::Copy for AssocItem { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AssocItem {
    #[inline]
    fn clone(&self) -> AssocItem {
        let _: ::core::clone::AssertParamIsClone<DefId>;
        let _: ::core::clone::AssertParamIsClone<AssocKind>;
        let _: ::core::clone::AssertParamIsClone<AssocContainer>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for AssocItem {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "AssocItem",
            "def_id", &self.def_id, "kind", &self.kind, "container",
            &&self.container)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocItem {
    #[inline]
    fn eq(&self, other: &AssocItem) -> bool {
        self.def_id == other.def_id && self.kind == other.kind &&
            self.container == other.container
    }
}PartialEq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AssocItem {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AssocItem {
                        def_id: ref __binding_0,
                        kind: ref __binding_1,
                        container: ref __binding_2 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::cmp::Eq for AssocItem {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<DefId>;
        let _: ::core::cmp::AssertParamIsEq<AssocKind>;
        let _: ::core::cmp::AssertParamIsEq<AssocContainer>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AssocItem {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.def_id, state);
        ::core::hash::Hash::hash(&self.kind, state);
        ::core::hash::Hash::hash(&self.container, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AssocItem {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    AssocItem {
                        def_id: ref __binding_0,
                        kind: ref __binding_1,
                        container: ref __binding_2 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AssocItem {
            fn decode(__decoder: &mut __D) -> Self {
                AssocItem {
                    def_id: ::rustc_serialize::Decodable::decode(__decoder),
                    kind: ::rustc_serialize::Decodable::decode(__decoder),
                    container: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
22pub struct AssocItem {
23    pub def_id: DefId,
24    pub kind: AssocKind,
25    pub container: AssocContainer,
26}
27
28impl AssocItem {
29    // Gets the identifier, if it has one.
30    pub fn opt_name(&self) -> Option<Symbol> {
31        match self.kind {
32            ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name),
33            ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None,
34            ty::AssocKind::Const { name, .. } => Some(name),
35            ty::AssocKind::Fn { name, .. } => Some(name),
36        }
37    }
38
39    // Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT
40    // associated type.
41    pub fn name(&self) -> Symbol {
42        self.opt_name().expect("name of non-Rpitit assoc item")
43    }
44
45    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
46        Ident::new(self.name(), tcx.def_ident_span(self.def_id).unwrap())
47    }
48
49    /// Gets the defaultness of the associated item.
50    /// To get the default associated type, use the [`type_of`] query on the
51    /// [`DefId`] of the type.
52    ///
53    /// [`type_of`]: crate::ty::TyCtxt::type_of
54    pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
55        match self.container {
56            AssocContainer::InherentImpl => hir::Defaultness::Final,
57            AssocContainer::Trait | AssocContainer::TraitImpl(_) => tcx.defaultness(self.def_id),
58        }
59    }
60
61    pub fn expect_trait_impl(&self) -> Result<DefId, ErrorGuaranteed> {
62        let AssocContainer::TraitImpl(trait_item_id) = self.container else {
63            crate::util::bug::bug_fmt(format_args!("expected item to be in a trait impl: {0:?}",
        self.def_id));bug!("expected item to be in a trait impl: {:?}", self.def_id);
64        };
65        trait_item_id
66    }
67
68    /// If this is a trait impl item, returns the `DefId` of the trait item this implements.
69    /// Otherwise, returns `DefId` for self. Returns an Err in case the trait item was not
70    /// resolved successfully.
71    pub fn trait_item_or_self(&self) -> Result<DefId, ErrorGuaranteed> {
72        match self.container {
73            AssocContainer::TraitImpl(id) => id,
74            AssocContainer::Trait | AssocContainer::InherentImpl => Ok(self.def_id),
75        }
76    }
77
78    pub fn trait_item_def_id(&self) -> Option<DefId> {
79        match self.container {
80            AssocContainer::TraitImpl(Ok(id)) => Some(id),
81            _ => None,
82        }
83    }
84
85    #[inline]
86    pub fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility<ModId> {
87        tcx.visibility(self.def_id)
88    }
89
90    #[inline]
91    pub fn container_id(&self, tcx: TyCtxt<'_>) -> DefId {
92        tcx.parent(self.def_id)
93    }
94
95    #[inline]
96    pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
97        match self.container {
98            AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => None,
99            AssocContainer::Trait => Some(tcx.parent(self.def_id)),
100        }
101    }
102
103    #[inline]
104    pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
105        match self.container {
106            AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => {
107                Some(tcx.parent(self.def_id))
108            }
109            AssocContainer::Trait => None,
110        }
111    }
112
113    pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
114        match self.kind {
115            ty::AssocKind::Fn { .. } => {
116                // We skip the binder here because the binder would deanonymize all
117                // late-bound regions, and we don't want method signatures to show up
118                // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
119                // regions just fine, showing `fn(&MyType)`.
120                tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
121            }
122            ty::AssocKind::Type { .. } => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("type {0};", self.name()))
    })format!("type {};", self.name()),
123            ty::AssocKind::Const { name, .. } => {
124                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("const {0}: {1:?};", name,
                tcx.type_of(self.def_id).instantiate_identity()))
    })format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity())
125            }
126        }
127    }
128
129    pub fn descr(&self) -> &'static str {
130        self.kind.descr()
131    }
132
133    pub fn namespace(&self) -> Namespace {
134        self.kind.namespace()
135    }
136
137    pub fn as_def_kind(&self) -> DefKind {
138        self.kind.as_def_kind()
139    }
140
141    pub fn is_type_const(&self) -> bool {
142        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    ty::AssocKind::Const { is_type_const: true, .. } => true,
    _ => false,
}matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. })
143    }
144
145    /// Whether this associated item can be constrained with an equality binding.
146    pub fn can_have_equality_constraint(&self, tcx: TyCtxt<'_>) -> bool {
147        match self.kind {
148            ty::AssocKind::Type { .. } => true,
149            ty::AssocKind::Const { is_type_const: true, .. } => true,
150            ty::AssocKind::Const { is_type_const: false, .. } => {
151                tcx.features().generic_const_args()
152            }
153            ty::AssocKind::Fn { .. } => false,
154        }
155    }
156
157    pub fn is_fn(&self) -> bool {
158        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    ty::AssocKind::Fn { .. } => true,
    _ => false,
}matches!(self.kind, ty::AssocKind::Fn { .. })
159    }
160
161    pub fn is_method(&self) -> bool {
162        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    ty::AssocKind::Fn { has_self: true, .. } => true,
    _ => false,
}matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
163    }
164
165    pub fn is_type(&self) -> bool {
166        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    ty::AssocKind::Type { .. } => true,
    _ => false,
}matches!(self.kind, ty::AssocKind::Type { .. })
167    }
168
169    pub fn tag(&self) -> AssocTag {
170        self.kind.tag()
171    }
172
173    pub fn is_impl_trait_in_trait(&self) -> bool {
174        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    AssocKind::Type { data: AssocTypeData::Rpitit(_) } => true,
    _ => false,
}matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
175    }
176}
177
178#[derive(#[automatically_derived]
impl ::core::marker::Copy for AssocTypeData { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AssocTypeData {
    #[inline]
    fn clone(&self) -> AssocTypeData {
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<ty::ImplTraitInTraitData>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocTypeData {
    #[inline]
    fn eq(&self, other: &AssocTypeData) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AssocTypeData::Normal(__self_0),
                    AssocTypeData::Normal(__arg1_0)) => __self_0 == __arg1_0,
                (AssocTypeData::Rpitit(__self_0),
                    AssocTypeData::Rpitit(__arg1_0)) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for AssocTypeData {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AssocTypeData::Normal(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Normal",
                    &__self_0),
            AssocTypeData::Rpitit(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Rpitit",
                    &__self_0),
        }
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            AssocTypeData {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    AssocTypeData::Normal(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    AssocTypeData::Rpitit(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::cmp::Eq for AssocTypeData {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Symbol>;
        let _: ::core::cmp::AssertParamIsEq<ty::ImplTraitInTraitData>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AssocTypeData {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            AssocTypeData::Normal(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            AssocTypeData::Rpitit(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AssocTypeData {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AssocTypeData::Normal(ref __binding_0) => { 0usize }
                        AssocTypeData::Rpitit(ref __binding_0) => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AssocTypeData::Normal(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    AssocTypeData::Rpitit(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AssocTypeData {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        AssocTypeData::Normal(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        AssocTypeData::Rpitit(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AssocTypeData`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
179pub enum AssocTypeData {
180    Normal(Symbol),
181    /// The associated type comes from an RPITIT. It has no name, and the
182    /// `ImplTraitInTraitData` provides additional information about its
183    /// source.
184    Rpitit(ty::ImplTraitInTraitData),
185}
186
187#[derive(#[automatically_derived]
impl ::core::marker::Copy for AssocKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AssocKind {
    #[inline]
    fn clone(&self) -> AssocKind {
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<AssocTypeData>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocKind {
    #[inline]
    fn eq(&self, other: &AssocKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AssocKind::Const { name: __self_0, is_type_const: __self_1 },
                    AssocKind::Const { name: __arg1_0, is_type_const: __arg1_1
                    }) => __self_1 == __arg1_1 && __self_0 == __arg1_0,
                (AssocKind::Fn { name: __self_0, has_self: __self_1 },
                    AssocKind::Fn { name: __arg1_0, has_self: __arg1_1 }) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0,
                (AssocKind::Type { data: __self_0 }, AssocKind::Type {
                    data: __arg1_0 }) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for AssocKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AssocKind::Const { name: __self_0, is_type_const: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Const",
                    "name", __self_0, "is_type_const", &__self_1),
            AssocKind::Fn { name: __self_0, has_self: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Fn",
                    "name", __self_0, "has_self", &__self_1),
            AssocKind::Type { data: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Type",
                    "data", &__self_0),
        }
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AssocKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    AssocKind::Const {
                        name: ref __binding_0, is_type_const: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    AssocKind::Fn {
                        name: ref __binding_0, has_self: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    AssocKind::Type { data: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::cmp::Eq for AssocKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Symbol>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<AssocTypeData>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AssocKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            AssocKind::Const { name: __self_0, is_type_const: __self_1 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            AssocKind::Fn { name: __self_0, has_self: __self_1 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            AssocKind::Type { data: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AssocKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AssocKind::Const {
                            name: ref __binding_0, is_type_const: ref __binding_1 } => {
                            0usize
                        }
                        AssocKind::Fn {
                            name: ref __binding_0, has_self: ref __binding_1 } => {
                            1usize
                        }
                        AssocKind::Type { data: ref __binding_0 } => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AssocKind::Const {
                        name: ref __binding_0, is_type_const: ref __binding_1 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    AssocKind::Fn {
                        name: ref __binding_0, has_self: ref __binding_1 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    AssocKind::Type { data: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AssocKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        AssocKind::Const {
                            name: ::rustc_serialize::Decodable::decode(__decoder),
                            is_type_const: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    1usize => {
                        AssocKind::Fn {
                            name: ::rustc_serialize::Decodable::decode(__decoder),
                            has_self: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    2usize => {
                        AssocKind::Type {
                            data: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AssocKind`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
188pub enum AssocKind {
189    Const { name: Symbol, is_type_const: bool },
190    Fn { name: Symbol, has_self: bool },
191    Type { data: AssocTypeData },
192}
193
194impl AssocKind {
195    pub fn namespace(&self) -> Namespace {
196        match self {
197            Self::Type { .. } => Namespace::TypeNS,
198            Self::Const { .. } | Self::Fn { .. } => Namespace::ValueNS,
199        }
200    }
201
202    pub fn tag(&self) -> AssocTag {
203        match self {
204            Self::Const { .. } => AssocTag::Const,
205            Self::Fn { .. } => AssocTag::Fn,
206            Self::Type { .. } => AssocTag::Type,
207        }
208    }
209
210    pub fn as_def_kind(&self) -> DefKind {
211        match self {
212            Self::Const { is_type_const, .. } => {
213                DefKind::AssocConst { is_type_const: *is_type_const }
214            }
215            Self::Fn { .. } => DefKind::AssocFn,
216            Self::Type { .. } => DefKind::AssocTy,
217        }
218    }
219
220    pub fn descr(&self) -> &'static str {
221        match self {
222            Self::Fn { has_self: true, .. } => "method",
223            _ => self.tag().descr(),
224        }
225    }
226}
227
228impl std::fmt::Display for AssocKind {
229    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230        f.write_str(self.descr())
231    }
232}
233
234/// Like [`AssocKind`], but just the tag, no fields. Used in various kinds of matching.
235#[derive(#[automatically_derived]
impl ::core::clone::Clone for AssocTag {
    #[inline]
    fn clone(&self) -> AssocTag { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AssocTag { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for AssocTag {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                AssocTag::Const => "Const",
                AssocTag::Fn => "Fn",
                AssocTag::Type => "Type",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocTag {
    #[inline]
    fn eq(&self, other: &AssocTag) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AssocTag {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AssocTag {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash)]
236pub enum AssocTag {
237    Const,
238    Fn,
239    Type,
240}
241
242impl AssocTag {
243    pub fn descr(self) -> &'static str {
244        // This should match `DefKind::descr`.
245        match self {
246            Self::Const => "associated constant",
247            Self::Fn => "associated function",
248            Self::Type => "associated type",
249        }
250    }
251}
252
253/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
254///
255/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
256/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
257/// done only on items with the same name.
258#[derive(#[automatically_derived]
impl ::core::fmt::Debug for AssocItems {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "AssocItems",
            "items", &&self.items)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for AssocItems {
    #[inline]
    fn clone(&self) -> AssocItems {
        AssocItems { items: ::core::clone::Clone::clone(&self.items) }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AssocItems {
    #[inline]
    fn eq(&self, other: &AssocItems) -> bool { self.items == other.items }
}PartialEq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AssocItems {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AssocItems { items: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
259pub struct AssocItems {
260    items: SortedIndexMultiMap<u32, Option<Symbol>, ty::AssocItem>,
261}
262
263impl AssocItems {
264    /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
265    pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
266        let items = items_in_def_order.into_iter().map(|item| (item.opt_name(), item)).collect();
267        AssocItems { items }
268    }
269
270    /// Returns an iterator over associated items in the order they were defined.
271    ///
272    /// New code should avoid relying on definition order. If you need a particular associated item
273    /// for a known trait, make that trait a lang item instead of indexing this array.
274    pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
275        self.items.iter().map(|(_, v)| v)
276    }
277
278    pub fn len(&self) -> usize {
279        self.items.len()
280    }
281
282    /// Returns an iterator over all associated items with the given name, ignoring hygiene.
283    ///
284    /// Panics if `name.is_empty()` returns `true`.
285    pub fn filter_by_name_unhygienic(
286        &self,
287        name: Symbol,
288    ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
289        if !!name.is_empty() {
    ::core::panicking::panic("assertion failed: !name.is_empty()")
};assert!(!name.is_empty());
290        self.items.get_by_key(Some(name))
291    }
292
293    /// Returns the associated item with the given identifier and `AssocKind`, if one exists.
294    /// The identifier is ignoring hygiene. This is meant to be used for lints and diagnostics.
295    pub fn filter_by_name_unhygienic_and_kind(
296        &self,
297        name: Symbol,
298        assoc_tag: AssocTag,
299    ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
300        self.filter_by_name_unhygienic(name).filter(move |item| item.tag() == assoc_tag)
301    }
302
303    /// Returns the associated item with the given identifier and `AssocKind`, if one exists.
304    /// The identifier is matched hygienically.
305    pub fn find_by_ident_and_kind(
306        &self,
307        tcx: TyCtxt<'_>,
308        ident: Ident,
309        assoc_tag: AssocTag,
310        parent_def_id: DefId,
311    ) -> Option<&ty::AssocItem> {
312        self.filter_by_name_unhygienic(ident.name)
313            .filter(|item| item.tag() == assoc_tag)
314            .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
315    }
316
317    /// Returns the associated item with the given identifier in the given `Namespace`, if one
318    /// exists. The identifier is matched hygienically.
319    pub fn find_by_ident_and_namespace(
320        &self,
321        tcx: TyCtxt<'_>,
322        ident: Ident,
323        ns: Namespace,
324        parent_def_id: DefId,
325    ) -> Option<&ty::AssocItem> {
326        self.filter_by_name_unhygienic(ident.name)
327            .filter(|item| item.namespace() == ns)
328            .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
329    }
330}
331
332impl<'tcx> TyCtxt<'tcx> {
333    /// Given an `fn_def_id` of a trait or a trait implementation:
334    ///
335    /// if `fn_def_id` is a function defined inside a trait, then it synthesizes
336    /// a new def id corresponding to a new associated type for each return-
337    /// position `impl Trait` in the signature.
338    ///
339    /// if `fn_def_id` is a function inside of an impl, then for each synthetic
340    /// associated type generated for the corresponding trait function described
341    /// above, synthesize a corresponding associated type in the impl.
342    pub fn associated_types_for_impl_traits_in_associated_fn(
343        self,
344        fn_def_id: DefId,
345    ) -> &'tcx [DefId] {
346        let parent_def_id = self.parent(fn_def_id);
347        &self.associated_types_for_impl_traits_in_trait_or_impl(parent_def_id)[&fn_def_id]
348    }
349}