rustc_metadata/rmeta/
decoder.rs

1// Decoding metadata from a single crate's metadata
2
3use std::iter::TrustedLen;
4use std::path::Path;
5use std::sync::{Arc, OnceLock};
6use std::{io, iter, mem};
7
8pub(super) use cstore_impl::provide;
9use proc_macro::bridge::client::ProcMacro;
10use rustc_ast as ast;
11use rustc_data_structures::fingerprint::Fingerprint;
12use rustc_data_structures::fx::FxIndexMap;
13use rustc_data_structures::owned_slice::OwnedSlice;
14use rustc_data_structures::sync::Lock;
15use rustc_data_structures::unhash::UnhashMap;
16use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
17use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
18use rustc_hir::Safety;
19use rustc_hir::def::Res;
20use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE};
21use rustc_hir::definitions::{DefPath, DefPathData};
22use rustc_hir::diagnostic_items::DiagnosticItems;
23use rustc_index::Idx;
24use rustc_middle::middle::lib_features::LibFeatures;
25use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
26use rustc_middle::ty::Visibility;
27use rustc_middle::ty::codec::TyDecoder;
28use rustc_middle::{bug, implement_ty_decoder};
29use rustc_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::{BytePos, DUMMY_SP, Pos, SpanData, SpanDecoder, SyntaxContext, kw};
36use tracing::debug;
37
38use crate::creader::CStore;
39use crate::rmeta::table::IsDefault;
40use crate::rmeta::*;
41
42mod cstore_impl;
43
44/// A reference to the raw binary version of crate metadata.
45/// This struct applies [`MemDecoder`]'s validation when constructed
46/// so that later constructions are guaranteed to succeed.
47pub(crate) struct MetadataBlob(OwnedSlice);
48
49impl std::ops::Deref for MetadataBlob {
50    type Target = [u8];
51
52    #[inline]
53    fn deref(&self) -> &[u8] {
54        &self.0[..]
55    }
56}
57
58impl MetadataBlob {
59    /// Runs the [`MemDecoder`] validation and if it passes, constructs a new [`MetadataBlob`].
60    pub(crate) fn new(slice: OwnedSlice) -> Result<Self, ()> {
61        if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) }
62    }
63
64    /// Since this has passed the validation of [`MetadataBlob::new`], this returns bytes which are
65    /// known to pass the [`MemDecoder`] validation.
66    pub(crate) fn bytes(&self) -> &OwnedSlice {
67        &self.0
68    }
69}
70
71/// A map from external crate numbers (as decoded from some crate file) to
72/// local crate numbers (as generated during this session). Each external
73/// crate may refer to types in other external crates, and each has their
74/// own crate numbers.
75pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
76
77/// Target modifiers - abi or exploit mitigations flags
78pub(crate) type TargetModifiers = Vec<TargetModifier>;
79
80pub(crate) struct CrateMetadata {
81    /// The primary crate data - binary metadata blob.
82    blob: MetadataBlob,
83
84    // --- Some data pre-decoded from the metadata blob, usually for performance ---
85    /// Data about the top-level items in a crate, as well as various crate-level metadata.
86    root: CrateRoot,
87    /// Trait impl data.
88    /// FIXME: Used only from queries and can use query cache,
89    /// so pre-decoding can probably be avoided.
90    trait_impls: FxIndexMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
91    /// Inherent impls which do not follow the normal coherence rules.
92    ///
93    /// These can be introduced using either `#![rustc_coherence_is_core]`
94    /// or `#[rustc_allow_incoherent_impl]`.
95    incoherent_impls: FxIndexMap<SimplifiedType, LazyArray<DefIndex>>,
96    /// Proc macro descriptions for this crate, if it's a proc macro crate.
97    raw_proc_macros: Option<&'static [ProcMacro]>,
98    /// Source maps for code from the crate.
99    source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>,
100    /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
101    def_path_hash_map: DefPathHashMapRef<'static>,
102    /// Likewise for ExpnHash.
103    expn_hash_map: OnceLock<UnhashMap<ExpnHash, ExpnIndex>>,
104    /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
105    alloc_decoding_state: AllocDecodingState,
106    /// Caches decoded `DefKey`s.
107    def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,
108
109    // --- Other significant crate properties ---
110    /// ID of this crate, from the current compilation session's point of view.
111    cnum: CrateNum,
112    /// Maps crate IDs as they are were seen from this crate's compilation sessions into
113    /// IDs as they are seen from the current compilation session.
114    cnum_map: CrateNumMap,
115    /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
116    dependencies: Vec<CrateNum>,
117    /// How to link (or not link) this crate to the currently compiled crate.
118    dep_kind: CrateDepKind,
119    /// Filesystem location of this crate.
120    source: Arc<CrateSource>,
121    /// Whether or not this crate should be consider a private dependency.
122    /// Used by the 'exported_private_dependencies' lint, and for determining
123    /// whether to emit suggestions that reference this crate.
124    private_dep: bool,
125    /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
126    host_hash: Option<Svh>,
127    /// The crate was used non-speculatively.
128    used: bool,
129
130    /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
131    /// and `ExpnId`).
132    /// Note that we store a `HygieneDecodeContext` for each `CrateMetadata`. This is
133    /// because `SyntaxContext` ids are not globally unique, so we need
134    /// to track which ids we've decoded on a per-crate basis.
135    hygiene_context: HygieneDecodeContext,
136
137    // --- Data used only for improving diagnostics ---
138    /// Information about the `extern crate` item or path that caused this crate to be loaded.
139    /// If this is `None`, then the crate was injected (e.g., by the allocator).
140    extern_crate: Option<ExternCrate>,
141}
142
143/// Holds information about a rustc_span::SourceFile imported from another crate.
144/// See `imported_source_file()` for more information.
145#[derive(Clone)]
146struct ImportedSourceFile {
147    /// This SourceFile's byte-offset within the source_map of its original crate
148    original_start_pos: rustc_span::BytePos,
149    /// The end of this SourceFile within the source_map of its original crate
150    original_end_pos: rustc_span::BytePos,
151    /// The imported SourceFile's representation within the local source_map
152    translated_source_file: Arc<rustc_span::SourceFile>,
153}
154
155pub(super) struct DecodeContext<'a, 'tcx> {
156    opaque: MemDecoder<'a>,
157    cdata: Option<CrateMetadataRef<'a>>,
158    blob: &'a MetadataBlob,
159    sess: Option<&'tcx Session>,
160    tcx: Option<TyCtxt<'tcx>>,
161
162    lazy_state: LazyState,
163
164    // Used for decoding interpret::AllocIds in a cached & thread-safe manner.
165    alloc_decoding_session: Option<AllocDecodingSession<'a>>,
166}
167
168/// Abstract over the various ways one can create metadata decoders.
169pub(super) trait Metadata<'a, 'tcx>: Copy {
170    fn blob(self) -> &'a MetadataBlob;
171
172    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
173        None
174    }
175    fn sess(self) -> Option<&'tcx Session> {
176        None
177    }
178    fn tcx(self) -> Option<TyCtxt<'tcx>> {
179        None
180    }
181
182    fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
183        let tcx = self.tcx();
184        DecodeContext {
185            // FIXME: This unwrap should never panic because we check that it won't when creating
186            // `MetadataBlob`. Ideally we'd just have a `MetadataDecoder` and hand out subslices of
187            // it as we do elsewhere in the compiler using `MetadataDecoder::split_at`. But we own
188            // the data for the decoder so holding onto the `MemDecoder` too would make us a
189            // self-referential struct which is downright goofy because `MetadataBlob` is already
190            // self-referential. Probably `MemDecoder` should contain an `OwnedSlice`, but that
191            // demands a significant refactoring due to our crate graph.
192            opaque: MemDecoder::new(self.blob(), pos).unwrap(),
193            cdata: self.cdata(),
194            blob: self.blob(),
195            sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
196            tcx,
197            lazy_state: LazyState::NoNode,
198            alloc_decoding_session: self
199                .cdata()
200                .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
201        }
202    }
203}
204
205impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
206    #[inline]
207    fn blob(self) -> &'a MetadataBlob {
208        self
209    }
210}
211
212impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
213    #[inline]
214    fn blob(self) -> &'a MetadataBlob {
215        self.0
216    }
217
218    #[inline]
219    fn sess(self) -> Option<&'tcx Session> {
220        let (_, sess) = self;
221        Some(sess)
222    }
223}
224
225impl<'a, 'tcx> Metadata<'a, 'tcx> for CrateMetadataRef<'a> {
226    #[inline]
227    fn blob(self) -> &'a MetadataBlob {
228        &self.cdata.blob
229    }
230    #[inline]
231    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
232        Some(self)
233    }
234}
235
236impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, &'tcx Session) {
237    #[inline]
238    fn blob(self) -> &'a MetadataBlob {
239        &self.0.cdata.blob
240    }
241    #[inline]
242    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
243        Some(self.0)
244    }
245    #[inline]
246    fn sess(self) -> Option<&'tcx Session> {
247        Some(self.1)
248    }
249}
250
251impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) {
252    #[inline]
253    fn blob(self) -> &'a MetadataBlob {
254        &self.0.cdata.blob
255    }
256    #[inline]
257    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
258        Some(self.0)
259    }
260    #[inline]
261    fn tcx(self) -> Option<TyCtxt<'tcx>> {
262        Some(self.1)
263    }
264}
265
266impl<T: ParameterizedOverTcx> LazyValue<T> {
267    #[inline]
268    fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(self, metadata: M) -> T::Value<'tcx>
269    where
270        T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
271    {
272        let mut dcx = metadata.decoder(self.position.get());
273        dcx.lazy_state = LazyState::NodeStart(self.position);
274        T::Value::decode(&mut dcx)
275    }
276}
277
278struct DecodeIterator<'a, 'tcx, T> {
279    elem_counter: std::ops::Range<usize>,
280    dcx: DecodeContext<'a, 'tcx>,
281    _phantom: PhantomData<fn() -> T>,
282}
283
284impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Iterator for DecodeIterator<'a, 'tcx, T> {
285    type Item = T;
286
287    #[inline(always)]
288    fn next(&mut self) -> Option<Self::Item> {
289        self.elem_counter.next().map(|_| T::decode(&mut self.dcx))
290    }
291
292    #[inline(always)]
293    fn size_hint(&self) -> (usize, Option<usize>) {
294        self.elem_counter.size_hint()
295    }
296}
297
298impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> ExactSizeIterator
299    for DecodeIterator<'a, 'tcx, T>
300{
301    fn len(&self) -> usize {
302        self.elem_counter.len()
303    }
304}
305
306unsafe impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> TrustedLen
307    for DecodeIterator<'a, 'tcx, T>
308{
309}
310
311impl<T: ParameterizedOverTcx> LazyArray<T> {
312    #[inline]
313    fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(
314        self,
315        metadata: M,
316    ) -> DecodeIterator<'a, 'tcx, T::Value<'tcx>>
317    where
318        T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
319    {
320        let mut dcx = metadata.decoder(self.position.get());
321        dcx.lazy_state = LazyState::NodeStart(self.position);
322        DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData }
323    }
324}
325
326impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
327    #[inline]
328    fn tcx(&self) -> TyCtxt<'tcx> {
329        let Some(tcx) = self.tcx else {
330            bug!(
331                "No TyCtxt found for decoding. \
332                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
333            );
334        };
335        tcx
336    }
337
338    #[inline]
339    pub(crate) fn blob(&self) -> &'a MetadataBlob {
340        self.blob
341    }
342
343    #[inline]
344    fn cdata(&self) -> CrateMetadataRef<'a> {
345        debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
346        self.cdata.unwrap()
347    }
348
349    #[inline]
350    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
351        self.cdata().map_encoded_cnum_to_current(cnum)
352    }
353
354    #[inline]
355    fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZero<usize>) -> T) -> T {
356        let distance = self.read_usize();
357        let position = match self.lazy_state {
358            LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
359            LazyState::NodeStart(start) => {
360                let start = start.get();
361                assert!(distance <= start);
362                start - distance
363            }
364            LazyState::Previous(last_pos) => last_pos.get() + distance,
365        };
366        let position = NonZero::new(position).unwrap();
367        self.lazy_state = LazyState::Previous(position);
368        f(position)
369    }
370
371    fn read_lazy<T>(&mut self) -> LazyValue<T> {
372        self.read_lazy_offset_then(|pos| LazyValue::from_position(pos))
373    }
374
375    fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> {
376        self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
377    }
378
379    fn read_lazy_table<I, T>(&mut self, width: usize, len: usize) -> LazyTable<I, T> {
380        self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len))
381    }
382
383    #[inline]
384    fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
385        self.opaque.read_raw_bytes(len)
386    }
387}
388
389impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
390    const CLEAR_CROSS_CRATE: bool = true;
391
392    #[inline]
393    fn interner(&self) -> TyCtxt<'tcx> {
394        self.tcx()
395    }
396
397    fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
398    where
399        F: FnOnce(&mut Self) -> Ty<'tcx>,
400    {
401        let tcx = self.tcx();
402
403        let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand };
404
405        if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) {
406            return ty;
407        }
408
409        let ty = or_insert_with(self);
410        tcx.ty_rcache.borrow_mut().insert(key, ty);
411        ty
412    }
413
414    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
415    where
416        F: FnOnce(&mut Self) -> R,
417    {
418        let new_opaque = self.opaque.split_at(pos);
419        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
420        let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
421        let r = f(self);
422        self.opaque = old_opaque;
423        self.lazy_state = old_state;
424        r
425    }
426
427    fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId {
428        if let Some(alloc_decoding_session) = self.alloc_decoding_session {
429            alloc_decoding_session.decode_alloc_id(self)
430        } else {
431            bug!("Attempting to decode interpret::AllocId without CrateMetadata")
432        }
433    }
434}
435
436impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
437    #[inline]
438    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex {
439        ExpnIndex::from_u32(d.read_u32())
440    }
441}
442
443impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
444    fn decode_attr_id(&mut self) -> rustc_span::AttrId {
445        let sess = self.sess.expect("can't decode AttrId without Session");
446        sess.psess.attr_id_generator.mk_attr_id()
447    }
448
449    fn decode_crate_num(&mut self) -> CrateNum {
450        let cnum = CrateNum::from_u32(self.read_u32());
451        self.map_encoded_cnum_to_current(cnum)
452    }
453
454    fn decode_def_index(&mut self) -> DefIndex {
455        DefIndex::from_u32(self.read_u32())
456    }
457
458    fn decode_def_id(&mut self) -> DefId {
459        DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
460    }
461
462    fn decode_syntax_context(&mut self) -> SyntaxContext {
463        let cdata = self.cdata();
464
465        let Some(sess) = self.sess else {
466            bug!(
467                "Cannot decode SyntaxContext without Session.\
468                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
469            );
470        };
471
472        let cname = cdata.root.name();
473        rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
474            debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
475            cdata
476                .root
477                .syntax_contexts
478                .get(cdata, id)
479                .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
480                .decode((cdata, sess))
481        })
482    }
483
484    fn decode_expn_id(&mut self) -> ExpnId {
485        let local_cdata = self.cdata();
486
487        let Some(sess) = self.sess else {
488            bug!(
489                "Cannot decode ExpnId without Session. \
490                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
491            );
492        };
493
494        let cnum = CrateNum::decode(self);
495        let index = u32::decode(self);
496
497        let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
498            let ExpnId { krate: cnum, local_id: index } = expn_id;
499            // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
500            // are stored in the owning crate, to avoid duplication.
501            debug_assert_ne!(cnum, LOCAL_CRATE);
502            let crate_data = if cnum == local_cdata.cnum {
503                local_cdata
504            } else {
505                local_cdata.cstore.get_crate_data(cnum)
506            };
507            let expn_data = crate_data
508                .root
509                .expn_data
510                .get(crate_data, index)
511                .unwrap()
512                .decode((crate_data, sess));
513            let expn_hash = crate_data
514                .root
515                .expn_hashes
516                .get(crate_data, index)
517                .unwrap()
518                .decode((crate_data, sess));
519            (expn_data, expn_hash)
520        });
521        expn_id
522    }
523
524    fn decode_span(&mut self) -> Span {
525        let start = self.position();
526        let tag = SpanTag(self.peek_byte());
527        let data = if tag.kind() == SpanKind::Indirect {
528            // Skip past the tag we just peek'd.
529            self.read_u8();
530            // indirect tag lengths are safe to access, since they're (0, 8)
531            let bytes_needed = tag.length().unwrap().0 as usize;
532            let mut total = [0u8; usize::BITS as usize / 8];
533            total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
534            let offset_or_position = usize::from_le_bytes(total);
535            let position = if tag.is_relative_offset() {
536                start - offset_or_position
537            } else {
538                offset_or_position
539            };
540            self.with_position(position, SpanData::decode)
541        } else {
542            SpanData::decode(self)
543        };
544        data.span()
545    }
546
547    fn decode_symbol(&mut self) -> Symbol {
548        let tag = self.read_u8();
549
550        match tag {
551            SYMBOL_STR => {
552                let s = self.read_str();
553                Symbol::intern(s)
554            }
555            SYMBOL_OFFSET => {
556                // read str offset
557                let pos = self.read_usize();
558
559                // move to str offset and read
560                self.opaque.with_position(pos, |d| {
561                    let s = d.read_str();
562                    Symbol::intern(s)
563                })
564            }
565            SYMBOL_PREDEFINED => {
566                let symbol_index = self.read_u32();
567                Symbol::new(symbol_index)
568            }
569            _ => unreachable!(),
570        }
571    }
572}
573
574impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
575    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData {
576        let tag = SpanTag::decode(decoder);
577        let ctxt = tag.context().unwrap_or_else(|| SyntaxContext::decode(decoder));
578
579        if tag.kind() == SpanKind::Partial {
580            return DUMMY_SP.with_ctxt(ctxt).data();
581        }
582
583        debug_assert!(tag.kind() == SpanKind::Local || tag.kind() == SpanKind::Foreign);
584
585        let lo = BytePos::decode(decoder);
586        let len = tag.length().unwrap_or_else(|| BytePos::decode(decoder));
587        let hi = lo + len;
588
589        let Some(sess) = decoder.sess else {
590            bug!(
591                "Cannot decode Span without Session. \
592                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
593            )
594        };
595
596        // Index of the file in the corresponding crate's list of encoded files.
597        let metadata_index = u32::decode(decoder);
598
599        // There are two possibilities here:
600        // 1. This is a 'local span', which is located inside a `SourceFile`
601        // that came from this crate. In this case, we use the source map data
602        // encoded in this crate. This branch should be taken nearly all of the time.
603        // 2. This is a 'foreign span', which is located inside a `SourceFile`
604        // that came from a *different* crate (some crate upstream of the one
605        // whose metadata we're looking at). For example, consider this dependency graph:
606        //
607        // A -> B -> C
608        //
609        // Suppose that we're currently compiling crate A, and start deserializing
610        // metadata from crate B. When we deserialize a Span from crate B's metadata,
611        // there are two possibilities:
612        //
613        // 1. The span references a file from crate B. This makes it a 'local' span,
614        // which means that we can use crate B's serialized source map information.
615        // 2. The span references a file from crate C. This makes it a 'foreign' span,
616        // which means we need to use Crate *C* (not crate B) to determine the source
617        // map information. We only record source map information for a file in the
618        // crate that 'owns' it, so deserializing a Span may require us to look at
619        // a transitive dependency.
620        //
621        // When we encode a foreign span, we adjust its 'lo' and 'high' values
622        // to be based on the *foreign* crate (e.g. crate C), not the crate
623        // we are writing metadata for (e.g. crate B). This allows us to
624        // treat the 'local' and 'foreign' cases almost identically during deserialization:
625        // we can call `imported_source_file` for the proper crate, and binary search
626        // through the returned slice using our span.
627        let source_file = if tag.kind() == SpanKind::Local {
628            decoder.cdata().imported_source_file(metadata_index, sess)
629        } else {
630            // When we encode a proc-macro crate, all `Span`s should be encoded
631            // with `TAG_VALID_SPAN_LOCAL`
632            if decoder.cdata().root.is_proc_macro_crate() {
633                // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
634                // since we don't have `cnum_map` populated.
635                let cnum = u32::decode(decoder);
636                panic!(
637                    "Decoding of crate {:?} tried to access proc-macro dep {:?}",
638                    decoder.cdata().root.header.name,
639                    cnum
640                );
641            }
642            // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
643            let cnum = CrateNum::decode(decoder);
644            debug!(
645                "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
646                cnum
647            );
648
649            let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
650            foreign_data.imported_source_file(metadata_index, sess)
651        };
652
653        // Make sure our span is well-formed.
654        debug_assert!(
655            lo + source_file.original_start_pos <= source_file.original_end_pos,
656            "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
657            lo,
658            source_file.original_start_pos,
659            source_file.original_end_pos
660        );
661
662        // Make sure we correctly filtered out invalid spans during encoding.
663        debug_assert!(
664            hi + source_file.original_start_pos <= source_file.original_end_pos,
665            "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
666            hi,
667            source_file.original_start_pos,
668            source_file.original_end_pos
669        );
670
671        let lo = lo + source_file.translated_source_file.start_pos;
672        let hi = hi + source_file.translated_source_file.start_pos;
673
674        // Do not try to decode parent for foreign spans (it wasn't encoded in the first place).
675        SpanData { lo, hi, ctxt, parent: None }
676    }
677}
678
679impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
680    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
681        ty::codec::RefDecodable::decode(d)
682    }
683}
684
685impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
686    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
687        decoder.read_lazy()
688    }
689}
690
691impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
692    #[inline]
693    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
694        let len = decoder.read_usize();
695        if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) }
696    }
697}
698
699impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> {
700    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
701        let width = decoder.read_usize();
702        let len = decoder.read_usize();
703        decoder.read_lazy_table(width, len)
704    }
705}
706
707implement_ty_decoder!(DecodeContext<'a, 'tcx>);
708
709impl MetadataBlob {
710    pub(crate) fn check_compatibility(
711        &self,
712        cfg_version: &'static str,
713    ) -> Result<(), Option<String>> {
714        if !self.blob().starts_with(METADATA_HEADER) {
715            if self.blob().starts_with(b"rust") {
716                return Err(Some("<unknown rustc version>".to_owned()));
717            }
718            return Err(None);
719        }
720
721        let found_version =
722            LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
723                .decode(self);
724        if rustc_version(cfg_version) != found_version {
725            return Err(Some(found_version));
726        }
727
728        Ok(())
729    }
730
731    fn root_pos(&self) -> NonZero<usize> {
732        let offset = METADATA_HEADER.len();
733        let pos_bytes = self.blob()[offset..][..8].try_into().unwrap();
734        let pos = u64::from_le_bytes(pos_bytes);
735        NonZero::new(pos as usize).unwrap()
736    }
737
738    pub(crate) fn get_header(&self) -> CrateHeader {
739        let pos = self.root_pos();
740        LazyValue::<CrateHeader>::from_position(pos).decode(self)
741    }
742
743    pub(crate) fn get_root(&self) -> CrateRoot {
744        let pos = self.root_pos();
745        LazyValue::<CrateRoot>::from_position(pos).decode(self)
746    }
747
748    pub(crate) fn list_crate_metadata(
749        &self,
750        out: &mut dyn io::Write,
751        ls_kinds: &[String],
752    ) -> io::Result<()> {
753        let root = self.get_root();
754
755        let all_ls_kinds = vec![
756            "root".to_owned(),
757            "lang_items".to_owned(),
758            "features".to_owned(),
759            "items".to_owned(),
760        ];
761        let ls_kinds = if ls_kinds.contains(&"all".to_owned()) { &all_ls_kinds } else { ls_kinds };
762
763        for kind in ls_kinds {
764            match &**kind {
765                "root" => {
766                    writeln!(out, "Crate info:")?;
767                    writeln!(out, "name {}{}", root.name(), root.extra_filename)?;
768                    writeln!(
769                        out,
770                        "hash {} stable_crate_id {:?}",
771                        root.hash(),
772                        root.stable_crate_id
773                    )?;
774                    writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
775                    writeln!(out, "triple {}", root.header.triple.tuple())?;
776                    writeln!(out, "edition {}", root.edition)?;
777                    writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?;
778                    writeln!(
779                        out,
780                        "required_panic_strategy {:?} panic_in_drop_strategy {:?}",
781                        root.required_panic_strategy, root.panic_in_drop_strategy
782                    )?;
783                    writeln!(
784                        out,
785                        "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}",
786                        root.has_global_allocator,
787                        root.has_alloc_error_handler,
788                        root.has_panic_handler,
789                        root.has_default_lib_allocator
790                    )?;
791                    writeln!(
792                        out,
793                        "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}",
794                        root.compiler_builtins,
795                        root.needs_allocator,
796                        root.needs_panic_runtime,
797                        root.no_builtins,
798                        root.panic_runtime,
799                        root.profiler_runtime
800                    )?;
801
802                    writeln!(out, "=External Dependencies=")?;
803                    let dylib_dependency_formats =
804                        root.dylib_dependency_formats.decode(self).collect::<Vec<_>>();
805                    for (i, dep) in root.crate_deps.decode(self).enumerate() {
806                        let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } =
807                            dep;
808                        let number = i + 1;
809
810                        writeln!(
811                            out,
812                            "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}",
813                            privacy = if is_private { "private" } else { "public" },
814                            linkage = if dylib_dependency_formats.is_empty() {
815                                String::new()
816                            } else {
817                                format!(" linkage {:?}", dylib_dependency_formats[i])
818                            }
819                        )?;
820                    }
821                    write!(out, "\n")?;
822                }
823
824                "lang_items" => {
825                    writeln!(out, "=Lang items=")?;
826                    for (id, lang_item) in root.lang_items.decode(self) {
827                        writeln!(
828                            out,
829                            "{} = crate{}",
830                            lang_item.name(),
831                            DefPath::make(LOCAL_CRATE, id, |parent| root
832                                .tables
833                                .def_keys
834                                .get(self, parent)
835                                .unwrap()
836                                .decode(self))
837                            .to_string_no_crate_verbose()
838                        )?;
839                    }
840                    for lang_item in root.lang_items_missing.decode(self) {
841                        writeln!(out, "{} = <missing>", lang_item.name())?;
842                    }
843                    write!(out, "\n")?;
844                }
845
846                "features" => {
847                    writeln!(out, "=Lib features=")?;
848                    for (feature, since) in root.lib_features.decode(self) {
849                        writeln!(
850                            out,
851                            "{}{}",
852                            feature,
853                            if let FeatureStability::AcceptedSince(since) = since {
854                                format!(" since {since}")
855                            } else {
856                                String::new()
857                            }
858                        )?;
859                    }
860                    write!(out, "\n")?;
861                }
862
863                "items" => {
864                    writeln!(out, "=Items=")?;
865
866                    fn print_item(
867                        blob: &MetadataBlob,
868                        out: &mut dyn io::Write,
869                        item: DefIndex,
870                        indent: usize,
871                    ) -> io::Result<()> {
872                        let root = blob.get_root();
873
874                        let def_kind = root.tables.def_kind.get(blob, item).unwrap();
875                        let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
876                        #[allow(rustc::symbol_intern_string_literal)]
877                        let def_name = if item == CRATE_DEF_INDEX {
878                            kw::Crate
879                        } else {
880                            def_key
881                                .disambiguated_data
882                                .data
883                                .get_opt_name()
884                                .unwrap_or_else(|| Symbol::intern("???"))
885                        };
886                        let visibility =
887                            root.tables.visibility.get(blob, item).unwrap().decode(blob).map_id(
888                                |index| {
889                                    format!(
890                                        "crate{}",
891                                        DefPath::make(LOCAL_CRATE, index, |parent| root
892                                            .tables
893                                            .def_keys
894                                            .get(blob, parent)
895                                            .unwrap()
896                                            .decode(blob))
897                                        .to_string_no_crate_verbose()
898                                    )
899                                },
900                            );
901                        write!(
902                            out,
903                            "{nil: <indent$}{:?} {:?} {} {{",
904                            visibility,
905                            def_kind,
906                            def_name,
907                            nil = "",
908                        )?;
909
910                        if let Some(children) =
911                            root.tables.module_children_non_reexports.get(blob, item)
912                        {
913                            write!(out, "\n")?;
914                            for child in children.decode(blob) {
915                                print_item(blob, out, child, indent + 4)?;
916                            }
917                            writeln!(out, "{nil: <indent$}}}", nil = "")?;
918                        } else {
919                            writeln!(out, "}}")?;
920                        }
921
922                        Ok(())
923                    }
924
925                    print_item(self, out, CRATE_DEF_INDEX, 0)?;
926
927                    write!(out, "\n")?;
928                }
929
930                _ => {
931                    writeln!(
932                        out,
933                        "unknown -Zls kind. allowed values are: all, root, lang_items, features, items"
934                    )?;
935                }
936            }
937        }
938
939        Ok(())
940    }
941}
942
943impl CrateRoot {
944    pub(crate) fn is_proc_macro_crate(&self) -> bool {
945        self.proc_macro_data.is_some()
946    }
947
948    pub(crate) fn name(&self) -> Symbol {
949        self.header.name
950    }
951
952    pub(crate) fn hash(&self) -> Svh {
953        self.header.hash
954    }
955
956    pub(crate) fn stable_crate_id(&self) -> StableCrateId {
957        self.stable_crate_id
958    }
959
960    pub(crate) fn decode_crate_deps<'a>(
961        &self,
962        metadata: &'a MetadataBlob,
963    ) -> impl ExactSizeIterator<Item = CrateDep> {
964        self.crate_deps.decode(metadata)
965    }
966
967    pub(crate) fn decode_target_modifiers<'a>(
968        &self,
969        metadata: &'a MetadataBlob,
970    ) -> impl ExactSizeIterator<Item = TargetModifier> {
971        self.target_modifiers.decode(metadata)
972    }
973}
974
975impl<'a> CrateMetadataRef<'a> {
976    fn missing(self, descr: &str, id: DefIndex) -> ! {
977        bug!("missing `{descr}` for {:?}", self.local_def_id(id))
978    }
979
980    fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro {
981        // DefIndex's in root.proc_macro_data have a one-to-one correspondence
982        // with items in 'raw_proc_macros'.
983        let pos = self
984            .root
985            .proc_macro_data
986            .as_ref()
987            .unwrap()
988            .macros
989            .decode(self)
990            .position(|i| i == id)
991            .unwrap();
992        &self.raw_proc_macros.unwrap()[pos]
993    }
994
995    fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> {
996        let def_key = self.def_key(item_index);
997        def_key.disambiguated_data.data.get_opt_name().or_else(|| {
998            if def_key.disambiguated_data.data == DefPathData::Ctor {
999                let parent_index = def_key.parent.expect("no parent for a constructor");
1000                self.def_key(parent_index).disambiguated_data.data.get_opt_name()
1001            } else {
1002                None
1003            }
1004        })
1005    }
1006
1007    fn item_name(self, item_index: DefIndex) -> Symbol {
1008        self.opt_item_name(item_index).expect("no encoded ident for item")
1009    }
1010
1011    fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> {
1012        let name = self.opt_item_name(item_index)?;
1013        let span = self
1014            .root
1015            .tables
1016            .def_ident_span
1017            .get(self, item_index)
1018            .unwrap_or_else(|| self.missing("def_ident_span", item_index))
1019            .decode((self, sess));
1020        Some(Ident::new(name, span))
1021    }
1022
1023    fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident {
1024        self.opt_item_ident(item_index, sess).expect("no encoded ident for item")
1025    }
1026
1027    #[inline]
1028    pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum {
1029        if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] }
1030    }
1031
1032    fn def_kind(self, item_id: DefIndex) -> DefKind {
1033        self.root
1034            .tables
1035            .def_kind
1036            .get(self, item_id)
1037            .unwrap_or_else(|| self.missing("def_kind", item_id))
1038    }
1039
1040    fn get_span(self, index: DefIndex, sess: &Session) -> Span {
1041        self.root
1042            .tables
1043            .def_span
1044            .get(self, index)
1045            .unwrap_or_else(|| self.missing("def_span", index))
1046            .decode((self, sess))
1047    }
1048
1049    fn load_proc_macro<'tcx>(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension {
1050        let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
1051            ProcMacro::CustomDerive { trait_name, attributes, client } => {
1052                let helper_attrs =
1053                    attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
1054                (
1055                    trait_name,
1056                    SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })),
1057                    helper_attrs,
1058                )
1059            }
1060            ProcMacro::Attr { name, client } => {
1061                (name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new())
1062            }
1063            ProcMacro::Bang { name, client } => {
1064                (name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new())
1065            }
1066        };
1067
1068        let sess = tcx.sess;
1069        let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
1070        SyntaxExtension::new(
1071            sess,
1072            kind,
1073            self.get_span(id, sess),
1074            helper_attrs,
1075            self.root.edition,
1076            Symbol::intern(name),
1077            &attrs,
1078            false,
1079        )
1080    }
1081
1082    fn get_variant(
1083        self,
1084        kind: DefKind,
1085        index: DefIndex,
1086        parent_did: DefId,
1087    ) -> (VariantIdx, ty::VariantDef) {
1088        let adt_kind = match kind {
1089            DefKind::Variant => ty::AdtKind::Enum,
1090            DefKind::Struct => ty::AdtKind::Struct,
1091            DefKind::Union => ty::AdtKind::Union,
1092            _ => bug!(),
1093        };
1094
1095        let data = self.root.tables.variant_data.get(self, index).unwrap().decode(self);
1096
1097        let variant_did =
1098            if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
1099        let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));
1100
1101        (
1102            data.idx,
1103            ty::VariantDef::new(
1104                self.item_name(index),
1105                variant_did,
1106                ctor,
1107                data.discr,
1108                self.get_associated_item_or_field_def_ids(index)
1109                    .map(|did| ty::FieldDef {
1110                        did,
1111                        name: self.item_name(did.index),
1112                        vis: self.get_visibility(did.index),
1113                        safety: self.get_safety(did.index),
1114                        value: self.get_default_field(did.index),
1115                    })
1116                    .collect(),
1117                parent_did,
1118                None,
1119                data.is_non_exhaustive,
1120            ),
1121        )
1122    }
1123
1124    fn get_adt_def<'tcx>(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
1125        let kind = self.def_kind(item_id);
1126        let did = self.local_def_id(item_id);
1127
1128        let adt_kind = match kind {
1129            DefKind::Enum => ty::AdtKind::Enum,
1130            DefKind::Struct => ty::AdtKind::Struct,
1131            DefKind::Union => ty::AdtKind::Union,
1132            _ => bug!("get_adt_def called on a non-ADT {:?}", did),
1133        };
1134        let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self);
1135
1136        let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind {
1137            self.root
1138                .tables
1139                .module_children_non_reexports
1140                .get(self, item_id)
1141                .expect("variants are not encoded for an enum")
1142                .decode(self)
1143                .filter_map(|index| {
1144                    let kind = self.def_kind(index);
1145                    match kind {
1146                        DefKind::Ctor(..) => None,
1147                        _ => Some(self.get_variant(kind, index, did)),
1148                    }
1149                })
1150                .collect()
1151        } else {
1152            std::iter::once(self.get_variant(kind, item_id, did)).collect()
1153        };
1154
1155        variants.sort_by_key(|(idx, _)| *idx);
1156
1157        tcx.mk_adt_def(
1158            did,
1159            adt_kind,
1160            variants.into_iter().map(|(_, variant)| variant).collect(),
1161            repr,
1162        )
1163    }
1164
1165    fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
1166        self.root
1167            .tables
1168            .visibility
1169            .get(self, id)
1170            .unwrap_or_else(|| self.missing("visibility", id))
1171            .decode(self)
1172            .map_id(|index| self.local_def_id(index))
1173    }
1174
1175    fn get_safety(self, id: DefIndex) -> Safety {
1176        self.root.tables.safety.get(self, id).unwrap_or_else(|| self.missing("safety", id))
1177    }
1178
1179    fn get_default_field(self, id: DefIndex) -> Option<DefId> {
1180        self.root.tables.default_fields.get(self, id).map(|d| d.decode(self))
1181    }
1182
1183    fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
1184        self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
1185    }
1186
1187    fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
1188        self.root
1189            .tables
1190            .expn_that_defined
1191            .get(self, id)
1192            .unwrap_or_else(|| self.missing("expn_that_defined", id))
1193            .decode((self, sess))
1194    }
1195
1196    fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
1197        self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
1198    }
1199
1200    /// Iterates over all the stability attributes in the given crate.
1201    fn get_lib_features(self) -> LibFeatures {
1202        LibFeatures {
1203            stability: self
1204                .root
1205                .lib_features
1206                .decode(self)
1207                .map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
1208                .collect(),
1209        }
1210    }
1211
1212    /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
1213    /// has an `implied_by` meta item, then the mapping from the implied feature to the actual
1214    /// feature is a stability implication).
1215    fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
1216        tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
1217    }
1218
1219    /// Iterates over the lang items in the given crate.
1220    fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
1221        tcx.arena.alloc_from_iter(
1222            self.root
1223                .lang_items
1224                .decode(self)
1225                .map(move |(def_index, index)| (self.local_def_id(def_index), index)),
1226        )
1227    }
1228
1229    fn get_stripped_cfg_items<'tcx>(
1230        self,
1231        cnum: CrateNum,
1232        tcx: TyCtxt<'tcx>,
1233    ) -> &'tcx [StrippedCfgItem] {
1234        let item_names = self
1235            .root
1236            .stripped_cfg_items
1237            .decode((self, tcx))
1238            .map(|item| item.map_mod_id(|index| DefId { krate: cnum, index }));
1239        tcx.arena.alloc_from_iter(item_names)
1240    }
1241
1242    /// Iterates over the diagnostic items in the given crate.
1243    fn get_diagnostic_items(self) -> DiagnosticItems {
1244        let mut id_to_name = DefIdMap::default();
1245        let name_to_id = self
1246            .root
1247            .diagnostic_items
1248            .decode(self)
1249            .map(|(name, def_index)| {
1250                let id = self.local_def_id(def_index);
1251                id_to_name.insert(id, name);
1252                (name, id)
1253            })
1254            .collect();
1255        DiagnosticItems { id_to_name, name_to_id }
1256    }
1257
1258    fn get_mod_child(self, id: DefIndex, sess: &Session) -> ModChild {
1259        let ident = self.item_ident(id, sess);
1260        let res = Res::Def(self.def_kind(id), self.local_def_id(id));
1261        let vis = self.get_visibility(id);
1262
1263        ModChild { ident, res, vis, reexport_chain: Default::default() }
1264    }
1265
1266    /// Iterates over all named children of the given module,
1267    /// including both proper items and reexports.
1268    /// Module here is understood in name resolution sense - it can be a `mod` item,
1269    /// or a crate root, or an enum, or a trait.
1270    fn get_module_children(
1271        self,
1272        id: DefIndex,
1273        sess: &'a Session,
1274    ) -> impl Iterator<Item = ModChild> {
1275        iter::from_coroutine(
1276            #[coroutine]
1277            move || {
1278                if let Some(data) = &self.root.proc_macro_data {
1279                    // If we are loading as a proc macro, we want to return
1280                    // the view of this crate as a proc macro crate.
1281                    if id == CRATE_DEF_INDEX {
1282                        for child_index in data.macros.decode(self) {
1283                            yield self.get_mod_child(child_index, sess);
1284                        }
1285                    }
1286                } else {
1287                    // Iterate over all children.
1288                    let non_reexports =
1289                        self.root.tables.module_children_non_reexports.get(self, id);
1290                    for child_index in non_reexports.unwrap().decode(self) {
1291                        yield self.get_mod_child(child_index, sess);
1292                    }
1293
1294                    let reexports = self.root.tables.module_children_reexports.get(self, id);
1295                    if !reexports.is_default() {
1296                        for reexport in reexports.decode((self, sess)) {
1297                            yield reexport;
1298                        }
1299                    }
1300                }
1301            },
1302        )
1303    }
1304
1305    fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
1306        self.root.tables.mir_for_ctfe.get(self, id).is_some()
1307    }
1308
1309    fn is_item_mir_available(self, id: DefIndex) -> bool {
1310        self.root.tables.optimized_mir.get(self, id).is_some()
1311    }
1312
1313    fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool {
1314        self.root
1315            .tables
1316            .fn_arg_idents
1317            .get(self, id)
1318            .expect("argument names not encoded for a function")
1319            .decode((self, sess))
1320            .nth(0)
1321            .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
1322    }
1323
1324    fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
1325        self.root
1326            .tables
1327            .associated_item_or_field_def_ids
1328            .get(self, id)
1329            .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id))
1330            .decode(self)
1331            .map(move |child_index| self.local_def_id(child_index))
1332    }
1333
1334    fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
1335        let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
1336            kw::Empty
1337        } else {
1338            self.item_name(id)
1339        };
1340        let (kind, has_self) = match self.def_kind(id) {
1341            DefKind::AssocConst => (ty::AssocKind::Const, false),
1342            DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
1343            DefKind::AssocTy => (ty::AssocKind::Type, false),
1344            _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
1345        };
1346        let container = self.root.tables.assoc_container.get(self, id).unwrap();
1347        let opt_rpitit_info =
1348            self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self));
1349
1350        ty::AssocItem {
1351            name,
1352            kind,
1353            def_id: self.local_def_id(id),
1354            trait_item_def_id: self.get_trait_item_def_id(id),
1355            container,
1356            fn_has_self_parameter: has_self,
1357            opt_rpitit_info,
1358        }
1359    }
1360
1361    fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
1362        match self.def_kind(node_id) {
1363            DefKind::Struct | DefKind::Variant => {
1364                let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
1365                vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
1366            }
1367            _ => None,
1368        }
1369    }
1370
1371    fn get_item_attrs(
1372        self,
1373        id: DefIndex,
1374        sess: &'a Session,
1375    ) -> impl Iterator<Item = hir::Attribute> {
1376        self.root
1377            .tables
1378            .attributes
1379            .get(self, id)
1380            .unwrap_or_else(|| {
1381                // Structure and variant constructors don't have any attributes encoded for them,
1382                // but we assume that someone passing a constructor ID actually wants to look at
1383                // the attributes on the corresponding struct or variant.
1384                let def_key = self.def_key(id);
1385                assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
1386                let parent_id = def_key.parent.expect("no parent for a constructor");
1387                self.root
1388                    .tables
1389                    .attributes
1390                    .get(self, parent_id)
1391                    .expect("no encoded attributes for a structure or variant")
1392            })
1393            .decode((self, sess))
1394    }
1395
1396    fn get_inherent_implementations_for_type<'tcx>(
1397        self,
1398        tcx: TyCtxt<'tcx>,
1399        id: DefIndex,
1400    ) -> &'tcx [DefId] {
1401        tcx.arena.alloc_from_iter(
1402            self.root
1403                .tables
1404                .inherent_impls
1405                .get(self, id)
1406                .decode(self)
1407                .map(|index| self.local_def_id(index)),
1408        )
1409    }
1410
1411    /// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
1412    fn get_traits(self) -> impl Iterator<Item = DefId> {
1413        self.root.traits.decode(self).map(move |index| self.local_def_id(index))
1414    }
1415
1416    /// Decodes all trait impls in the crate (for rustdoc).
1417    fn get_trait_impls(self) -> impl Iterator<Item = DefId> {
1418        self.cdata.trait_impls.values().flat_map(move |impls| {
1419            impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index))
1420        })
1421    }
1422
1423    fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
1424        if let Some(impls) = self.cdata.incoherent_impls.get(&simp) {
1425            tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
1426        } else {
1427            &[]
1428        }
1429    }
1430
1431    fn get_implementations_of_trait<'tcx>(
1432        self,
1433        tcx: TyCtxt<'tcx>,
1434        trait_def_id: DefId,
1435    ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
1436        if self.trait_impls.is_empty() {
1437            return &[];
1438        }
1439
1440        // Do a reverse lookup beforehand to avoid touching the crate_num
1441        // hash map in the loop below.
1442        let key = match self.reverse_translate_def_id(trait_def_id) {
1443            Some(def_id) => (def_id.krate.as_u32(), def_id.index),
1444            None => return &[],
1445        };
1446
1447        if let Some(impls) = self.trait_impls.get(&key) {
1448            tcx.arena.alloc_from_iter(
1449                impls
1450                    .decode(self)
1451                    .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)),
1452            )
1453        } else {
1454            &[]
1455        }
1456    }
1457
1458    fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> {
1459        self.root.native_libraries.decode((self, sess))
1460    }
1461
1462    fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
1463        self.root
1464            .tables
1465            .proc_macro_quoted_spans
1466            .get(self, index)
1467            .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
1468            .decode((self, sess))
1469    }
1470
1471    fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> {
1472        self.root.foreign_modules.decode((self, sess))
1473    }
1474
1475    fn get_dylib_dependency_formats<'tcx>(
1476        self,
1477        tcx: TyCtxt<'tcx>,
1478    ) -> &'tcx [(CrateNum, LinkagePreference)] {
1479        tcx.arena.alloc_from_iter(
1480            self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
1481                let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding
1482                link.map(|link| (self.cnum_map[cnum], link))
1483            }),
1484        )
1485    }
1486
1487    fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
1488        tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
1489    }
1490
1491    fn exported_symbols<'tcx>(
1492        self,
1493        tcx: TyCtxt<'tcx>,
1494    ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1495        tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
1496    }
1497
1498    fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
1499        match self.def_kind(id) {
1500            DefKind::Macro(_) => {
1501                let macro_rules = self.root.tables.is_macro_rules.get(self, id);
1502                let body =
1503                    self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
1504                ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
1505            }
1506            _ => bug!(),
1507        }
1508    }
1509
1510    #[inline]
1511    fn def_key(self, index: DefIndex) -> DefKey {
1512        *self
1513            .def_key_cache
1514            .lock()
1515            .entry(index)
1516            .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
1517    }
1518
1519    // Returns the path leading to the thing with this `id`.
1520    fn def_path(self, id: DefIndex) -> DefPath {
1521        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
1522        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
1523    }
1524
1525    #[inline]
1526    fn def_path_hash(self, index: DefIndex) -> DefPathHash {
1527        // This is a hack to workaround the fact that we can't easily encode/decode a Hash64
1528        // into the FixedSizeEncoding, as Hash64 lacks a Default impl. A future refactor to
1529        // relax the Default restriction will likely fix this.
1530        let fingerprint = Fingerprint::new(
1531            self.root.stable_crate_id.as_u64(),
1532            self.root.tables.def_path_hashes.get(self, index),
1533        );
1534        DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1)
1535    }
1536
1537    #[inline]
1538    fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex {
1539        self.def_path_hash_map.def_path_hash_to_def_index(&hash)
1540    }
1541
1542    fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
1543        debug_assert_eq!(ExpnId::from_hash(hash), None);
1544        let index_guess = ExpnIndex::from_u32(index_guess);
1545        let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1546
1547        let index = if old_hash == Some(hash) {
1548            // Fast path: the expn and its index is unchanged from the
1549            // previous compilation session. There is no need to decode anything
1550            // else.
1551            index_guess
1552        } else {
1553            // Slow path: We need to find out the new `DefIndex` of the provided
1554            // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
1555            // stored in this crate.
1556            let map = self.cdata.expn_hash_map.get_or_init(|| {
1557                let end_id = self.root.expn_hashes.size() as u32;
1558                let mut map =
1559                    UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1560                for i in 0..end_id {
1561                    let i = ExpnIndex::from_u32(i);
1562                    if let Some(hash) = self.root.expn_hashes.get(self, i) {
1563                        map.insert(hash.decode(self), i);
1564                    }
1565                }
1566                map
1567            });
1568            map[&hash]
1569        };
1570
1571        let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
1572        rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
1573    }
1574
1575    /// Imports the source_map from an external crate into the source_map of the crate
1576    /// currently being compiled (the "local crate").
1577    ///
1578    /// The import algorithm works analogous to how AST items are inlined from an
1579    /// external crate's metadata:
1580    /// For every SourceFile in the external source_map an 'inline' copy is created in the
1581    /// local source_map. The correspondence relation between external and local
1582    /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this
1583    /// function. When an item from an external crate is later inlined into this
1584    /// crate, this correspondence information is used to translate the span
1585    /// information of the inlined item so that it refers the correct positions in
1586    /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
1587    ///
1588    /// The import algorithm in the function below will reuse SourceFiles already
1589    /// existing in the local source_map. For example, even if the SourceFile of some
1590    /// source file of libstd gets imported many times, there will only ever be
1591    /// one SourceFile object for the corresponding file in the local source_map.
1592    ///
1593    /// Note that imported SourceFiles do not actually contain the source code of the
1594    /// file they represent, just information about length, line breaks, and
1595    /// multibyte characters. This information is enough to generate valid debuginfo
1596    /// for items inlined from other crates.
1597    ///
1598    /// Proc macro crates don't currently export spans, so this function does not have
1599    /// to work for them.
1600    fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1601        fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1602            path.filter(|_| {
1603                // Only spend time on further checks if we have what to translate *to*.
1604                sess.opts.real_rust_source_base_dir.is_some()
1605                // Some tests need the translation to be always skipped.
1606                && sess.opts.unstable_opts.translate_remapped_path_to_local_path
1607            })
1608            .filter(|virtual_dir| {
1609                // Don't translate away `/rustc/$hash` if we're still remapping to it,
1610                // since that means we're still building `std`/`rustc` that need it,
1611                // and we don't want the real path to leak into codegen/debuginfo.
1612                !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
1613            })
1614        }
1615
1616        let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
1617            // Translate the virtual `/rustc/$hash` prefix back to a real directory
1618            // that should hold actual sources, where possible.
1619            //
1620            // NOTE: if you update this, you might need to also update bootstrap's code for generating
1621            // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1622            let virtual_rust_source_base_dir = [
1623                filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1624                filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1625            ];
1626
1627            debug!(
1628                "try_to_translate_virtual_to_real(name={:?}): \
1629                 virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1630                name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1631            );
1632
1633            for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1634                if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1635                    && let rustc_span::FileName::Real(old_name) = name
1636                    && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1637                        old_name
1638                    && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1639                {
1640                    // The std library crates are in
1641                    // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates
1642                    // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we
1643                    // detect crates from the std libs and handle them specially.
1644                    const STD_LIBS: &[&str] = &[
1645                        "core",
1646                        "alloc",
1647                        "std",
1648                        "test",
1649                        "term",
1650                        "unwind",
1651                        "proc_macro",
1652                        "panic_abort",
1653                        "panic_unwind",
1654                        "profiler_builtins",
1655                        "rtstartup",
1656                        "rustc-std-workspace-core",
1657                        "rustc-std-workspace-alloc",
1658                        "rustc-std-workspace-std",
1659                        "backtrace",
1660                    ];
1661                    let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l));
1662
1663                    let new_path = if is_std_lib {
1664                        real_dir.join("library").join(rest)
1665                    } else {
1666                        real_dir.join(rest)
1667                    };
1668
1669                    debug!(
1670                        "try_to_translate_virtual_to_real: `{}` -> `{}`",
1671                        virtual_name.display(),
1672                        new_path.display(),
1673                    );
1674
1675                    // Check if the translated real path is affected by any user-requested
1676                    // remaps via --remap-path-prefix. Apply them if so.
1677                    // Note that this is a special case for imported rust-src paths specified by
1678                    // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1679                    // Other imported paths are not currently remapped (see #66251).
1680                    let (user_remapped, applied) =
1681                        sess.source_map().path_mapping().map_prefix(&new_path);
1682                    let new_name = if applied {
1683                        rustc_span::RealFileName::Remapped {
1684                            local_path: Some(new_path.clone()),
1685                            virtual_name: user_remapped.to_path_buf(),
1686                        }
1687                    } else {
1688                        rustc_span::RealFileName::LocalPath(new_path)
1689                    };
1690                    *old_name = new_name;
1691                }
1692            }
1693        };
1694
1695        let mut import_info = self.cdata.source_map_import_info.lock();
1696        for _ in import_info.len()..=(source_file_index as usize) {
1697            import_info.push(None);
1698        }
1699        import_info[source_file_index as usize]
1700            .get_or_insert_with(|| {
1701                let source_file_to_import = self
1702                    .root
1703                    .source_map
1704                    .get(self, source_file_index)
1705                    .expect("missing source file")
1706                    .decode(self);
1707
1708                // We can't reuse an existing SourceFile, so allocate a new one
1709                // containing the information we need.
1710                let original_end_pos = source_file_to_import.end_position();
1711                let rustc_span::SourceFile {
1712                    mut name,
1713                    src_hash,
1714                    checksum_hash,
1715                    start_pos: original_start_pos,
1716                    source_len,
1717                    lines,
1718                    multibyte_chars,
1719                    normalized_pos,
1720                    stable_id,
1721                    ..
1722                } = source_file_to_import;
1723
1724                // If this file is under $sysroot/lib/rustlib/src/
1725                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
1726                // then we change `name` to a similar state as if the rust was bootstrapped
1727                // with `remap-debuginfo = true`.
1728                // This is useful for testing so that tests about the effects of
1729                // `try_to_translate_virtual_to_real` don't have to worry about how the
1730                // compiler is bootstrapped.
1731                if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1732                    && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1733                    && let rustc_span::FileName::Real(ref mut old_name) = name
1734                {
1735                    let relative_path = match old_name {
1736                        rustc_span::RealFileName::LocalPath(local) => {
1737                            local.strip_prefix(real_dir).ok()
1738                        }
1739                        rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1740                            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
1741                                .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1742                        }
1743                    };
1744                    debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
1745                    for subdir in ["library", "compiler"] {
1746                        if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok())
1747                        {
1748                            *old_name = rustc_span::RealFileName::Remapped {
1749                                local_path: None, // FIXME: maybe we should preserve this?
1750                                virtual_name: virtual_dir.join(subdir).join(rest),
1751                            };
1752                            break;
1753                        }
1754                    }
1755                }
1756
1757                // If this file's path has been remapped to `/rustc/$hash`,
1758                // we might be able to reverse that (also see comments above,
1759                // on `try_to_translate_virtual_to_real`).
1760                try_to_translate_virtual_to_real(&mut name);
1761
1762                let local_version = sess.source_map().new_imported_source_file(
1763                    name,
1764                    src_hash,
1765                    checksum_hash,
1766                    stable_id,
1767                    source_len.to_u32(),
1768                    self.cnum,
1769                    lines,
1770                    multibyte_chars,
1771                    normalized_pos,
1772                    source_file_index,
1773                );
1774                debug!(
1775                    "CrateMetaData::imported_source_files alloc \
1776                         source_file {:?} original (start_pos {:?} source_len {:?}) \
1777                         translated (start_pos {:?} source_len {:?})",
1778                    local_version.name,
1779                    original_start_pos,
1780                    source_len,
1781                    local_version.start_pos,
1782                    local_version.source_len
1783                );
1784
1785                ImportedSourceFile {
1786                    original_start_pos,
1787                    original_end_pos,
1788                    translated_source_file: local_version,
1789                }
1790            })
1791            .clone()
1792    }
1793
1794    fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1795        self.root.tables.attr_flags.get(self, index)
1796    }
1797
1798    fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
1799        self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
1800    }
1801
1802    fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
1803        self.root
1804            .tables
1805            .doc_link_resolutions
1806            .get(self, index)
1807            .expect("no resolutions for a doc link")
1808            .decode(self)
1809    }
1810
1811    fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> {
1812        self.root
1813            .tables
1814            .doc_link_traits_in_scope
1815            .get(self, index)
1816            .expect("no traits in scope for a doc link")
1817            .decode(self)
1818    }
1819}
1820
1821impl CrateMetadata {
1822    pub(crate) fn new(
1823        sess: &Session,
1824        cstore: &CStore,
1825        blob: MetadataBlob,
1826        root: CrateRoot,
1827        raw_proc_macros: Option<&'static [ProcMacro]>,
1828        cnum: CrateNum,
1829        cnum_map: CrateNumMap,
1830        dep_kind: CrateDepKind,
1831        source: CrateSource,
1832        private_dep: bool,
1833        host_hash: Option<Svh>,
1834    ) -> CrateMetadata {
1835        let trait_impls = root
1836            .impls
1837            .decode((&blob, sess))
1838            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
1839            .collect();
1840        let alloc_decoding_state =
1841            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
1842        let dependencies = cnum_map.iter().copied().collect();
1843
1844        // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation
1845        // that does not copy any data. It just does some data verification.
1846        let def_path_hash_map = root.def_path_hash_map.decode(&blob);
1847
1848        let mut cdata = CrateMetadata {
1849            blob,
1850            root,
1851            trait_impls,
1852            incoherent_impls: Default::default(),
1853            raw_proc_macros,
1854            source_map_import_info: Lock::new(Vec::new()),
1855            def_path_hash_map,
1856            expn_hash_map: Default::default(),
1857            alloc_decoding_state,
1858            cnum,
1859            cnum_map,
1860            dependencies,
1861            dep_kind,
1862            source: Arc::new(source),
1863            private_dep,
1864            host_hash,
1865            used: false,
1866            extern_crate: None,
1867            hygiene_context: Default::default(),
1868            def_key_cache: Default::default(),
1869        };
1870
1871        // Need `CrateMetadataRef` to decode `DefId`s in simplified types.
1872        cdata.incoherent_impls = cdata
1873            .root
1874            .incoherent_impls
1875            .decode(CrateMetadataRef { cdata: &cdata, cstore })
1876            .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls))
1877            .collect();
1878
1879        cdata
1880    }
1881
1882    pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
1883        self.dependencies.iter().copied()
1884    }
1885
1886    pub(crate) fn add_dependency(&mut self, cnum: CrateNum) {
1887        self.dependencies.push(cnum);
1888    }
1889
1890    pub(crate) fn target_modifiers(&self) -> TargetModifiers {
1891        self.root.decode_target_modifiers(&self.blob).collect()
1892    }
1893
1894    pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
1895        let update =
1896            Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank);
1897        if update {
1898            self.extern_crate = Some(new_extern_crate);
1899        }
1900        update
1901    }
1902
1903    pub(crate) fn source(&self) -> &CrateSource {
1904        &*self.source
1905    }
1906
1907    pub(crate) fn dep_kind(&self) -> CrateDepKind {
1908        self.dep_kind
1909    }
1910
1911    pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
1912        self.dep_kind = dep_kind;
1913    }
1914
1915    pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
1916        self.private_dep &= private_dep;
1917    }
1918
1919    pub(crate) fn used(&self) -> bool {
1920        self.used
1921    }
1922
1923    pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
1924        self.root.required_panic_strategy
1925    }
1926
1927    pub(crate) fn needs_panic_runtime(&self) -> bool {
1928        self.root.needs_panic_runtime
1929    }
1930
1931    pub(crate) fn is_private_dep(&self) -> bool {
1932        self.private_dep
1933    }
1934
1935    pub(crate) fn is_panic_runtime(&self) -> bool {
1936        self.root.panic_runtime
1937    }
1938
1939    pub(crate) fn is_profiler_runtime(&self) -> bool {
1940        self.root.profiler_runtime
1941    }
1942
1943    pub(crate) fn is_compiler_builtins(&self) -> bool {
1944        self.root.compiler_builtins
1945    }
1946
1947    pub(crate) fn needs_allocator(&self) -> bool {
1948        self.root.needs_allocator
1949    }
1950
1951    pub(crate) fn has_global_allocator(&self) -> bool {
1952        self.root.has_global_allocator
1953    }
1954
1955    pub(crate) fn has_alloc_error_handler(&self) -> bool {
1956        self.root.has_alloc_error_handler
1957    }
1958
1959    pub(crate) fn has_default_lib_allocator(&self) -> bool {
1960        self.root.has_default_lib_allocator
1961    }
1962
1963    pub(crate) fn is_proc_macro_crate(&self) -> bool {
1964        self.root.is_proc_macro_crate()
1965    }
1966
1967    pub(crate) fn name(&self) -> Symbol {
1968        self.root.header.name
1969    }
1970
1971    pub(crate) fn hash(&self) -> Svh {
1972        self.root.header.hash
1973    }
1974
1975    fn num_def_ids(&self) -> usize {
1976        self.root.tables.def_keys.size()
1977    }
1978
1979    fn local_def_id(&self, index: DefIndex) -> DefId {
1980        DefId { krate: self.cnum, index }
1981    }
1982
1983    // Translate a DefId from the current compilation environment to a DefId
1984    // for an external crate.
1985    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
1986        for (local, &global) in self.cnum_map.iter_enumerated() {
1987            if global == did.krate {
1988                return Some(DefId { krate: local, index: did.index });
1989            }
1990        }
1991
1992        None
1993    }
1994}