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