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