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