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::ich::StableHashingContext;
11use crate::ty::TyCtxt;
12
13pub trait DepNodeKey<'tcx>: Debug + Sized {
15 fn key_fingerprint_style() -> KeyFingerprintStyle;
16
17 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint;
20
21 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String;
22
23 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
30}
31
32impl<'tcx, T> DepNodeKey<'tcx> for T
34where
35 T: for<'a> HashStable<StableHashingContext<'a>> + Debug,
36{
37 #[inline(always)]
38 default fn key_fingerprint_style() -> KeyFingerprintStyle {
39 KeyFingerprintStyle::Opaque
40 }
41
42 #[inline(always)]
43 default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
44 tcx.with_stable_hashing_context(|mut hcx| {
45 let mut hasher = StableHasher::new();
46 self.hash_stable(&mut hcx, &mut hasher);
47 hasher.finish()
48 })
49 }
50
51 #[inline(always)]
52 default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
53 tcx.with_reduced_queries(|| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
})format!("{self:?}"))
57 }
58
59 #[inline(always)]
60 default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
61 None
62 }
63}
64
65impl<'tcx> DepNodeKey<'tcx> for () {
66 #[inline(always)]
67 fn key_fingerprint_style() -> KeyFingerprintStyle {
68 KeyFingerprintStyle::Unit
69 }
70
71 #[inline(always)]
72 fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
73 Fingerprint::ZERO
74 }
75
76 #[inline(always)]
77 fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
78 Some(())
79 }
80}
81
82impl<'tcx> DepNodeKey<'tcx> for DefId {
83 #[inline(always)]
84 fn key_fingerprint_style() -> KeyFingerprintStyle {
85 KeyFingerprintStyle::DefPathHash
86 }
87
88 #[inline(always)]
89 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
90 tcx.def_path_hash(*self).0
91 }
92
93 #[inline(always)]
94 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
95 tcx.def_path_str(*self)
96 }
97
98 #[inline(always)]
99 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
100 dep_node.extract_def_id(tcx)
101 }
102}
103
104impl<'tcx> DepNodeKey<'tcx> for LocalDefId {
105 #[inline(always)]
106 fn key_fingerprint_style() -> KeyFingerprintStyle {
107 KeyFingerprintStyle::DefPathHash
108 }
109
110 #[inline(always)]
111 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
112 self.to_def_id().to_fingerprint(tcx)
113 }
114
115 #[inline(always)]
116 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
117 self.to_def_id().to_debug_str(tcx)
118 }
119
120 #[inline(always)]
121 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
122 dep_node.extract_def_id(tcx).map(|id| id.expect_local())
123 }
124}
125
126impl<'tcx> DepNodeKey<'tcx> for OwnerId {
127 #[inline(always)]
128 fn key_fingerprint_style() -> KeyFingerprintStyle {
129 KeyFingerprintStyle::DefPathHash
130 }
131
132 #[inline(always)]
133 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
134 self.to_def_id().to_fingerprint(tcx)
135 }
136
137 #[inline(always)]
138 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
139 self.to_def_id().to_debug_str(tcx)
140 }
141
142 #[inline(always)]
143 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
144 dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
145 }
146}
147
148impl<'tcx> DepNodeKey<'tcx> for CrateNum {
149 #[inline(always)]
150 fn key_fingerprint_style() -> KeyFingerprintStyle {
151 KeyFingerprintStyle::DefPathHash
152 }
153
154 #[inline(always)]
155 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
156 let def_id = self.as_def_id();
157 def_id.to_fingerprint(tcx)
158 }
159
160 #[inline(always)]
161 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
162 tcx.crate_name(*self).to_string()
163 }
164
165 #[inline(always)]
166 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
167 dep_node.extract_def_id(tcx).map(|id| id.krate)
168 }
169}
170
171impl<'tcx> DepNodeKey<'tcx> for (DefId, DefId) {
172 #[inline(always)]
173 fn key_fingerprint_style() -> KeyFingerprintStyle {
174 KeyFingerprintStyle::Opaque
175 }
176
177 #[inline(always)]
181 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
182 let (def_id_0, def_id_1) = *self;
183
184 let def_path_hash_0 = tcx.def_path_hash(def_id_0);
185 let def_path_hash_1 = tcx.def_path_hash(def_id_1);
186
187 def_path_hash_0.0.combine(def_path_hash_1.0)
188 }
189
190 #[inline(always)]
191 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
192 let (def_id_0, def_id_1) = *self;
193
194 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}, {1})",
tcx.def_path_debug_str(def_id_0),
tcx.def_path_debug_str(def_id_1)))
})format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1))
195 }
196}
197
198impl<'tcx> DepNodeKey<'tcx> for HirId {
199 #[inline(always)]
200 fn key_fingerprint_style() -> KeyFingerprintStyle {
201 KeyFingerprintStyle::HirId
202 }
203
204 #[inline(always)]
208 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
209 let HirId { owner, local_id } = *self;
210 let def_path_hash = tcx.def_path_hash(owner.to_def_id());
211 Fingerprint::new(
212 def_path_hash.local_hash(),
214 local_id.as_u32() as u64,
215 )
216 }
217
218 #[inline(always)]
219 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
220 let HirId { owner, local_id } = *self;
221 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}.{1}", tcx.def_path_str(owner),
local_id.as_u32()))
})format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32())
222 }
223
224 #[inline(always)]
225 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
226 if tcx.key_fingerprint_style(dep_node.kind) == KeyFingerprintStyle::HirId {
227 let (local_hash, local_id) = Fingerprint::from(dep_node.key_fingerprint).split();
228 let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
229 let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
230 let local_id = local_id
231 .as_u64()
232 .try_into()
233 .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:?}"));
234 Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
235 } else {
236 None
237 }
238 }
239}
240
241impl<'tcx> DepNodeKey<'tcx> for ModDefId {
242 #[inline(always)]
243 fn key_fingerprint_style() -> KeyFingerprintStyle {
244 KeyFingerprintStyle::DefPathHash
245 }
246
247 #[inline(always)]
248 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
249 self.to_def_id().to_fingerprint(tcx)
250 }
251
252 #[inline(always)]
253 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
254 self.to_def_id().to_debug_str(tcx)
255 }
256
257 #[inline(always)]
258 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
259 DefId::try_recover_key(tcx, dep_node).map(ModDefId::new_unchecked)
260 }
261}
262
263impl<'tcx> DepNodeKey<'tcx> for LocalModDefId {
264 #[inline(always)]
265 fn key_fingerprint_style() -> KeyFingerprintStyle {
266 KeyFingerprintStyle::DefPathHash
267 }
268
269 #[inline(always)]
270 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
271 self.to_def_id().to_fingerprint(tcx)
272 }
273
274 #[inline(always)]
275 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
276 self.to_def_id().to_debug_str(tcx)
277 }
278
279 #[inline(always)]
280 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
281 LocalDefId::try_recover_key(tcx, dep_node).map(LocalModDefId::new_unchecked)
282 }
283}