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_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
1198 self.root
1199 .tables
1200 .expn_that_defined
1201 .get(self, id)
1202 .unwrap_or_else(|| self.missing("expn_that_defined", id))
1203 .decode((self, sess))
1204 }
1205
1206 fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
1207 self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
1208 }
1209
1210 fn get_lib_features(self) -> LibFeatures {
1212 LibFeatures {
1213 stability: self
1214 .root
1215 .lib_features
1216 .decode(self)
1217 .map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
1218 .collect(),
1219 }
1220 }
1221
1222 fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
1226 tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
1227 }
1228
1229 fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
1231 tcx.arena.alloc_from_iter(
1232 self.root
1233 .lang_items
1234 .decode(self)
1235 .map(move |(def_index, index)| (self.local_def_id(def_index), index)),
1236 )
1237 }
1238
1239 fn get_stripped_cfg_items<'tcx>(
1240 self,
1241 cnum: CrateNum,
1242 tcx: TyCtxt<'tcx>,
1243 ) -> &'tcx [StrippedCfgItem] {
1244 let item_names = self
1245 .root
1246 .stripped_cfg_items
1247 .decode((self, tcx))
1248 .map(|item| item.map_mod_id(|index| DefId { krate: cnum, index }));
1249 tcx.arena.alloc_from_iter(item_names)
1250 }
1251
1252 fn get_diagnostic_items(self) -> DiagnosticItems {
1254 let mut id_to_name = DefIdMap::default();
1255 let name_to_id = self
1256 .root
1257 .diagnostic_items
1258 .decode(self)
1259 .map(|(name, def_index)| {
1260 let id = self.local_def_id(def_index);
1261 id_to_name.insert(id, name);
1262 (name, id)
1263 })
1264 .collect();
1265 DiagnosticItems { id_to_name, name_to_id }
1266 }
1267
1268 fn get_mod_child(self, id: DefIndex, sess: &Session) -> ModChild {
1269 let ident = self.item_ident(id, sess);
1270 let res = Res::Def(self.def_kind(id), self.local_def_id(id));
1271 let vis = self.get_visibility(id);
1272
1273 ModChild { ident, res, vis, reexport_chain: Default::default() }
1274 }
1275
1276 fn get_module_children(
1281 self,
1282 id: DefIndex,
1283 sess: &'a Session,
1284 ) -> impl Iterator<Item = ModChild> {
1285 gen move {
1286 if let Some(data) = &self.root.proc_macro_data {
1287 if id == CRATE_DEF_INDEX {
1290 for child_index in data.macros.decode(self) {
1291 yield self.get_mod_child(child_index, sess);
1292 }
1293 }
1294 } else {
1295 let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
1297 for child_index in non_reexports.unwrap().decode(self) {
1298 yield self.get_mod_child(child_index, sess);
1299 }
1300
1301 let reexports = self.root.tables.module_children_reexports.get(self, id);
1302 if !reexports.is_default() {
1303 for reexport in reexports.decode((self, sess)) {
1304 yield reexport;
1305 }
1306 }
1307 }
1308 }
1309 }
1310
1311 fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
1312 self.root.tables.mir_for_ctfe.get(self, id).is_some()
1313 }
1314
1315 fn is_item_mir_available(self, id: DefIndex) -> bool {
1316 self.root.tables.optimized_mir.get(self, id).is_some()
1317 }
1318
1319 fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool {
1320 self.root
1321 .tables
1322 .fn_arg_idents
1323 .get(self, id)
1324 .expect("argument names not encoded for a function")
1325 .decode((self, sess))
1326 .nth(0)
1327 .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
1328 }
1329
1330 fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
1331 self.root
1332 .tables
1333 .associated_item_or_field_def_ids
1334 .get(self, id)
1335 .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id))
1336 .decode(self)
1337 .map(move |child_index| self.local_def_id(child_index))
1338 }
1339
1340 fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
1341 let kind = match self.def_kind(id) {
1342 DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) },
1343 DefKind::AssocFn => ty::AssocKind::Fn {
1344 name: self.item_name(id),
1345 has_self: self.get_fn_has_self_parameter(id, sess),
1346 },
1347 DefKind::AssocTy => {
1348 let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id)
1349 {
1350 ty::AssocTypeData::Rpitit(rpitit_info.decode(self))
1351 } else {
1352 ty::AssocTypeData::Normal(self.item_name(id))
1353 };
1354 ty::AssocKind::Type { data }
1355 }
1356 _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
1357 };
1358 let container = self.root.tables.assoc_container.get(self, id).unwrap().decode(self);
1359
1360 ty::AssocItem { kind, def_id: self.local_def_id(id), container }
1361 }
1362
1363 fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
1364 match self.def_kind(node_id) {
1365 DefKind::Struct | DefKind::Variant => {
1366 let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
1367 vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
1368 }
1369 _ => None,
1370 }
1371 }
1372
1373 fn get_item_attrs(
1374 self,
1375 id: DefIndex,
1376 sess: &'a Session,
1377 ) -> impl Iterator<Item = hir::Attribute> {
1378 self.root
1379 .tables
1380 .attributes
1381 .get(self, id)
1382 .unwrap_or_else(|| {
1383 let def_key = self.def_key(id);
1387 assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
1388 let parent_id = def_key.parent.expect("no parent for a constructor");
1389 self.root
1390 .tables
1391 .attributes
1392 .get(self, parent_id)
1393 .expect("no encoded attributes for a structure or variant")
1394 })
1395 .decode((self, sess))
1396 }
1397
1398 fn get_inherent_implementations_for_type<'tcx>(
1399 self,
1400 tcx: TyCtxt<'tcx>,
1401 id: DefIndex,
1402 ) -> &'tcx [DefId] {
1403 tcx.arena.alloc_from_iter(
1404 self.root
1405 .tables
1406 .inherent_impls
1407 .get(self, id)
1408 .decode(self)
1409 .map(|index| self.local_def_id(index)),
1410 )
1411 }
1412
1413 fn get_traits(self) -> impl Iterator<Item = DefId> {
1415 self.root.traits.decode(self).map(move |index| self.local_def_id(index))
1416 }
1417
1418 fn get_trait_impls(self) -> impl Iterator<Item = DefId> {
1420 self.cdata.trait_impls.values().flat_map(move |impls| {
1421 impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index))
1422 })
1423 }
1424
1425 fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
1426 if let Some(impls) = self.cdata.incoherent_impls.get(&simp) {
1427 tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
1428 } else {
1429 &[]
1430 }
1431 }
1432
1433 fn get_implementations_of_trait<'tcx>(
1434 self,
1435 tcx: TyCtxt<'tcx>,
1436 trait_def_id: DefId,
1437 ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
1438 if self.trait_impls.is_empty() {
1439 return &[];
1440 }
1441
1442 let key = match self.reverse_translate_def_id(trait_def_id) {
1445 Some(def_id) => (def_id.krate.as_u32(), def_id.index),
1446 None => return &[],
1447 };
1448
1449 if let Some(impls) = self.trait_impls.get(&key) {
1450 tcx.arena.alloc_from_iter(
1451 impls
1452 .decode(self)
1453 .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)),
1454 )
1455 } else {
1456 &[]
1457 }
1458 }
1459
1460 fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> {
1461 self.root.native_libraries.decode((self, sess))
1462 }
1463
1464 fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
1465 self.root
1466 .tables
1467 .proc_macro_quoted_spans
1468 .get(self, index)
1469 .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
1470 .decode((self, sess))
1471 }
1472
1473 fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> {
1474 self.root.foreign_modules.decode((self, sess))
1475 }
1476
1477 fn get_dylib_dependency_formats<'tcx>(
1478 self,
1479 tcx: TyCtxt<'tcx>,
1480 ) -> &'tcx [(CrateNum, LinkagePreference)] {
1481 tcx.arena.alloc_from_iter(
1482 self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
1483 let cnum = CrateNum::new(i + 1); link.map(|link| (self.cnum_map[cnum], link))
1485 }),
1486 )
1487 }
1488
1489 fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
1490 tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
1491 }
1492
1493 fn get_exportable_items(self) -> impl Iterator<Item = DefId> {
1494 self.root.exportable_items.decode(self).map(move |index| self.local_def_id(index))
1495 }
1496
1497 fn get_stable_order_of_exportable_impls(self) -> impl Iterator<Item = (DefId, usize)> {
1498 self.root
1499 .stable_order_of_exportable_impls
1500 .decode(self)
1501 .map(move |v| (self.local_def_id(v.0), v.1))
1502 }
1503
1504 fn exported_non_generic_symbols<'tcx>(
1505 self,
1506 tcx: TyCtxt<'tcx>,
1507 ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1508 tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx)))
1509 }
1510
1511 fn exported_generic_symbols<'tcx>(
1512 self,
1513 tcx: TyCtxt<'tcx>,
1514 ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1515 tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx)))
1516 }
1517
1518 fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
1519 match self.def_kind(id) {
1520 DefKind::Macro(_) => {
1521 let macro_rules = self.root.tables.is_macro_rules.get(self, id);
1522 let body =
1523 self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
1524 ast::MacroDef { macro_rules, body: Box::new(body) }
1525 }
1526 _ => bug!(),
1527 }
1528 }
1529
1530 #[inline]
1531 fn def_key(self, index: DefIndex) -> DefKey {
1532 *self
1533 .def_key_cache
1534 .lock()
1535 .entry(index)
1536 .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
1537 }
1538
1539 fn def_path(self, id: DefIndex) -> DefPath {
1541 debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
1542 DefPath::make(self.cnum, id, |parent| self.def_key(parent))
1543 }
1544
1545 #[inline]
1546 fn def_path_hash(self, index: DefIndex) -> DefPathHash {
1547 let fingerprint = Fingerprint::new(
1551 self.root.stable_crate_id.as_u64(),
1552 self.root.tables.def_path_hashes.get(self, index),
1553 );
1554 DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1)
1555 }
1556
1557 #[inline]
1558 fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex {
1559 self.def_path_hash_map.def_path_hash_to_def_index(&hash)
1560 }
1561
1562 fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
1563 debug_assert_eq!(ExpnId::from_hash(hash), None);
1564 let index_guess = ExpnIndex::from_u32(index_guess);
1565 let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1566
1567 let index = if old_hash == Some(hash) {
1568 index_guess
1572 } else {
1573 let map = self.cdata.expn_hash_map.get_or_init(|| {
1577 let end_id = self.root.expn_hashes.size() as u32;
1578 let mut map =
1579 UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1580 for i in 0..end_id {
1581 let i = ExpnIndex::from_u32(i);
1582 if let Some(hash) = self.root.expn_hashes.get(self, i) {
1583 map.insert(hash.decode(self), i);
1584 }
1585 }
1586 map
1587 });
1588 map[&hash]
1589 };
1590
1591 let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
1592 rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
1593 }
1594
1595 fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1621 fn filter<'a>(
1622 sess: &Session,
1623 real_source_base_dir: &Option<PathBuf>,
1624 path: Option<&'a Path>,
1625 ) -> Option<&'a Path> {
1626 path.filter(|_| {
1627 real_source_base_dir.is_some()
1629 && sess.opts.unstable_opts.translate_remapped_path_to_local_path
1631 })
1632 .filter(|virtual_dir| {
1633 !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
1637 })
1638 }
1639
1640 let try_to_translate_virtual_to_real =
1641 |virtual_source_base_dir: Option<&str>,
1642 real_source_base_dir: &Option<PathBuf>,
1643 name: &mut rustc_span::FileName| {
1644 let virtual_source_base_dir = [
1645 filter(sess, real_source_base_dir, virtual_source_base_dir.map(Path::new)),
1646 filter(
1647 sess,
1648 real_source_base_dir,
1649 sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
1650 ),
1651 ];
1652
1653 debug!(
1654 "try_to_translate_virtual_to_real(name={:?}): \
1655 virtual_source_base_dir={:?}, real_source_base_dir={:?}",
1656 name, virtual_source_base_dir, real_source_base_dir,
1657 );
1658
1659 for virtual_dir in virtual_source_base_dir.iter().flatten() {
1660 if let Some(real_dir) = &real_source_base_dir
1661 && let rustc_span::FileName::Real(old_name) = name
1662 && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1663 old_name
1664 && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1665 {
1666 let new_path = real_dir.join(rest);
1667
1668 debug!(
1669 "try_to_translate_virtual_to_real: `{}` -> `{}`",
1670 virtual_name.display(),
1671 new_path.display(),
1672 );
1673
1674 let (user_remapped, applied) =
1680 sess.source_map().path_mapping().map_prefix(&new_path);
1681 let new_name = if applied {
1682 rustc_span::RealFileName::Remapped {
1683 local_path: Some(new_path.clone()),
1684 virtual_name: user_remapped.to_path_buf(),
1685 }
1686 } else {
1687 rustc_span::RealFileName::LocalPath(new_path)
1688 };
1689 *old_name = new_name;
1690 }
1691 }
1692 };
1693
1694 let try_to_translate_real_to_virtual =
1695 |virtual_source_base_dir: Option<&str>,
1696 real_source_base_dir: &Option<PathBuf>,
1697 subdir: &str,
1698 name: &mut rustc_span::FileName| {
1699 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1700 && let Some(real_dir) = real_source_base_dir
1701 && let rustc_span::FileName::Real(old_name) = name
1702 {
1703 let relative_path = match old_name {
1704 rustc_span::RealFileName::LocalPath(local) => {
1705 local.strip_prefix(real_dir).ok()
1706 }
1707 rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1708 virtual_source_base_dir
1709 .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1710 }
1711 };
1712 debug!(
1713 ?relative_path,
1714 ?virtual_dir,
1715 ?subdir,
1716 "simulate_remapped_rust_src_base"
1717 );
1718 if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
1719 *old_name = rustc_span::RealFileName::Remapped {
1720 local_path: None,
1721 virtual_name: virtual_dir.join(subdir).join(rest),
1722 };
1723 }
1724 }
1725 };
1726
1727 let mut import_info = self.cdata.source_map_import_info.lock();
1728 for _ in import_info.len()..=(source_file_index as usize) {
1729 import_info.push(None);
1730 }
1731 import_info[source_file_index as usize]
1732 .get_or_insert_with(|| {
1733 let source_file_to_import = self
1734 .root
1735 .source_map
1736 .get(self, source_file_index)
1737 .expect("missing source file")
1738 .decode(self);
1739
1740 let original_end_pos = source_file_to_import.end_position();
1743 let rustc_span::SourceFile {
1744 mut name,
1745 src_hash,
1746 checksum_hash,
1747 start_pos: original_start_pos,
1748 source_len,
1749 lines,
1750 multibyte_chars,
1751 normalized_pos,
1752 stable_id,
1753 ..
1754 } = source_file_to_import;
1755
1756 try_to_translate_real_to_virtual(
1764 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1765 &sess.opts.real_rust_source_base_dir,
1766 "library",
1767 &mut name,
1768 );
1769
1770 try_to_translate_real_to_virtual(
1775 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1776 &sess.opts.real_rustc_dev_source_base_dir,
1777 "compiler",
1778 &mut name,
1779 );
1780
1781 try_to_translate_virtual_to_real(
1787 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1788 &sess.opts.real_rust_source_base_dir,
1789 &mut name,
1790 );
1791
1792 try_to_translate_virtual_to_real(
1798 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1799 &sess.opts.real_rustc_dev_source_base_dir,
1800 &mut name,
1801 );
1802
1803 let local_version = sess.source_map().new_imported_source_file(
1804 name,
1805 src_hash,
1806 checksum_hash,
1807 stable_id,
1808 source_len.to_u32(),
1809 self.cnum,
1810 lines,
1811 multibyte_chars,
1812 normalized_pos,
1813 source_file_index,
1814 );
1815 debug!(
1816 "CrateMetaData::imported_source_files alloc \
1817 source_file {:?} original (start_pos {:?} source_len {:?}) \
1818 translated (start_pos {:?} source_len {:?})",
1819 local_version.name,
1820 original_start_pos,
1821 source_len,
1822 local_version.start_pos,
1823 local_version.source_len
1824 );
1825
1826 ImportedSourceFile {
1827 original_start_pos,
1828 original_end_pos,
1829 translated_source_file: local_version,
1830 }
1831 })
1832 .clone()
1833 }
1834
1835 fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1836 self.root.tables.attr_flags.get(self, index)
1837 }
1838
1839 fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
1840 self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
1841 }
1842
1843 fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
1844 self.root
1845 .tables
1846 .doc_link_resolutions
1847 .get(self, index)
1848 .expect("no resolutions for a doc link")
1849 .decode(self)
1850 }
1851
1852 fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> {
1853 self.root
1854 .tables
1855 .doc_link_traits_in_scope
1856 .get(self, index)
1857 .expect("no traits in scope for a doc link")
1858 .decode(self)
1859 }
1860}
1861
1862impl CrateMetadata {
1863 pub(crate) fn new(
1864 sess: &Session,
1865 cstore: &CStore,
1866 blob: MetadataBlob,
1867 root: CrateRoot,
1868 raw_proc_macros: Option<&'static [ProcMacro]>,
1869 cnum: CrateNum,
1870 cnum_map: CrateNumMap,
1871 dep_kind: CrateDepKind,
1872 source: CrateSource,
1873 private_dep: bool,
1874 host_hash: Option<Svh>,
1875 ) -> CrateMetadata {
1876 let trait_impls = root
1877 .impls
1878 .decode((&blob, sess))
1879 .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
1880 .collect();
1881 let alloc_decoding_state =
1882 AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
1883 let dependencies = cnum_map.iter().copied().collect();
1884
1885 let def_path_hash_map = root.def_path_hash_map.decode(&blob);
1888
1889 let mut cdata = CrateMetadata {
1890 blob,
1891 root,
1892 trait_impls,
1893 incoherent_impls: Default::default(),
1894 raw_proc_macros,
1895 source_map_import_info: Lock::new(Vec::new()),
1896 def_path_hash_map,
1897 expn_hash_map: Default::default(),
1898 alloc_decoding_state,
1899 cnum,
1900 cnum_map,
1901 dependencies,
1902 dep_kind,
1903 source: Arc::new(source),
1904 private_dep,
1905 host_hash,
1906 used: false,
1907 extern_crate: None,
1908 hygiene_context: Default::default(),
1909 def_key_cache: Default::default(),
1910 };
1911
1912 cdata.incoherent_impls = cdata
1914 .root
1915 .incoherent_impls
1916 .decode(CrateMetadataRef { cdata: &cdata, cstore })
1917 .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls))
1918 .collect();
1919
1920 cdata
1921 }
1922
1923 pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
1924 self.dependencies.iter().copied()
1925 }
1926
1927 pub(crate) fn target_modifiers(&self) -> TargetModifiers {
1928 self.root.decode_target_modifiers(&self.blob).collect()
1929 }
1930
1931 pub(crate) fn update_extern_crate_diagnostics(
1933 &mut self,
1934 new_extern_crate: ExternCrate,
1935 ) -> bool {
1936 let update =
1937 self.extern_crate.as_ref().is_none_or(|old| old.rank() < new_extern_crate.rank());
1938 if update {
1939 self.extern_crate = Some(new_extern_crate);
1940 }
1941 update
1942 }
1943
1944 pub(crate) fn source(&self) -> &CrateSource {
1945 &*self.source
1946 }
1947
1948 pub(crate) fn dep_kind(&self) -> CrateDepKind {
1949 self.dep_kind
1950 }
1951
1952 pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
1953 self.dep_kind = dep_kind;
1954 }
1955
1956 pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
1957 self.private_dep &= private_dep;
1958 }
1959
1960 pub(crate) fn used(&self) -> bool {
1961 self.used
1962 }
1963
1964 pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
1965 self.root.required_panic_strategy
1966 }
1967
1968 pub(crate) fn needs_panic_runtime(&self) -> bool {
1969 self.root.needs_panic_runtime
1970 }
1971
1972 pub(crate) fn is_private_dep(&self) -> bool {
1973 self.private_dep
1974 }
1975
1976 pub(crate) fn is_panic_runtime(&self) -> bool {
1977 self.root.panic_runtime
1978 }
1979
1980 pub(crate) fn is_profiler_runtime(&self) -> bool {
1981 self.root.profiler_runtime
1982 }
1983
1984 pub(crate) fn is_compiler_builtins(&self) -> bool {
1985 self.root.compiler_builtins
1986 }
1987
1988 pub(crate) fn needs_allocator(&self) -> bool {
1989 self.root.needs_allocator
1990 }
1991
1992 pub(crate) fn has_global_allocator(&self) -> bool {
1993 self.root.has_global_allocator
1994 }
1995
1996 pub(crate) fn has_alloc_error_handler(&self) -> bool {
1997 self.root.has_alloc_error_handler
1998 }
1999
2000 pub(crate) fn has_default_lib_allocator(&self) -> bool {
2001 self.root.has_default_lib_allocator
2002 }
2003
2004 pub(crate) fn is_proc_macro_crate(&self) -> bool {
2005 self.root.is_proc_macro_crate()
2006 }
2007
2008 pub(crate) fn proc_macros_for_crate(
2009 &self,
2010 krate: CrateNum,
2011 cstore: &CStore,
2012 ) -> impl Iterator<Item = DefId> {
2013 gen move {
2014 for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| {
2015 data.macros
2016 .decode(CrateMetadataRef { cdata: self, cstore })
2017 .map(move |index| DefId { index, krate })
2018 }) {
2019 yield def_id;
2020 }
2021 }
2022 }
2023
2024 pub(crate) fn name(&self) -> Symbol {
2025 self.root.header.name
2026 }
2027
2028 pub(crate) fn hash(&self) -> Svh {
2029 self.root.header.hash
2030 }
2031
2032 pub(crate) fn has_async_drops(&self) -> bool {
2033 self.root.tables.adt_async_destructor.len > 0
2034 }
2035
2036 fn num_def_ids(&self) -> usize {
2037 self.root.tables.def_keys.size()
2038 }
2039
2040 fn local_def_id(&self, index: DefIndex) -> DefId {
2041 DefId { krate: self.cnum, index }
2042 }
2043
2044 fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
2047 for (local, &global) in self.cnum_map.iter_enumerated() {
2048 if global == did.krate {
2049 return Some(DefId { krate: local, index: did.index });
2050 }
2051 }
2052
2053 None
2054 }
2055}