]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir/src/hir_id.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_hir / src / hir_id.rs
CommitLineData
ba9703b0 1use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
6a06907d 2use rustc_index::vec::IndexVec;
dfeec247
XL
3use std::fmt;
4
5/// Uniquely identifies a node in the HIR of the current crate. It is
ba9703b0 6/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
dfeec247
XL
7/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
8/// and the `local_id` which is unique within the given owner.
9///
10/// This two-level structure makes for more stable values: One can move an item
11/// around within the source code, or add or remove stuff before it, without
12/// the `local_id` part of the `HirId` changing, which is a very useful property in
13/// incremental compilation where we have to persist things through changes to
14/// the code base.
3dfed10e
XL
15#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
16#[derive(Encodable, Decodable)]
dfeec247 17pub struct HirId {
ba9703b0 18 pub owner: LocalDefId,
dfeec247
XL
19 pub local_id: ItemLocalId,
20}
21
6a06907d
XL
22impl HirId {
23 pub fn expect_owner(self) -> LocalDefId {
24 assert_eq!(self.local_id.index(), 0);
25 self.owner
26 }
27
28 pub fn as_owner(self) -> Option<LocalDefId> {
29 if self.local_id.index() == 0 { Some(self.owner) } else { None }
30 }
31
32 #[inline]
33 pub fn make_owner(owner: LocalDefId) -> Self {
34 Self { owner, local_id: ItemLocalId::from_u32(0) }
35 }
36}
37
dfeec247
XL
38impl fmt::Display for HirId {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "{:?}", self)
41 }
42}
43
44rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
45rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);
46
47rustc_index::newtype_index! {
48 /// An `ItemLocalId` uniquely identifies something within a given "item-like";
49 /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
50 /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
51 /// the node's position within the owning item in any way, but there is a
52 /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
53 /// integers starting at zero, so a mapping that maps all or most nodes within
54 /// an "item-like" to something else can be implemented by a `Vec` instead of a
55 /// tree or hash map.
56 pub struct ItemLocalId { .. }
57}
58rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
59
60/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
ba9703b0
XL
61pub const CRATE_HIR_ID: HirId = HirId {
62 owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
63 local_id: ItemLocalId::from_u32(0),
64};
6a06907d
XL
65
66#[derive(Clone, Default, Debug, Encodable, Decodable)]
67pub struct HirIdVec<T> {
68 map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
69}
70
71impl<T> HirIdVec<T> {
72 pub fn push_owner(&mut self, id: LocalDefId) {
73 self.map.ensure_contains_elem(id, IndexVec::new);
74 }
75
76 pub fn push(&mut self, id: HirId, value: T) {
77 if id.local_id == ItemLocalId::from_u32(0) {
78 self.push_owner(id.owner);
79 }
80 let submap = &mut self.map[id.owner];
81 let _ret_id = submap.push(value);
82 debug_assert_eq!(_ret_id, id.local_id);
83 }
84
85 pub fn push_sparse(&mut self, id: HirId, value: T)
86 where
87 T: Default,
88 {
89 self.map.ensure_contains_elem(id.owner, IndexVec::new);
90 let submap = &mut self.map[id.owner];
91 let i = id.local_id.index();
92 let len = submap.len();
93 if i >= len {
94 submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
95 }
96 submap[id.local_id] = value;
97 }
98
99 pub fn get(&self, id: HirId) -> Option<&T> {
100 self.map.get(id.owner)?.get(id.local_id)
101 }
102
103 pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
104 &self.map[id]
105 }
106
107 pub fn iter(&self) -> impl Iterator<Item = &T> {
108 self.map.iter().flat_map(|la| la.iter())
109 }
110
111 pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
112 self.map.iter_enumerated().flat_map(|(owner, la)| {
113 la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
114 })
115 }
116}
117
118impl<T> std::ops::Index<HirId> for HirIdVec<T> {
119 type Output = T;
120
121 fn index(&self, id: HirId) -> &T {
122 &self.map[id.owner][id.local_id]
123 }
124}
125
126impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
127 fn index_mut(&mut self, id: HirId) -> &mut T {
128 &mut self.map[id.owner][id.local_id]
129 }
130}