1use std::iter::TrustedLen;
4use std::path::Path;
5use std::sync::{Arc, OnceLock};
6use std::{io, iter, mem};
7
8pub(super) use cstore_impl::provide;
9use proc_macro::bridge::client::ProcMacro;
10use rustc_ast as ast;
11use rustc_data_structures::fingerprint::Fingerprint;
12use rustc_data_structures::fx::FxIndexMap;
13use rustc_data_structures::owned_slice::OwnedSlice;
14use rustc_data_structures::sync::Lock;
15use rustc_data_structures::unhash::UnhashMap;
16use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
17use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
18use rustc_hir::Safety;
19use rustc_hir::def::Res;
20use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE};
21use rustc_hir::definitions::{DefPath, DefPathData};
22use rustc_hir::diagnostic_items::DiagnosticItems;
23use rustc_index::Idx;
24use rustc_middle::middle::lib_features::LibFeatures;
25use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
26use rustc_middle::ty::Visibility;
27use rustc_middle::ty::codec::TyDecoder;
28use rustc_middle::{bug, implement_ty_decoder};
29use rustc_serialize::opaque::MemDecoder;
30use rustc_serialize::{Decodable, Decoder};
31use rustc_session::Session;
32use rustc_session::config::TargetModifier;
33use rustc_session::cstore::{CrateSource, ExternCrate};
34use rustc_span::hygiene::HygieneDecodeContext;
35use rustc_span::{BytePos, DUMMY_SP, Pos, SpanData, SpanDecoder, SyntaxContext, kw};
36use tracing::debug;
37
38use crate::creader::CStore;
39use crate::rmeta::table::IsDefault;
40use crate::rmeta::*;
41
42mod cstore_impl;
43
44pub(crate) struct MetadataBlob(OwnedSlice);
48
49impl std::ops::Deref for MetadataBlob {
50 type Target = [u8];
51
52 #[inline]
53 fn deref(&self) -> &[u8] {
54 &self.0[..]
55 }
56}
57
58impl MetadataBlob {
59 pub(crate) fn new(slice: OwnedSlice) -> Result<Self, ()> {
61 if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) }
62 }
63
64 pub(crate) fn bytes(&self) -> &OwnedSlice {
67 &self.0
68 }
69}
70
71pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
76
77pub(crate) type TargetModifiers = Vec<TargetModifier>;
79
80pub(crate) struct CrateMetadata {
81 blob: MetadataBlob,
83
84 root: CrateRoot,
87 trait_impls: FxIndexMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
91 incoherent_impls: FxIndexMap<SimplifiedType, LazyArray<DefIndex>>,
96 raw_proc_macros: Option<&'static [ProcMacro]>,
98 source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>,
100 def_path_hash_map: DefPathHashMapRef<'static>,
102 expn_hash_map: OnceLock<UnhashMap<ExpnHash, ExpnIndex>>,
104 alloc_decoding_state: AllocDecodingState,
106 def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,
108
109 cnum: CrateNum,
112 cnum_map: CrateNumMap,
115 dependencies: Vec<CrateNum>,
117 dep_kind: CrateDepKind,
119 source: Arc<CrateSource>,
121 private_dep: bool,
125 host_hash: Option<Svh>,
127 used: bool,
129
130 hygiene_context: HygieneDecodeContext,
136
137 extern_crate: Option<ExternCrate>,
141}
142
143#[derive(Clone)]
146struct ImportedSourceFile {
147 original_start_pos: rustc_span::BytePos,
149 original_end_pos: rustc_span::BytePos,
151 translated_source_file: Arc<rustc_span::SourceFile>,
153}
154
155pub(super) struct DecodeContext<'a, 'tcx> {
156 opaque: MemDecoder<'a>,
157 cdata: Option<CrateMetadataRef<'a>>,
158 blob: &'a MetadataBlob,
159 sess: Option<&'tcx Session>,
160 tcx: Option<TyCtxt<'tcx>>,
161
162 lazy_state: LazyState,
163
164 alloc_decoding_session: Option<AllocDecodingSession<'a>>,
166}
167
168pub(super) trait Metadata<'a, 'tcx>: Copy {
170 fn blob(self) -> &'a MetadataBlob;
171
172 fn cdata(self) -> Option<CrateMetadataRef<'a>> {
173 None
174 }
175 fn sess(self) -> Option<&'tcx Session> {
176 None
177 }
178 fn tcx(self) -> Option<TyCtxt<'tcx>> {
179 None
180 }
181
182 fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
183 let tcx = self.tcx();
184 DecodeContext {
185 opaque: MemDecoder::new(self.blob(), pos).unwrap(),
193 cdata: self.cdata(),
194 blob: self.blob(),
195 sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
196 tcx,
197 lazy_state: LazyState::NoNode,
198 alloc_decoding_session: self
199 .cdata()
200 .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
201 }
202 }
203}
204
205impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
206 #[inline]
207 fn blob(self) -> &'a MetadataBlob {
208 self
209 }
210}
211
212impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
213 #[inline]
214 fn blob(self) -> &'a MetadataBlob {
215 self.0
216 }
217
218 #[inline]
219 fn sess(self) -> Option<&'tcx Session> {
220 let (_, sess) = self;
221 Some(sess)
222 }
223}
224
225impl<'a, 'tcx> Metadata<'a, 'tcx> for CrateMetadataRef<'a> {
226 #[inline]
227 fn blob(self) -> &'a MetadataBlob {
228 &self.cdata.blob
229 }
230 #[inline]
231 fn cdata(self) -> Option<CrateMetadataRef<'a>> {
232 Some(self)
233 }
234}
235
236impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, &'tcx Session) {
237 #[inline]
238 fn blob(self) -> &'a MetadataBlob {
239 &self.0.cdata.blob
240 }
241 #[inline]
242 fn cdata(self) -> Option<CrateMetadataRef<'a>> {
243 Some(self.0)
244 }
245 #[inline]
246 fn sess(self) -> Option<&'tcx Session> {
247 Some(self.1)
248 }
249}
250
251impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) {
252 #[inline]
253 fn blob(self) -> &'a MetadataBlob {
254 &self.0.cdata.blob
255 }
256 #[inline]
257 fn cdata(self) -> Option<CrateMetadataRef<'a>> {
258 Some(self.0)
259 }
260 #[inline]
261 fn tcx(self) -> Option<TyCtxt<'tcx>> {
262 Some(self.1)
263 }
264}
265
266impl<T: ParameterizedOverTcx> LazyValue<T> {
267 #[inline]
268 fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(self, metadata: M) -> T::Value<'tcx>
269 where
270 T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
271 {
272 let mut dcx = metadata.decoder(self.position.get());
273 dcx.lazy_state = LazyState::NodeStart(self.position);
274 T::Value::decode(&mut dcx)
275 }
276}
277
278struct DecodeIterator<'a, 'tcx, T> {
279 elem_counter: std::ops::Range<usize>,
280 dcx: DecodeContext<'a, 'tcx>,
281 _phantom: PhantomData<fn() -> T>,
282}
283
284impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Iterator for DecodeIterator<'a, 'tcx, T> {
285 type Item = T;
286
287 #[inline(always)]
288 fn next(&mut self) -> Option<Self::Item> {
289 self.elem_counter.next().map(|_| T::decode(&mut self.dcx))
290 }
291
292 #[inline(always)]
293 fn size_hint(&self) -> (usize, Option<usize>) {
294 self.elem_counter.size_hint()
295 }
296}
297
298impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> ExactSizeIterator
299 for DecodeIterator<'a, 'tcx, T>
300{
301 fn len(&self) -> usize {
302 self.elem_counter.len()
303 }
304}
305
306unsafe impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> TrustedLen
307 for DecodeIterator<'a, 'tcx, T>
308{
309}
310
311impl<T: ParameterizedOverTcx> LazyArray<T> {
312 #[inline]
313 fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(
314 self,
315 metadata: M,
316 ) -> DecodeIterator<'a, 'tcx, T::Value<'tcx>>
317 where
318 T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
319 {
320 let mut dcx = metadata.decoder(self.position.get());
321 dcx.lazy_state = LazyState::NodeStart(self.position);
322 DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData }
323 }
324}
325
326impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
327 #[inline]
328 fn tcx(&self) -> TyCtxt<'tcx> {
329 let Some(tcx) = self.tcx else {
330 bug!(
331 "No TyCtxt found for decoding. \
332 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
333 );
334 };
335 tcx
336 }
337
338 #[inline]
339 pub(crate) fn blob(&self) -> &'a MetadataBlob {
340 self.blob
341 }
342
343 #[inline]
344 fn cdata(&self) -> CrateMetadataRef<'a> {
345 debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
346 self.cdata.unwrap()
347 }
348
349 #[inline]
350 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
351 self.cdata().map_encoded_cnum_to_current(cnum)
352 }
353
354 #[inline]
355 fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZero<usize>) -> T) -> T {
356 let distance = self.read_usize();
357 let position = match self.lazy_state {
358 LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
359 LazyState::NodeStart(start) => {
360 let start = start.get();
361 assert!(distance <= start);
362 start - distance
363 }
364 LazyState::Previous(last_pos) => last_pos.get() + distance,
365 };
366 let position = NonZero::new(position).unwrap();
367 self.lazy_state = LazyState::Previous(position);
368 f(position)
369 }
370
371 fn read_lazy<T>(&mut self) -> LazyValue<T> {
372 self.read_lazy_offset_then(|pos| LazyValue::from_position(pos))
373 }
374
375 fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> {
376 self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
377 }
378
379 fn read_lazy_table<I, T>(&mut self, width: usize, len: usize) -> LazyTable<I, T> {
380 self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len))
381 }
382
383 #[inline]
384 fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
385 self.opaque.read_raw_bytes(len)
386 }
387}
388
389impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
390 const CLEAR_CROSS_CRATE: bool = true;
391
392 #[inline]
393 fn interner(&self) -> TyCtxt<'tcx> {
394 self.tcx()
395 }
396
397 fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
398 where
399 F: FnOnce(&mut Self) -> Ty<'tcx>,
400 {
401 let tcx = self.tcx();
402
403 let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand };
404
405 if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) {
406 return ty;
407 }
408
409 let ty = or_insert_with(self);
410 tcx.ty_rcache.borrow_mut().insert(key, ty);
411 ty
412 }
413
414 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
415 where
416 F: FnOnce(&mut Self) -> R,
417 {
418 let new_opaque = self.opaque.split_at(pos);
419 let old_opaque = mem::replace(&mut self.opaque, new_opaque);
420 let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
421 let r = f(self);
422 self.opaque = old_opaque;
423 self.lazy_state = old_state;
424 r
425 }
426
427 fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId {
428 if let Some(alloc_decoding_session) = self.alloc_decoding_session {
429 alloc_decoding_session.decode_alloc_id(self)
430 } else {
431 bug!("Attempting to decode interpret::AllocId without CrateMetadata")
432 }
433 }
434}
435
436impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
437 #[inline]
438 fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex {
439 ExpnIndex::from_u32(d.read_u32())
440 }
441}
442
443impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
444 fn decode_attr_id(&mut self) -> rustc_span::AttrId {
445 let sess = self.sess.expect("can't decode AttrId without Session");
446 sess.psess.attr_id_generator.mk_attr_id()
447 }
448
449 fn decode_crate_num(&mut self) -> CrateNum {
450 let cnum = CrateNum::from_u32(self.read_u32());
451 self.map_encoded_cnum_to_current(cnum)
452 }
453
454 fn decode_def_index(&mut self) -> DefIndex {
455 DefIndex::from_u32(self.read_u32())
456 }
457
458 fn decode_def_id(&mut self) -> DefId {
459 DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
460 }
461
462 fn decode_syntax_context(&mut self) -> SyntaxContext {
463 let cdata = self.cdata();
464
465 let Some(sess) = self.sess else {
466 bug!(
467 "Cannot decode SyntaxContext without Session.\
468 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
469 );
470 };
471
472 let cname = cdata.root.name();
473 rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
474 debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
475 cdata
476 .root
477 .syntax_contexts
478 .get(cdata, id)
479 .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
480 .decode((cdata, sess))
481 })
482 }
483
484 fn decode_expn_id(&mut self) -> ExpnId {
485 let local_cdata = self.cdata();
486
487 let Some(sess) = self.sess else {
488 bug!(
489 "Cannot decode ExpnId without Session. \
490 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
491 );
492 };
493
494 let cnum = CrateNum::decode(self);
495 let index = u32::decode(self);
496
497 let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
498 let ExpnId { krate: cnum, local_id: index } = expn_id;
499 debug_assert_ne!(cnum, LOCAL_CRATE);
502 let crate_data = if cnum == local_cdata.cnum {
503 local_cdata
504 } else {
505 local_cdata.cstore.get_crate_data(cnum)
506 };
507 let expn_data = crate_data
508 .root
509 .expn_data
510 .get(crate_data, index)
511 .unwrap()
512 .decode((crate_data, sess));
513 let expn_hash = crate_data
514 .root
515 .expn_hashes
516 .get(crate_data, index)
517 .unwrap()
518 .decode((crate_data, sess));
519 (expn_data, expn_hash)
520 });
521 expn_id
522 }
523
524 fn decode_span(&mut self) -> Span {
525 let start = self.position();
526 let tag = SpanTag(self.peek_byte());
527 let data = if tag.kind() == SpanKind::Indirect {
528 self.read_u8();
530 let bytes_needed = tag.length().unwrap().0 as usize;
532 let mut total = [0u8; usize::BITS as usize / 8];
533 total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
534 let offset_or_position = usize::from_le_bytes(total);
535 let position = if tag.is_relative_offset() {
536 start - offset_or_position
537 } else {
538 offset_or_position
539 };
540 self.with_position(position, SpanData::decode)
541 } else {
542 SpanData::decode(self)
543 };
544 data.span()
545 }
546
547 fn decode_symbol(&mut self) -> Symbol {
548 let tag = self.read_u8();
549
550 match tag {
551 SYMBOL_STR => {
552 let s = self.read_str();
553 Symbol::intern(s)
554 }
555 SYMBOL_OFFSET => {
556 let pos = self.read_usize();
558
559 self.opaque.with_position(pos, |d| {
561 let s = d.read_str();
562 Symbol::intern(s)
563 })
564 }
565 SYMBOL_PREDEFINED => {
566 let symbol_index = self.read_u32();
567 Symbol::new(symbol_index)
568 }
569 _ => unreachable!(),
570 }
571 }
572}
573
574impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
575 fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData {
576 let tag = SpanTag::decode(decoder);
577 let ctxt = tag.context().unwrap_or_else(|| SyntaxContext::decode(decoder));
578
579 if tag.kind() == SpanKind::Partial {
580 return DUMMY_SP.with_ctxt(ctxt).data();
581 }
582
583 debug_assert!(tag.kind() == SpanKind::Local || tag.kind() == SpanKind::Foreign);
584
585 let lo = BytePos::decode(decoder);
586 let len = tag.length().unwrap_or_else(|| BytePos::decode(decoder));
587 let hi = lo + len;
588
589 let Some(sess) = decoder.sess else {
590 bug!(
591 "Cannot decode Span without Session. \
592 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
593 )
594 };
595
596 let metadata_index = u32::decode(decoder);
598
599 let source_file = if tag.kind() == SpanKind::Local {
628 decoder.cdata().imported_source_file(metadata_index, sess)
629 } else {
630 if decoder.cdata().root.is_proc_macro_crate() {
633 let cnum = u32::decode(decoder);
636 panic!(
637 "Decoding of crate {:?} tried to access proc-macro dep {:?}",
638 decoder.cdata().root.header.name,
639 cnum
640 );
641 }
642 let cnum = CrateNum::decode(decoder);
644 debug!(
645 "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
646 cnum
647 );
648
649 let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
650 foreign_data.imported_source_file(metadata_index, sess)
651 };
652
653 debug_assert!(
655 lo + source_file.original_start_pos <= source_file.original_end_pos,
656 "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
657 lo,
658 source_file.original_start_pos,
659 source_file.original_end_pos
660 );
661
662 debug_assert!(
664 hi + source_file.original_start_pos <= source_file.original_end_pos,
665 "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
666 hi,
667 source_file.original_start_pos,
668 source_file.original_end_pos
669 );
670
671 let lo = lo + source_file.translated_source_file.start_pos;
672 let hi = hi + source_file.translated_source_file.start_pos;
673
674 SpanData { lo, hi, ctxt, parent: None }
676 }
677}
678
679impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
680 fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
681 ty::codec::RefDecodable::decode(d)
682 }
683}
684
685impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
686 fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
687 decoder.read_lazy()
688 }
689}
690
691impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
692 #[inline]
693 fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
694 let len = decoder.read_usize();
695 if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) }
696 }
697}
698
699impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> {
700 fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
701 let width = decoder.read_usize();
702 let len = decoder.read_usize();
703 decoder.read_lazy_table(width, len)
704 }
705}
706
707implement_ty_decoder!(DecodeContext<'a, 'tcx>);
708
709impl MetadataBlob {
710 pub(crate) fn check_compatibility(
711 &self,
712 cfg_version: &'static str,
713 ) -> Result<(), Option<String>> {
714 if !self.blob().starts_with(METADATA_HEADER) {
715 if self.blob().starts_with(b"rust") {
716 return Err(Some("<unknown rustc version>".to_owned()));
717 }
718 return Err(None);
719 }
720
721 let found_version =
722 LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
723 .decode(self);
724 if rustc_version(cfg_version) != found_version {
725 return Err(Some(found_version));
726 }
727
728 Ok(())
729 }
730
731 fn root_pos(&self) -> NonZero<usize> {
732 let offset = METADATA_HEADER.len();
733 let pos_bytes = self.blob()[offset..][..8].try_into().unwrap();
734 let pos = u64::from_le_bytes(pos_bytes);
735 NonZero::new(pos as usize).unwrap()
736 }
737
738 pub(crate) fn get_header(&self) -> CrateHeader {
739 let pos = self.root_pos();
740 LazyValue::<CrateHeader>::from_position(pos).decode(self)
741 }
742
743 pub(crate) fn get_root(&self) -> CrateRoot {
744 let pos = self.root_pos();
745 LazyValue::<CrateRoot>::from_position(pos).decode(self)
746 }
747
748 pub(crate) fn list_crate_metadata(
749 &self,
750 out: &mut dyn io::Write,
751 ls_kinds: &[String],
752 ) -> io::Result<()> {
753 let root = self.get_root();
754
755 let all_ls_kinds = vec![
756 "root".to_owned(),
757 "lang_items".to_owned(),
758 "features".to_owned(),
759 "items".to_owned(),
760 ];
761 let ls_kinds = if ls_kinds.contains(&"all".to_owned()) { &all_ls_kinds } else { ls_kinds };
762
763 for kind in ls_kinds {
764 match &**kind {
765 "root" => {
766 writeln!(out, "Crate info:")?;
767 writeln!(out, "name {}{}", root.name(), root.extra_filename)?;
768 writeln!(
769 out,
770 "hash {} stable_crate_id {:?}",
771 root.hash(),
772 root.stable_crate_id
773 )?;
774 writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
775 writeln!(out, "triple {}", root.header.triple.tuple())?;
776 writeln!(out, "edition {}", root.edition)?;
777 writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?;
778 writeln!(
779 out,
780 "required_panic_strategy {:?} panic_in_drop_strategy {:?}",
781 root.required_panic_strategy, root.panic_in_drop_strategy
782 )?;
783 writeln!(
784 out,
785 "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}",
786 root.has_global_allocator,
787 root.has_alloc_error_handler,
788 root.has_panic_handler,
789 root.has_default_lib_allocator
790 )?;
791 writeln!(
792 out,
793 "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}",
794 root.compiler_builtins,
795 root.needs_allocator,
796 root.needs_panic_runtime,
797 root.no_builtins,
798 root.panic_runtime,
799 root.profiler_runtime
800 )?;
801
802 writeln!(out, "=External Dependencies=")?;
803 let dylib_dependency_formats =
804 root.dylib_dependency_formats.decode(self).collect::<Vec<_>>();
805 for (i, dep) in root.crate_deps.decode(self).enumerate() {
806 let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } =
807 dep;
808 let number = i + 1;
809
810 writeln!(
811 out,
812 "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}",
813 privacy = if is_private { "private" } else { "public" },
814 linkage = if dylib_dependency_formats.is_empty() {
815 String::new()
816 } else {
817 format!(" linkage {:?}", dylib_dependency_formats[i])
818 }
819 )?;
820 }
821 write!(out, "\n")?;
822 }
823
824 "lang_items" => {
825 writeln!(out, "=Lang items=")?;
826 for (id, lang_item) in root.lang_items.decode(self) {
827 writeln!(
828 out,
829 "{} = crate{}",
830 lang_item.name(),
831 DefPath::make(LOCAL_CRATE, id, |parent| root
832 .tables
833 .def_keys
834 .get(self, parent)
835 .unwrap()
836 .decode(self))
837 .to_string_no_crate_verbose()
838 )?;
839 }
840 for lang_item in root.lang_items_missing.decode(self) {
841 writeln!(out, "{} = <missing>", lang_item.name())?;
842 }
843 write!(out, "\n")?;
844 }
845
846 "features" => {
847 writeln!(out, "=Lib features=")?;
848 for (feature, since) in root.lib_features.decode(self) {
849 writeln!(
850 out,
851 "{}{}",
852 feature,
853 if let FeatureStability::AcceptedSince(since) = since {
854 format!(" since {since}")
855 } else {
856 String::new()
857 }
858 )?;
859 }
860 write!(out, "\n")?;
861 }
862
863 "items" => {
864 writeln!(out, "=Items=")?;
865
866 fn print_item(
867 blob: &MetadataBlob,
868 out: &mut dyn io::Write,
869 item: DefIndex,
870 indent: usize,
871 ) -> io::Result<()> {
872 let root = blob.get_root();
873
874 let def_kind = root.tables.def_kind.get(blob, item).unwrap();
875 let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
876 #[allow(rustc::symbol_intern_string_literal)]
877 let def_name = if item == CRATE_DEF_INDEX {
878 kw::Crate
879 } else {
880 def_key
881 .disambiguated_data
882 .data
883 .get_opt_name()
884 .unwrap_or_else(|| Symbol::intern("???"))
885 };
886 let visibility =
887 root.tables.visibility.get(blob, item).unwrap().decode(blob).map_id(
888 |index| {
889 format!(
890 "crate{}",
891 DefPath::make(LOCAL_CRATE, index, |parent| root
892 .tables
893 .def_keys
894 .get(blob, parent)
895 .unwrap()
896 .decode(blob))
897 .to_string_no_crate_verbose()
898 )
899 },
900 );
901 write!(
902 out,
903 "{nil: <indent$}{:?} {:?} {} {{",
904 visibility,
905 def_kind,
906 def_name,
907 nil = "",
908 )?;
909
910 if let Some(children) =
911 root.tables.module_children_non_reexports.get(blob, item)
912 {
913 write!(out, "\n")?;
914 for child in children.decode(blob) {
915 print_item(blob, out, child, indent + 4)?;
916 }
917 writeln!(out, "{nil: <indent$}}}", nil = "")?;
918 } else {
919 writeln!(out, "}}")?;
920 }
921
922 Ok(())
923 }
924
925 print_item(self, out, CRATE_DEF_INDEX, 0)?;
926
927 write!(out, "\n")?;
928 }
929
930 _ => {
931 writeln!(
932 out,
933 "unknown -Zls kind. allowed values are: all, root, lang_items, features, items"
934 )?;
935 }
936 }
937 }
938
939 Ok(())
940 }
941}
942
943impl CrateRoot {
944 pub(crate) fn is_proc_macro_crate(&self) -> bool {
945 self.proc_macro_data.is_some()
946 }
947
948 pub(crate) fn name(&self) -> Symbol {
949 self.header.name
950 }
951
952 pub(crate) fn hash(&self) -> Svh {
953 self.header.hash
954 }
955
956 pub(crate) fn stable_crate_id(&self) -> StableCrateId {
957 self.stable_crate_id
958 }
959
960 pub(crate) fn decode_crate_deps<'a>(
961 &self,
962 metadata: &'a MetadataBlob,
963 ) -> impl ExactSizeIterator<Item = CrateDep> {
964 self.crate_deps.decode(metadata)
965 }
966
967 pub(crate) fn decode_target_modifiers<'a>(
968 &self,
969 metadata: &'a MetadataBlob,
970 ) -> impl ExactSizeIterator<Item = TargetModifier> {
971 self.target_modifiers.decode(metadata)
972 }
973}
974
975impl<'a> CrateMetadataRef<'a> {
976 fn missing(self, descr: &str, id: DefIndex) -> ! {
977 bug!("missing `{descr}` for {:?}", self.local_def_id(id))
978 }
979
980 fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro {
981 let pos = self
984 .root
985 .proc_macro_data
986 .as_ref()
987 .unwrap()
988 .macros
989 .decode(self)
990 .position(|i| i == id)
991 .unwrap();
992 &self.raw_proc_macros.unwrap()[pos]
993 }
994
995 fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> {
996 let def_key = self.def_key(item_index);
997 def_key.disambiguated_data.data.get_opt_name().or_else(|| {
998 if def_key.disambiguated_data.data == DefPathData::Ctor {
999 let parent_index = def_key.parent.expect("no parent for a constructor");
1000 self.def_key(parent_index).disambiguated_data.data.get_opt_name()
1001 } else {
1002 None
1003 }
1004 })
1005 }
1006
1007 fn item_name(self, item_index: DefIndex) -> Symbol {
1008 self.opt_item_name(item_index).expect("no encoded ident for item")
1009 }
1010
1011 fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> {
1012 let name = self.opt_item_name(item_index)?;
1013 let span = self
1014 .root
1015 .tables
1016 .def_ident_span
1017 .get(self, item_index)
1018 .unwrap_or_else(|| self.missing("def_ident_span", item_index))
1019 .decode((self, sess));
1020 Some(Ident::new(name, span))
1021 }
1022
1023 fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident {
1024 self.opt_item_ident(item_index, sess).expect("no encoded ident for item")
1025 }
1026
1027 #[inline]
1028 pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum {
1029 if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] }
1030 }
1031
1032 fn def_kind(self, item_id: DefIndex) -> DefKind {
1033 self.root
1034 .tables
1035 .def_kind
1036 .get(self, item_id)
1037 .unwrap_or_else(|| self.missing("def_kind", item_id))
1038 }
1039
1040 fn get_span(self, index: DefIndex, sess: &Session) -> Span {
1041 self.root
1042 .tables
1043 .def_span
1044 .get(self, index)
1045 .unwrap_or_else(|| self.missing("def_span", index))
1046 .decode((self, sess))
1047 }
1048
1049 fn load_proc_macro<'tcx>(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension {
1050 let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
1051 ProcMacro::CustomDerive { trait_name, attributes, client } => {
1052 let helper_attrs =
1053 attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
1054 (
1055 trait_name,
1056 SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })),
1057 helper_attrs,
1058 )
1059 }
1060 ProcMacro::Attr { name, client } => {
1061 (name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new())
1062 }
1063 ProcMacro::Bang { name, client } => {
1064 (name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new())
1065 }
1066 };
1067
1068 let sess = tcx.sess;
1069 let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
1070 SyntaxExtension::new(
1071 sess,
1072 kind,
1073 self.get_span(id, sess),
1074 helper_attrs,
1075 self.root.edition,
1076 Symbol::intern(name),
1077 &attrs,
1078 false,
1079 )
1080 }
1081
1082 fn get_variant(
1083 self,
1084 kind: DefKind,
1085 index: DefIndex,
1086 parent_did: DefId,
1087 ) -> (VariantIdx, ty::VariantDef) {
1088 let adt_kind = match kind {
1089 DefKind::Variant => ty::AdtKind::Enum,
1090 DefKind::Struct => ty::AdtKind::Struct,
1091 DefKind::Union => ty::AdtKind::Union,
1092 _ => bug!(),
1093 };
1094
1095 let data = self.root.tables.variant_data.get(self, index).unwrap().decode(self);
1096
1097 let variant_did =
1098 if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
1099 let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));
1100
1101 (
1102 data.idx,
1103 ty::VariantDef::new(
1104 self.item_name(index),
1105 variant_did,
1106 ctor,
1107 data.discr,
1108 self.get_associated_item_or_field_def_ids(index)
1109 .map(|did| ty::FieldDef {
1110 did,
1111 name: self.item_name(did.index),
1112 vis: self.get_visibility(did.index),
1113 safety: self.get_safety(did.index),
1114 value: self.get_default_field(did.index),
1115 })
1116 .collect(),
1117 parent_did,
1118 None,
1119 data.is_non_exhaustive,
1120 ),
1121 )
1122 }
1123
1124 fn get_adt_def<'tcx>(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
1125 let kind = self.def_kind(item_id);
1126 let did = self.local_def_id(item_id);
1127
1128 let adt_kind = match kind {
1129 DefKind::Enum => ty::AdtKind::Enum,
1130 DefKind::Struct => ty::AdtKind::Struct,
1131 DefKind::Union => ty::AdtKind::Union,
1132 _ => bug!("get_adt_def called on a non-ADT {:?}", did),
1133 };
1134 let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self);
1135
1136 let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind {
1137 self.root
1138 .tables
1139 .module_children_non_reexports
1140 .get(self, item_id)
1141 .expect("variants are not encoded for an enum")
1142 .decode(self)
1143 .filter_map(|index| {
1144 let kind = self.def_kind(index);
1145 match kind {
1146 DefKind::Ctor(..) => None,
1147 _ => Some(self.get_variant(kind, index, did)),
1148 }
1149 })
1150 .collect()
1151 } else {
1152 std::iter::once(self.get_variant(kind, item_id, did)).collect()
1153 };
1154
1155 variants.sort_by_key(|(idx, _)| *idx);
1156
1157 tcx.mk_adt_def(
1158 did,
1159 adt_kind,
1160 variants.into_iter().map(|(_, variant)| variant).collect(),
1161 repr,
1162 )
1163 }
1164
1165 fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
1166 self.root
1167 .tables
1168 .visibility
1169 .get(self, id)
1170 .unwrap_or_else(|| self.missing("visibility", id))
1171 .decode(self)
1172 .map_id(|index| self.local_def_id(index))
1173 }
1174
1175 fn get_safety(self, id: DefIndex) -> Safety {
1176 self.root.tables.safety.get(self, id).unwrap_or_else(|| self.missing("safety", id))
1177 }
1178
1179 fn get_default_field(self, id: DefIndex) -> Option<DefId> {
1180 self.root.tables.default_fields.get(self, id).map(|d| d.decode(self))
1181 }
1182
1183 fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
1184 self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
1185 }
1186
1187 fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
1188 self.root
1189 .tables
1190 .expn_that_defined
1191 .get(self, id)
1192 .unwrap_or_else(|| self.missing("expn_that_defined", id))
1193 .decode((self, sess))
1194 }
1195
1196 fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
1197 self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
1198 }
1199
1200 fn get_lib_features(self) -> LibFeatures {
1202 LibFeatures {
1203 stability: self
1204 .root
1205 .lib_features
1206 .decode(self)
1207 .map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
1208 .collect(),
1209 }
1210 }
1211
1212 fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
1216 tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
1217 }
1218
1219 fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
1221 tcx.arena.alloc_from_iter(
1222 self.root
1223 .lang_items
1224 .decode(self)
1225 .map(move |(def_index, index)| (self.local_def_id(def_index), index)),
1226 )
1227 }
1228
1229 fn get_stripped_cfg_items<'tcx>(
1230 self,
1231 cnum: CrateNum,
1232 tcx: TyCtxt<'tcx>,
1233 ) -> &'tcx [StrippedCfgItem] {
1234 let item_names = self
1235 .root
1236 .stripped_cfg_items
1237 .decode((self, tcx))
1238 .map(|item| item.map_mod_id(|index| DefId { krate: cnum, index }));
1239 tcx.arena.alloc_from_iter(item_names)
1240 }
1241
1242 fn get_diagnostic_items(self) -> DiagnosticItems {
1244 let mut id_to_name = DefIdMap::default();
1245 let name_to_id = self
1246 .root
1247 .diagnostic_items
1248 .decode(self)
1249 .map(|(name, def_index)| {
1250 let id = self.local_def_id(def_index);
1251 id_to_name.insert(id, name);
1252 (name, id)
1253 })
1254 .collect();
1255 DiagnosticItems { id_to_name, name_to_id }
1256 }
1257
1258 fn get_mod_child(self, id: DefIndex, sess: &Session) -> ModChild {
1259 let ident = self.item_ident(id, sess);
1260 let res = Res::Def(self.def_kind(id), self.local_def_id(id));
1261 let vis = self.get_visibility(id);
1262
1263 ModChild { ident, res, vis, reexport_chain: Default::default() }
1264 }
1265
1266 fn get_module_children(
1271 self,
1272 id: DefIndex,
1273 sess: &'a Session,
1274 ) -> impl Iterator<Item = ModChild> {
1275 iter::from_coroutine(
1276 #[coroutine]
1277 move || {
1278 if let Some(data) = &self.root.proc_macro_data {
1279 if id == CRATE_DEF_INDEX {
1282 for child_index in data.macros.decode(self) {
1283 yield self.get_mod_child(child_index, sess);
1284 }
1285 }
1286 } else {
1287 let non_reexports =
1289 self.root.tables.module_children_non_reexports.get(self, id);
1290 for child_index in non_reexports.unwrap().decode(self) {
1291 yield self.get_mod_child(child_index, sess);
1292 }
1293
1294 let reexports = self.root.tables.module_children_reexports.get(self, id);
1295 if !reexports.is_default() {
1296 for reexport in reexports.decode((self, sess)) {
1297 yield reexport;
1298 }
1299 }
1300 }
1301 },
1302 )
1303 }
1304
1305 fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
1306 self.root.tables.mir_for_ctfe.get(self, id).is_some()
1307 }
1308
1309 fn is_item_mir_available(self, id: DefIndex) -> bool {
1310 self.root.tables.optimized_mir.get(self, id).is_some()
1311 }
1312
1313 fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool {
1314 self.root
1315 .tables
1316 .fn_arg_idents
1317 .get(self, id)
1318 .expect("argument names not encoded for a function")
1319 .decode((self, sess))
1320 .nth(0)
1321 .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
1322 }
1323
1324 fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
1325 self.root
1326 .tables
1327 .associated_item_or_field_def_ids
1328 .get(self, id)
1329 .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id))
1330 .decode(self)
1331 .map(move |child_index| self.local_def_id(child_index))
1332 }
1333
1334 fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
1335 let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
1336 kw::Empty
1337 } else {
1338 self.item_name(id)
1339 };
1340 let (kind, has_self) = match self.def_kind(id) {
1341 DefKind::AssocConst => (ty::AssocKind::Const, false),
1342 DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
1343 DefKind::AssocTy => (ty::AssocKind::Type, false),
1344 _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
1345 };
1346 let container = self.root.tables.assoc_container.get(self, id).unwrap();
1347 let opt_rpitit_info =
1348 self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self));
1349
1350 ty::AssocItem {
1351 name,
1352 kind,
1353 def_id: self.local_def_id(id),
1354 trait_item_def_id: self.get_trait_item_def_id(id),
1355 container,
1356 fn_has_self_parameter: has_self,
1357 opt_rpitit_info,
1358 }
1359 }
1360
1361 fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
1362 match self.def_kind(node_id) {
1363 DefKind::Struct | DefKind::Variant => {
1364 let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
1365 vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
1366 }
1367 _ => None,
1368 }
1369 }
1370
1371 fn get_item_attrs(
1372 self,
1373 id: DefIndex,
1374 sess: &'a Session,
1375 ) -> impl Iterator<Item = hir::Attribute> {
1376 self.root
1377 .tables
1378 .attributes
1379 .get(self, id)
1380 .unwrap_or_else(|| {
1381 let def_key = self.def_key(id);
1385 assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
1386 let parent_id = def_key.parent.expect("no parent for a constructor");
1387 self.root
1388 .tables
1389 .attributes
1390 .get(self, parent_id)
1391 .expect("no encoded attributes for a structure or variant")
1392 })
1393 .decode((self, sess))
1394 }
1395
1396 fn get_inherent_implementations_for_type<'tcx>(
1397 self,
1398 tcx: TyCtxt<'tcx>,
1399 id: DefIndex,
1400 ) -> &'tcx [DefId] {
1401 tcx.arena.alloc_from_iter(
1402 self.root
1403 .tables
1404 .inherent_impls
1405 .get(self, id)
1406 .decode(self)
1407 .map(|index| self.local_def_id(index)),
1408 )
1409 }
1410
1411 fn get_traits(self) -> impl Iterator<Item = DefId> {
1413 self.root.traits.decode(self).map(move |index| self.local_def_id(index))
1414 }
1415
1416 fn get_trait_impls(self) -> impl Iterator<Item = DefId> {
1418 self.cdata.trait_impls.values().flat_map(move |impls| {
1419 impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index))
1420 })
1421 }
1422
1423 fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
1424 if let Some(impls) = self.cdata.incoherent_impls.get(&simp) {
1425 tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
1426 } else {
1427 &[]
1428 }
1429 }
1430
1431 fn get_implementations_of_trait<'tcx>(
1432 self,
1433 tcx: TyCtxt<'tcx>,
1434 trait_def_id: DefId,
1435 ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
1436 if self.trait_impls.is_empty() {
1437 return &[];
1438 }
1439
1440 let key = match self.reverse_translate_def_id(trait_def_id) {
1443 Some(def_id) => (def_id.krate.as_u32(), def_id.index),
1444 None => return &[],
1445 };
1446
1447 if let Some(impls) = self.trait_impls.get(&key) {
1448 tcx.arena.alloc_from_iter(
1449 impls
1450 .decode(self)
1451 .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)),
1452 )
1453 } else {
1454 &[]
1455 }
1456 }
1457
1458 fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> {
1459 self.root.native_libraries.decode((self, sess))
1460 }
1461
1462 fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
1463 self.root
1464 .tables
1465 .proc_macro_quoted_spans
1466 .get(self, index)
1467 .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
1468 .decode((self, sess))
1469 }
1470
1471 fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> {
1472 self.root.foreign_modules.decode((self, sess))
1473 }
1474
1475 fn get_dylib_dependency_formats<'tcx>(
1476 self,
1477 tcx: TyCtxt<'tcx>,
1478 ) -> &'tcx [(CrateNum, LinkagePreference)] {
1479 tcx.arena.alloc_from_iter(
1480 self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
1481 let cnum = CrateNum::new(i + 1); link.map(|link| (self.cnum_map[cnum], link))
1483 }),
1484 )
1485 }
1486
1487 fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
1488 tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
1489 }
1490
1491 fn exported_symbols<'tcx>(
1492 self,
1493 tcx: TyCtxt<'tcx>,
1494 ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1495 tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
1496 }
1497
1498 fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
1499 match self.def_kind(id) {
1500 DefKind::Macro(_) => {
1501 let macro_rules = self.root.tables.is_macro_rules.get(self, id);
1502 let body =
1503 self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
1504 ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
1505 }
1506 _ => bug!(),
1507 }
1508 }
1509
1510 #[inline]
1511 fn def_key(self, index: DefIndex) -> DefKey {
1512 *self
1513 .def_key_cache
1514 .lock()
1515 .entry(index)
1516 .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
1517 }
1518
1519 fn def_path(self, id: DefIndex) -> DefPath {
1521 debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
1522 DefPath::make(self.cnum, id, |parent| self.def_key(parent))
1523 }
1524
1525 #[inline]
1526 fn def_path_hash(self, index: DefIndex) -> DefPathHash {
1527 let fingerprint = Fingerprint::new(
1531 self.root.stable_crate_id.as_u64(),
1532 self.root.tables.def_path_hashes.get(self, index),
1533 );
1534 DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1)
1535 }
1536
1537 #[inline]
1538 fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex {
1539 self.def_path_hash_map.def_path_hash_to_def_index(&hash)
1540 }
1541
1542 fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
1543 debug_assert_eq!(ExpnId::from_hash(hash), None);
1544 let index_guess = ExpnIndex::from_u32(index_guess);
1545 let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1546
1547 let index = if old_hash == Some(hash) {
1548 index_guess
1552 } else {
1553 let map = self.cdata.expn_hash_map.get_or_init(|| {
1557 let end_id = self.root.expn_hashes.size() as u32;
1558 let mut map =
1559 UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1560 for i in 0..end_id {
1561 let i = ExpnIndex::from_u32(i);
1562 if let Some(hash) = self.root.expn_hashes.get(self, i) {
1563 map.insert(hash.decode(self), i);
1564 }
1565 }
1566 map
1567 });
1568 map[&hash]
1569 };
1570
1571 let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
1572 rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
1573 }
1574
1575 fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1601 fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1602 path.filter(|_| {
1603 sess.opts.real_rust_source_base_dir.is_some()
1605 && sess.opts.unstable_opts.translate_remapped_path_to_local_path
1607 })
1608 .filter(|virtual_dir| {
1609 !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
1613 })
1614 }
1615
1616 let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
1617 let virtual_rust_source_base_dir = [
1623 filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1624 filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1625 ];
1626
1627 debug!(
1628 "try_to_translate_virtual_to_real(name={:?}): \
1629 virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1630 name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1631 );
1632
1633 for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1634 if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1635 && let rustc_span::FileName::Real(old_name) = name
1636 && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1637 old_name
1638 && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1639 {
1640 const STD_LIBS: &[&str] = &[
1645 "core",
1646 "alloc",
1647 "std",
1648 "test",
1649 "term",
1650 "unwind",
1651 "proc_macro",
1652 "panic_abort",
1653 "panic_unwind",
1654 "profiler_builtins",
1655 "rtstartup",
1656 "rustc-std-workspace-core",
1657 "rustc-std-workspace-alloc",
1658 "rustc-std-workspace-std",
1659 "backtrace",
1660 ];
1661 let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l));
1662
1663 let new_path = if is_std_lib {
1664 real_dir.join("library").join(rest)
1665 } else {
1666 real_dir.join(rest)
1667 };
1668
1669 debug!(
1670 "try_to_translate_virtual_to_real: `{}` -> `{}`",
1671 virtual_name.display(),
1672 new_path.display(),
1673 );
1674
1675 let (user_remapped, applied) =
1681 sess.source_map().path_mapping().map_prefix(&new_path);
1682 let new_name = if applied {
1683 rustc_span::RealFileName::Remapped {
1684 local_path: Some(new_path.clone()),
1685 virtual_name: user_remapped.to_path_buf(),
1686 }
1687 } else {
1688 rustc_span::RealFileName::LocalPath(new_path)
1689 };
1690 *old_name = new_name;
1691 }
1692 }
1693 };
1694
1695 let mut import_info = self.cdata.source_map_import_info.lock();
1696 for _ in import_info.len()..=(source_file_index as usize) {
1697 import_info.push(None);
1698 }
1699 import_info[source_file_index as usize]
1700 .get_or_insert_with(|| {
1701 let source_file_to_import = self
1702 .root
1703 .source_map
1704 .get(self, source_file_index)
1705 .expect("missing source file")
1706 .decode(self);
1707
1708 let original_end_pos = source_file_to_import.end_position();
1711 let rustc_span::SourceFile {
1712 mut name,
1713 src_hash,
1714 checksum_hash,
1715 start_pos: original_start_pos,
1716 source_len,
1717 lines,
1718 multibyte_chars,
1719 normalized_pos,
1720 stable_id,
1721 ..
1722 } = source_file_to_import;
1723
1724 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1732 && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1733 && let rustc_span::FileName::Real(ref mut old_name) = name
1734 {
1735 let relative_path = match old_name {
1736 rustc_span::RealFileName::LocalPath(local) => {
1737 local.strip_prefix(real_dir).ok()
1738 }
1739 rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1740 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
1741 .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1742 }
1743 };
1744 debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
1745 for subdir in ["library", "compiler"] {
1746 if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok())
1747 {
1748 *old_name = rustc_span::RealFileName::Remapped {
1749 local_path: None, virtual_name: virtual_dir.join(subdir).join(rest),
1751 };
1752 break;
1753 }
1754 }
1755 }
1756
1757 try_to_translate_virtual_to_real(&mut name);
1761
1762 let local_version = sess.source_map().new_imported_source_file(
1763 name,
1764 src_hash,
1765 checksum_hash,
1766 stable_id,
1767 source_len.to_u32(),
1768 self.cnum,
1769 lines,
1770 multibyte_chars,
1771 normalized_pos,
1772 source_file_index,
1773 );
1774 debug!(
1775 "CrateMetaData::imported_source_files alloc \
1776 source_file {:?} original (start_pos {:?} source_len {:?}) \
1777 translated (start_pos {:?} source_len {:?})",
1778 local_version.name,
1779 original_start_pos,
1780 source_len,
1781 local_version.start_pos,
1782 local_version.source_len
1783 );
1784
1785 ImportedSourceFile {
1786 original_start_pos,
1787 original_end_pos,
1788 translated_source_file: local_version,
1789 }
1790 })
1791 .clone()
1792 }
1793
1794 fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1795 self.root.tables.attr_flags.get(self, index)
1796 }
1797
1798 fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
1799 self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
1800 }
1801
1802 fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
1803 self.root
1804 .tables
1805 .doc_link_resolutions
1806 .get(self, index)
1807 .expect("no resolutions for a doc link")
1808 .decode(self)
1809 }
1810
1811 fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> {
1812 self.root
1813 .tables
1814 .doc_link_traits_in_scope
1815 .get(self, index)
1816 .expect("no traits in scope for a doc link")
1817 .decode(self)
1818 }
1819}
1820
1821impl CrateMetadata {
1822 pub(crate) fn new(
1823 sess: &Session,
1824 cstore: &CStore,
1825 blob: MetadataBlob,
1826 root: CrateRoot,
1827 raw_proc_macros: Option<&'static [ProcMacro]>,
1828 cnum: CrateNum,
1829 cnum_map: CrateNumMap,
1830 dep_kind: CrateDepKind,
1831 source: CrateSource,
1832 private_dep: bool,
1833 host_hash: Option<Svh>,
1834 ) -> CrateMetadata {
1835 let trait_impls = root
1836 .impls
1837 .decode((&blob, sess))
1838 .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
1839 .collect();
1840 let alloc_decoding_state =
1841 AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
1842 let dependencies = cnum_map.iter().copied().collect();
1843
1844 let def_path_hash_map = root.def_path_hash_map.decode(&blob);
1847
1848 let mut cdata = CrateMetadata {
1849 blob,
1850 root,
1851 trait_impls,
1852 incoherent_impls: Default::default(),
1853 raw_proc_macros,
1854 source_map_import_info: Lock::new(Vec::new()),
1855 def_path_hash_map,
1856 expn_hash_map: Default::default(),
1857 alloc_decoding_state,
1858 cnum,
1859 cnum_map,
1860 dependencies,
1861 dep_kind,
1862 source: Arc::new(source),
1863 private_dep,
1864 host_hash,
1865 used: false,
1866 extern_crate: None,
1867 hygiene_context: Default::default(),
1868 def_key_cache: Default::default(),
1869 };
1870
1871 cdata.incoherent_impls = cdata
1873 .root
1874 .incoherent_impls
1875 .decode(CrateMetadataRef { cdata: &cdata, cstore })
1876 .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls))
1877 .collect();
1878
1879 cdata
1880 }
1881
1882 pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
1883 self.dependencies.iter().copied()
1884 }
1885
1886 pub(crate) fn add_dependency(&mut self, cnum: CrateNum) {
1887 self.dependencies.push(cnum);
1888 }
1889
1890 pub(crate) fn target_modifiers(&self) -> TargetModifiers {
1891 self.root.decode_target_modifiers(&self.blob).collect()
1892 }
1893
1894 pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
1895 let update =
1896 Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank);
1897 if update {
1898 self.extern_crate = Some(new_extern_crate);
1899 }
1900 update
1901 }
1902
1903 pub(crate) fn source(&self) -> &CrateSource {
1904 &*self.source
1905 }
1906
1907 pub(crate) fn dep_kind(&self) -> CrateDepKind {
1908 self.dep_kind
1909 }
1910
1911 pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
1912 self.dep_kind = dep_kind;
1913 }
1914
1915 pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
1916 self.private_dep &= private_dep;
1917 }
1918
1919 pub(crate) fn used(&self) -> bool {
1920 self.used
1921 }
1922
1923 pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
1924 self.root.required_panic_strategy
1925 }
1926
1927 pub(crate) fn needs_panic_runtime(&self) -> bool {
1928 self.root.needs_panic_runtime
1929 }
1930
1931 pub(crate) fn is_private_dep(&self) -> bool {
1932 self.private_dep
1933 }
1934
1935 pub(crate) fn is_panic_runtime(&self) -> bool {
1936 self.root.panic_runtime
1937 }
1938
1939 pub(crate) fn is_profiler_runtime(&self) -> bool {
1940 self.root.profiler_runtime
1941 }
1942
1943 pub(crate) fn is_compiler_builtins(&self) -> bool {
1944 self.root.compiler_builtins
1945 }
1946
1947 pub(crate) fn needs_allocator(&self) -> bool {
1948 self.root.needs_allocator
1949 }
1950
1951 pub(crate) fn has_global_allocator(&self) -> bool {
1952 self.root.has_global_allocator
1953 }
1954
1955 pub(crate) fn has_alloc_error_handler(&self) -> bool {
1956 self.root.has_alloc_error_handler
1957 }
1958
1959 pub(crate) fn has_default_lib_allocator(&self) -> bool {
1960 self.root.has_default_lib_allocator
1961 }
1962
1963 pub(crate) fn is_proc_macro_crate(&self) -> bool {
1964 self.root.is_proc_macro_crate()
1965 }
1966
1967 pub(crate) fn name(&self) -> Symbol {
1968 self.root.header.name
1969 }
1970
1971 pub(crate) fn hash(&self) -> Svh {
1972 self.root.header.hash
1973 }
1974
1975 fn num_def_ids(&self) -> usize {
1976 self.root.tables.def_keys.size()
1977 }
1978
1979 fn local_def_id(&self, index: DefIndex) -> DefId {
1980 DefId { krate: self.cnum, index }
1981 }
1982
1983 fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
1986 for (local, &global) in self.cnum_map.iter_enumerated() {
1987 if global == did.krate {
1988 return Some(DefId { krate: local, index: did.index });
1989 }
1990 }
1991
1992 None
1993 }
1994}