1use std::fmt;
2use std::hash::{BuildHasherDefault, Hash, Hasher};
3
4use rustc_data_structures::AtomicRef;
5use rustc_data_structures::fingerprint::Fingerprint;
6use rustc_data_structures::stable_hasher::{
7 Hash64, HashStable, StableHasher, StableOrd, ToStableHashKey,
8};
9use rustc_data_structures::unhash::Unhasher;
10use rustc_index::Idx;
11use rustc_macros::{Decodable, Encodable, HashStable_Generic};
12use rustc_serialize::{Decodable, Encodable};
13
14use crate::{HashStableContext, SpanDecoder, SpanEncoder, Symbol};
15
16pub type StableCrateIdMap =
17 indexmap::IndexMap<StableCrateId, CrateNum, BuildHasherDefault<Unhasher>>;
18
19rustc_index::newtype_index! {
20 #[orderable]
21 #[debug_format = "crate{}"]
22 pub struct CrateNum {}
23}
24
25pub const LOCAL_CRATE: CrateNum = CrateNum::ZERO;
28
29impl CrateNum {
30 #[inline]
31 pub fn new(x: usize) -> CrateNum {
32 CrateNum::from_usize(x)
33 }
34
35 #[inline]
37 pub fn as_def_id(self) -> DefId {
38 DefId { krate: self, index: CRATE_DEF_INDEX }
39 }
40
41 #[inline]
42 pub fn as_mod_def_id(self) -> ModDefId {
43 ModDefId::new_unchecked(DefId { krate: self, index: CRATE_DEF_INDEX })
44 }
45}
46
47impl fmt::Display for CrateNum {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 fmt::Display::fmt(&self.as_u32(), f)
50 }
51}
52
53#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
95#[derive(HashStable_Generic, Encodable, Decodable)]
96pub struct DefPathHash(pub Fingerprint);
97
98impl DefPathHash {
99 #[inline]
102 pub fn stable_crate_id(&self) -> StableCrateId {
103 StableCrateId(self.0.split().0)
104 }
105
106 #[inline]
108 pub fn local_hash(&self) -> Hash64 {
109 self.0.split().1
110 }
111
112 pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash {
115 DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash))
116 }
117}
118
119impl Default for DefPathHash {
120 fn default() -> Self {
121 DefPathHash(Fingerprint::ZERO)
122 }
123}
124
125impl StableOrd for DefPathHash {
126 const CAN_USE_UNSTABLE_SORT: bool = true;
127
128 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
130}
131
132#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
144#[derive(Hash, HashStable_Generic, Encodable, Decodable)]
145pub struct StableCrateId(pub(crate) Hash64);
146
147impl StableCrateId {
148 pub fn new(
151 crate_name: Symbol,
152 is_exe: bool,
153 mut metadata: Vec<String>,
154 cfg_version: &'static str,
155 ) -> StableCrateId {
156 let mut hasher = StableHasher::new();
157 crate_name.as_str().hash(&mut hasher);
160
161 metadata.sort();
164 metadata.dedup();
166
167 hasher.write(b"metadata");
168 for s in &metadata {
169 hasher.write_usize(s.len());
173 hasher.write(s.as_bytes());
174 }
175
176 hasher.write(if is_exe { b"exe" } else { b"lib" });
179
180 if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
187 hasher.write(val.to_string_lossy().into_owned().as_bytes())
188 } else {
189 hasher.write(cfg_version.as_bytes())
190 }
191
192 StableCrateId(hasher.finish())
193 }
194
195 #[inline]
196 pub fn as_u64(self) -> u64 {
197 self.0.as_u64()
198 }
199}
200
201impl fmt::LowerHex for StableCrateId {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 fmt::LowerHex::fmt(&self.0, f)
204 }
205}
206
207rustc_index::newtype_index! {
208 #[orderable]
212 #[debug_format = "DefIndex({})"]
213 pub struct DefIndex {
214 const CRATE_DEF_INDEX = 0;
217 }
218}
219
220#[derive(Clone, PartialEq, Eq, Copy)]
225#[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
227#[repr(C)]
228#[rustc_pass_by_value]
229pub struct DefId {
231 #[cfg(not(all(target_pointer_width = "64", target_endian = "big")))]
235 pub index: DefIndex,
236 pub krate: CrateNum,
237 #[cfg(all(target_pointer_width = "64", target_endian = "big"))]
238 pub index: DefIndex,
239}
240
241impl !Ord for DefId {}
245impl !PartialOrd for DefId {}
246
247#[cfg(target_pointer_width = "64")]
266impl Hash for DefId {
267 fn hash<H: Hasher>(&self, h: &mut H) {
268 (((self.krate.as_u32() as u64) << 32) | (self.index.as_u32() as u64)).hash(h)
269 }
270}
271
272impl DefId {
273 #[inline]
275 pub fn local(index: DefIndex) -> DefId {
276 DefId { krate: LOCAL_CRATE, index }
277 }
278
279 #[inline]
281 pub fn is_local(self) -> bool {
282 self.krate == LOCAL_CRATE
283 }
284
285 #[inline]
286 pub fn as_local(self) -> Option<LocalDefId> {
287 self.is_local().then(|| LocalDefId { local_def_index: self.index })
288 }
289
290 #[inline]
291 #[track_caller]
292 pub fn expect_local(self) -> LocalDefId {
293 match self.as_local() {
296 Some(local_def_id) => local_def_id,
297 None => panic!("DefId::expect_local: `{self:?}` isn't local"),
298 }
299 }
300
301 #[inline]
302 pub fn is_crate_root(self) -> bool {
303 self.index == CRATE_DEF_INDEX
304 }
305
306 #[inline]
307 pub fn as_crate_root(self) -> Option<CrateNum> {
308 self.is_crate_root().then_some(self.krate)
309 }
310
311 #[inline]
312 pub fn is_top_level_module(self) -> bool {
313 self.is_local() && self.is_crate_root()
314 }
315}
316
317impl From<LocalDefId> for DefId {
318 fn from(local: LocalDefId) -> DefId {
319 local.to_def_id()
320 }
321}
322
323pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324 f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
325}
326
327pub static DEF_ID_DEBUG: AtomicRef<fn(DefId, &mut fmt::Formatter<'_>) -> fmt::Result> =
328 AtomicRef::new(&(default_def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
329
330impl fmt::Debug for DefId {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 (*DEF_ID_DEBUG)(*self, f)
333 }
334}
335
336rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefIdMapEntry, DefId);
337
338#[derive(Clone, Copy, PartialEq, Eq, Hash)]
345pub struct LocalDefId {
346 pub local_def_index: DefIndex,
347}
348
349impl !Ord for LocalDefId {}
353impl !PartialOrd for LocalDefId {}
354
355pub const CRATE_DEF_ID: LocalDefId = LocalDefId { local_def_index: CRATE_DEF_INDEX };
356
357impl Idx for LocalDefId {
358 #[inline]
359 fn new(idx: usize) -> Self {
360 LocalDefId { local_def_index: Idx::new(idx) }
361 }
362 #[inline]
363 fn index(self) -> usize {
364 self.local_def_index.index()
365 }
366}
367
368impl LocalDefId {
369 #[inline]
370 pub fn to_def_id(self) -> DefId {
371 DefId { krate: LOCAL_CRATE, index: self.local_def_index }
372 }
373
374 #[inline]
375 pub fn is_top_level_module(self) -> bool {
376 self == CRATE_DEF_ID
377 }
378}
379
380impl fmt::Debug for LocalDefId {
381 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
382 self.to_def_id().fmt(f)
383 }
384}
385
386impl<E: SpanEncoder> Encodable<E> for LocalDefId {
387 fn encode(&self, s: &mut E) {
388 self.to_def_id().encode(s);
389 }
390}
391
392impl<D: SpanDecoder> Decodable<D> for LocalDefId {
393 fn decode(d: &mut D) -> LocalDefId {
394 DefId::decode(d).expect_local()
395 }
396}
397
398rustc_data_structures::define_id_collections!(
399 LocalDefIdMap,
400 LocalDefIdSet,
401 LocalDefIdMapEntry,
402 LocalDefId
403);
404
405impl<CTX: HashStableContext> HashStable<CTX> for DefId {
406 #[inline]
407 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
408 self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
409 }
410}
411
412impl<CTX: HashStableContext> HashStable<CTX> for LocalDefId {
413 #[inline]
414 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
415 self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
416 }
417}
418
419impl<CTX: HashStableContext> HashStable<CTX> for CrateNum {
420 #[inline]
421 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
422 self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
423 }
424}
425
426impl<CTX: HashStableContext> ToStableHashKey<CTX> for DefId {
427 type KeyType = DefPathHash;
428
429 #[inline]
430 fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
431 hcx.def_path_hash(*self)
432 }
433}
434
435impl<CTX: HashStableContext> ToStableHashKey<CTX> for LocalDefId {
436 type KeyType = DefPathHash;
437
438 #[inline]
439 fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
440 hcx.def_path_hash(self.to_def_id())
441 }
442}
443
444impl<CTX: HashStableContext> ToStableHashKey<CTX> for CrateNum {
445 type KeyType = DefPathHash;
446
447 #[inline]
448 fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
449 self.as_def_id().to_stable_hash_key(hcx)
450 }
451}
452
453impl<CTX: HashStableContext> ToStableHashKey<CTX> for DefPathHash {
454 type KeyType = DefPathHash;
455
456 #[inline]
457 fn to_stable_hash_key(&self, _: &CTX) -> DefPathHash {
458 *self
459 }
460}
461
462macro_rules! typed_def_id {
463 ($Name:ident, $LocalName:ident) => {
464 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
465 pub struct $Name(DefId);
466
467 impl $Name {
468 pub const fn new_unchecked(def_id: DefId) -> Self {
469 Self(def_id)
470 }
471
472 pub fn to_def_id(self) -> DefId {
473 self.into()
474 }
475
476 pub fn is_local(self) -> bool {
477 self.0.is_local()
478 }
479
480 pub fn as_local(self) -> Option<$LocalName> {
481 self.0.as_local().map($LocalName::new_unchecked)
482 }
483 }
484
485 impl From<$LocalName> for $Name {
486 fn from(local: $LocalName) -> Self {
487 Self(local.0.to_def_id())
488 }
489 }
490
491 impl From<$Name> for DefId {
492 fn from(typed: $Name) -> Self {
493 typed.0
494 }
495 }
496
497 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
498 pub struct $LocalName(LocalDefId);
499
500 impl !Ord for $LocalName {}
501 impl !PartialOrd for $LocalName {}
502
503 impl $LocalName {
504 pub const fn new_unchecked(def_id: LocalDefId) -> Self {
505 Self(def_id)
506 }
507
508 pub fn to_def_id(self) -> DefId {
509 self.0.into()
510 }
511
512 pub fn to_local_def_id(self) -> LocalDefId {
513 self.0
514 }
515 }
516
517 impl From<$LocalName> for LocalDefId {
518 fn from(typed: $LocalName) -> Self {
519 typed.0
520 }
521 }
522
523 impl From<$LocalName> for DefId {
524 fn from(typed: $LocalName) -> Self {
525 typed.0.into()
526 }
527 }
528 };
529}
530
531typed_def_id! { ModDefId, LocalModDefId }
534
535impl LocalModDefId {
536 pub const CRATE_DEF_ID: Self = Self::new_unchecked(CRATE_DEF_ID);
537}
538
539impl ModDefId {
540 pub fn is_top_level_module(self) -> bool {
541 self.0.is_top_level_module()
542 }
543}
544
545impl LocalModDefId {
546 pub fn is_top_level_module(self) -> bool {
547 self.0.is_top_level_module()
548 }
549}