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) -> Option<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 let index_guess = ExpnIndex::from_u32(index_guess);
1564 let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1565
1566 let index = if old_hash == Some(hash) {
1567 index_guess
1571 } else {
1572 let map = self.cdata.expn_hash_map.get_or_init(|| {
1576 let end_id = self.root.expn_hashes.size() as u32;
1577 let mut map =
1578 UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1579 for i in 0..end_id {
1580 let i = ExpnIndex::from_u32(i);
1581 if let Some(hash) = self.root.expn_hashes.get(self, i) {
1582 map.insert(hash.decode(self), i);
1583 }
1584 }
1585 map
1586 });
1587 map[&hash]
1588 };
1589
1590 let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
1591 rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
1592 }
1593
1594 fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1620 fn filter<'a>(
1621 sess: &Session,
1622 real_source_base_dir: &Option<PathBuf>,
1623 path: Option<&'a Path>,
1624 ) -> Option<&'a Path> {
1625 path.filter(|_| {
1626 real_source_base_dir.is_some()
1628 && sess.opts.unstable_opts.translate_remapped_path_to_local_path
1630 })
1631 .filter(|virtual_dir| {
1632 !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
1636 })
1637 }
1638
1639 let try_to_translate_virtual_to_real =
1640 |virtual_source_base_dir: Option<&str>,
1641 real_source_base_dir: &Option<PathBuf>,
1642 name: &mut rustc_span::FileName| {
1643 let virtual_source_base_dir = [
1644 filter(sess, real_source_base_dir, virtual_source_base_dir.map(Path::new)),
1645 filter(
1646 sess,
1647 real_source_base_dir,
1648 sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
1649 ),
1650 ];
1651
1652 debug!(
1653 "try_to_translate_virtual_to_real(name={:?}): \
1654 virtual_source_base_dir={:?}, real_source_base_dir={:?}",
1655 name, virtual_source_base_dir, real_source_base_dir,
1656 );
1657
1658 for virtual_dir in virtual_source_base_dir.iter().flatten() {
1659 if let Some(real_dir) = &real_source_base_dir
1660 && let rustc_span::FileName::Real(old_name) = name
1661 && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1662 old_name
1663 && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1664 {
1665 let new_path = real_dir.join(rest);
1666
1667 debug!(
1668 "try_to_translate_virtual_to_real: `{}` -> `{}`",
1669 virtual_name.display(),
1670 new_path.display(),
1671 );
1672
1673 let (user_remapped, applied) =
1679 sess.source_map().path_mapping().map_prefix(&new_path);
1680 let new_name = if applied {
1681 rustc_span::RealFileName::Remapped {
1682 local_path: Some(new_path.clone()),
1683 virtual_name: user_remapped.to_path_buf(),
1684 }
1685 } else {
1686 rustc_span::RealFileName::LocalPath(new_path)
1687 };
1688 *old_name = new_name;
1689 }
1690 }
1691 };
1692
1693 let try_to_translate_real_to_virtual =
1694 |virtual_source_base_dir: Option<&str>,
1695 real_source_base_dir: &Option<PathBuf>,
1696 subdir: &str,
1697 name: &mut rustc_span::FileName| {
1698 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1699 && let Some(real_dir) = real_source_base_dir
1700 && let rustc_span::FileName::Real(old_name) = name
1701 {
1702 let relative_path = match old_name {
1703 rustc_span::RealFileName::LocalPath(local) => {
1704 local.strip_prefix(real_dir).ok()
1705 }
1706 rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1707 virtual_source_base_dir
1708 .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1709 }
1710 };
1711 debug!(
1712 ?relative_path,
1713 ?virtual_dir,
1714 ?subdir,
1715 "simulate_remapped_rust_src_base"
1716 );
1717 if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
1718 *old_name = rustc_span::RealFileName::Remapped {
1719 local_path: None,
1720 virtual_name: virtual_dir.join(subdir).join(rest),
1721 };
1722 }
1723 }
1724 };
1725
1726 let mut import_info = self.cdata.source_map_import_info.lock();
1727 for _ in import_info.len()..=(source_file_index as usize) {
1728 import_info.push(None);
1729 }
1730 import_info[source_file_index as usize]
1731 .get_or_insert_with(|| {
1732 let source_file_to_import = self
1733 .root
1734 .source_map
1735 .get(self, source_file_index)
1736 .expect("missing source file")
1737 .decode(self);
1738
1739 let original_end_pos = source_file_to_import.end_position();
1742 let rustc_span::SourceFile {
1743 mut name,
1744 src_hash,
1745 checksum_hash,
1746 start_pos: original_start_pos,
1747 source_len,
1748 lines,
1749 multibyte_chars,
1750 normalized_pos,
1751 stable_id,
1752 ..
1753 } = source_file_to_import;
1754
1755 try_to_translate_real_to_virtual(
1763 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1764 &sess.opts.real_rust_source_base_dir,
1765 "library",
1766 &mut name,
1767 );
1768
1769 try_to_translate_real_to_virtual(
1774 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1775 &sess.opts.real_rustc_dev_source_base_dir,
1776 "compiler",
1777 &mut name,
1778 );
1779
1780 try_to_translate_virtual_to_real(
1786 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1787 &sess.opts.real_rust_source_base_dir,
1788 &mut name,
1789 );
1790
1791 try_to_translate_virtual_to_real(
1797 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1798 &sess.opts.real_rustc_dev_source_base_dir,
1799 &mut name,
1800 );
1801
1802 let local_version = sess.source_map().new_imported_source_file(
1803 name,
1804 src_hash,
1805 checksum_hash,
1806 stable_id,
1807 source_len.to_u32(),
1808 self.cnum,
1809 lines,
1810 multibyte_chars,
1811 normalized_pos,
1812 source_file_index,
1813 );
1814 debug!(
1815 "CrateMetaData::imported_source_files alloc \
1816 source_file {:?} original (start_pos {:?} source_len {:?}) \
1817 translated (start_pos {:?} source_len {:?})",
1818 local_version.name,
1819 original_start_pos,
1820 source_len,
1821 local_version.start_pos,
1822 local_version.source_len
1823 );
1824
1825 ImportedSourceFile {
1826 original_start_pos,
1827 original_end_pos,
1828 translated_source_file: local_version,
1829 }
1830 })
1831 .clone()
1832 }
1833
1834 fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1835 self.root.tables.attr_flags.get(self, index)
1836 }
1837
1838 fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
1839 self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
1840 }
1841
1842 fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
1843 self.root
1844 .tables
1845 .doc_link_resolutions
1846 .get(self, index)
1847 .expect("no resolutions for a doc link")
1848 .decode(self)
1849 }
1850
1851 fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> {
1852 self.root
1853 .tables
1854 .doc_link_traits_in_scope
1855 .get(self, index)
1856 .expect("no traits in scope for a doc link")
1857 .decode(self)
1858 }
1859}
1860
1861impl CrateMetadata {
1862 pub(crate) fn new(
1863 sess: &Session,
1864 cstore: &CStore,
1865 blob: MetadataBlob,
1866 root: CrateRoot,
1867 raw_proc_macros: Option<&'static [ProcMacro]>,
1868 cnum: CrateNum,
1869 cnum_map: CrateNumMap,
1870 dep_kind: CrateDepKind,
1871 source: CrateSource,
1872 private_dep: bool,
1873 host_hash: Option<Svh>,
1874 ) -> CrateMetadata {
1875 let trait_impls = root
1876 .impls
1877 .decode((&blob, sess))
1878 .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
1879 .collect();
1880 let alloc_decoding_state =
1881 AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
1882 let dependencies = cnum_map.iter().copied().collect();
1883
1884 let def_path_hash_map = root.def_path_hash_map.decode(&blob);
1887
1888 let mut cdata = CrateMetadata {
1889 blob,
1890 root,
1891 trait_impls,
1892 incoherent_impls: Default::default(),
1893 raw_proc_macros,
1894 source_map_import_info: Lock::new(Vec::new()),
1895 def_path_hash_map,
1896 expn_hash_map: Default::default(),
1897 alloc_decoding_state,
1898 cnum,
1899 cnum_map,
1900 dependencies,
1901 dep_kind,
1902 source: Arc::new(source),
1903 private_dep,
1904 host_hash,
1905 used: false,
1906 extern_crate: None,
1907 hygiene_context: Default::default(),
1908 def_key_cache: Default::default(),
1909 };
1910
1911 cdata.incoherent_impls = cdata
1913 .root
1914 .incoherent_impls
1915 .decode(CrateMetadataRef { cdata: &cdata, cstore })
1916 .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls))
1917 .collect();
1918
1919 cdata
1920 }
1921
1922 pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
1923 self.dependencies.iter().copied()
1924 }
1925
1926 pub(crate) fn target_modifiers(&self) -> TargetModifiers {
1927 self.root.decode_target_modifiers(&self.blob).collect()
1928 }
1929
1930 pub(crate) fn update_extern_crate_diagnostics(
1932 &mut self,
1933 new_extern_crate: ExternCrate,
1934 ) -> bool {
1935 let update =
1936 self.extern_crate.as_ref().is_none_or(|old| old.rank() < new_extern_crate.rank());
1937 if update {
1938 self.extern_crate = Some(new_extern_crate);
1939 }
1940 update
1941 }
1942
1943 pub(crate) fn source(&self) -> &CrateSource {
1944 &*self.source
1945 }
1946
1947 pub(crate) fn dep_kind(&self) -> CrateDepKind {
1948 self.dep_kind
1949 }
1950
1951 pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
1952 self.dep_kind = dep_kind;
1953 }
1954
1955 pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
1956 self.private_dep &= private_dep;
1957 }
1958
1959 pub(crate) fn used(&self) -> bool {
1960 self.used
1961 }
1962
1963 pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
1964 self.root.required_panic_strategy
1965 }
1966
1967 pub(crate) fn needs_panic_runtime(&self) -> bool {
1968 self.root.needs_panic_runtime
1969 }
1970
1971 pub(crate) fn is_private_dep(&self) -> bool {
1972 self.private_dep
1973 }
1974
1975 pub(crate) fn is_panic_runtime(&self) -> bool {
1976 self.root.panic_runtime
1977 }
1978
1979 pub(crate) fn is_profiler_runtime(&self) -> bool {
1980 self.root.profiler_runtime
1981 }
1982
1983 pub(crate) fn is_compiler_builtins(&self) -> bool {
1984 self.root.compiler_builtins
1985 }
1986
1987 pub(crate) fn needs_allocator(&self) -> bool {
1988 self.root.needs_allocator
1989 }
1990
1991 pub(crate) fn has_global_allocator(&self) -> bool {
1992 self.root.has_global_allocator
1993 }
1994
1995 pub(crate) fn has_alloc_error_handler(&self) -> bool {
1996 self.root.has_alloc_error_handler
1997 }
1998
1999 pub(crate) fn has_default_lib_allocator(&self) -> bool {
2000 self.root.has_default_lib_allocator
2001 }
2002
2003 pub(crate) fn is_proc_macro_crate(&self) -> bool {
2004 self.root.is_proc_macro_crate()
2005 }
2006
2007 pub(crate) fn proc_macros_for_crate(
2008 &self,
2009 krate: CrateNum,
2010 cstore: &CStore,
2011 ) -> impl Iterator<Item = DefId> {
2012 gen move {
2013 for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| {
2014 data.macros
2015 .decode(CrateMetadataRef { cdata: self, cstore })
2016 .map(move |index| DefId { index, krate })
2017 }) {
2018 yield def_id;
2019 }
2020 }
2021 }
2022
2023 pub(crate) fn name(&self) -> Symbol {
2024 self.root.header.name
2025 }
2026
2027 pub(crate) fn hash(&self) -> Svh {
2028 self.root.header.hash
2029 }
2030
2031 pub(crate) fn has_async_drops(&self) -> bool {
2032 self.root.tables.adt_async_destructor.len > 0
2033 }
2034
2035 fn num_def_ids(&self) -> usize {
2036 self.root.tables.def_keys.size()
2037 }
2038
2039 fn local_def_id(&self, index: DefIndex) -> DefId {
2040 DefId { krate: self.cnum, index }
2041 }
2042
2043 fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
2046 for (local, &global) in self.cnum_map.iter_enumerated() {
2047 if global == did.krate {
2048 return Some(DefId { krate: local, index: did.index });
2049 }
2050 }
2051
2052 None
2053 }
2054}