]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_hir/src/hir_id.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_hir / src / hir_id.rs
1 use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
2 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
3 use rustc_span::{def_id::DefPathHash, HashStableContext};
4 use std::fmt::{self, Debug};
5
6 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
7 #[derive(Encodable, Decodable)]
8 pub struct OwnerId {
9 pub def_id: LocalDefId,
10 }
11
12 impl Debug for OwnerId {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 // Example: DefId(0:1 ~ aa[7697]::{use#0})
15 Debug::fmt(&self.def_id, f)
16 }
17 }
18
19 impl From<OwnerId> for HirId {
20 fn from(owner: OwnerId) -> HirId {
21 HirId { owner, local_id: ItemLocalId::from_u32(0) }
22 }
23 }
24
25 impl From<OwnerId> for DefId {
26 fn from(value: OwnerId) -> Self {
27 value.to_def_id()
28 }
29 }
30
31 impl OwnerId {
32 #[inline]
33 pub fn to_def_id(self) -> DefId {
34 self.def_id.to_def_id()
35 }
36 }
37
38 impl rustc_index::vec::Idx for OwnerId {
39 #[inline]
40 fn new(idx: usize) -> Self {
41 OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } }
42 }
43
44 #[inline]
45 fn index(self) -> usize {
46 self.def_id.local_def_index.as_usize()
47 }
48 }
49
50 impl<CTX: HashStableContext> HashStable<CTX> for OwnerId {
51 #[inline]
52 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
53 self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
54 }
55 }
56
57 impl<CTX: HashStableContext> ToStableHashKey<CTX> for OwnerId {
58 type KeyType = DefPathHash;
59
60 #[inline]
61 fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
62 hcx.def_path_hash(self.to_def_id())
63 }
64 }
65
66 /// Uniquely identifies a node in the HIR of the current crate. It is
67 /// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
68 /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
69 /// and the `local_id` which is unique within the given owner.
70 ///
71 /// This two-level structure makes for more stable values: One can move an item
72 /// around within the source code, or add or remove stuff before it, without
73 /// the `local_id` part of the `HirId` changing, which is a very useful property in
74 /// incremental compilation where we have to persist things through changes to
75 /// the code base.
76 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
77 #[derive(Encodable, Decodable, HashStable_Generic)]
78 #[rustc_pass_by_value]
79 pub struct HirId {
80 pub owner: OwnerId,
81 pub local_id: ItemLocalId,
82 }
83
84 impl Debug for HirId {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10)
87 // Don't use debug_tuple to always keep this on one line.
88 write!(f, "HirId({:?}.{:?})", self.owner, self.local_id)
89 }
90 }
91
92 impl HirId {
93 /// Signal local id which should never be used.
94 pub const INVALID: HirId =
95 HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID };
96
97 #[inline]
98 pub fn expect_owner(self) -> OwnerId {
99 assert_eq!(self.local_id.index(), 0);
100 self.owner
101 }
102
103 #[inline]
104 pub fn as_owner(self) -> Option<OwnerId> {
105 if self.local_id.index() == 0 { Some(self.owner) } else { None }
106 }
107
108 #[inline]
109 pub fn is_owner(self) -> bool {
110 self.local_id.index() == 0
111 }
112
113 #[inline]
114 pub fn make_owner(owner: LocalDefId) -> Self {
115 Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::from_u32(0) }
116 }
117
118 pub fn index(self) -> (usize, usize) {
119 (
120 rustc_index::vec::Idx::index(self.owner.def_id),
121 rustc_index::vec::Idx::index(self.local_id),
122 )
123 }
124 }
125
126 impl fmt::Display for HirId {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 write!(f, "{self:?}")
129 }
130 }
131
132 impl Ord for HirId {
133 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
134 (self.index()).cmp(&(other.index()))
135 }
136 }
137
138 impl PartialOrd for HirId {
139 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
140 Some(self.cmp(other))
141 }
142 }
143
144 rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId);
145 rustc_data_structures::define_id_collections!(
146 ItemLocalMap,
147 ItemLocalSet,
148 ItemLocalMapEntry,
149 ItemLocalId
150 );
151
152 rustc_index::newtype_index! {
153 /// An `ItemLocalId` uniquely identifies something within a given "item-like";
154 /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
155 /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
156 /// the node's position within the owning item in any way, but there is a
157 /// guarantee that the `ItemLocalId`s within an owner occupy a dense range of
158 /// integers starting at zero, so a mapping that maps all or most nodes within
159 /// an "item-like" to something else can be implemented by a `Vec` instead of a
160 /// tree or hash map.
161 #[derive(HashStable_Generic)]
162 pub struct ItemLocalId {}
163 }
164
165 impl ItemLocalId {
166 /// Signal local id which should never be used.
167 pub const INVALID: ItemLocalId = ItemLocalId::MAX;
168 }
169
170 // Safety: Ord is implement as just comparing the ItemLocalId's numerical
171 // values and these are not changed by (de-)serialization.
172 unsafe impl StableOrd for ItemLocalId {}
173
174 /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
175 pub const CRATE_HIR_ID: HirId =
176 HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
177
178 pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };