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
7pub mod def_path_hash_map;
8pub mod definitions;
9
10#[cfg(test)]
11mod tests;
12
13use std::fmt::{self, Debug};
14
15use rustc_data_structures::stable_hash::{
16    StableHash, StableHashCtxt, StableHasher, StableOrd, ToStableHashKey,
17};
18use rustc_macros::{Decodable, Encodable, StableHash};
19use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId, LocalModId};
20
21#[derive(#[automatically_derived]
impl ::core::marker::Copy for OwnerId { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for OwnerId { }
#[automatically_derived]
impl ::core::clone::Clone for OwnerId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<LocalDefId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for OwnerId { }
#[automatically_derived]
impl ::core::cmp::PartialEq for OwnerId {
    #[inline]
    fn eq(&self, other: &Self) -> 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) {
                let OwnerId { def_id: ref __binding_0 } = *self;
                ::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)]
22pub struct OwnerId {
23    pub def_id: LocalDefId,
24}
25
26impl Debug for OwnerId {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        // Example: DefId(0:1 ~ aa[7697]::{use#0})
29        Debug::fmt(&self.def_id, f)
30    }
31}
32
33impl From<OwnerId> for HirId {
34    fn from(owner: OwnerId) -> HirId {
35        HirId { owner, local_id: ItemLocalId::ZERO }
36    }
37}
38
39impl From<OwnerId> for DefId {
40    fn from(value: OwnerId) -> Self {
41        value.to_def_id()
42    }
43}
44
45impl From<LocalModId> for OwnerId {
46    fn from(value: LocalModId) -> Self {
47        OwnerId { def_id: value.to_local_def_id() }
48    }
49}
50
51impl OwnerId {
52    #[inline]
53    pub fn to_def_id(self) -> DefId {
54        self.def_id.to_def_id()
55    }
56}
57
58impl rustc_index::Idx for OwnerId {
59    #[inline]
60    fn new(idx: usize) -> Self {
61        OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } }
62    }
63
64    #[inline]
65    fn index(self) -> usize {
66        self.def_id.local_def_index.as_usize()
67    }
68}
69
70impl StableHash for OwnerId {
71    #[inline]
72    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
73        self.to_stable_hash_key(hcx).stable_hash(hcx, hasher);
74    }
75}
76
77impl ToStableHashKey for OwnerId {
78    type KeyType = DefPathHash;
79
80    #[inline]
81    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> DefPathHash {
82        self.to_def_id().to_stable_hash_key(hcx)
83    }
84}
85
86/// Uniquely identifies a node in the HIR of the current crate. It is
87/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
88/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
89/// and the `local_id` which is unique within the given owner.
90///
91/// This two-level structure makes for more stable values: One can move an item
92/// around within the source code, or add or remove stuff before it, without
93/// the `local_id` part of the `HirId` changing, which is a very useful property in
94/// incremental compilation where we have to persist things through changes to
95/// the code base.
96#[derive(#[automatically_derived]
impl ::core::marker::Copy for HirId { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for HirId { }
#[automatically_derived]
impl ::core::clone::Clone for HirId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<OwnerId>;
        let _: ::core::clone::AssertParamIsClone<ItemLocalId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for HirId { }
#[automatically_derived]
impl ::core::cmp::PartialEq for HirId {
    #[inline]
    fn eq(&self, other: &Self) -> 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) {
                let HirId { owner: ref __binding_0, local_id: ref __binding_1
                        } = *self;
                ::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_hash::StableHash for HirId {
            #[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 {
                    HirId { owner: ref __binding_0, local_id: ref __binding_1 }
                        => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
97#[rustc_pass_by_value]
98pub struct HirId {
99    pub owner: OwnerId,
100    pub local_id: ItemLocalId,
101}
102
103// To ensure correctness of incremental compilation,
104// `HirId` must not implement `Ord` or `PartialOrd`.
105// See https://github.com/rust-lang/rust/issues/90317.
106impl !Ord for HirId {}
107impl !PartialOrd for HirId {}
108
109impl Debug for HirId {
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10)
112        // Don't use debug_tuple to always keep this on one line.
113        f.write_fmt(format_args!("HirId({0:?}.{1:?})", self.owner, self.local_id))write!(f, "HirId({:?}.{:?})", self.owner, self.local_id)
114    }
115}
116
117impl HirId {
118    /// Signal local id which should never be used.
119    pub const INVALID: HirId =
120        HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID };
121
122    #[inline]
123    pub fn expect_owner(self) -> OwnerId {
124        {
    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);
125        self.owner
126    }
127
128    #[inline]
129    pub fn as_owner(self) -> Option<OwnerId> {
130        if self.local_id.index() == 0 { Some(self.owner) } else { None }
131    }
132
133    #[inline]
134    pub fn is_owner(self) -> bool {
135        self.local_id.index() == 0
136    }
137
138    #[inline]
139    pub fn make_owner(owner: LocalDefId) -> Self {
140        Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO }
141    }
142}
143
144impl fmt::Display for HirId {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        f.write_fmt(format_args!("{0:?}", self))write!(f, "{self:?}")
147    }
148}
149
150impl From<LocalModId> for HirId {
151    fn from(id: LocalModId) -> Self {
152        HirId::make_owner(id.to_local_def_id())
153    }
154}
155
156pub 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);
157pub 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!(
158    ItemLocalMap,
159    ItemLocalSet,
160    ItemLocalMapEntry,
161    ItemLocalId
162);
163
164#[automatically_derived]
impl ::core::marker::Copy for ItemLocalId { }
impl ItemLocalId {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0xFFFF_FF00 as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for ItemLocalId {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for ItemLocalId {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for ItemLocalId {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for ItemLocalId {
    #[inline]
    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
        <usize as
                ::std::iter::Step>::steps_between(&Self::index(*start),
            &Self::index(*end))
    }
    #[inline]
    fn forward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_add(u).map(Self::from_usize)
    }
    #[inline]
    fn backward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_sub(u).map(Self::from_usize)
    }
    #[inline]
    fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_add(u);
        (Self::from_usize(s), o)
    }
    #[inline]
    fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_sub(u);
        (Self::from_usize(s), o)
    }
}
impl ::std::cmp::Ord for ItemLocalId {
    #[inline]
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_u32().cmp(&other.as_u32())
    }
}
impl ::std::cmp::PartialOrd for ItemLocalId {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl ::rustc_data_structures::stable_hash::StableHash for ItemLocalId {
    fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
        hcx: &mut __Hcx,
        hasher: &mut ::rustc_data_structures::stable_hash::StableHasher) {
        self.as_u32().stable_hash(hcx, hasher)
    }
}
impl From<ItemLocalId> for u32 {
    #[inline]
    fn from(v: ItemLocalId) -> u32 { v.as_u32() }
}
impl From<ItemLocalId> for usize {
    #[inline]
    fn from(v: ItemLocalId) -> usize { v.as_usize() }
}
impl From<usize> for ItemLocalId {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for ItemLocalId {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for ItemLocalId {}
impl ::std::cmp::PartialEq for ItemLocalId {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for ItemLocalId {}
impl ::std::hash::Hash for ItemLocalId {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for
    ItemLocalId {
    fn decode(d: &mut D) -> Self { Self::from_u32(d.read_u32()) }
}
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for
    ItemLocalId {
    fn encode(&self, e: &mut E) { e.emit_u32(self.as_u32()); }
}
impl ::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! {
165    /// An `ItemLocalId` uniquely identifies something within a given "item-like";
166    /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
167    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
168    /// the node's position within the owning item in any way, but there is a
169    /// guarantee that the `ItemLocalId`s within an owner occupy a dense range of
170    /// integers starting at zero, so a mapping that maps all or most nodes within
171    /// an "item-like" to something else can be implemented by a `Vec` instead of a
172    /// tree or hash map.
173    #[stable_hash]
174    #[encodable]
175    #[orderable]
176    pub struct ItemLocalId {}
177}
178
179impl ItemLocalId {
180    /// Signal local id which should never be used.
181    pub const INVALID: ItemLocalId = ItemLocalId::MAX;
182}
183
184impl StableOrd for ItemLocalId {
185    const CAN_USE_UNSTABLE_SORT: bool = true;
186
187    // `Ord` is implemented as just comparing the ItemLocalId's numerical
188    // values and these are not changed by (de-)serialization.
189    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
190}
191
192/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
193pub const CRATE_HIR_ID: HirId =
194    HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::ZERO };
195
196pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };