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 kind = match self.def_kind(id) {
1336            DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) },
1337            DefKind::AssocFn => ty::AssocKind::Fn {
1338                name: self.item_name(id),
1339                has_self: self.get_fn_has_self_parameter(id, sess),
1340            },
1341            DefKind::AssocTy => {
1342                let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id)
1343                {
1344                    ty::AssocTypeData::Rpitit(rpitit_info.decode(self))
1345                } else {
1346                    ty::AssocTypeData::Normal(self.item_name(id))
1347                };
1348                ty::AssocKind::Type { data }
1349            }
1350            _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
1351        };
1352        let container = self.root.tables.assoc_container.get(self, id).unwrap();
1353
1354        ty::AssocItem {
1355            kind,
1356            def_id: self.local_def_id(id),
1357            trait_item_def_id: self.get_trait_item_def_id(id),
1358            container,
1359        }
1360    }
1361
1362    fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
1363        match self.def_kind(node_id) {
1364            DefKind::Struct | DefKind::Variant => {
1365                let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
1366                vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
1367            }
1368            _ => None,
1369        }
1370    }
1371
1372    fn get_item_attrs(
1373        self,
1374        id: DefIndex,
1375        sess: &'a Session,
1376    ) -> impl Iterator<Item = hir::Attribute> {
1377        self.root
1378            .tables
1379            .attributes
1380            .get(self, id)
1381            .unwrap_or_else(|| {
1382                // Structure and variant constructors don't have any attributes encoded for them,
1383                // but we assume that someone passing a constructor ID actually wants to look at
1384                // the attributes on the corresponding struct or variant.
1385                let def_key = self.def_key(id);
1386                assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
1387                let parent_id = def_key.parent.expect("no parent for a constructor");
1388                self.root
1389                    .tables
1390                    .attributes
1391                    .get(self, parent_id)
1392                    .expect("no encoded attributes for a structure or variant")
1393            })
1394            .decode((self, sess))
1395    }
1396
1397    fn get_inherent_implementations_for_type<'tcx>(
1398        self,
1399        tcx: TyCtxt<'tcx>,
1400        id: DefIndex,
1401    ) -> &'tcx [DefId] {
1402        tcx.arena.alloc_from_iter(
1403            self.root
1404                .tables
1405                .inherent_impls
1406                .get(self, id)
1407                .decode(self)
1408                .map(|index| self.local_def_id(index)),
1409        )
1410    }
1411
1412    /// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
1413    fn get_traits(self) -> impl Iterator<Item = DefId> {
1414        self.root.traits.decode(self).map(move |index| self.local_def_id(index))
1415    }
1416
1417    /// Decodes all trait impls in the crate (for rustdoc).
1418    fn get_trait_impls(self) -> impl Iterator<Item = DefId> {
1419        self.cdata.trait_impls.values().flat_map(move |impls| {
1420            impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index))
1421        })
1422    }
1423
1424    fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
1425        if let Some(impls) = self.cdata.incoherent_impls.get(&simp) {
1426            tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
1427        } else {
1428            &[]
1429        }
1430    }
1431
1432    fn get_implementations_of_trait<'tcx>(
1433        self,
1434        tcx: TyCtxt<'tcx>,
1435        trait_def_id: DefId,
1436    ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
1437        if self.trait_impls.is_empty() {
1438            return &[];
1439        }
1440
1441        // Do a reverse lookup beforehand to avoid touching the crate_num
1442        // hash map in the loop below.
1443        let key = match self.reverse_translate_def_id(trait_def_id) {
1444            Some(def_id) => (def_id.krate.as_u32(), def_id.index),
1445            None => return &[],
1446        };
1447
1448        if let Some(impls) = self.trait_impls.get(&key) {
1449            tcx.arena.alloc_from_iter(
1450                impls
1451                    .decode(self)
1452                    .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)),
1453            )
1454        } else {
1455            &[]
1456        }
1457    }
1458
1459    fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> {
1460        self.root.native_libraries.decode((self, sess))
1461    }
1462
1463    fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
1464        self.root
1465            .tables
1466            .proc_macro_quoted_spans
1467            .get(self, index)
1468            .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
1469            .decode((self, sess))
1470    }
1471
1472    fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> {
1473        self.root.foreign_modules.decode((self, sess))
1474    }
1475
1476    fn get_dylib_dependency_formats<'tcx>(
1477        self,
1478        tcx: TyCtxt<'tcx>,
1479    ) -> &'tcx [(CrateNum, LinkagePreference)] {
1480        tcx.arena.alloc_from_iter(
1481            self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
1482                let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding
1483                link.map(|link| (self.cnum_map[cnum], link))
1484            }),
1485        )
1486    }
1487
1488    fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
1489        tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
1490    }
1491
1492    fn get_exportable_items(self) -> impl Iterator<Item = DefId> {
1493        self.root.exportable_items.decode(self).map(move |index| self.local_def_id(index))
1494    }
1495
1496    fn get_stable_order_of_exportable_impls(self) -> impl Iterator<Item = (DefId, usize)> {
1497        self.root
1498            .stable_order_of_exportable_impls
1499            .decode(self)
1500            .map(move |v| (self.local_def_id(v.0), v.1))
1501    }
1502
1503    fn exported_symbols<'tcx>(
1504        self,
1505        tcx: TyCtxt<'tcx>,
1506    ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1507        tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
1508    }
1509
1510    fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
1511        match self.def_kind(id) {
1512            DefKind::Macro(_) => {
1513                let macro_rules = self.root.tables.is_macro_rules.get(self, id);
1514                let body =
1515                    self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
1516                ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
1517            }
1518            _ => bug!(),
1519        }
1520    }
1521
1522    #[inline]
1523    fn def_key(self, index: DefIndex) -> DefKey {
1524        *self
1525            .def_key_cache
1526            .lock()
1527            .entry(index)
1528            .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
1529    }
1530
1531    // Returns the path leading to the thing with this `id`.
1532    fn def_path(self, id: DefIndex) -> DefPath {
1533        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
1534        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
1535    }
1536
1537    #[inline]
1538    fn def_path_hash(self, index: DefIndex) -> DefPathHash {
1539        // This is a hack to workaround the fact that we can't easily encode/decode a Hash64
1540        // into the FixedSizeEncoding, as Hash64 lacks a Default impl. A future refactor to
1541        // relax the Default restriction will likely fix this.
1542        let fingerprint = Fingerprint::new(
1543            self.root.stable_crate_id.as_u64(),
1544            self.root.tables.def_path_hashes.get(self, index),
1545        );
1546        DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1)
1547    }
1548
1549    #[inline]
1550    fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex {
1551        self.def_path_hash_map.def_path_hash_to_def_index(&hash)
1552    }
1553
1554    fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
1555        debug_assert_eq!(ExpnId::from_hash(hash), None);
1556        let index_guess = ExpnIndex::from_u32(index_guess);
1557        let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1558
1559        let index = if old_hash == Some(hash) {
1560            // Fast path: the expn and its index is unchanged from the
1561            // previous compilation session. There is no need to decode anything
1562            // else.
1563            index_guess
1564        } else {
1565            // Slow path: We need to find out the new `DefIndex` of the provided
1566            // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
1567            // stored in this crate.
1568            let map = self.cdata.expn_hash_map.get_or_init(|| {
1569                let end_id = self.root.expn_hashes.size() as u32;
1570                let mut map =
1571                    UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1572                for i in 0..end_id {
1573                    let i = ExpnIndex::from_u32(i);
1574                    if let Some(hash) = self.root.expn_hashes.get(self, i) {
1575                        map.insert(hash.decode(self), i);
1576                    }
1577                }
1578                map
1579            });
1580            map[&hash]
1581        };
1582
1583        let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess));
1584        rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
1585    }
1586
1587    /// Imports the source_map from an external crate into the source_map of the crate
1588    /// currently being compiled (the "local crate").
1589    ///
1590    /// The import algorithm works analogous to how AST items are inlined from an
1591    /// external crate's metadata:
1592    /// For every SourceFile in the external source_map an 'inline' copy is created in the
1593    /// local source_map. The correspondence relation between external and local
1594    /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this
1595    /// function. When an item from an external crate is later inlined into this
1596    /// crate, this correspondence information is used to translate the span
1597    /// information of the inlined item so that it refers the correct positions in
1598    /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
1599    ///
1600    /// The import algorithm in the function below will reuse SourceFiles already
1601    /// existing in the local source_map. For example, even if the SourceFile of some
1602    /// source file of libstd gets imported many times, there will only ever be
1603    /// one SourceFile object for the corresponding file in the local source_map.
1604    ///
1605    /// Note that imported SourceFiles do not actually contain the source code of the
1606    /// file they represent, just information about length, line breaks, and
1607    /// multibyte characters. This information is enough to generate valid debuginfo
1608    /// for items inlined from other crates.
1609    ///
1610    /// Proc macro crates don't currently export spans, so this function does not have
1611    /// to work for them.
1612    fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1613        fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1614            path.filter(|_| {
1615                // Only spend time on further checks if we have what to translate *to*.
1616                sess.opts.real_rust_source_base_dir.is_some()
1617                // Some tests need the translation to be always skipped.
1618                && sess.opts.unstable_opts.translate_remapped_path_to_local_path
1619            })
1620            .filter(|virtual_dir| {
1621                // Don't translate away `/rustc/$hash` if we're still remapping to it,
1622                // since that means we're still building `std`/`rustc` that need it,
1623                // and we don't want the real path to leak into codegen/debuginfo.
1624                !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
1625            })
1626        }
1627
1628        let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
1629            // Translate the virtual `/rustc/$hash` prefix back to a real directory
1630            // that should hold actual sources, where possible.
1631            //
1632            // NOTE: if you update this, you might need to also update bootstrap's code for generating
1633            // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1634            let virtual_rust_source_base_dir = [
1635                filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1636                filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1637            ];
1638
1639            debug!(
1640                "try_to_translate_virtual_to_real(name={:?}): \
1641                 virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1642                name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1643            );
1644
1645            for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1646                if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1647                    && let rustc_span::FileName::Real(old_name) = name
1648                    && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1649                        old_name
1650                    && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1651                {
1652                    // The std library crates are in
1653                    // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates
1654                    // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we
1655                    // detect crates from the std libs and handle them specially.
1656                    const STD_LIBS: &[&str] = &[
1657                        "core",
1658                        "alloc",
1659                        "std",
1660                        "test",
1661                        "term",
1662                        "unwind",
1663                        "proc_macro",
1664                        "panic_abort",
1665                        "panic_unwind",
1666                        "profiler_builtins",
1667                        "rtstartup",
1668                        "rustc-std-workspace-core",
1669                        "rustc-std-workspace-alloc",
1670                        "rustc-std-workspace-std",
1671                        "backtrace",
1672                    ];
1673                    let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l));
1674
1675                    let new_path = if is_std_lib {
1676                        real_dir.join("library").join(rest)
1677                    } else {
1678                        real_dir.join(rest)
1679                    };
1680
1681                    debug!(
1682                        "try_to_translate_virtual_to_real: `{}` -> `{}`",
1683                        virtual_name.display(),
1684                        new_path.display(),
1685                    );
1686
1687                    // Check if the translated real path is affected by any user-requested
1688                    // remaps via --remap-path-prefix. Apply them if so.
1689                    // Note that this is a special case for imported rust-src paths specified by
1690                    // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1691                    // Other imported paths are not currently remapped (see #66251).
1692                    let (user_remapped, applied) =
1693                        sess.source_map().path_mapping().map_prefix(&new_path);
1694                    let new_name = if applied {
1695                        rustc_span::RealFileName::Remapped {
1696                            local_path: Some(new_path.clone()),
1697                            virtual_name: user_remapped.to_path_buf(),
1698                        }
1699                    } else {
1700                        rustc_span::RealFileName::LocalPath(new_path)
1701                    };
1702                    *old_name = new_name;
1703                }
1704            }
1705        };
1706
1707        let mut import_info = self.cdata.source_map_import_info.lock();
1708        for _ in import_info.len()..=(source_file_index as usize) {
1709            import_info.push(None);
1710        }
1711        import_info[source_file_index as usize]
1712            .get_or_insert_with(|| {
1713                let source_file_to_import = self
1714                    .root
1715                    .source_map
1716                    .get(self, source_file_index)
1717                    .expect("missing source file")
1718                    .decode(self);
1719
1720                // We can't reuse an existing SourceFile, so allocate a new one
1721                // containing the information we need.
1722                let original_end_pos = source_file_to_import.end_position();
1723                let rustc_span::SourceFile {
1724                    mut name,
1725                    src_hash,
1726                    checksum_hash,
1727                    start_pos: original_start_pos,
1728                    source_len,
1729                    lines,
1730                    multibyte_chars,
1731                    normalized_pos,
1732                    stable_id,
1733                    ..
1734                } = source_file_to_import;
1735
1736                // If this file is under $sysroot/lib/rustlib/src/
1737                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
1738                // then we change `name` to a similar state as if the rust was bootstrapped
1739                // with `remap-debuginfo = true`.
1740                // This is useful for testing so that tests about the effects of
1741                // `try_to_translate_virtual_to_real` don't have to worry about how the
1742                // compiler is bootstrapped.
1743                if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1744                    && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1745                    && let rustc_span::FileName::Real(ref mut old_name) = name
1746                {
1747                    let relative_path = match old_name {
1748                        rustc_span::RealFileName::LocalPath(local) => {
1749                            local.strip_prefix(real_dir).ok()
1750                        }
1751                        rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1752                            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
1753                                .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1754                        }
1755                    };
1756                    debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
1757                    for subdir in ["library", "compiler"] {
1758                        if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok())
1759                        {
1760                            *old_name = rustc_span::RealFileName::Remapped {
1761                                local_path: None, // FIXME: maybe we should preserve this?
1762                                virtual_name: virtual_dir.join(subdir).join(rest),
1763                            };
1764                            break;
1765                        }
1766                    }
1767                }
1768
1769                // If this file's path has been remapped to `/rustc/$hash`,
1770                // we might be able to reverse that (also see comments above,
1771                // on `try_to_translate_virtual_to_real`).
1772                try_to_translate_virtual_to_real(&mut name);
1773
1774                let local_version = sess.source_map().new_imported_source_file(
1775                    name,
1776                    src_hash,
1777                    checksum_hash,
1778                    stable_id,
1779                    source_len.to_u32(),
1780                    self.cnum,
1781                    lines,
1782                    multibyte_chars,
1783                    normalized_pos,
1784                    source_file_index,
1785                );
1786                debug!(
1787                    "CrateMetaData::imported_source_files alloc \
1788                         source_file {:?} original (start_pos {:?} source_len {:?}) \
1789                         translated (start_pos {:?} source_len {:?})",
1790                    local_version.name,
1791                    original_start_pos,
1792                    source_len,
1793                    local_version.start_pos,
1794                    local_version.source_len
1795                );
1796
1797                ImportedSourceFile {
1798                    original_start_pos,
1799                    original_end_pos,
1800                    translated_source_file: local_version,
1801                }
1802            })
1803            .clone()
1804    }
1805
1806    fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1807        self.root.tables.attr_flags.get(self, index)
1808    }
1809
1810    fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
1811        self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
1812    }
1813
1814    fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
1815        self.root
1816            .tables
1817            .doc_link_resolutions
1818            .get(self, index)
1819            .expect("no resolutions for a doc link")
1820            .decode(self)
1821    }
1822
1823    fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> {
1824        self.root
1825            .tables
1826            .doc_link_traits_in_scope
1827            .get(self, index)
1828            .expect("no traits in scope for a doc link")
1829            .decode(self)
1830    }
1831}
1832
1833impl CrateMetadata {
1834    pub(crate) fn new(
1835        sess: &Session,
1836        cstore: &CStore,
1837        blob: MetadataBlob,
1838        root: CrateRoot,
1839        raw_proc_macros: Option<&'static [ProcMacro]>,
1840        cnum: CrateNum,
1841        cnum_map: CrateNumMap,
1842        dep_kind: CrateDepKind,
1843        source: CrateSource,
1844        private_dep: bool,
1845        host_hash: Option<Svh>,
1846    ) -> CrateMetadata {
1847        let trait_impls = root
1848            .impls
1849            .decode((&blob, sess))
1850            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
1851            .collect();
1852        let alloc_decoding_state =
1853            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
1854        let dependencies = cnum_map.iter().copied().collect();
1855
1856        // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation
1857        // that does not copy any data. It just does some data verification.
1858        let def_path_hash_map = root.def_path_hash_map.decode(&blob);
1859
1860        let mut cdata = CrateMetadata {
1861            blob,
1862            root,
1863            trait_impls,
1864            incoherent_impls: Default::default(),
1865            raw_proc_macros,
1866            source_map_import_info: Lock::new(Vec::new()),
1867            def_path_hash_map,
1868            expn_hash_map: Default::default(),
1869            alloc_decoding_state,
1870            cnum,
1871            cnum_map,
1872            dependencies,
1873            dep_kind,
1874            source: Arc::new(source),
1875            private_dep,
1876            host_hash,
1877            used: false,
1878            extern_crate: None,
1879            hygiene_context: Default::default(),
1880            def_key_cache: Default::default(),
1881        };
1882
1883        // Need `CrateMetadataRef` to decode `DefId`s in simplified types.
1884        cdata.incoherent_impls = cdata
1885            .root
1886            .incoherent_impls
1887            .decode(CrateMetadataRef { cdata: &cdata, cstore })
1888            .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls))
1889            .collect();
1890
1891        cdata
1892    }
1893
1894    pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
1895        self.dependencies.iter().copied()
1896    }
1897
1898    pub(crate) fn add_dependency(&mut self, cnum: CrateNum) {
1899        self.dependencies.push(cnum);
1900    }
1901
1902    pub(crate) fn target_modifiers(&self) -> TargetModifiers {
1903        self.root.decode_target_modifiers(&self.blob).collect()
1904    }
1905
1906    pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
1907        let update =
1908            Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank);
1909        if update {
1910            self.extern_crate = Some(new_extern_crate);
1911        }
1912        update
1913    }
1914
1915    pub(crate) fn source(&self) -> &CrateSource {
1916        &*self.source
1917    }
1918
1919    pub(crate) fn dep_kind(&self) -> CrateDepKind {
1920        self.dep_kind
1921    }
1922
1923    pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
1924        self.dep_kind = dep_kind;
1925    }
1926
1927    pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
1928        self.private_dep &= private_dep;
1929    }
1930
1931    pub(crate) fn used(&self) -> bool {
1932        self.used
1933    }
1934
1935    pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
1936        self.root.required_panic_strategy
1937    }
1938
1939    pub(crate) fn needs_panic_runtime(&self) -> bool {
1940        self.root.needs_panic_runtime
1941    }
1942
1943    pub(crate) fn is_private_dep(&self) -> bool {
1944        self.private_dep
1945    }
1946
1947    pub(crate) fn is_panic_runtime(&self) -> bool {
1948        self.root.panic_runtime
1949    }
1950
1951    pub(crate) fn is_profiler_runtime(&self) -> bool {
1952        self.root.profiler_runtime
1953    }
1954
1955    pub(crate) fn is_compiler_builtins(&self) -> bool {
1956        self.root.compiler_builtins
1957    }
1958
1959    pub(crate) fn needs_allocator(&self) -> bool {
1960        self.root.needs_allocator
1961    }
1962
1963    pub(crate) fn has_global_allocator(&self) -> bool {
1964        self.root.has_global_allocator
1965    }
1966
1967    pub(crate) fn has_alloc_error_handler(&self) -> bool {
1968        self.root.has_alloc_error_handler
1969    }
1970
1971    pub(crate) fn has_default_lib_allocator(&self) -> bool {
1972        self.root.has_default_lib_allocator
1973    }
1974
1975    pub(crate) fn is_proc_macro_crate(&self) -> bool {
1976        self.root.is_proc_macro_crate()
1977    }
1978
1979    pub(crate) fn name(&self) -> Symbol {
1980        self.root.header.name
1981    }
1982
1983    pub(crate) fn hash(&self) -> Svh {
1984        self.root.header.hash
1985    }
1986
1987    pub(crate) fn has_async_drops(&self) -> bool {
1988        self.root.tables.adt_async_destructor.len > 0
1989    }
1990
1991    fn num_def_ids(&self) -> usize {
1992        self.root.tables.def_keys.size()
1993    }
1994
1995    fn local_def_id(&self, index: DefIndex) -> DefId {
1996        DefId { krate: self.cnum, index }
1997    }
1998
1999    // Translate a DefId from the current compilation environment to a DefId
2000    // for an external crate.
2001    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
2002        for (local, &global) in self.cnum_map.iter_enumerated() {
2003            if global == did.krate {
2004                return Some(DefId { krate: local, index: did.index });
2005            }
2006        }
2007
2008        None
2009    }
2010}