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