// Decoding metadata from a single crate's metadata

use std::iter::TrustedLen;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock};
use std::{io, mem};

pub(super) use cstore_impl::provide;
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::unhash::UnhashMap;
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
use rustc_hir::Safety;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefPath, DefPathData};
use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_index::Idx;
use rustc_middle::middle::lib_features::LibFeatures;
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::ty::Visibility;
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::{bug, implement_ty_decoder};
use rustc_proc_macro::bridge::client::ProcMacro;
use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::{Decodable, Decoder};
use rustc_session::config::TargetModifier;
use rustc_session::config::mitigation_coverage::DeniedPartialMitigation;
use rustc_session::cstore::{CrateSource, ExternCrate};
use rustc_span::hygiene::HygieneDecodeContext;
use rustc_span::{
    BlobDecoder, BytePos, ByteSymbol, DUMMY_SP, Pos, RemapPathScopeComponents, SpanData,
    SpanDecoder, Symbol, SyntaxContext, kw,
};
use tracing::debug;

use crate::creader::CStore;
use crate::eii::EiiMapEncodedKeyValue;
use crate::rmeta::table::IsDefault;
use crate::rmeta::*;

mod cstore_impl;

/// A reference to the raw binary version of crate metadata.
/// This struct applies [`MemDecoder`]'s validation when constructed
/// so that later constructions are guaranteed to succeed.
pub(crate) struct MetadataBlob(OwnedSlice);

impl std::ops::Deref for MetadataBlob {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        &self.0[..]
    }
}

impl MetadataBlob {
    /// Runs the [`MemDecoder`] validation and if it passes, constructs a new [`MetadataBlob`].
    pub(crate) fn new(slice: OwnedSlice) -> Result<Self, ()> {
        if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) }
    }

    /// Since this has passed the validation of [`MetadataBlob::new`], this returns bytes which are
    /// known to pass the [`MemDecoder`] validation.
    pub(crate) fn bytes(&self) -> &OwnedSlice {
        &self.0
    }
}

/// A map from external crate numbers (as decoded from some crate file) to
/// local crate numbers (as generated during this session). Each external
/// crate may refer to types in other external crates, and each has their
/// own crate numbers.
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;

/// Target modifiers - abi or exploit mitigations options that may cause unsoundness when mixed or
/// partially enabled.
pub(crate) type TargetModifiers = Vec<TargetModifier>;

/// The set of mitigations that cannot be partially enabled (see
/// [RFC 3855](https://github.com/rust-lang/rfcs/pull/3855)), but are currently enabled for this
/// crate.
pub(crate) type DeniedPartialMitigations = Vec<DeniedPartialMitigation>;

pub(crate) struct CrateMetadata {
    /// The primary crate data - binary metadata blob.
    blob: MetadataBlob,

    // --- Some data pre-decoded from the metadata blob, usually for performance ---
    /// Data about the top-level items in a crate, as well as various crate-level metadata.
    root: CrateRoot,
    /// Trait impl data.
    /// FIXME: Used only from queries and can use query cache,
    /// so pre-decoding can probably be avoided.
    trait_impls: FxIndexMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
    /// Inherent impls which do not follow the normal coherence rules.
    ///
    /// These can be introduced using either `#![rustc_coherence_is_core]`
    /// or `#[rustc_allow_incoherent_impl]`.
    incoherent_impls: FxIndexMap<SimplifiedType, LazyArray<DefIndex>>,
    /// Proc macro descriptions for this crate, if it's a proc macro crate.
    raw_proc_macros: Option<&'static [ProcMacro]>,
    /// Source maps for code from the crate.
    source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>,
    /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
    def_path_hash_map: DefPathHashMapRef<'static>,
    /// Likewise for ExpnHash.
    expn_hash_map: OnceLock<UnhashMap<ExpnHash, ExpnIndex>>,
    /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
    alloc_decoding_state: AllocDecodingState,
    /// Caches decoded `DefKey`s.
    def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,

    // --- Other significant crate properties ---
    /// ID of this crate, from the current compilation session's point of view.
    cnum: CrateNum,
    /// Maps crate IDs as they are were seen from this crate's compilation sessions into
    /// IDs as they are seen from the current compilation session.
    cnum_map: CrateNumMap,
    /// How to link (or not link) this crate to the currently compiled crate.
    dep_kind: CrateDepKind,
    /// Filesystem location of this crate.
    source: Arc<CrateSource>,
    /// Whether or not this crate should be consider a private dependency.
    /// Used by the 'exported_private_dependencies' lint, and for determining
    /// whether to emit suggestions that reference this crate.
    private_dep: bool,
    /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
    host_hash: Option<Svh>,
    /// The crate was used non-speculatively.
    used: bool,

    /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
    /// and `ExpnId`).
    /// Note that we store a `HygieneDecodeContext` for each `CrateMetadata`. This is
    /// because `SyntaxContext` ids are not globally unique, so we need
    /// to track which ids we've decoded on a per-crate basis.
    hygiene_context: HygieneDecodeContext,

    // --- Data used only for improving diagnostics ---
    /// Information about the `extern crate` item or path that caused this crate to be loaded.
    /// If this is `None`, then the crate was injected (e.g., by the allocator).
    extern_crate: Option<ExternCrate>,
}

/// Holds information about a rustc_span::SourceFile imported from another crate.
/// See `imported_source_file()` for more information.
#[derive(Clone)]
struct ImportedSourceFile {
    /// This SourceFile's byte-offset within the source_map of its original crate
    original_start_pos: rustc_span::BytePos,
    /// The end of this SourceFile within the source_map of its original crate
    original_end_pos: rustc_span::BytePos,
    /// The imported SourceFile's representation within the local source_map
    translated_source_file: Arc<rustc_span::SourceFile>,
}

/// Decode context used when we just have a blob of metadata from which we have to decode a header
/// and [`CrateRoot`]. After that, [`MetadataDecodeContext`] can be used.
/// Most notably, [`BlobDecodeContext]` doesn't implement [`SpanDecoder`]
pub(super) struct BlobDecodeContext<'a> {
    opaque: MemDecoder<'a>,
    blob: &'a MetadataBlob,
    lazy_state: LazyState,
}

/// This trait abstracts over decoders that can decode lazy values using [`LazyState`]:
///
/// - [`LazyValue`]
/// - [`LazyArray`]
/// - [`LazyTable`]
pub(super) trait LazyDecoder: BlobDecoder {
    fn set_lazy_state(&mut self, state: LazyState);
    fn get_lazy_state(&self) -> LazyState;

    fn read_lazy<T>(&mut self) -> LazyValue<T> {
        self.read_lazy_offset_then(|pos| LazyValue::from_position(pos))
    }

    fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> {
        self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
    }

    fn read_lazy_table<I, T>(&mut self, width: usize, len: usize) -> LazyTable<I, T> {
        self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len))
    }

    #[inline]
    fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZero<usize>) -> T) -> T {
        let distance = self.read_usize();
        let position = match self.get_lazy_state() {
            LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
            LazyState::NodeStart(start) => {
                let start = start.get();
                assert!(distance <= start);
                start - distance
            }
            LazyState::Previous(last_pos) => last_pos.get() + distance,
        };
        let position = NonZero::new(position).unwrap();
        self.set_lazy_state(LazyState::Previous(position));
        f(position)
    }
}

impl<'a> LazyDecoder for BlobDecodeContext<'a> {
    fn set_lazy_state(&mut self, state: LazyState) {
        self.lazy_state = state;
    }

    fn get_lazy_state(&self) -> LazyState {
        self.lazy_state
    }
}

/// This is the decode context used when crate metadata was already read.
/// Decoding of some types, like `Span` require some information to already been read.
/// Can be constructed from a [`TyCtxt`] and [`CrateMetadata`] (see impls of the [`MetaDecoder`]
/// trait).
pub(super) struct MetadataDecodeContext<'a, 'tcx> {
    blob_decoder: BlobDecodeContext<'a>,
    cdata: &'a CrateMetadata,
    tcx: TyCtxt<'tcx>,

    // Used for decoding interpret::AllocIds in a cached & thread-safe manner.
    alloc_decoding_session: AllocDecodingSession<'a>,
}

impl<'a, 'tcx> LazyDecoder for MetadataDecodeContext<'a, 'tcx> {
    fn set_lazy_state(&mut self, state: LazyState) {
        self.lazy_state = state;
    }

    fn get_lazy_state(&self) -> LazyState {
        self.lazy_state
    }
}

impl<'a, 'tcx> DerefMut for MetadataDecodeContext<'a, 'tcx> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.blob_decoder
    }
}

impl<'a, 'tcx> Deref for MetadataDecodeContext<'a, 'tcx> {
    type Target = BlobDecodeContext<'a>;

    fn deref(&self) -> &Self::Target {
        &self.blob_decoder
    }
}

pub(super) trait MetaBlob<'a>: Copy {
    fn blob(&self) -> &'a MetadataBlob;
}

pub(super) trait MetaDecoder: Copy {
    type Context: BlobDecoder + LazyDecoder;

    fn decoder(self, pos: usize) -> Self::Context;
}

impl<'a> MetaBlob<'a> for &'a MetadataBlob {
    fn blob(&self) -> &'a MetadataBlob {
        self
    }
}

impl<'a> MetaDecoder for &'a MetadataBlob {
    type Context = BlobDecodeContext<'a>;

    fn decoder(self, pos: usize) -> Self::Context {
        BlobDecodeContext {
            // FIXME: This unwrap should never panic because we check that it won't when creating
            // `MetadataBlob`. Ideally we'd just have a `MetadataDecoder` and hand out subslices of
            // it as we do elsewhere in the compiler using `MetadataDecoder::split_at`. But we own
            // the data for the decoder so holding onto the `MemDecoder` too would make us a
            // self-referential struct which is downright goofy because `MetadataBlob` is already
            // self-referential. Probably `MemDecoder` should contain an `OwnedSlice`, but that
            // demands a significant refactoring due to our crate graph.
            opaque: MemDecoder::new(self, pos).unwrap(),
            lazy_state: LazyState::NoNode,
            blob: self.blob(),
        }
    }
}

impl<'a> MetaBlob<'a> for &'a CrateMetadata {
    fn blob(&self) -> &'a MetadataBlob {
        &self.blob
    }
}

impl<'a, 'tcx> MetaDecoder for (&'a CrateMetadata, TyCtxt<'tcx>) {
    type Context = MetadataDecodeContext<'a, 'tcx>;

    fn decoder(self, pos: usize) -> MetadataDecodeContext<'a, 'tcx> {
        MetadataDecodeContext {
            blob_decoder: self.0.blob().decoder(pos),
            cdata: self.0,
            tcx: self.1,
            alloc_decoding_session: self.0.alloc_decoding_state.new_decoding_session(),
        }
    }
}

impl<T: ParameterizedOverTcx> LazyValue<T> {
    #[inline]
    fn decode<'tcx, M: MetaDecoder>(self, metadata: M) -> T::Value<'tcx>
    where
        T::Value<'tcx>: Decodable<M::Context>,
    {
        let mut dcx = metadata.decoder(self.position.get());
        dcx.set_lazy_state(LazyState::NodeStart(self.position));
        T::Value::decode(&mut dcx)
    }
}

struct DecodeIterator<T, D> {
    elem_counter: std::ops::Range<usize>,
    dcx: D,
    _phantom: PhantomData<fn() -> T>,
}

impl<D: Decoder, T: Decodable<D>> Iterator for DecodeIterator<T, D> {
    type Item = T;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.elem_counter.next().map(|_| T::decode(&mut self.dcx))
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.elem_counter.size_hint()
    }
}

impl<D: Decoder, T: Decodable<D>> ExactSizeIterator for DecodeIterator<T, D> {
    fn len(&self) -> usize {
        self.elem_counter.len()
    }
}

unsafe impl<D: Decoder, T: Decodable<D>> TrustedLen for DecodeIterator<T, D> {}

impl<T: ParameterizedOverTcx> LazyArray<T> {
    #[inline]
    fn decode<'tcx, M: MetaDecoder>(self, metadata: M) -> DecodeIterator<T::Value<'tcx>, M::Context>
    where
        T::Value<'tcx>: Decodable<M::Context>,
    {
        let mut dcx = metadata.decoder(self.position.get());
        dcx.set_lazy_state(LazyState::NodeStart(self.position));
        DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData }
    }
}

impl<'a, 'tcx> MetadataDecodeContext<'a, 'tcx> {
    #[inline]
    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
        self.cdata.map_encoded_cnum_to_current(cnum)
    }
}

impl<'a> BlobDecodeContext<'a> {
    #[inline]
    pub(crate) fn blob(&self) -> &'a MetadataBlob {
        self.blob
    }

    fn decode_symbol_or_byte_symbol<S>(
        &mut self,
        new_from_index: impl Fn(u32) -> S,
        read_and_intern_str_or_byte_str_this: impl Fn(&mut Self) -> S,
        read_and_intern_str_or_byte_str_opaque: impl Fn(&mut MemDecoder<'a>) -> S,
    ) -> S {
        let tag = self.read_u8();

        match tag {
            SYMBOL_STR => read_and_intern_str_or_byte_str_this(self),
            SYMBOL_OFFSET => {
                // read str offset
                let pos = self.read_usize();

                // move to str offset and read
                self.opaque.with_position(pos, |d| read_and_intern_str_or_byte_str_opaque(d))
            }
            SYMBOL_PREDEFINED => new_from_index(self.read_u32()),
            _ => unreachable!(),
        }
    }
}

impl<'a, 'tcx> TyDecoder<'tcx> for MetadataDecodeContext<'a, 'tcx> {
    const CLEAR_CROSS_CRATE: bool = true;

    #[inline]
    fn interner(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
    where
        F: FnOnce(&mut Self) -> Ty<'tcx>,
    {
        let tcx = self.tcx;

        let key = ty::CReaderCacheKey { cnum: Some(self.cdata.cnum), pos: shorthand };

        if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) {
            return ty;
        }

        let ty = or_insert_with(self);
        tcx.ty_rcache.borrow_mut().insert(key, ty);
        ty
    }

    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
    where
        F: FnOnce(&mut Self) -> R,
    {
        let new_opaque = self.blob_decoder.opaque.split_at(pos);
        let old_opaque = mem::replace(&mut self.blob_decoder.opaque, new_opaque);
        let old_state = mem::replace(&mut self.blob_decoder.lazy_state, LazyState::NoNode);
        let r = f(self);
        self.blob_decoder.opaque = old_opaque;
        self.blob_decoder.lazy_state = old_state;
        r
    }

    fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId {
        let ads = self.alloc_decoding_session;
        ads.decode_alloc_id(self)
    }
}

impl<'a, 'tcx> Decodable<MetadataDecodeContext<'a, 'tcx>> for ExpnIndex {
    #[inline]
    fn decode(d: &mut MetadataDecodeContext<'a, 'tcx>) -> ExpnIndex {
        ExpnIndex::from_u32(d.read_u32())
    }
}

impl<'a, 'tcx> SpanDecoder for MetadataDecodeContext<'a, 'tcx> {
    fn decode_attr_id(&mut self) -> rustc_span::AttrId {
        self.tcx.sess.psess.attr_id_generator.mk_attr_id()
    }

    fn decode_crate_num(&mut self) -> CrateNum {
        let cnum = CrateNum::from_u32(self.read_u32());
        self.map_encoded_cnum_to_current(cnum)
    }

    fn decode_def_id(&mut self) -> DefId {
        DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
    }

    fn decode_syntax_context(&mut self) -> SyntaxContext {
        let cdata = self.cdata;
        let tcx = self.tcx;

        let cname = cdata.root.name();
        rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
            debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
            cdata
                .root
                .syntax_contexts
                .get(cdata, id)
                .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
                .decode((cdata, tcx))
        })
    }

    fn decode_expn_id(&mut self) -> ExpnId {
        let tcx = self.tcx;
        let cnum = CrateNum::decode(self);
        let index = u32::decode(self);

        let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
            let ExpnId { krate: cnum, local_id: index } = expn_id;
            // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
            // are stored in the owning crate, to avoid duplication.
            debug_assert_ne!(cnum, LOCAL_CRATE);
            let cstore;
            let cdata = if cnum == self.cdata.cnum {
                self.cdata
            } else {
                cstore = CStore::from_tcx(tcx);
                cstore.get_crate_data(cnum)
            };
            let expn_data = cdata.root.expn_data.get(cdata, index).unwrap().decode((cdata, tcx));
            let expn_hash = cdata.root.expn_hashes.get(cdata, index).unwrap().decode((cdata, tcx));
            (expn_data, expn_hash)
        });
        expn_id
    }

    fn decode_span(&mut self) -> Span {
        let start = self.position();
        let tag = SpanTag(self.peek_byte());
        let data = if tag.kind() == SpanKind::Indirect {
            // Skip past the tag we just peek'd.
            self.read_u8();
            // indirect tag lengths are safe to access, since they're (0, 8)
            let bytes_needed = tag.length().unwrap().0 as usize;
            let mut total = [0u8; usize::BITS as usize / 8];
            total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
            let offset_or_position = usize::from_le_bytes(total);
            let position = if tag.is_relative_offset() {
                start - offset_or_position
            } else {
                offset_or_position
            };
            self.with_position(position, SpanData::decode)
        } else {
            SpanData::decode(self)
        };
        data.span()
    }
}

impl<'a, 'tcx> BlobDecoder for MetadataDecodeContext<'a, 'tcx> {
    fn decode_def_index(&mut self) -> DefIndex {
        self.blob_decoder.decode_def_index()
    }
    fn decode_symbol(&mut self) -> Symbol {
        self.blob_decoder.decode_symbol()
    }

    fn decode_byte_symbol(&mut self) -> ByteSymbol {
        self.blob_decoder.decode_byte_symbol()
    }
}

impl<'a> BlobDecoder for BlobDecodeContext<'a> {
    fn decode_def_index(&mut self) -> DefIndex {
        DefIndex::from_u32(self.read_u32())
    }
    fn decode_symbol(&mut self) -> Symbol {
        self.decode_symbol_or_byte_symbol(
            Symbol::new,
            |this| Symbol::intern(this.read_str()),
            |opaque| Symbol::intern(opaque.read_str()),
        )
    }

    fn decode_byte_symbol(&mut self) -> ByteSymbol {
        self.decode_symbol_or_byte_symbol(
            ByteSymbol::new,
            |this| ByteSymbol::intern(this.read_byte_str()),
            |opaque| ByteSymbol::intern(opaque.read_byte_str()),
        )
    }
}

impl<'a, 'tcx> Decodable<MetadataDecodeContext<'a, 'tcx>> for SpanData {
    fn decode(decoder: &mut MetadataDecodeContext<'a, 'tcx>) -> SpanData {
        let tag = SpanTag::decode(decoder);
        let ctxt = tag.context().unwrap_or_else(|| SyntaxContext::decode(decoder));

        if tag.kind() == SpanKind::Partial {
            return DUMMY_SP.with_ctxt(ctxt).data();
        }

        debug_assert!(tag.kind() == SpanKind::Local || tag.kind() == SpanKind::Foreign);

        let lo = BytePos::decode(decoder);
        let len = tag.length().unwrap_or_else(|| BytePos::decode(decoder));
        let hi = lo + len;

        let tcx = decoder.tcx;

        // Index of the file in the corresponding crate's list of encoded files.
        let metadata_index = u32::decode(decoder);

        // There are two possibilities here:
        // 1. This is a 'local span', which is located inside a `SourceFile`
        // that came from this crate. In this case, we use the source map data
        // encoded in this crate. This branch should be taken nearly all of the time.
        // 2. This is a 'foreign span', which is located inside a `SourceFile`
        // that came from a *different* crate (some crate upstream of the one
        // whose metadata we're looking at). For example, consider this dependency graph:
        //
        // A -> B -> C
        //
        // Suppose that we're currently compiling crate A, and start deserializing
        // metadata from crate B. When we deserialize a Span from crate B's metadata,
        // there are two possibilities:
        //
        // 1. The span references a file from crate B. This makes it a 'local' span,
        // which means that we can use crate B's serialized source map information.
        // 2. The span references a file from crate C. This makes it a 'foreign' span,
        // which means we need to use Crate *C* (not crate B) to determine the source
        // map information. We only record source map information for a file in the
        // crate that 'owns' it, so deserializing a Span may require us to look at
        // a transitive dependency.
        //
        // When we encode a foreign span, we adjust its 'lo' and 'high' values
        // to be based on the *foreign* crate (e.g. crate C), not the crate
        // we are writing metadata for (e.g. crate B). This allows us to
        // treat the 'local' and 'foreign' cases almost identically during deserialization:
        // we can call `imported_source_file` for the proper crate, and binary search
        // through the returned slice using our span.
        let source_file = if tag.kind() == SpanKind::Local {
            decoder.cdata.imported_source_file(tcx, metadata_index)
        } else {
            // When we encode a proc-macro crate, all `Span`s should be encoded
            // with `TAG_VALID_SPAN_LOCAL`
            if decoder.cdata.root.is_proc_macro_crate() {
                // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
                // since we don't have `cnum_map` populated.
                let cnum = u32::decode(decoder);
                panic!(
                    "Decoding of crate {:?} tried to access proc-macro dep {:?}",
                    decoder.cdata.root.header.name, cnum
                );
            }
            // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
            let cnum = CrateNum::decode(decoder);
            debug!(
                "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
                cnum
            );

            let cstore = CStore::from_tcx(tcx);
            let foreign_cdata = cstore.get_crate_data(cnum);
            foreign_cdata.imported_source_file(tcx, metadata_index)
        };

        // Make sure our span is well-formed.
        debug_assert!(
            lo + source_file.original_start_pos <= source_file.original_end_pos,
            "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
            lo,
            source_file.original_start_pos,
            source_file.original_end_pos
        );

        // Make sure we correctly filtered out invalid spans during encoding.
        debug_assert!(
            hi + source_file.original_start_pos <= source_file.original_end_pos,
            "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
            hi,
            source_file.original_start_pos,
            source_file.original_end_pos
        );

        let lo = lo + source_file.translated_source_file.start_pos;
        let hi = hi + source_file.translated_source_file.start_pos;

        // Do not try to decode parent for foreign spans (it wasn't encoded in the first place).
        SpanData { lo, hi, ctxt, parent: None }
    }
}

impl<'a, 'tcx> Decodable<MetadataDecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
    fn decode(d: &mut MetadataDecodeContext<'a, 'tcx>) -> Self {
        ty::codec::RefDecodable::decode(d)
    }
}

impl<D: LazyDecoder, T> Decodable<D> for LazyValue<T> {
    fn decode(decoder: &mut D) -> Self {
        decoder.read_lazy()
    }
}

impl<D: LazyDecoder, T> Decodable<D> for LazyArray<T> {
    #[inline]
    fn decode(decoder: &mut D) -> Self {
        let len = decoder.read_usize();
        if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) }
    }
}

impl<I: Idx, D: LazyDecoder, T> Decodable<D> for LazyTable<I, T> {
    fn decode(decoder: &mut D) -> Self {
        let width = decoder.read_usize();
        let len = decoder.read_usize();
        decoder.read_lazy_table(width, len)
    }
}

mod meta {
    use super::*;
    implement_ty_decoder!(MetadataDecodeContext<'a, 'tcx>);
}
mod blob {
    use super::*;
    implement_ty_decoder!(BlobDecodeContext<'a>);
}

impl MetadataBlob {
    pub(crate) fn check_compatibility(
        &self,
        cfg_version: &'static str,
    ) -> Result<(), Option<String>> {
        if !self.starts_with(METADATA_HEADER) {
            if self.starts_with(b"rust") {
                return Err(Some("<unknown rustc version>".to_owned()));
            }
            return Err(None);
        }

        let found_version =
            LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
                .decode(self);
        if rustc_version(cfg_version) != found_version {
            return Err(Some(found_version));
        }

        Ok(())
    }

    fn root_pos(&self) -> NonZero<usize> {
        let offset = METADATA_HEADER.len();
        let pos_bytes = self[offset..][..8].try_into().unwrap();
        let pos = u64::from_le_bytes(pos_bytes);
        NonZero::new(pos as usize).unwrap()
    }

    pub(crate) fn get_header(&self) -> CrateHeader {
        let pos = self.root_pos();
        LazyValue::<CrateHeader>::from_position(pos).decode(self)
    }

    pub(crate) fn get_root(&self) -> CrateRoot {
        let pos = self.root_pos();
        LazyValue::<CrateRoot>::from_position(pos).decode(self)
    }

    pub(crate) fn list_crate_metadata(
        &self,
        out: &mut dyn io::Write,
        ls_kinds: &[String],
    ) -> io::Result<()> {
        let root = self.get_root();

        let all_ls_kinds = vec![
            "root".to_owned(),
            "lang_items".to_owned(),
            "features".to_owned(),
            "items".to_owned(),
        ];
        let ls_kinds = if ls_kinds.contains(&"all".to_owned()) { &all_ls_kinds } else { ls_kinds };

        for kind in ls_kinds {
            match &**kind {
                "root" => {
                    writeln!(out, "Crate info:")?;
                    writeln!(out, "name {}{}", root.name(), root.extra_filename)?;
                    writeln!(
                        out,
                        "hash {} stable_crate_id {:?}",
                        root.hash(),
                        root.stable_crate_id
                    )?;
                    writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
                    writeln!(out, "triple {}", root.header.triple.tuple())?;
                    writeln!(out, "edition {}", root.edition)?;
                    writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?;
                    writeln!(
                        out,
                        "required_panic_strategy {:?} panic_in_drop_strategy {:?}",
                        root.required_panic_strategy, root.panic_in_drop_strategy
                    )?;
                    writeln!(
                        out,
                        "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}",
                        root.has_global_allocator,
                        root.has_alloc_error_handler,
                        root.has_panic_handler,
                        root.has_default_lib_allocator
                    )?;
                    writeln!(
                        out,
                        "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}",
                        root.compiler_builtins,
                        root.needs_allocator,
                        root.needs_panic_runtime,
                        root.no_builtins,
                        root.panic_runtime,
                        root.profiler_runtime
                    )?;

                    writeln!(out, "=External Dependencies=")?;
                    let dylib_dependency_formats =
                        root.dylib_dependency_formats.decode(self).collect::<Vec<_>>();
                    for (i, dep) in root.crate_deps.decode(self).enumerate() {
                        let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } =
                            dep;
                        let number = i + 1;

                        writeln!(
                            out,
                            "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}",
                            privacy = if is_private { "private" } else { "public" },
                            linkage = if dylib_dependency_formats.is_empty() {
                                String::new()
                            } else {
                                format!(" linkage {:?}", dylib_dependency_formats[i])
                            }
                        )?;
                    }
                    write!(out, "\n")?;
                }

                "lang_items" => {
                    writeln!(out, "=Lang items=")?;
                    for (id, lang_item) in root.lang_items.decode(self) {
                        writeln!(
                            out,
                            "{} = crate{}",
                            lang_item.name(),
                            DefPath::make(LOCAL_CRATE, id, |parent| root
                                .tables
                                .def_keys
                                .get(self, parent)
                                .unwrap()
                                .decode(self))
                            .to_string_no_crate_verbose()
                        )?;
                    }
                    for lang_item in root.lang_items_missing.decode(self) {
                        writeln!(out, "{} = <missing>", lang_item.name())?;
                    }
                    write!(out, "\n")?;
                }

                "features" => {
                    writeln!(out, "=Lib features=")?;
                    for (feature, since) in root.lib_features.decode(self) {
                        writeln!(
                            out,
                            "{}{}",
                            feature,
                            if let FeatureStability::AcceptedSince(since) = since {
                                format!(" since {since}")
                            } else {
                                String::new()
                            }
                        )?;
                    }
                    write!(out, "\n")?;
                }

                "items" => {
                    writeln!(out, "=Items=")?;

                    fn print_item(
                        blob: &MetadataBlob,
                        out: &mut dyn io::Write,
                        item: DefIndex,
                        indent: usize,
                    ) -> io::Result<()> {
                        let root = blob.get_root();

                        let def_kind = root.tables.def_kind.get(blob, item).unwrap();
                        let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
                        #[allow(rustc::symbol_intern_string_literal)]
                        let def_name = if item == CRATE_DEF_INDEX {
                            kw::Crate
                        } else {
                            def_key
                                .disambiguated_data
                                .data
                                .get_opt_name()
                                .unwrap_or_else(|| Symbol::intern("???"))
                        };
                        let visibility =
                            root.tables.visibility.get(blob, item).unwrap().decode(blob).map_id(
                                |index| {
                                    format!(
                                        "crate{}",
                                        DefPath::make(LOCAL_CRATE, index, |parent| root
                                            .tables
                                            .def_keys
                                            .get(blob, parent)
                                            .unwrap()
                                            .decode(blob))
                                        .to_string_no_crate_verbose()
                                    )
                                },
                            );
                        write!(
                            out,
                            "{nil: <indent$}{:?} {:?} {} {{",
                            visibility,
                            def_kind,
                            def_name,
                            nil = "",
                        )?;

                        if let Some(children) =
                            root.tables.module_children_non_reexports.get(blob, item)
                        {
                            write!(out, "\n")?;
                            for child in children.decode(blob) {
                                print_item(blob, out, child, indent + 4)?;
                            }
                            writeln!(out, "{nil: <indent$}}}", nil = "")?;
                        } else {
                            writeln!(out, "}}")?;
                        }

                        Ok(())
                    }

                    print_item(self, out, CRATE_DEF_INDEX, 0)?;

                    write!(out, "\n")?;
                }

                _ => {
                    writeln!(
                        out,
                        "unknown -Zls kind. allowed values are: all, root, lang_items, features, items"
                    )?;
                }
            }
        }

        Ok(())
    }
}

impl CrateRoot {
    pub(crate) fn is_proc_macro_crate(&self) -> bool {
        self.proc_macro_data.is_some()
    }

    pub(crate) fn name(&self) -> Symbol {
        self.header.name
    }

    pub(crate) fn hash(&self) -> Svh {
        self.header.hash
    }

    pub(crate) fn stable_crate_id(&self) -> StableCrateId {
        self.stable_crate_id
    }

    pub(crate) fn decode_crate_deps<'a>(
        &self,
        metadata: &'a MetadataBlob,
    ) -> impl ExactSizeIterator<Item = CrateDep> {
        self.crate_deps.decode(metadata)
    }

    pub(crate) fn decode_target_modifiers<'a>(
        &self,
        metadata: &'a MetadataBlob,
    ) -> impl ExactSizeIterator<Item = TargetModifier> {
        self.target_modifiers.decode(metadata)
    }

    pub(crate) fn decode_denied_partial_mitigations<'a>(
        &self,
        metadata: &'a MetadataBlob,
    ) -> impl ExactSizeIterator<Item = DeniedPartialMitigation> {
        self.denied_partial_mitigations.decode(metadata)
    }
}

impl CrateMetadata {
    fn missing(&self, descr: &str, id: DefIndex) -> ! {
        bug!("missing `{descr}` for {:?}", self.local_def_id(id))
    }

    fn raw_proc_macro(&self, tcx: TyCtxt<'_>, id: DefIndex) -> &ProcMacro {
        // DefIndex's in root.proc_macro_data have a one-to-one correspondence
        // with items in 'raw_proc_macros'.
        let pos = self
            .root
            .proc_macro_data
            .as_ref()
            .unwrap()
            .macros
            .decode((self, tcx))
            .position(|i| i == id)
            .unwrap();
        &self.raw_proc_macros.unwrap()[pos]
    }

    fn opt_item_name(&self, item_index: DefIndex) -> Option<Symbol> {
        let def_key = self.def_key(item_index);
        def_key.disambiguated_data.data.get_opt_name().or_else(|| {
            if def_key.disambiguated_data.data == DefPathData::Ctor {
                let parent_index = def_key.parent.expect("no parent for a constructor");
                self.def_key(parent_index).disambiguated_data.data.get_opt_name()
            } else {
                None
            }
        })
    }

    fn item_name(&self, item_index: DefIndex) -> Symbol {
        self.opt_item_name(item_index).expect("no encoded ident for item")
    }

    fn opt_item_ident(&self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Option<Ident> {
        let name = self.opt_item_name(item_index)?;
        let span = self
            .root
            .tables
            .def_ident_span
            .get(self, item_index)
            .unwrap_or_else(|| self.missing("def_ident_span", item_index))
            .decode((self, tcx));
        Some(Ident::new(name, span))
    }

    fn item_ident(&self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Ident {
        self.opt_item_ident(tcx, item_index).expect("no encoded ident for item")
    }

    #[inline]
    pub(super) fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
        if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] }
    }

    fn def_kind(&self, item_id: DefIndex) -> DefKind {
        self.root
            .tables
            .def_kind
            .get(self, item_id)
            .unwrap_or_else(|| self.missing("def_kind", item_id))
    }

    fn get_span(&self, tcx: TyCtxt<'_>, index: DefIndex) -> Span {
        self.root
            .tables
            .def_span
            .get(self, index)
            .unwrap_or_else(|| self.missing("def_span", index))
            .decode((self, tcx))
    }

    fn load_proc_macro<'tcx>(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> SyntaxExtension {
        let (name, kind, helper_attrs) = match *self.raw_proc_macro(tcx, id) {
            ProcMacro::CustomDerive { trait_name, attributes, client } => {
                let helper_attrs =
                    attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
                (
                    trait_name,
                    SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })),
                    helper_attrs,
                )
            }
            ProcMacro::Attr { name, client } => {
                (name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new())
            }
            ProcMacro::Bang { name, client } => {
                (name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new())
            }
        };

        let sess = tcx.sess;
        let attrs: Vec<_> = self.get_item_attrs(tcx, id).collect();
        SyntaxExtension::new(
            sess,
            kind,
            self.get_span(tcx, id),
            helper_attrs,
            self.root.edition,
            Symbol::intern(name),
            &attrs,
            false,
        )
    }

    fn get_variant(
        &self,
        tcx: TyCtxt<'_>,
        kind: DefKind,
        index: DefIndex,
        parent_did: DefId,
    ) -> (VariantIdx, ty::VariantDef) {
        let adt_kind = match kind {
            DefKind::Variant => ty::AdtKind::Enum,
            DefKind::Struct => ty::AdtKind::Struct,
            DefKind::Union => ty::AdtKind::Union,
            _ => bug!(),
        };

        let data = self.root.tables.variant_data.get(self, index).unwrap().decode((self, tcx));

        let variant_did =
            if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
        let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));

        (
            data.idx,
            ty::VariantDef::new(
                self.item_name(index),
                variant_did,
                ctor,
                data.discr,
                self.get_associated_item_or_field_def_ids(tcx, index)
                    .map(|did| ty::FieldDef {
                        did,
                        name: self.item_name(did.index),
                        vis: self.get_visibility(tcx, did.index),
                        safety: self.get_safety(did.index),
                        value: self.get_default_field(tcx, did.index),
                    })
                    .collect(),
                parent_did,
                None,
                data.is_non_exhaustive,
            ),
        )
    }

    fn get_adt_def<'tcx>(&self, tcx: TyCtxt<'tcx>, item_id: DefIndex) -> ty::AdtDef<'tcx> {
        let kind = self.def_kind(item_id);
        let did = self.local_def_id(item_id);

        let adt_kind = match kind {
            DefKind::Enum => ty::AdtKind::Enum,
            DefKind::Struct => ty::AdtKind::Struct,
            DefKind::Union => ty::AdtKind::Union,
            _ => bug!("get_adt_def called on a non-ADT {:?}", did),
        };
        let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode((self, tcx));

        let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind {
            self.root
                .tables
                .module_children_non_reexports
                .get(self, item_id)
                .expect("variants are not encoded for an enum")
                .decode((self, tcx))
                .filter_map(|index| {
                    let kind = self.def_kind(index);
                    match kind {
                        DefKind::Ctor(..) => None,
                        _ => Some(self.get_variant(tcx, kind, index, did)),
                    }
                })
                .collect()
        } else {
            std::iter::once(self.get_variant(tcx, kind, item_id, did)).collect()
        };

        variants.sort_by_key(|(idx, _)| *idx);

        tcx.mk_adt_def(
            did,
            adt_kind,
            variants.into_iter().map(|(_, variant)| variant).collect(),
            repr,
        )
    }

    fn get_visibility(&self, tcx: TyCtxt<'_>, id: DefIndex) -> Visibility<DefId> {
        self.root
            .tables
            .visibility
            .get(self, id)
            .unwrap_or_else(|| self.missing("visibility", id))
            .decode((self, tcx))
            .map_id(|index| self.local_def_id(index))
    }

    fn get_safety(&self, id: DefIndex) -> Safety {
        self.root.tables.safety.get(self, id)
    }

    fn get_default_field(&self, tcx: TyCtxt<'_>, id: DefIndex) -> Option<DefId> {
        self.root.tables.default_fields.get(self, id).map(|d| d.decode((self, tcx)))
    }

    fn get_expn_that_defined(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ExpnId {
        self.root
            .tables
            .expn_that_defined
            .get(self, id)
            .unwrap_or_else(|| self.missing("expn_that_defined", id))
            .decode((self, tcx))
    }

    fn get_debugger_visualizers(&self, tcx: TyCtxt<'_>) -> Vec<DebuggerVisualizerFile> {
        self.root.debugger_visualizers.decode((self, tcx)).collect::<Vec<_>>()
    }

    /// Iterates over all the stability attributes in the given crate.
    fn get_lib_features(&self, tcx: TyCtxt<'_>) -> LibFeatures {
        LibFeatures {
            stability: self
                .root
                .lib_features
                .decode((self, tcx))
                .map(|(sym, stab)| (sym, (stab, DUMMY_SP)))
                .collect(),
        }
    }

    /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
    /// has an `implied_by` meta item, then the mapping from the implied feature to the actual
    /// feature is a stability implication).
    fn get_stability_implications<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
        tcx.arena.alloc_from_iter(self.root.stability_implications.decode((self, tcx)))
    }

    /// Iterates over the lang items in the given crate.
    fn get_lang_items<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
        tcx.arena.alloc_from_iter(
            self.root
                .lang_items
                .decode((self, tcx))
                .map(move |(def_index, index)| (self.local_def_id(def_index), index)),
        )
    }

    fn get_stripped_cfg_items<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        cnum: CrateNum,
    ) -> &'tcx [StrippedCfgItem] {
        let item_names = self
            .root
            .stripped_cfg_items
            .decode((self, tcx))
            .map(|item| item.map_scope_id(|index| DefId { krate: cnum, index }));
        tcx.arena.alloc_from_iter(item_names)
    }

    /// Iterates over the diagnostic items in the given crate.
    fn get_diagnostic_items(&self, tcx: TyCtxt<'_>) -> DiagnosticItems {
        let mut id_to_name = DefIdMap::default();
        let name_to_id = self
            .root
            .diagnostic_items
            .decode((self, tcx))
            .map(|(name, def_index)| {
                let id = self.local_def_id(def_index);
                id_to_name.insert(id, name);
                (name, id)
            })
            .collect();
        DiagnosticItems { id_to_name, name_to_id }
    }

    fn get_mod_child(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ModChild {
        let ident = self.item_ident(tcx, id);
        let res = Res::Def(self.def_kind(id), self.local_def_id(id));
        let vis = self.get_visibility(tcx, id);

        ModChild { ident, res, vis, reexport_chain: Default::default() }
    }

    /// Iterates over all named children of the given module,
    /// including both proper items and reexports.
    /// Module here is understood in name resolution sense - it can be a `mod` item,
    /// or a crate root, or an enum, or a trait.
    fn get_module_children(&self, tcx: TyCtxt<'_>, id: DefIndex) -> impl Iterator<Item = ModChild> {
        gen move {
            if let Some(data) = &self.root.proc_macro_data {
                // If we are loading as a proc macro, we want to return
                // the view of this crate as a proc macro crate.
                if id == CRATE_DEF_INDEX {
                    for child_index in data.macros.decode((self, tcx)) {
                        yield self.get_mod_child(tcx, child_index);
                    }
                }
            } else {
                // Iterate over all children.
                let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
                for child_index in non_reexports.unwrap().decode((self, tcx)) {
                    yield self.get_mod_child(tcx, child_index);
                }

                let reexports = self.root.tables.module_children_reexports.get(self, id);
                if !reexports.is_default() {
                    for reexport in reexports.decode((self, tcx)) {
                        yield reexport;
                    }
                }
            }
        }
    }

    fn get_ambig_module_children(
        &self,
        tcx: TyCtxt<'_>,
        id: DefIndex,
    ) -> impl Iterator<Item = AmbigModChild> {
        gen move {
            let children = self.root.tables.ambig_module_children.get(self, id);
            if !children.is_default() {
                for child in children.decode((self, tcx)) {
                    yield child;
                }
            }
        }
    }

    fn is_item_mir_available(&self, id: DefIndex) -> bool {
        self.root.tables.optimized_mir.get(self, id).is_some()
    }

    fn get_fn_has_self_parameter(&self, tcx: TyCtxt<'_>, id: DefIndex) -> bool {
        self.root
            .tables
            .fn_arg_idents
            .get(self, id)
            .expect("argument names not encoded for a function")
            .decode((self, tcx))
            .nth(0)
            .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
    }

    fn get_associated_item_or_field_def_ids(
        &self,
        tcx: TyCtxt<'_>,
        id: DefIndex,
    ) -> impl Iterator<Item = DefId> {
        self.root
            .tables
            .associated_item_or_field_def_ids
            .get(self, id)
            .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id))
            .decode((self, tcx))
            .map(move |child_index| self.local_def_id(child_index))
    }

    fn get_associated_item(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ty::AssocItem {
        let kind = match self.def_kind(id) {
            DefKind::AssocConst { is_type_const } => {
                ty::AssocKind::Const { name: self.item_name(id), is_type_const }
            }
            DefKind::AssocFn => ty::AssocKind::Fn {
                name: self.item_name(id),
                has_self: self.get_fn_has_self_parameter(tcx, id),
            },
            DefKind::AssocTy => {
                let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id)
                {
                    ty::AssocTypeData::Rpitit(rpitit_info.decode((self, tcx)))
                } else {
                    ty::AssocTypeData::Normal(self.item_name(id))
                };
                ty::AssocKind::Type { data }
            }
            _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
        };
        let container = self.root.tables.assoc_container.get(self, id).unwrap().decode((self, tcx));

        ty::AssocItem { kind, def_id: self.local_def_id(id), container }
    }

    fn get_ctor(&self, tcx: TyCtxt<'_>, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
        match self.def_kind(node_id) {
            DefKind::Struct | DefKind::Variant => {
                let vdata =
                    self.root.tables.variant_data.get(self, node_id).unwrap().decode((self, tcx));
                vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index)))
            }
            _ => None,
        }
    }

    fn get_item_attrs(
        &self,
        tcx: TyCtxt<'_>,
        id: DefIndex,
    ) -> impl Iterator<Item = hir::Attribute> {
        self.root
            .tables
            .attributes
            .get(self, id)
            .unwrap_or_else(|| {
                // Structure and variant constructors don't have any attributes encoded for them,
                // but we assume that someone passing a constructor ID actually wants to look at
                // the attributes on the corresponding struct or variant.
                let def_key = self.def_key(id);
                assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
                let parent_id = def_key.parent.expect("no parent for a constructor");
                self.root
                    .tables
                    .attributes
                    .get(self, parent_id)
                    .expect("no encoded attributes for a structure or variant")
            })
            .decode((self, tcx))
    }

    fn get_inherent_implementations_for_type<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        id: DefIndex,
    ) -> &'tcx [DefId] {
        tcx.arena.alloc_from_iter(
            self.root
                .tables
                .inherent_impls
                .get(self, id)
                .decode((self, tcx))
                .map(|index| self.local_def_id(index)),
        )
    }

    /// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
    fn get_traits(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
        self.root.traits.decode((self, tcx)).map(move |index| self.local_def_id(index))
    }

    /// Decodes all trait impls in the crate (for rustdoc).
    fn get_trait_impls(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
        self.trait_impls.values().flat_map(move |impls| {
            impls.decode((self, tcx)).map(move |(impl_index, _)| self.local_def_id(impl_index))
        })
    }

    fn get_incoherent_impls<'tcx>(&self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
        if let Some(impls) = self.incoherent_impls.get(&simp) {
            tcx.arena.alloc_from_iter(impls.decode((self, tcx)).map(|idx| self.local_def_id(idx)))
        } else {
            &[]
        }
    }

    fn get_implementations_of_trait<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        trait_def_id: DefId,
    ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
        if self.trait_impls.is_empty() {
            return &[];
        }

        // Do a reverse lookup beforehand to avoid touching the crate_num
        // hash map in the loop below.
        let key = match self.reverse_translate_def_id(trait_def_id) {
            Some(def_id) => (def_id.krate.as_u32(), def_id.index),
            None => return &[],
        };

        if let Some(impls) = self.trait_impls.get(&key) {
            tcx.arena.alloc_from_iter(
                impls
                    .decode((self, tcx))
                    .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)),
            )
        } else {
            &[]
        }
    }

    fn get_native_libraries(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = NativeLib> {
        self.root.native_libraries.decode((self, tcx))
    }

    fn get_proc_macro_quoted_span(&self, tcx: TyCtxt<'_>, index: usize) -> Span {
        self.root
            .tables
            .proc_macro_quoted_spans
            .get(self, index)
            .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
            .decode((self, tcx))
    }

    fn get_foreign_modules(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = ForeignModule> {
        self.root.foreign_modules.decode((self, tcx))
    }

    fn get_dylib_dependency_formats<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
    ) -> &'tcx [(CrateNum, LinkagePreference)] {
        tcx.arena.alloc_from_iter(
            self.root.dylib_dependency_formats.decode((self, tcx)).enumerate().flat_map(
                |(i, link)| {
                    let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding
                    link.map(|link| (self.cnum_map[cnum], link))
                },
            ),
        )
    }

    fn get_externally_implementable_items(
        &self,
        tcx: TyCtxt<'_>,
    ) -> impl Iterator<Item = EiiMapEncodedKeyValue> {
        self.root.externally_implementable_items.decode((self, tcx))
    }

    fn get_missing_lang_items<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
        tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode((self, tcx)))
    }

    fn get_exportable_items(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
        self.root.exportable_items.decode((self, tcx)).map(move |index| self.local_def_id(index))
    }

    fn get_stable_order_of_exportable_impls(
        &self,
        tcx: TyCtxt<'_>,
    ) -> impl Iterator<Item = (DefId, usize)> {
        self.root
            .stable_order_of_exportable_impls
            .decode((self, tcx))
            .map(move |v| (self.local_def_id(v.0), v.1))
    }

    fn exported_non_generic_symbols<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
    ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
        tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx)))
    }

    fn exported_generic_symbols<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
    ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
        tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx)))
    }

    fn get_macro(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ast::MacroDef {
        match self.def_kind(id) {
            DefKind::Macro(_) => {
                let macro_rules = self.root.tables.is_macro_rules.get(self, id);
                let body =
                    self.root.tables.macro_definition.get(self, id).unwrap().decode((self, tcx));
                ast::MacroDef { macro_rules, body: Box::new(body), eii_declaration: None }
            }
            _ => bug!(),
        }
    }

    #[inline]
    fn def_key(&self, index: DefIndex) -> DefKey {
        *self.def_key_cache.lock().entry(index).or_insert_with(|| {
            self.root.tables.def_keys.get(&self.blob, index).unwrap().decode(&self.blob)
        })
    }

    // Returns the path leading to the thing with this `id`.
    fn def_path(&self, id: DefIndex) -> DefPath {
        debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
    }

    #[inline]
    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
        // This is a hack to workaround the fact that we can't easily encode/decode a Hash64
        // into the FixedSizeEncoding, as Hash64 lacks a Default impl. A future refactor to
        // relax the Default restriction will likely fix this.
        let fingerprint = Fingerprint::new(
            self.root.stable_crate_id.as_u64(),
            self.root.tables.def_path_hashes.get(&self.blob, index),
        );
        DefPathHash::new(self.root.stable_crate_id, fingerprint.split().1)
    }

    #[inline]
    fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> Option<DefIndex> {
        self.def_path_hash_map.def_path_hash_to_def_index(&hash)
    }

    fn expn_hash_to_expn_id(&self, tcx: TyCtxt<'_>, index_guess: u32, hash: ExpnHash) -> ExpnId {
        let index_guess = ExpnIndex::from_u32(index_guess);
        let old_hash =
            self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode((self, tcx)));

        let index = if old_hash == Some(hash) {
            // Fast path: the expn and its index is unchanged from the
            // previous compilation session. There is no need to decode anything
            // else.
            index_guess
        } else {
            // Slow path: We need to find out the new `DefIndex` of the provided
            // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
            // stored in this crate.
            let map = self.expn_hash_map.get_or_init(|| {
                let end_id = self.root.expn_hashes.size() as u32;
                let mut map =
                    UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
                for i in 0..end_id {
                    let i = ExpnIndex::from_u32(i);
                    if let Some(hash) = self.root.expn_hashes.get(self, i) {
                        map.insert(hash.decode((self, tcx)), i);
                    }
                }
                map
            });
            map[&hash]
        };

        let data = self.root.expn_data.get(self, index).unwrap().decode((self, tcx));
        rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
    }

    /// Imports the source_map from an external crate into the source_map of the crate
    /// currently being compiled (the "local crate").
    ///
    /// The import algorithm works analogous to how AST items are inlined from an
    /// external crate's metadata:
    /// For every SourceFile in the external source_map an 'inline' copy is created in the
    /// local source_map. The correspondence relation between external and local
    /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this
    /// function. When an item from an external crate is later inlined into this
    /// crate, this correspondence information is used to translate the span
    /// information of the inlined item so that it refers the correct positions in
    /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
    ///
    /// The import algorithm in the function below will reuse SourceFiles already
    /// existing in the local source_map. For example, even if the SourceFile of some
    /// source file of libstd gets imported many times, there will only ever be
    /// one SourceFile object for the corresponding file in the local source_map.
    ///
    /// Note that imported SourceFiles do not actually contain the source code of the
    /// file they represent, just information about length, line breaks, and
    /// multibyte characters. This information is enough to generate valid debuginfo
    /// for items inlined from other crates.
    ///
    /// Proc macro crates don't currently export spans, so this function does not have
    /// to work for them.
    fn imported_source_file(&self, tcx: TyCtxt<'_>, source_file_index: u32) -> ImportedSourceFile {
        fn filter<'a>(
            tcx: TyCtxt<'_>,
            real_source_base_dir: &Option<PathBuf>,
            path: Option<&'a Path>,
        ) -> Option<&'a Path> {
            path.filter(|_| {
                // Only spend time on further checks if we have what to translate *to*.
                real_source_base_dir.is_some()
                // Some tests need the translation to be always skipped.
                && tcx.sess.opts.unstable_opts.translate_remapped_path_to_local_path
            })
            .filter(|virtual_dir| {
                // Don't translate away `/rustc/$hash` if we're still remapping to it,
                // since that means we're still building `std`/`rustc` that need it,
                // and we don't want the real path to leak into codegen/debuginfo.
                !tcx.sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
            })
        }

        let try_to_translate_virtual_to_real =
            |virtual_source_base_dir: Option<&str>,
             real_source_base_dir: &Option<PathBuf>,
             name: &mut rustc_span::FileName| {
                let virtual_source_base_dir = [
                    filter(tcx, real_source_base_dir, virtual_source_base_dir.map(Path::new)),
                    filter(
                        tcx,
                        real_source_base_dir,
                        tcx.sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
                    ),
                ];

                debug!(
                    "try_to_translate_virtual_to_real(name={:?}): \
                     virtual_source_base_dir={:?}, real_source_base_dir={:?}",
                    name, virtual_source_base_dir, real_source_base_dir,
                );

                for virtual_dir in virtual_source_base_dir.iter().flatten() {
                    if let Some(real_dir) = &real_source_base_dir
                        && let rustc_span::FileName::Real(old_name) = name
                        && let virtual_path = old_name.path(RemapPathScopeComponents::MACRO)
                        && let Ok(rest) = virtual_path.strip_prefix(virtual_dir)
                    {
                        let new_path = real_dir.join(rest);

                        debug!(
                            "try_to_translate_virtual_to_real: `{}` -> `{}`",
                            virtual_path.display(),
                            new_path.display(),
                        );

                        // Check if the translated real path is affected by any user-requested
                        // remaps via --remap-path-prefix. Apply them if so.
                        // Note that this is a special case for imported rust-src paths specified by
                        // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
                        // Other imported paths are not currently remapped (see #66251).
                        *name = rustc_span::FileName::Real(
                            tcx.sess
                                .source_map()
                                .path_mapping()
                                .to_real_filename(&rustc_span::RealFileName::empty(), new_path),
                        );
                    }
                }
            };

        let try_to_translate_real_to_virtual =
            |virtual_source_base_dir: Option<&str>,
             real_source_base_dir: &Option<PathBuf>,
             subdir: &str,
             name: &mut rustc_span::FileName| {
                if let Some(virtual_dir) =
                    &tcx.sess.opts.unstable_opts.simulate_remapped_rust_src_base
                    && let Some(real_dir) = real_source_base_dir
                    && let rustc_span::FileName::Real(old_name) = name
                {
                    let (_working_dir, embeddable_path) =
                        old_name.embeddable_name(RemapPathScopeComponents::MACRO);
                    let relative_path = embeddable_path.strip_prefix(real_dir).ok().or_else(|| {
                        virtual_source_base_dir
                            .and_then(|virtual_dir| embeddable_path.strip_prefix(virtual_dir).ok())
                    });
                    debug!(
                        ?relative_path,
                        ?virtual_dir,
                        ?subdir,
                        "simulate_remapped_rust_src_base"
                    );
                    if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
                        *name =
                            rustc_span::FileName::Real(rustc_span::RealFileName::from_virtual_path(
                                &virtual_dir.join(subdir).join(rest),
                            ))
                    }
                }
            };

        let mut import_info = self.source_map_import_info.lock();
        for _ in import_info.len()..=(source_file_index as usize) {
            import_info.push(None);
        }
        import_info[source_file_index as usize]
            .get_or_insert_with(|| {
                let source_file_to_import = self
                    .root
                    .source_map
                    .get(self, source_file_index)
                    .expect("missing source file")
                    .decode((self, tcx));

                // We can't reuse an existing SourceFile, so allocate a new one
                // containing the information we need.
                let original_end_pos = source_file_to_import.end_position();
                let rustc_span::SourceFile {
                    mut name,
                    src_hash,
                    checksum_hash,
                    start_pos: original_start_pos,
                    normalized_source_len,
                    unnormalized_source_len,
                    lines,
                    multibyte_chars,
                    normalized_pos,
                    stable_id,
                    ..
                } = source_file_to_import;

                // If this file is under $sysroot/lib/rustlib/src/
                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
                // then we change `name` to a similar state as if the rust was bootstrapped
                // with `remap-debuginfo = true`.
                // This is useful for testing so that tests about the effects of
                // `try_to_translate_virtual_to_real` don't have to worry about how the
                // compiler is bootstrapped.
                try_to_translate_real_to_virtual(
                    option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
                    &tcx.sess.opts.real_rust_source_base_dir,
                    "library",
                    &mut name,
                );

                // If this file is under $sysroot/lib/rustlib/rustc-src/
                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
                // then we change `name` to a similar state as if the rust was bootstrapped
                // with `remap-debuginfo = true`.
                try_to_translate_real_to_virtual(
                    option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
                    &tcx.sess.opts.real_rustc_dev_source_base_dir,
                    "compiler",
                    &mut name,
                );

                // If this file's path has been remapped to `/rustc/$hash`,
                // we might be able to reverse that.
                //
                // NOTE: if you update this, you might need to also update bootstrap's code for generating
                // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
                try_to_translate_virtual_to_real(
                    option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
                    &tcx.sess.opts.real_rust_source_base_dir,
                    &mut name,
                );

                // If this file's path has been remapped to `/rustc-dev/$hash`,
                // we might be able to reverse that.
                //
                // NOTE: if you update this, you might need to also update bootstrap's code for generating
                // the `rustc-dev` component in `Src::run` in `src/bootstrap/dist.rs`.
                try_to_translate_virtual_to_real(
                    option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
                    &tcx.sess.opts.real_rustc_dev_source_base_dir,
                    &mut name,
                );

                let local_version = tcx.sess.source_map().new_imported_source_file(
                    name,
                    src_hash,
                    checksum_hash,
                    stable_id,
                    normalized_source_len.to_u32(),
                    unnormalized_source_len,
                    self.cnum,
                    lines,
                    multibyte_chars,
                    normalized_pos,
                    source_file_index,
                );
                debug!(
                    "CrateMetaData::imported_source_files alloc \
                         source_file {:?} original (start_pos {:?} source_len {:?}) \
                         translated (start_pos {:?} source_len {:?})",
                    local_version.name,
                    original_start_pos,
                    normalized_source_len,
                    local_version.start_pos,
                    local_version.normalized_source_len
                );

                ImportedSourceFile {
                    original_start_pos,
                    original_end_pos,
                    translated_source_file: local_version,
                }
            })
            .clone()
    }

    fn get_attr_flags(&self, index: DefIndex) -> AttrFlags {
        self.root.tables.attr_flags.get(self, index)
    }

    fn get_intrinsic(&self, tcx: TyCtxt<'_>, index: DefIndex) -> Option<ty::IntrinsicDef> {
        self.root.tables.intrinsic.get(self, index).map(|d| d.decode((self, tcx)))
    }

    fn get_doc_link_resolutions(&self, tcx: TyCtxt<'_>, index: DefIndex) -> DocLinkResMap {
        self.root
            .tables
            .doc_link_resolutions
            .get(self, index)
            .expect("no resolutions for a doc link")
            .decode((self, tcx))
    }

    fn get_doc_link_traits_in_scope(
        &self,
        tcx: TyCtxt<'_>,
        index: DefIndex,
    ) -> impl Iterator<Item = DefId> {
        self.root
            .tables
            .doc_link_traits_in_scope
            .get(self, index)
            .expect("no traits in scope for a doc link")
            .decode((self, tcx))
    }
}

impl CrateMetadata {
    pub(crate) fn new(
        tcx: TyCtxt<'_>,
        blob: MetadataBlob,
        root: CrateRoot,
        raw_proc_macros: Option<&'static [ProcMacro]>,
        cnum: CrateNum,
        cnum_map: CrateNumMap,
        dep_kind: CrateDepKind,
        source: CrateSource,
        private_dep: bool,
        host_hash: Option<Svh>,
    ) -> CrateMetadata {
        let trait_impls = root
            .impls
            .decode(&blob)
            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
            .collect();
        let alloc_decoding_state =
            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());

        // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation
        // that does not copy any data. It just does some data verification.
        let def_path_hash_map = root.def_path_hash_map.decode(&blob);

        let mut cdata = CrateMetadata {
            blob,
            root,
            trait_impls,
            incoherent_impls: Default::default(),
            raw_proc_macros,
            source_map_import_info: Lock::new(Vec::new()),
            def_path_hash_map,
            expn_hash_map: Default::default(),
            alloc_decoding_state,
            cnum,
            cnum_map,
            dep_kind,
            source: Arc::new(source),
            private_dep,
            host_hash,
            used: false,
            extern_crate: None,
            hygiene_context: Default::default(),
            def_key_cache: Default::default(),
        };

        cdata.incoherent_impls = cdata
            .root
            .incoherent_impls
            .decode((&cdata, tcx))
            .map(|incoherent_impls| {
                (incoherent_impls.self_ty.decode((&cdata, tcx)), incoherent_impls.impls)
            })
            .collect();

        cdata
    }

    pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> {
        self.cnum_map.iter().copied()
    }

    pub(crate) fn target_modifiers(&self) -> TargetModifiers {
        self.root.decode_target_modifiers(&self.blob).collect()
    }

    pub(crate) fn enabled_denied_partial_mitigations(&self) -> DeniedPartialMitigations {
        self.root.decode_denied_partial_mitigations(&self.blob).collect()
    }

    /// Keep `new_extern_crate` if it looks better in diagnostics
    pub(crate) fn update_extern_crate_diagnostics(
        &mut self,
        new_extern_crate: ExternCrate,
    ) -> bool {
        let update =
            self.extern_crate.as_ref().is_none_or(|old| old.rank() < new_extern_crate.rank());
        if update {
            self.extern_crate = Some(new_extern_crate);
        }
        update
    }

    pub(crate) fn source(&self) -> &CrateSource {
        &*self.source
    }

    pub(crate) fn dep_kind(&self) -> CrateDepKind {
        self.dep_kind
    }

    pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) {
        self.dep_kind = dep_kind;
    }

    pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) {
        self.private_dep &= private_dep;
    }

    pub(crate) fn used(&self) -> bool {
        self.used
    }

    pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
        self.root.required_panic_strategy
    }

    pub(crate) fn needs_panic_runtime(&self) -> bool {
        self.root.needs_panic_runtime
    }

    pub(crate) fn is_private_dep(&self) -> bool {
        self.private_dep
    }

    pub(crate) fn is_panic_runtime(&self) -> bool {
        self.root.panic_runtime
    }

    pub(crate) fn is_profiler_runtime(&self) -> bool {
        self.root.profiler_runtime
    }

    pub(crate) fn is_compiler_builtins(&self) -> bool {
        self.root.compiler_builtins
    }

    pub(crate) fn needs_allocator(&self) -> bool {
        self.root.needs_allocator
    }

    pub(crate) fn has_global_allocator(&self) -> bool {
        self.root.has_global_allocator
    }

    pub(crate) fn has_alloc_error_handler(&self) -> bool {
        self.root.has_alloc_error_handler
    }

    pub(crate) fn has_default_lib_allocator(&self) -> bool {
        self.root.has_default_lib_allocator
    }

    pub(crate) fn is_proc_macro_crate(&self) -> bool {
        self.root.is_proc_macro_crate()
    }

    pub(crate) fn proc_macros_for_crate(
        &self,
        tcx: TyCtxt<'_>,
        krate: CrateNum,
    ) -> impl Iterator<Item = DefId> {
        gen move {
            for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| {
                data.macros.decode((self, tcx)).map(move |index| DefId { index, krate })
            }) {
                yield def_id;
            }
        }
    }

    pub(crate) fn name(&self) -> Symbol {
        self.root.header.name
    }

    pub(crate) fn hash(&self) -> Svh {
        self.root.header.hash
    }

    pub(crate) fn has_async_drops(&self) -> bool {
        self.root.tables.adt_async_destructor.len > 0
    }

    fn num_def_ids(&self) -> usize {
        self.root.tables.def_keys.size()
    }

    fn local_def_id(&self, index: DefIndex) -> DefId {
        DefId { krate: self.cnum, index }
    }

    // Translate a DefId from the current compilation environment to a DefId
    // for an external crate.
    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
        for (local, &global) in self.cnum_map.iter_enumerated() {
            if global == did.krate {
                return Some(DefId { krate: local, index: did.index });
            }
        }

        None
    }
}
