Skip to main content

rustc_hir_id/
lib.rs

1//! Library containing Id types from `rustc_hir`, split out so crates can use it without depending
2//! on all of `rustc_hir` (which is large and depends on other large things like `rustc_target`).
3#![allow(internal_features)]
4#![feature(negative_impls)]
5#![feature(rustc_attrs)]
6
7use std::fmt::{self, Debug};
8
9use rustc_data_structures::stable_hasher::{
10    HashStable, HashStableContext, StableHasher, StableOrd, ToStableHashKey,
11};
12use rustc_macros::{Decodable, Encodable, HashStable};
13use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId};
14
15#[derive(#[automatically_derived]
impl ::core::marker::Copy for OwnerId { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OwnerId {
    #[inline]
    fn clone(&self) -> OwnerId {
        let _: ::core::clone::AssertParamIsClone<LocalDefId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for OwnerId {
    #[inline]
    fn eq(&self, other: &OwnerId) -> bool { self.def_id == other.def_id }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OwnerId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<LocalDefId>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for OwnerId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.def_id, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OwnerId {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    OwnerId { def_id: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OwnerId {
            fn decode(__decoder: &mut __D) -> Self {
                OwnerId {
                    def_id: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
16pub struct OwnerId {
17    pub def_id: LocalDefId,
18}
19
20impl Debug for OwnerId {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        // Example: DefId(0:1 ~ aa[7697]::{use#0})
23        Debug::fmt(&self.def_id, f)
24    }
25}
26
27impl From<OwnerId> for HirId {
28    fn from(owner: OwnerId) -> HirId {
29        HirId { owner, local_id: ItemLocalId::ZERO }
30    }
31}
32
33impl From<OwnerId> for DefId {
34    fn from(value: OwnerId) -> Self {
35        value.to_def_id()
36    }
37}
38
39impl OwnerId {
40    #[inline]
41    pub fn to_def_id(self) -> DefId {
42        self.def_id.to_def_id()
43    }
44}
45
46impl rustc_index::Idx for OwnerId {
47    #[inline]
48    fn new(idx: usize) -> Self {
49        OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } }
50    }
51
52    #[inline]
53    fn index(self) -> usize {
54        self.def_id.local_def_index.as_usize()
55    }
56}
57
58impl HashStable for OwnerId {
59    #[inline]
60    fn hash_stable<Hcx: HashStableContext>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
61        self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
62    }
63}
64
65impl ToStableHashKey for OwnerId {
66    type KeyType = DefPathHash;
67
68    #[inline]
69    fn to_stable_hash_key<Hcx: HashStableContext>(&self, hcx: &mut Hcx) -> DefPathHash {
70        self.to_def_id().to_stable_hash_key(hcx)
71    }
72}
73
74/// Uniquely identifies a node in the HIR of the current crate. It is
75/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
76/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
77/// and the `local_id` which is unique within the given owner.
78///
79/// This two-level structure makes for more stable values: One can move an item
80/// around within the source code, or add or remove stuff before it, without
81/// the `local_id` part of the `HirId` changing, which is a very useful property in
82/// incremental compilation where we have to persist things through changes to
83/// the code base.
84#[derive(#[automatically_derived]
impl ::core::marker::Copy for HirId { }Copy, #[automatically_derived]
impl ::core::clone::Clone for HirId {
    #[inline]
    fn clone(&self) -> HirId {
        let _: ::core::clone::AssertParamIsClone<OwnerId>;
        let _: ::core::clone::AssertParamIsClone<ItemLocalId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for HirId {
    #[inline]
    fn eq(&self, other: &HirId) -> bool {
        self.owner == other.owner && self.local_id == other.local_id
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for HirId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<OwnerId>;
        let _: ::core::cmp::AssertParamIsEq<ItemLocalId>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for HirId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.owner, state);
        ::core::hash::Hash::hash(&self.local_id, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for HirId {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    HirId { owner: ref __binding_0, local_id: ref __binding_1 }
                        => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for HirId {
            fn decode(__decoder: &mut __D) -> Self {
                HirId {
                    owner: ::rustc_serialize::Decodable::decode(__decoder),
                    local_id: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hasher::HashStable for HirId {
            #[inline]
            fn hash_stable<__Hcx: ::rustc_data_structures::stable_hasher::HashStableContext>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    HirId { owner: ref __binding_0, local_id: ref __binding_1 }
                        => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable)]
85#[rustc_pass_by_value]
86pub struct HirId {
87    pub owner: OwnerId,
88    pub local_id: ItemLocalId,
89}
90
91// To ensure correctness of incremental compilation,
92// `HirId` must not implement `Ord` or `PartialOrd`.
93// See https://github.com/rust-lang/rust/issues/90317.
94impl !Ord for HirId {}
95impl !PartialOrd for HirId {}
96
97impl Debug for HirId {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10)
100        // Don't use debug_tuple to always keep this on one line.
101        f.write_fmt(format_args!("HirId({0:?}.{1:?})", self.owner, self.local_id))write!(f, "HirId({:?}.{:?})", self.owner, self.local_id)
102    }
103}
104
105impl HirId {
106    /// Signal local id which should never be used.
107    pub const INVALID: HirId =
108        HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID };
109
110    #[inline]
111    pub fn expect_owner(self) -> OwnerId {
112        match (&self.local_id.index(), &0) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(self.local_id.index(), 0);
113        self.owner
114    }
115
116    #[inline]
117    pub fn as_owner(self) -> Option<OwnerId> {
118        if self.local_id.index() == 0 { Some(self.owner) } else { None }
119    }
120
121    #[inline]
122    pub fn is_owner(self) -> bool {
123        self.local_id.index() == 0
124    }
125
126    #[inline]
127    pub fn make_owner(owner: LocalDefId) -> Self {
128        Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO }
129    }
130}
131
132impl fmt::Display for HirId {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        f.write_fmt(format_args!("{0:?}", self))write!(f, "{self:?}")
135    }
136}
137
138pub type HirIdMap<T> = ::rustc_data_structures::fx::FxIndexMap<HirId, T>;
pub type HirIdSet = ::rustc_data_structures::fx::FxIndexSet<HirId>;
pub type HirIdMapEntry<'a, T> =
    ::rustc_data_structures::fx::IndexEntry<'a, HirId, T>;rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId);
139pub type ItemLocalMap<T> =
    ::rustc_data_structures::unord::UnordMap<ItemLocalId, T>;
pub type ItemLocalSet = ::rustc_data_structures::unord::UnordSet<ItemLocalId>;
pub type ItemLocalMapEntry<'a, T> =
    ::rustc_data_structures::fx::StdEntry<'a, ItemLocalId, T>;rustc_data_structures::define_id_collections!(
140    ItemLocalMap,
141    ItemLocalSet,
142    ItemLocalMapEntry,
143    ItemLocalId
144);
145
146impl ::std::fmt::Debug for ItemLocalId {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
147    /// An `ItemLocalId` uniquely identifies something within a given "item-like";
148    /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
149    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
150    /// the node's position within the owning item in any way, but there is a
151    /// guarantee that the `ItemLocalId`s within an owner occupy a dense range of
152    /// integers starting at zero, so a mapping that maps all or most nodes within
153    /// an "item-like" to something else can be implemented by a `Vec` instead of a
154    /// tree or hash map.
155    #[stable_hash]
156    #[encodable]
157    #[orderable]
158    pub struct ItemLocalId {}
159}
160
161impl ItemLocalId {
162    /// Signal local id which should never be used.
163    pub const INVALID: ItemLocalId = ItemLocalId::MAX;
164}
165
166impl StableOrd for ItemLocalId {
167    const CAN_USE_UNSTABLE_SORT: bool = true;
168
169    // `Ord` is implemented as just comparing the ItemLocalId's numerical
170    // values and these are not changed by (de-)serialization.
171    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
172}
173
174/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
175pub const CRATE_HIR_ID: HirId =
176    HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::ZERO };
177
178pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };
179
180impl ToStableHashKey for HirId {
181    type KeyType = (DefPathHash, ItemLocalId);
182
183    #[inline]
184    fn to_stable_hash_key<Hcx: HashStableContext>(
185        &self,
186        hcx: &mut Hcx,
187    ) -> (DefPathHash, ItemLocalId) {
188        let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx);
189        (def_path_hash, self.local_id)
190    }
191}
192
193impl ToStableHashKey for ItemLocalId {
194    type KeyType = ItemLocalId;
195
196    #[inline]
197    fn to_stable_hash_key<Hcx>(&self, _: &mut Hcx) -> ItemLocalId {
198        *self
199    }
200}