rustc_middle/dep_graph/
dep_node_key.rs1use std::fmt::Debug;
2
3use rustc_data_structures::fingerprint::Fingerprint;
4use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
6use rustc_hir::definitions::DefPathHash;
7use rustc_hir::{HirId, ItemLocalId, OwnerId};
8
9use crate::dep_graph::{DepNode, KeyFingerprintStyle};
10use crate::ty::TyCtxt;
11
12pub trait DepNodeKey<'tcx>: Debug + Sized {
14 fn key_fingerprint_style() -> KeyFingerprintStyle;
15
16 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint;
19
20 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
27}
28
29impl<'tcx, T> DepNodeKey<'tcx> for T
31where
32 T: HashStable + Debug,
33{
34 #[inline(always)]
35 default fn key_fingerprint_style() -> KeyFingerprintStyle {
36 KeyFingerprintStyle::Opaque
37 }
38
39 #[inline(always)]
40 default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
41 tcx.with_stable_hashing_context(|mut hcx| {
42 let mut hasher = StableHasher::new();
43 self.hash_stable(&mut hcx, &mut hasher);
44 hasher.finish()
45 })
46 }
47
48 #[inline(always)]
49 default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
50 None
51 }
52}
53
54impl<'tcx> DepNodeKey<'tcx> for () {
55 #[inline(always)]
56 fn key_fingerprint_style() -> KeyFingerprintStyle {
57 KeyFingerprintStyle::Unit
58 }
59
60 #[inline(always)]
61 fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
62 Fingerprint::ZERO
63 }
64
65 #[inline(always)]
66 fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
67 Some(())
68 }
69}
70
71impl<'tcx> DepNodeKey<'tcx> for DefId {
72 #[inline(always)]
73 fn key_fingerprint_style() -> KeyFingerprintStyle {
74 KeyFingerprintStyle::DefPathHash
75 }
76
77 #[inline(always)]
78 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
79 tcx.def_path_hash(*self).0
80 }
81
82 #[inline(always)]
83 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
84 dep_node.extract_def_id(tcx)
85 }
86}
87
88impl<'tcx> DepNodeKey<'tcx> for LocalDefId {
89 #[inline(always)]
90 fn key_fingerprint_style() -> KeyFingerprintStyle {
91 KeyFingerprintStyle::DefPathHash
92 }
93
94 #[inline(always)]
95 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
96 self.to_def_id().to_fingerprint(tcx)
97 }
98
99 #[inline(always)]
100 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
101 dep_node.extract_def_id(tcx).map(|id| id.expect_local())
102 }
103}
104
105impl<'tcx> DepNodeKey<'tcx> for OwnerId {
106 #[inline(always)]
107 fn key_fingerprint_style() -> KeyFingerprintStyle {
108 KeyFingerprintStyle::DefPathHash
109 }
110
111 #[inline(always)]
112 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
113 self.to_def_id().to_fingerprint(tcx)
114 }
115
116 #[inline(always)]
117 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
118 dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
119 }
120}
121
122impl<'tcx> DepNodeKey<'tcx> for CrateNum {
123 #[inline(always)]
124 fn key_fingerprint_style() -> KeyFingerprintStyle {
125 KeyFingerprintStyle::DefPathHash
126 }
127
128 #[inline(always)]
129 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
130 let def_id = self.as_def_id();
131 def_id.to_fingerprint(tcx)
132 }
133
134 #[inline(always)]
135 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
136 dep_node.extract_def_id(tcx).map(|id| id.krate)
137 }
138}
139
140impl<'tcx> DepNodeKey<'tcx> for (DefId, DefId) {
141 #[inline(always)]
142 fn key_fingerprint_style() -> KeyFingerprintStyle {
143 KeyFingerprintStyle::Opaque
144 }
145
146 #[inline(always)]
150 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
151 let (def_id_0, def_id_1) = *self;
152
153 let def_path_hash_0 = tcx.def_path_hash(def_id_0);
154 let def_path_hash_1 = tcx.def_path_hash(def_id_1);
155
156 def_path_hash_0.0.combine(def_path_hash_1.0)
157 }
158}
159
160impl<'tcx> DepNodeKey<'tcx> for HirId {
161 #[inline(always)]
162 fn key_fingerprint_style() -> KeyFingerprintStyle {
163 KeyFingerprintStyle::HirId
164 }
165
166 #[inline(always)]
170 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
171 let HirId { owner, local_id } = *self;
172 let def_path_hash = tcx.def_path_hash(owner.to_def_id());
173 Fingerprint::new(
174 def_path_hash.local_hash(),
176 local_id.as_u32() as u64,
177 )
178 }
179
180 #[inline(always)]
181 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
182 if tcx.key_fingerprint_style(dep_node.kind) == KeyFingerprintStyle::HirId {
183 let (local_hash, local_id) = Fingerprint::from(dep_node.key_fingerprint).split();
184 let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
185 let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
186 let local_id = local_id
187 .as_u64()
188 .try_into()
189 .unwrap_or_else(|_| {
::core::panicking::panic_fmt(format_args!("local id should be u32, found {0:?}",
local_id));
}panic!("local id should be u32, found {local_id:?}"));
190 Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
191 } else {
192 None
193 }
194 }
195}
196
197impl<'tcx> DepNodeKey<'tcx> for ModDefId {
198 #[inline(always)]
199 fn key_fingerprint_style() -> KeyFingerprintStyle {
200 KeyFingerprintStyle::DefPathHash
201 }
202
203 #[inline(always)]
204 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
205 self.to_def_id().to_fingerprint(tcx)
206 }
207
208 #[inline(always)]
209 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
210 DefId::try_recover_key(tcx, dep_node).map(ModDefId::new_unchecked)
211 }
212}
213
214impl<'tcx> DepNodeKey<'tcx> for LocalModDefId {
215 #[inline(always)]
216 fn key_fingerprint_style() -> KeyFingerprintStyle {
217 KeyFingerprintStyle::DefPathHash
218 }
219
220 #[inline(always)]
221 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
222 self.to_def_id().to_fingerprint(tcx)
223 }
224
225 #[inline(always)]
226 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
227 LocalDefId::try_recover_key(tcx, dep_node).map(LocalModDefId::new_unchecked)
228 }
229}