1 use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
2 use rustc_index::vec::IndexVec;
5 /// Uniquely identifies a node in the HIR of the current crate. It is
6 /// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
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.
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
15 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
16 #[derive(Encodable, Decodable)]
18 pub owner: LocalDefId,
19 pub local_id: ItemLocalId,
23 pub fn expect_owner(self) -> LocalDefId {
24 assert_eq!(self.local_id.index(), 0);
28 pub fn as_owner(self) -> Option<LocalDefId> {
29 if self.local_id.index() == 0 { Some(self.owner) } else { None }
33 pub fn make_owner(owner: LocalDefId) -> Self {
34 Self { owner, local_id: ItemLocalId::from_u32(0) }
38 impl fmt::Display for HirId {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "{:?}", self)
44 rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
45 rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);
47 rustc_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
56 pub struct ItemLocalId { .. }
58 rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
60 /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
61 pub const CRATE_HIR_ID: HirId = HirId {
62 owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
63 local_id: ItemLocalId::from_u32(0),
66 /// N.B. This collection is currently unused, but will be used by #72015 and future PRs.
67 #[derive(Clone, Default, Debug, Encodable, Decodable)]
68 pub struct HirIdVec<T> {
69 map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
73 pub fn push_owner(&mut self, id: LocalDefId) {
74 self.map.ensure_contains_elem(id, IndexVec::new);
77 pub fn push(&mut self, id: HirId, value: T) {
78 if id.local_id == ItemLocalId::from_u32(0) {
79 self.push_owner(id.owner);
81 let submap = &mut self.map[id.owner];
82 let _ret_id = submap.push(value);
83 debug_assert_eq!(_ret_id, id.local_id);
86 pub fn push_sparse(&mut self, id: HirId, value: T)
90 self.map.ensure_contains_elem(id.owner, IndexVec::new);
91 let submap = &mut self.map[id.owner];
92 let i = id.local_id.index();
93 let len = submap.len();
95 submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
97 submap[id.local_id] = value;
100 pub fn get(&self, id: HirId) -> Option<&T> {
101 self.map.get(id.owner)?.get(id.local_id)
104 pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
108 pub fn iter(&self) -> impl Iterator<Item = &T> {
109 self.map.iter().flat_map(|la| la.iter())
112 pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
113 self.map.iter_enumerated().flat_map(|(owner, la)| {
114 la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
119 impl<T> std::ops::Index<HirId> for HirIdVec<T> {
122 fn index(&self, id: HirId) -> &T {
123 &self.map[id.owner][id.local_id]
127 impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
128 fn index_mut(&mut self, id: HirId) -> &mut T {
129 &mut self.map[id.owner][id.local_id]