//! Source positions and related helper functions.
//!
//! Important concepts in this module include:
//!
//! - the *span*, represented by [`SpanData`] and related types;
//! - source code as represented by a [`SourceMap`]; and
//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically
//!   in the [`sym`] module.
//!
//! Unlike most compilers, the span contains not only the position in the source code, but also
//! various other metadata, such as the edition and macro hygiene. This metadata is stored in
//! [`SyntaxContext`] and [`ExpnData`].
//!
//! ## Note
//!
//! This API is completely unstable and subject to change.

// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(target_arch = "loongarch64", feature(stdarch_loongarch))]
#![feature(core_io_borrowed_buf)]
#![feature(map_try_insert)]
#![feature(negative_impls)]
#![feature(read_buf)]
#![feature(rustc_attrs)]
// tidy-alphabetical-end

// The code produced by the `Encodable`/`Decodable` derive macros refer to
// `rustc_span::Span{Encoder,Decoder}`. That's fine outside this crate, but doesn't work inside
// this crate without this line making `rustc_span` available.
extern crate self as rustc_span;

use derive_where::derive_where;
use rustc_data_structures::stable_hash::StableHashCtxt;
use rustc_data_structures::{AtomicRef, outline};
use rustc_macros::{Decodable, Encodable, StableHash};
use rustc_serialize::opaque::mem_encoder::MemEncoder;
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use tracing::debug;
pub use unicode_width::UNICODE_VERSION;

mod caching_source_map_view;
pub mod source_map;
use source_map::{SourceMap, SourceMapInputs};

pub use self::caching_source_map_view::CachingSourceMapView;
use crate::fatal_error::FatalError;

pub mod edition;
use edition::Edition;
pub mod hygiene;
use hygiene::Transparency;
pub use hygiene::{
    DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext,
};
pub mod def_id;
use def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
pub mod edit_distance;
mod span_encoding;
pub use span_encoding::{DUMMY_SP, Span};

pub mod symbol;
pub use symbol::{
    ByteSymbol, Ident, MacroRulesNormalizedIdent, STDLIB_STABLE_CRATES, Symbol, kw, sym,
};

mod analyze_source_file;
pub mod fatal_error;

pub mod profiling;

use std::borrow::Cow;
use std::cmp::{self, Ordering};
use std::fmt::Display;
use std::hash::Hash;
use std::io::{self, Read};
use std::ops::{Add, Range, Sub};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
use std::{fmt, iter};

use md5::{Digest, Md5};
use rustc_data_structures::stable_hash::{StableHash, StableHasher};
use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock};
use rustc_data_structures::unord::UnordMap;
use rustc_hashes::{Hash64, Hash128};
use sha1::Sha1;
use sha2::Sha256;

#[cfg(test)]
mod tests;

#[derive(Clone, Encodable, Decodable, Debug, Copy, PartialEq, Hash, StableHash)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

pub fn respan<T>(sp: Span, t: T) -> Spanned<T> {
    Spanned { node: t, span: sp }
}

pub fn dummy_spanned<T>(t: T) -> Spanned<T> {
    respan(DUMMY_SP, t)
}

/// Per-session global variables: this struct is stored in thread-local storage
/// in such a way that it is accessible without any kind of handle to all
/// threads within the compilation session, but is not accessible outside the
/// session.
pub struct SessionGlobals {
    symbol_interner: symbol::Interner,
    span_interner: Lock<span_encoding::SpanInterner>,
    /// Maps a macro argument token into use of the corresponding metavariable in the macro body.
    /// Collisions are possible and processed in `maybe_use_metavar_location` on best effort basis.
    metavar_spans: MetavarSpansMap,
    hygiene_data: Lock<hygiene::HygieneData>,

    /// The session's source map, if there is one. This field should only be
    /// used in places where the `Session` is truly not available, such as
    /// `<Span as Debug>::fmt`.
    source_map: Option<Arc<SourceMap>>,
}

impl SessionGlobals {
    pub fn new(
        edition: Edition,
        extra_symbols: &[&'static str],
        sm_inputs: Option<SourceMapInputs>,
    ) -> SessionGlobals {
        SessionGlobals {
            symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols),
            span_interner: Lock::new(span_encoding::SpanInterner::default()),
            metavar_spans: Default::default(),
            hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
            source_map: sm_inputs.map(|inputs| Arc::new(SourceMap::with_inputs(inputs))),
        }
    }
}

pub fn create_session_globals_then<R>(
    edition: Edition,
    extra_symbols: &[&'static str],
    sm_inputs: Option<SourceMapInputs>,
    f: impl FnOnce() -> R,
) -> R {
    assert!(
        !SESSION_GLOBALS.is_set(),
        "SESSION_GLOBALS should never be overwritten! \
         Use another thread if you need another SessionGlobals"
    );
    let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs);
    SESSION_GLOBALS.set(&session_globals, f)
}

pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
    assert!(
        !SESSION_GLOBALS.is_set(),
        "SESSION_GLOBALS should never be overwritten! \
         Use another thread if you need another SessionGlobals"
    );
    SESSION_GLOBALS.set(session_globals, f)
}

/// No source map.
pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
where
    F: FnOnce(&SessionGlobals) -> R,
{
    if !SESSION_GLOBALS.is_set() {
        let session_globals = SessionGlobals::new(edition, &[], None);
        SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
    } else {
        SESSION_GLOBALS.with(f)
    }
}

#[inline]
pub fn with_session_globals<R, F>(f: F) -> R
where
    F: FnOnce(&SessionGlobals) -> R,
{
    SESSION_GLOBALS.with(f)
}

/// Default edition, no source map.
pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
    create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f)
}

// If this ever becomes non thread-local, `decode_syntax_context`
// and `decode_expn_id` will need to be updated to handle concurrent
// deserialization.
scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);

#[derive(Default)]
pub struct MetavarSpansMap(FreezeLock<UnordMap<Span, (Span, bool)>>);

impl MetavarSpansMap {
    pub fn insert(&self, span: Span, var_span: Span) -> bool {
        match self.0.write().try_insert(span, (var_span, false)) {
            Ok(_) => true,
            Err(entry) => entry.entry.get().0 == var_span,
        }
    }

    /// Read a span and record that it was read.
    pub fn get(&self, span: Span) -> Option<Span> {
        if let Some(mut mspans) = self.0.try_write() {
            if let Some((var_span, read)) = mspans.get_mut(&span) {
                *read = true;
                Some(*var_span)
            } else {
                None
            }
        } else {
            if let Some((span, true)) = self.0.read().get(&span) { Some(*span) } else { None }
        }
    }

    /// Freeze the set, and return the spans which have been read.
    ///
    /// After this is frozen, no spans that have not been read can be read.
    pub fn freeze_and_get_read_spans(&self) -> UnordMap<Span, Span> {
        self.0.freeze().items().filter(|(_, (_, b))| *b).map(|(s1, (s2, _))| (*s1, *s2)).collect()
    }
}

#[inline]
pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R {
    with_session_globals(|session_globals| f(&session_globals.metavar_spans))
}

bitflags::bitflags! {
    /// Scopes used to determined if it need to apply to `--remap-path-prefix`
    #[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)]
    pub struct RemapPathScopeComponents: u8 {
        /// Apply remappings to the expansion of `std::file!()` macro
        const MACRO = 1 << 0;
        /// Apply remappings to printed compiler diagnostics
        const DIAGNOSTICS = 1 << 1;
        /// Apply remappings to debug information
        const DEBUGINFO = 1 << 3;
        /// Apply remappings to coverage information
        const COVERAGE = 1 << 4;
        /// Apply remappings to documentation information
        const DOCUMENTATION = 1 << 5;

        /// An alias for `macro`, `debuginfo` and `coverage`. This ensures all paths in compiled
        /// executables, libraries and objects are remapped but not elsewhere.
        const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits() | Self::COVERAGE.bits();
    }
}

impl<E: Encoder> Encodable<E> for RemapPathScopeComponents {
    #[inline]
    fn encode(&self, s: &mut E) {
        s.emit_u8(self.bits());
    }
}

impl<D: Decoder> Decodable<D> for RemapPathScopeComponents {
    #[inline]
    fn decode(s: &mut D) -> RemapPathScopeComponents {
        RemapPathScopeComponents::from_bits(s.read_u8())
            .expect("invalid bits for RemapPathScopeComponents")
    }
}

/// A self-contained "real" filename.
///
/// It is produced by `SourceMap::to_real_filename`.
///
/// `RealFileName` represents a filename that may have been (partly) remapped
/// by `--remap-path-prefix` and `-Zremap-path-scope`.
///
/// It also contains an embedabble component which gives a working directory
/// and a maybe-remapped maybe-aboslote name. This is useful for debuginfo where
/// some formats and tools highly prefer absolute paths.
///
/// ## Consistency across compiler sessions
///
/// The type-system, const-eval and other parts of the compiler rely on `FileName`
/// and by extension `RealFileName` to be consistent across compiler sessions.
///
/// Otherwise unsoudness (like rust-lang/rust#148328) may occur.
///
/// As such this type is self-sufficient and consistent in it's output.
///
/// The [`RealFileName::path`] and [`RealFileName::embeddable_name`] methods
/// are guaranteed to always return the same output across compiler sessions.
///
/// ## Usage
///
/// Creation of a [`RealFileName`] should be done using
/// [`FilePathMapping::to_real_filename`][rustc_span::source_map::FilePathMapping::to_real_filename].
///
/// Retrieving a path can be done in two main ways:
///  - by using [`RealFileName::path`] with a given scope (should be preferred)
///  - or by using [`RealFileName::embeddable_name`] with a given scope
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)]
pub struct RealFileName {
    /// The local name (always present in the original crate)
    local: Option<InnerRealFileName>,
    /// The maybe remapped part. Correspond to `local` when no remapped happened.
    maybe_remapped: InnerRealFileName,
    /// The remapped scopes. Any active scope MUST use `maybe_virtual`
    scopes: RemapPathScopeComponents,
}

/// The inner workings of `RealFileName`.
///
/// It contains the `name`, `working_directory` and `embeddable_name` components.
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable, Hash)]
struct InnerRealFileName {
    /// The name.
    name: PathBuf,
    /// The working directory associated with the embeddable name.
    working_directory: PathBuf,
    /// The embeddable name.
    embeddable_name: PathBuf,
}

impl Hash for RealFileName {
    #[inline]
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        // To prevent #70924 from happening again we should only hash the
        // remapped path if that exists. This is because remapped paths to
        // sysroot crates (/rust/$hash or /rust/$version) remain stable even
        // if the corresponding local path changes.
        if !self.was_fully_remapped() {
            self.local.hash(state);
        }
        self.maybe_remapped.hash(state);
        self.scopes.bits().hash(state);
    }
}

impl RealFileName {
    /// Returns the associated path for the given remapping scope.
    ///
    /// ## Panic
    ///
    /// Only one scope components can be given to this function.
    #[inline]
    pub fn path(&self, scope: RemapPathScopeComponents) -> &Path {
        assert!(
            scope.bits().count_ones() == 1,
            "one and only one scope should be passed to `RealFileName::path`: {scope:?}"
        );
        if !self.scopes.contains(scope)
            && let Some(local_name) = &self.local
        {
            local_name.name.as_path()
        } else {
            self.maybe_remapped.name.as_path()
        }
    }

    /// Returns the working directory and embeddable path for the given remapping scope.
    ///
    /// Useful for embedding a mostly abosolute path (modulo remapping) in the compiler outputs.
    ///
    /// The embedabble path is not guaranteed to be an absolute path, nor is it garuenteed
    /// that the working directory part is always a prefix of embeddable path.
    ///
    /// ## Panic
    ///
    /// Only one scope components can be given to this function.
    #[inline]
    pub fn embeddable_name(&self, scope: RemapPathScopeComponents) -> (&Path, &Path) {
        assert!(
            scope.bits().count_ones() == 1,
            "one and only one scope should be passed to `RealFileName::embeddable_path`: {scope:?}"
        );
        if !self.scopes.contains(scope)
            && let Some(local_name) = &self.local
        {
            (&local_name.working_directory, &local_name.embeddable_name)
        } else {
            (&self.maybe_remapped.working_directory, &self.maybe_remapped.embeddable_name)
        }
    }

    /// Returns the path suitable for reading from the file system on the local host,
    /// if this information exists.
    ///
    /// May not exists if the filename was imported from another crate.
    ///
    /// Avoid embedding this in build artifacts; prefer `path()` or `embeddable_name()`.
    #[inline]
    pub fn local_path(&self) -> Option<&Path> {
        if self.was_not_remapped() {
            Some(&self.maybe_remapped.name)
        } else if let Some(local) = &self.local {
            Some(&local.name)
        } else {
            None
        }
    }

    /// Returns the path suitable for reading from the file system on the local host,
    /// if this information exists.
    ///
    /// May not exists if the filename was imported from another crate.
    ///
    /// Avoid embedding this in build artifacts; prefer `path()` or `embeddable_name()`.
    #[inline]
    pub fn into_local_path(self) -> Option<PathBuf> {
        if self.was_not_remapped() {
            Some(self.maybe_remapped.name)
        } else if let Some(local) = self.local {
            Some(local.name)
        } else {
            None
        }
    }

    /// Returns whenever the filename was remapped.
    #[inline]
    pub(crate) fn was_remapped(&self) -> bool {
        !self.scopes.is_empty()
    }

    /// Returns whenever the filename was fully remapped.
    #[inline]
    fn was_fully_remapped(&self) -> bool {
        self.scopes.is_all()
    }

    /// Returns whenever the filename was not remapped.
    #[inline]
    fn was_not_remapped(&self) -> bool {
        self.scopes.is_empty()
    }

    /// Returns an empty `RealFileName`
    ///
    /// Useful as the working directory input to `SourceMap::to_real_filename`.
    #[inline]
    pub fn empty() -> RealFileName {
        RealFileName {
            local: Some(InnerRealFileName {
                name: PathBuf::new(),
                working_directory: PathBuf::new(),
                embeddable_name: PathBuf::new(),
            }),
            maybe_remapped: InnerRealFileName {
                name: PathBuf::new(),
                working_directory: PathBuf::new(),
                embeddable_name: PathBuf::new(),
            },
            scopes: RemapPathScopeComponents::empty(),
        }
    }

    /// Returns a `RealFileName` that is completely remapped without any local components.
    ///
    /// Only exposed for the purpose of `-Zsimulate-remapped-rust-src-base`.
    pub fn from_virtual_path(path: &Path) -> RealFileName {
        let name = InnerRealFileName {
            name: path.to_owned(),
            embeddable_name: path.to_owned(),
            working_directory: PathBuf::new(),
        };
        RealFileName { local: None, maybe_remapped: name, scopes: RemapPathScopeComponents::all() }
    }

    /// Update the filename for encoding in the crate metadata.
    ///
    /// Currently it's about removing the local part when the filename
    /// is either fully remapped or not remapped at all.
    #[inline]
    pub fn update_for_crate_metadata(&mut self) {
        if self.was_fully_remapped() || self.was_not_remapped() {
            // NOTE: This works because when the filename is fully
            // remapped, we don't care about the `local` part,
            // and when the filename is not remapped at all,
            // `maybe_remapped` and `local` are equal.
            self.local = None;
        }
    }

    /// Internal routine to display the filename.
    ///
    /// Users should always use the `RealFileName::path` method or `FileName` methods instead.
    fn to_string_lossy<'a>(&'a self, display_pref: FileNameDisplayPreference) -> Cow<'a, str> {
        match display_pref {
            FileNameDisplayPreference::Remapped => self.maybe_remapped.name.to_string_lossy(),
            FileNameDisplayPreference::Local => {
                self.local.as_ref().unwrap_or(&self.maybe_remapped).name.to_string_lossy()
            }
            FileNameDisplayPreference::Short => self
                .maybe_remapped
                .name
                .file_name()
                .map_or_else(|| "".into(), |f| f.to_string_lossy()),
            FileNameDisplayPreference::Scope(scope) => self.path(scope).to_string_lossy(),
        }
    }
}

/// Differentiates between real files and common virtual files.
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)]
pub enum FileName {
    Real(RealFileName),
    /// Strings provided as `--cfg [cfgspec]`.
    CfgSpec(Hash64),
    /// Command line.
    Anon(Hash64),
    /// Hack in `src/librustc_ast/parse.rs`.
    // FIXME(jseyfried)
    MacroExpansion(Hash64),
    ProcMacroSourceCode(Hash64),
    /// Strings provided as crate attributes in the CLI.
    CliCrateAttr(Hash64),
    /// Custom sources for explicit parser calls from plugins and drivers.
    Custom(String),
    DocTest(PathBuf, isize),
    /// Post-substitution inline assembly from LLVM.
    InlineAsm(Hash64),
}

pub struct FileNameDisplay<'a> {
    inner: &'a FileName,
    display_pref: FileNameDisplayPreference,
}

// Internal enum. Should not be exposed.
#[derive(Clone, Copy)]
enum FileNameDisplayPreference {
    Remapped,
    Local,
    Short,
    Scope(RemapPathScopeComponents),
}

impl fmt::Display for FileNameDisplay<'_> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        use FileName::*;
        match *self.inner {
            Real(ref name) => {
                write!(fmt, "{}", name.to_string_lossy(self.display_pref))
            }
            CfgSpec(_) => write!(fmt, "<cfgspec>"),
            MacroExpansion(_) => write!(fmt, "<macro expansion>"),
            Anon(_) => write!(fmt, "<anon>"),
            ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"),
            CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
            Custom(ref s) => write!(fmt, "<{s}>"),
            DocTest(ref path, _) => write!(fmt, "{}", path.display()),
            InlineAsm(_) => write!(fmt, "<inline asm>"),
        }
    }
}

impl<'a> FileNameDisplay<'a> {
    pub fn to_string_lossy(&self) -> Cow<'a, str> {
        match self.inner {
            FileName::Real(inner) => inner.to_string_lossy(self.display_pref),
            _ => Cow::from(self.to_string()),
        }
    }
}

impl FileName {
    pub fn is_real(&self) -> bool {
        use FileName::*;
        match *self {
            Real(_) => true,
            Anon(_)
            | MacroExpansion(_)
            | ProcMacroSourceCode(_)
            | CliCrateAttr(_)
            | Custom(_)
            | CfgSpec(_)
            | DocTest(_, _)
            | InlineAsm(_) => false,
        }
    }

    /// Returns the path suitable for reading from the file system on the local host,
    /// if this information exists.
    ///
    /// Avoid embedding this in build artifacts. Prefer using the `display` method.
    #[inline]
    pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> {
        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
    }

    /// Returns the path suitable for reading from the file system on the local host,
    /// if this information exists.
    ///
    /// Avoid embedding this in build artifacts. Prefer using the `display` method.
    #[inline]
    pub fn prefer_local_unconditionally(&self) -> FileNameDisplay<'_> {
        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
    }

    /// Returns a short (either the filename or an empty string).
    #[inline]
    pub fn short(&self) -> FileNameDisplay<'_> {
        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Short }
    }

    /// Returns a `Display`-able path for the given scope.
    #[inline]
    pub fn display(&self, scope: RemapPathScopeComponents) -> FileNameDisplay<'_> {
        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Scope(scope) }
    }

    pub fn macro_expansion_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::MacroExpansion(hasher.finish())
    }

    pub fn anon_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::Anon(hasher.finish())
    }

    pub fn proc_macro_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::ProcMacroSourceCode(hasher.finish())
    }

    pub fn cfg_spec_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::CfgSpec(hasher.finish())
    }

    pub fn cli_crate_attr_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::CliCrateAttr(hasher.finish())
    }

    pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName {
        FileName::DocTest(path, line)
    }

    pub fn inline_asm_source_code(src: &str) -> FileName {
        let mut hasher = StableHasher::new();
        src.hash(&mut hasher);
        FileName::InlineAsm(hasher.finish())
    }

    /// Returns the path suitable for reading from the file system on the local host,
    /// if this information exists.
    ///
    /// Avoid embedding this in build artifacts.
    pub fn into_local_path(self) -> Option<PathBuf> {
        match self {
            FileName::Real(path) => path.into_local_path(),
            FileName::DocTest(path, _) => Some(path),
            _ => None,
        }
    }
}

/// Represents a span.
///
/// Spans represent a region of code, used for error reporting. Positions in spans
/// are *absolute* positions from the beginning of the [`SourceMap`], not positions
/// relative to [`SourceFile`]s. Methods on the `SourceMap` can be used to relate spans back
/// to the original source.
///
/// You must be careful if the span crosses more than one file, since you will not be
/// able to use many of the functions on spans in source_map and you cannot assume
/// that the length of the span is equal to `span.hi - span.lo`; there may be space in the
/// [`BytePos`] range between files.
///
/// `SpanData` is public because `Span` uses a thread-local interner and can't be
/// sent to other threads, but some pieces of performance infra run in a separate thread.
/// Using `Span` is generally preferred.
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
#[derive_where(PartialOrd, Ord)]
pub struct SpanData {
    pub lo: BytePos,
    pub hi: BytePos,
    /// Information about where the macro came from, if this piece of
    /// code was created by a macro expansion.
    #[derive_where(skip)]
    // `SyntaxContext` does not implement `Ord`.
    // The other fields are enough to determine in-file order.
    pub ctxt: SyntaxContext,
    #[derive_where(skip)]
    // `LocalDefId` does not implement `Ord`.
    // The other fields are enough to determine in-file order.
    pub parent: Option<LocalDefId>,
}

impl SpanData {
    #[inline]
    pub fn span(&self) -> Span {
        Span::new(self.lo, self.hi, self.ctxt, self.parent)
    }
    #[inline]
    pub fn with_lo(&self, lo: BytePos) -> Span {
        Span::new(lo, self.hi, self.ctxt, self.parent)
    }
    #[inline]
    pub fn with_hi(&self, hi: BytePos) -> Span {
        Span::new(self.lo, hi, self.ctxt, self.parent)
    }
    /// Avoid if possible, `Span::map_ctxt` should be preferred.
    #[inline]
    fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
        Span::new(self.lo, self.hi, ctxt, self.parent)
    }
    /// Avoid if possible, `Span::with_parent` should be preferred.
    #[inline]
    fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
        Span::new(self.lo, self.hi, self.ctxt, parent)
    }
    /// Returns `true` if this is a dummy span with any hygienic context.
    #[inline]
    pub fn is_dummy(self) -> bool {
        self.lo.0 == 0 && self.hi.0 == 0
    }
    /// Returns `true` if `self` fully encloses `other`.
    pub fn contains(self, other: Self) -> bool {
        self.lo <= other.lo && other.hi <= self.hi
    }
}

impl Default for SpanData {
    fn default() -> Self {
        Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None }
    }
}

impl PartialOrd for Span {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        PartialOrd::partial_cmp(&self.data(), &rhs.data())
    }
}
impl Ord for Span {
    fn cmp(&self, rhs: &Self) -> Ordering {
        Ord::cmp(&self.data(), &rhs.data())
    }
}

impl Span {
    #[inline]
    pub fn lo(self) -> BytePos {
        self.data().lo
    }
    #[inline]
    pub fn with_lo(self, lo: BytePos) -> Span {
        self.data().with_lo(lo)
    }
    #[inline]
    pub fn hi(self) -> BytePos {
        self.data().hi
    }
    #[inline]
    pub fn with_hi(self, hi: BytePos) -> Span {
        self.data().with_hi(hi)
    }
    #[inline]
    pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
        self.map_ctxt(|_| ctxt)
    }

    #[inline]
    pub fn is_visible(self, sm: &SourceMap) -> bool {
        !self.is_dummy() && sm.is_span_accessible(self)
    }

    /// Returns whether this span originates in a foreign crate's external macro.
    ///
    /// This is used to test whether a lint should not even begin to figure out whether it should
    /// be reported on the current node.
    #[inline]
    pub fn in_external_macro(self, sm: &SourceMap) -> bool {
        self.ctxt().in_external_macro(sm)
    }

    /// Returns `true` if `span` originates in a derive-macro's expansion.
    pub fn in_derive_expansion(self) -> bool {
        matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
    }

    /// Return whether `span` is generated by `async` or `await`.
    pub fn is_from_async_await(self) -> bool {
        matches!(
            self.ctxt().outer_expn_data().kind,
            ExpnKind::Desugaring(DesugaringKind::Async | DesugaringKind::Await),
        )
    }

    /// Gate suggestions that would not be appropriate in a context the user didn't write.
    pub fn can_be_used_for_suggestions(self) -> bool {
        !self.from_expansion()
        // FIXME: If this span comes from a `derive` macro but it points at code the user wrote,
        // the callsite span and the span will be pointing at different places. It also means that
        // we can safely provide suggestions on this span.
            || (self.in_derive_expansion()
                && self.parent_callsite().map(|p| (p.lo(), p.hi())) != Some((self.lo(), self.hi())))
    }

    #[inline]
    pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
        Span::new(lo, hi, SyntaxContext::root(), None)
    }

    /// Returns a new span representing an empty span at the beginning of this span.
    #[inline]
    pub fn shrink_to_lo(self) -> Span {
        let span = self.data_untracked();
        span.with_hi(span.lo)
    }
    /// Returns a new span representing an empty span at the end of this span.
    #[inline]
    pub fn shrink_to_hi(self) -> Span {
        let span = self.data_untracked();
        span.with_lo(span.hi)
    }

    #[inline]
    /// Returns `true` if `hi == lo`.
    pub fn is_empty(self) -> bool {
        let span = self.data_untracked();
        span.hi == span.lo
    }

    /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
    pub fn substitute_dummy(self, other: Span) -> Span {
        if self.is_dummy() { other } else { self }
    }

    /// Returns `true` if `self` fully encloses `other`.
    pub fn contains(self, other: Span) -> bool {
        let span = self.data();
        let other = other.data();
        span.contains(other)
    }

    /// Returns `true` if `self` touches `other`.
    pub fn overlaps(self, other: Span) -> bool {
        let span = self.data();
        let other = other.data();
        span.lo < other.hi && other.lo < span.hi
    }

    /// Returns `true` if `self` touches or adjoins `other`.
    pub fn overlaps_or_adjacent(self, other: Span) -> bool {
        let span = self.data();
        let other = other.data();
        span.lo <= other.hi && other.lo <= span.hi
    }

    /// Returns `true` if the spans are equal with regards to the source text.
    ///
    /// Use this instead of `==` when either span could be generated code,
    /// and you only care that they point to the same bytes of source text.
    pub fn source_equal(self, other: Span) -> bool {
        let span = self.data();
        let other = other.data();
        span.lo == other.lo && span.hi == other.hi
    }

    /// Returns `Some(span)`, where the start is trimmed by the end of `other`.
    pub fn trim_start(self, other: Span) -> Option<Span> {
        let span = self.data();
        let other = other.data();
        if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None }
    }

    /// Returns `Some(span)`, where the end is trimmed by the start of `other`.
    pub fn trim_end(self, other: Span) -> Option<Span> {
        let span = self.data();
        let other = other.data();
        if span.lo < other.lo { Some(span.with_hi(cmp::min(span.hi, other.lo))) } else { None }
    }

    /// Returns the source span -- this is either the supplied span, or the span for
    /// the macro callsite that expanded to it.
    pub fn source_callsite(self) -> Span {
        let ctxt = self.ctxt();
        if !ctxt.is_root() { ctxt.outer_expn_data().call_site.source_callsite() } else { self }
    }

    /// Returns the call-site span of the last macro expansion which produced this `Span`.
    /// (see [`ExpnData::call_site`]). Returns `None` if this is not an expansion.
    pub fn parent_callsite(self) -> Option<Span> {
        let ctxt = self.ctxt();
        (!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
    }

    /// Find the first ancestor span that's contained within `outer`.
    ///
    /// This method traverses the macro expansion ancestors until it finds the first span
    /// that's contained within `outer`.
    ///
    /// The span returned by this method may have a different [`SyntaxContext`] than `outer`.
    /// If you need to extend the span, use [`find_ancestor_inside_same_ctxt`] instead,
    /// because joining spans with different syntax contexts can create unexpected results.
    ///
    /// This is used to find the span of the macro call when a parent expr span, i.e. `outer`, is known.
    ///
    /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
    pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
        while !outer.contains(self) {
            self = self.parent_callsite()?;
        }
        Some(self)
    }

    /// Find the first ancestor span with the same [`SyntaxContext`] as `other`.
    ///
    /// This method traverses the macro expansion ancestors until it finds a span
    /// that has the same [`SyntaxContext`] as `other`.
    ///
    /// Like [`find_ancestor_inside_same_ctxt`], but specifically for when spans might not
    /// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or
    /// [`find_ancestor_inside_same_ctxt`] when you know that the spans are nested (modulo
    /// macro expansion).
    ///
    /// [`find_ancestor_inside`]: Self::find_ancestor_inside
    /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
    pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> {
        while !self.eq_ctxt(other) {
            self = self.parent_callsite()?;
        }
        Some(self)
    }

    /// Find the first ancestor span that's contained within `outer` and
    /// has the same [`SyntaxContext`] as `outer`.
    ///
    /// This method traverses the macro expansion ancestors until it finds a span
    /// that is both contained within `outer` and has the same [`SyntaxContext`] as `outer`.
    ///
    /// This method is the combination of [`find_ancestor_inside`] and
    /// [`find_ancestor_in_same_ctxt`] and should be preferred when extending the returned span.
    /// If you do not need to modify the span, use [`find_ancestor_inside`] instead.
    ///
    /// [`find_ancestor_inside`]: Self::find_ancestor_inside
    /// [`find_ancestor_in_same_ctxt`]: Self::find_ancestor_in_same_ctxt
    pub fn find_ancestor_inside_same_ctxt(mut self, outer: Span) -> Option<Span> {
        while !outer.contains(self) || !self.eq_ctxt(outer) {
            self = self.parent_callsite()?;
        }
        Some(self)
    }

    /// Find the first ancestor span that does not come from an external macro.
    ///
    /// This method traverses the macro expansion ancestors until it finds a span
    /// that is either from user-written code or from a local macro (defined in the current crate).
    ///
    /// External macros are those defined in dependencies or the standard library.
    /// This method is useful for reporting errors in user-controllable code and avoiding
    /// diagnostics inside external macros.
    ///
    /// # See also
    ///
    /// - [`Self::find_ancestor_not_from_macro`]
    /// - [`Self::in_external_macro`]
    pub fn find_ancestor_not_from_extern_macro(mut self, sm: &SourceMap) -> Option<Span> {
        while self.in_external_macro(sm) {
            self = self.parent_callsite()?;
        }
        Some(self)
    }

    /// Find the first ancestor span that does not come from any macro expansion.
    ///
    /// This method traverses the macro expansion ancestors until it finds a span
    /// that originates from user-written code rather than any macro-generated code.
    ///
    /// This method is useful for reporting errors at the exact location users wrote code
    /// and providing suggestions at directly editable locations.
    ///
    /// # See also
    ///
    /// - [`Self::find_ancestor_not_from_extern_macro`]
    /// - [`Span::from_expansion`]
    pub fn find_ancestor_not_from_macro(mut self) -> Option<Span> {
        while self.from_expansion() {
            self = self.parent_callsite()?;
        }
        Some(self)
    }

    /// Edition of the crate from which this span came.
    pub fn edition(self) -> edition::Edition {
        self.ctxt().edition()
    }

    /// Is this edition 2015?
    #[inline]
    pub fn is_rust_2015(self) -> bool {
        self.edition().is_rust_2015()
    }

    /// Are we allowed to use features from the Rust 2018 edition?
    #[inline]
    pub fn at_least_rust_2018(self) -> bool {
        self.edition().at_least_rust_2018()
    }

    /// Are we allowed to use features from the Rust 2021 edition?
    #[inline]
    pub fn at_least_rust_2021(self) -> bool {
        self.edition().at_least_rust_2021()
    }

    /// Are we allowed to use features from the Rust 2024 edition?
    #[inline]
    pub fn at_least_rust_2024(self) -> bool {
        self.edition().at_least_rust_2024()
    }

    /// Returns the source callee.
    ///
    /// Returns `None` if the supplied span has no expansion trace,
    /// else returns the `ExpnData` for the macro definition
    /// corresponding to the source callsite.
    pub fn source_callee(self) -> Option<ExpnData> {
        let mut ctxt = self.ctxt();
        let mut opt_expn_data = None;
        while !ctxt.is_root() {
            let expn_data = ctxt.outer_expn_data();
            ctxt = expn_data.call_site.ctxt();
            opt_expn_data = Some(expn_data);
        }
        opt_expn_data
    }

    /// Checks if a span is "internal" to a macro in which `#[unstable]`
    /// items can be used (that is, a macro marked with
    /// `#[allow_internal_unstable]`).
    pub fn allows_unstable(self, feature: Symbol) -> bool {
        self.ctxt()
            .outer_expn_data()
            .allow_internal_unstable
            .is_some_and(|features| features.contains(&feature))
    }

    /// Checks if this span arises from a compiler desugaring of kind `kind`.
    pub fn is_desugaring(self, kind: DesugaringKind) -> bool {
        match self.ctxt().outer_expn_data().kind {
            ExpnKind::Desugaring(k) => k == kind,
            _ => false,
        }
    }

    /// Returns the compiler desugaring that created this span, or `None`
    /// if this span is not from a desugaring.
    pub fn desugaring_kind(self) -> Option<DesugaringKind> {
        match self.ctxt().outer_expn_data().kind {
            ExpnKind::Desugaring(k) => Some(k),
            _ => None,
        }
    }

    /// Checks if a span is "internal" to a macro in which `unsafe`
    /// can be used without triggering the `unsafe_code` lint.
    /// (that is, a macro marked with `#[allow_internal_unsafe]`).
    pub fn allows_unsafe(self) -> bool {
        self.ctxt().outer_expn_data().allow_internal_unsafe
    }

    pub fn macro_backtrace(mut self) -> impl Iterator<Item = ExpnData> {
        let mut prev_span = DUMMY_SP;
        iter::from_fn(move || {
            loop {
                let ctxt = self.ctxt();
                if ctxt.is_root() {
                    return None;
                }

                let expn_data = ctxt.outer_expn_data();
                let is_recursive = expn_data.call_site.source_equal(prev_span);

                prev_span = self;
                self = expn_data.call_site;

                // Don't print recursive invocations.
                if !is_recursive {
                    return Some(expn_data);
                }
            }
        })
    }

    /// Splits a span into two composite spans around a certain position.
    pub fn split_at(self, pos: u32) -> (Span, Span) {
        let len = self.hi().0 - self.lo().0;
        debug_assert!(pos <= len);

        let split_pos = BytePos(self.lo().0 + pos);
        (
            Span::new(self.lo(), split_pos, self.ctxt(), self.parent()),
            Span::new(split_pos, self.hi(), self.ctxt(), self.parent()),
        )
    }

    /// Check if you can select metavar spans for the given spans to get matching contexts.
    fn try_metavars(a: SpanData, b: SpanData, a_orig: Span, b_orig: Span) -> (SpanData, SpanData) {
        match with_metavar_spans(|mspans| (mspans.get(a_orig), mspans.get(b_orig))) {
            (None, None) => {}
            (Some(meta_a), None) => {
                let meta_a = meta_a.data();
                if meta_a.ctxt == b.ctxt {
                    return (meta_a, b);
                }
            }
            (None, Some(meta_b)) => {
                let meta_b = meta_b.data();
                if a.ctxt == meta_b.ctxt {
                    return (a, meta_b);
                }
            }
            (Some(meta_a), Some(meta_b)) => {
                let meta_b = meta_b.data();
                if a.ctxt == meta_b.ctxt {
                    return (a, meta_b);
                }
                let meta_a = meta_a.data();
                if meta_a.ctxt == b.ctxt {
                    return (meta_a, b);
                } else if meta_a.ctxt == meta_b.ctxt {
                    return (meta_a, meta_b);
                }
            }
        }

        (a, b)
    }

    /// Prepare two spans to a combine operation like `to` or `between`.
    fn prepare_to_combine(
        a_orig: Span,
        b_orig: Span,
    ) -> Result<(SpanData, SpanData, Option<LocalDefId>), Span> {
        let (a, b) = (a_orig.data(), b_orig.data());
        if a.ctxt == b.ctxt {
            return Ok((a, b, if a.parent == b.parent { a.parent } else { None }));
        }

        let (a, b) = Span::try_metavars(a, b, a_orig, b_orig);
        if a.ctxt == b.ctxt {
            return Ok((a, b, if a.parent == b.parent { a.parent } else { None }));
        }

        // Context mismatches usually happen when procedural macros combine spans copied from
        // the macro input with spans produced by the macro (`Span::*_site`).
        // In that case we consider the combined span to be produced by the macro and return
        // the original macro-produced span as the result.
        // Otherwise we just fall back to returning the first span.
        // Combining locations typically doesn't make sense in case of context mismatches.
        // `is_root` here is a fast path optimization.
        let a_is_callsite = a.ctxt.is_root() || a.ctxt == b.span().source_callsite().ctxt();
        Err(if a_is_callsite { b_orig } else { a_orig })
    }

    /// This span, but in a larger context, may switch to the metavariable span if suitable.
    pub fn with_neighbor(self, neighbor: Span) -> Span {
        match Span::prepare_to_combine(self, neighbor) {
            Ok((this, ..)) => this.span(),
            Err(_) => self,
        }
    }

    /// Returns a `Span` that would enclose both `self` and `end`.
    ///
    /// Note that this can also be used to extend the span "backwards":
    /// `start.to(end)` and `end.to(start)` return the same `Span`.
    ///
    /// ```text
    ///     ____             ___
    ///     self lorem ipsum end
    ///     ^^^^^^^^^^^^^^^^^^^^
    /// ```
    pub fn to(self, end: Span) -> Span {
        match Span::prepare_to_combine(self, end) {
            Ok((from, to, parent)) => {
                Span::new(cmp::min(from.lo, to.lo), cmp::max(from.hi, to.hi), from.ctxt, parent)
            }
            Err(fallback) => fallback,
        }
    }

    /// Returns a `Span` between the end of `self` to the beginning of `end`.
    ///
    /// ```text
    ///     ____             ___
    ///     self lorem ipsum end
    ///         ^^^^^^^^^^^^^
    /// ```
    pub fn between(self, end: Span) -> Span {
        match Span::prepare_to_combine(self, end) {
            Ok((from, to, parent)) => {
                Span::new(cmp::min(from.hi, to.hi), cmp::max(from.lo, to.lo), from.ctxt, parent)
            }
            Err(fallback) => fallback,
        }
    }

    /// Returns a `Span` from the beginning of `self` until the beginning of `end`.
    ///
    /// ```text
    ///     ____             ___
    ///     self lorem ipsum end
    ///     ^^^^^^^^^^^^^^^^^
    /// ```
    pub fn until(self, end: Span) -> Span {
        match Span::prepare_to_combine(self, end) {
            Ok((from, to, parent)) => {
                Span::new(cmp::min(from.lo, to.lo), cmp::max(from.lo, to.lo), from.ctxt, parent)
            }
            Err(fallback) => fallback,
        }
    }

    /// Returns the `Span` within the syntax context of "within". This is useful when
    /// "self" is an expansion from a macro variable, since this can be used for
    /// providing extra macro expansion context for certain errors.
    ///
    /// ```text
    /// macro_rules! m {
    ///     ($ident:ident) => { ($ident,) }
    /// }
    ///
    /// m!(outer_ident);
    /// ```
    ///
    /// If "self" is the span of the outer_ident, and "within" is the span of the `($ident,)`
    /// expr, then this will return the span of the `$ident` macro variable.
    pub fn within_macro(self, within: Span, sm: &SourceMap) -> Option<Span> {
        match Span::prepare_to_combine(self, within) {
            // Only return something if it doesn't overlap with the original span,
            // and the span isn't "imported" (i.e. from unavailable sources).
            // FIXME: This does limit the usefulness of the error when the macro is
            // from a foreign crate; we could also take into account `-Zmacro-backtrace`,
            // which doesn't redact this span (but that would mean passing in even more
            // args to this function, lol).
            Ok((self_, _, parent))
                if self_.hi < self.lo() || self.hi() < self_.lo && !sm.is_imported(within) =>
            {
                Some(Span::new(self_.lo, self_.hi, self_.ctxt, parent))
            }
            _ => None,
        }
    }

    pub fn from_inner(self, inner: InnerSpan) -> Span {
        let span = self.data();
        Span::new(
            span.lo + BytePos::from_usize(inner.start),
            span.lo + BytePos::from_usize(inner.end),
            span.ctxt,
            span.parent,
        )
    }

    /// Equivalent of `Span::def_site` from the proc macro API,
    /// except that the location is taken from the `self` span.
    pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span {
        self.with_ctxt_from_mark(expn_id, Transparency::Opaque)
    }

    /// Equivalent of `Span::call_site` from the proc macro API,
    /// except that the location is taken from the `self` span.
    pub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span {
        self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
    }

    /// Equivalent of `Span::mixed_site` from the proc macro API,
    /// except that the location is taken from the `self` span.
    pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span {
        self.with_ctxt_from_mark(expn_id, Transparency::SemiOpaque)
    }

    /// Produces a span with the same location as `self` and context produced by a macro with the
    /// given ID and transparency, assuming that macro was defined directly and not produced by
    /// some other macro (which is the case for built-in and procedural macros).
    fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
        self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
    }

    #[inline]
    pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
        self.map_ctxt(|ctxt| ctxt.apply_mark(expn_id, transparency))
    }

    #[inline]
    pub fn remove_mark(&mut self) -> ExpnId {
        let mut mark = ExpnId::root();
        *self = self.map_ctxt(|mut ctxt| {
            mark = ctxt.remove_mark();
            ctxt
        });
        mark
    }

    #[inline]
    pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
        let mut mark = None;
        *self = self.map_ctxt(|mut ctxt| {
            mark = ctxt.adjust(expn_id);
            ctxt
        });
        mark
    }

    #[inline]
    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
        let mut mark = None;
        *self = self.map_ctxt(|mut ctxt| {
            mark = ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
            ctxt
        });
        mark
    }

    #[inline]
    pub fn normalize_to_macros_2_0(self) -> Span {
        self.map_ctxt(|ctxt| ctxt.normalize_to_macros_2_0())
    }

    #[inline]
    pub fn normalize_to_macro_rules(self) -> Span {
        self.map_ctxt(|ctxt| ctxt.normalize_to_macro_rules())
    }
}

impl Default for Span {
    fn default() -> Self {
        DUMMY_SP
    }
}

rustc_index::newtype_index! {
    #[orderable]
    #[debug_format = "AttrId({})"]
    pub struct AttrId {}
}

/// This trait is used to allow encoder specific encodings of certain types.
/// It is similar to rustc_type_ir's TyEncoder.
pub trait SpanEncoder: Encoder {
    fn encode_span(&mut self, span: Span);
    fn encode_symbol(&mut self, sym: Symbol);
    fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol);
    fn encode_expn_id(&mut self, expn_id: ExpnId);
    fn encode_syntax_context(&mut self, syntax_context: SyntaxContext);
    /// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a
    /// tcx. Therefore, make sure to include the context when encode a `CrateNum`.
    fn encode_crate_num(&mut self, crate_num: CrateNum);
    fn encode_def_index(&mut self, def_index: DefIndex);
    fn encode_def_id(&mut self, def_id: DefId);
}

impl SpanEncoder for FileEncoder {
    fn encode_span(&mut self, span: Span) {
        let span = span.data();
        span.lo.encode(self);
        span.hi.encode(self);
    }

    fn encode_symbol(&mut self, sym: Symbol) {
        self.emit_str(sym.as_str());
    }

    fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
        self.emit_byte_str(byte_sym.as_byte_str());
    }

    fn encode_expn_id(&mut self, _expn_id: ExpnId) {
        panic!("cannot encode `ExpnId` with `FileEncoder`");
    }

    fn encode_syntax_context(&mut self, _syntax_context: SyntaxContext) {
        panic!("cannot encode `SyntaxContext` with `FileEncoder`");
    }

    fn encode_crate_num(&mut self, crate_num: CrateNum) {
        self.emit_u32(crate_num.as_u32());
    }

    fn encode_def_index(&mut self, _def_index: DefIndex) {
        panic!("cannot encode `DefIndex` with `FileEncoder`");
    }

    fn encode_def_id(&mut self, def_id: DefId) {
        def_id.krate.encode(self);
        def_id.index.encode(self);
    }
}

impl SpanEncoder for MemEncoder {
    fn encode_span(&mut self, span: Span) {
        let span = span.data();
        span.lo.encode(self);
        span.hi.encode(self);
    }

    fn encode_symbol(&mut self, sym: Symbol) {
        self.emit_str(sym.as_str());
    }

    fn encode_byte_symbol(&mut self, byte_sym: ByteSymbol) {
        self.emit_byte_str(byte_sym.as_byte_str());
    }

    fn encode_expn_id(&mut self, _expn_id: ExpnId) {
        panic!("cannot encode `ExpnId` with `FileEncoder`");
    }

    fn encode_syntax_context(&mut self, _syntax_context: SyntaxContext) {
        panic!("cannot encode `SyntaxContext` with `FileEncoder`");
    }

    fn encode_crate_num(&mut self, crate_num: CrateNum) {
        self.emit_u32(crate_num.as_u32());
    }

    fn encode_def_index(&mut self, _def_index: DefIndex) {
        panic!("cannot encode `DefIndex` with `FileEncoder`");
    }

    fn encode_def_id(&mut self, def_id: DefId) {
        def_id.krate.encode(self);
        def_id.index.encode(self);
    }
}

impl<E: SpanEncoder> Encodable<E> for Span {
    fn encode(&self, s: &mut E) {
        s.encode_span(*self);
    }
}

impl<E: SpanEncoder> Encodable<E> for Symbol {
    fn encode(&self, s: &mut E) {
        s.encode_symbol(*self);
    }
}

impl<E: SpanEncoder> Encodable<E> for ByteSymbol {
    fn encode(&self, s: &mut E) {
        s.encode_byte_symbol(*self);
    }
}

impl<E: SpanEncoder> Encodable<E> for ExpnId {
    fn encode(&self, s: &mut E) {
        s.encode_expn_id(*self)
    }
}

impl<E: SpanEncoder> Encodable<E> for SyntaxContext {
    fn encode(&self, s: &mut E) {
        s.encode_syntax_context(*self)
    }
}

impl<E: SpanEncoder> Encodable<E> for CrateNum {
    fn encode(&self, s: &mut E) {
        s.encode_crate_num(*self)
    }
}

impl<E: SpanEncoder> Encodable<E> for DefIndex {
    fn encode(&self, s: &mut E) {
        s.encode_def_index(*self)
    }
}

impl<E: SpanEncoder> Encodable<E> for DefId {
    fn encode(&self, s: &mut E) {
        s.encode_def_id(*self)
    }
}

impl<E: SpanEncoder> Encodable<E> for AttrId {
    fn encode(&self, _s: &mut E) {
        // A fresh id will be generated when decoding
    }
}

pub trait BlobDecoder: Decoder {
    fn decode_symbol(&mut self) -> Symbol;
    fn decode_byte_symbol(&mut self) -> ByteSymbol;
    fn decode_def_index(&mut self) -> DefIndex;
}

/// This trait is used to allow decoder specific encodings of certain types.
/// It is similar to rustc_type_ir's TyDecoder.
///
/// Specifically for metadata, an important note is that spans can only be decoded once
/// some other metadata is already read.
/// Spans have to be properly mapped into the decoding crate's sourcemap,
/// and crate numbers have to be converted sometimes.
/// This can only be done once the `CrateRoot` is available.
///
/// As such, some methods that used to be in the `SpanDecoder` trait
/// are now in the `BlobDecoder` trait. This hierarchy is not mirrored for `Encoder`s.
/// `BlobDecoder` has methods for deserializing types that are more complex than just those
/// that can be decoded with `Decoder`, but which can be decoded on their own, *before* any other metadata is.
/// Importantly, that means that types that can be decoded with `BlobDecoder` can show up in the crate root.
/// The place where this distinction is relevant is in `rustc_metadata` where metadata is decoded using either the
/// `MetadataDecodeContext` or the `BlobDecodeContext`.
pub trait SpanDecoder: BlobDecoder {
    fn decode_span(&mut self) -> Span;
    fn decode_expn_id(&mut self) -> ExpnId;
    fn decode_syntax_context(&mut self) -> SyntaxContext;
    fn decode_crate_num(&mut self) -> CrateNum;
    fn decode_def_id(&mut self) -> DefId;
    fn decode_attr_id(&mut self) -> AttrId;
}

impl BlobDecoder for MemDecoder<'_> {
    fn decode_symbol(&mut self) -> Symbol {
        Symbol::intern(self.read_str())
    }

    fn decode_byte_symbol(&mut self) -> ByteSymbol {
        ByteSymbol::intern(self.read_byte_str())
    }

    fn decode_def_index(&mut self) -> DefIndex {
        panic!("cannot decode `DefIndex` with `MemDecoder`");
    }
}

impl SpanDecoder for MemDecoder<'_> {
    fn decode_span(&mut self) -> Span {
        let lo = Decodable::decode(self);
        let hi = Decodable::decode(self);

        Span::new(lo, hi, SyntaxContext::root(), None)
    }

    fn decode_expn_id(&mut self) -> ExpnId {
        panic!("cannot decode `ExpnId` with `MemDecoder`");
    }

    fn decode_syntax_context(&mut self) -> SyntaxContext {
        panic!("cannot decode `SyntaxContext` with `MemDecoder`");
    }

    fn decode_crate_num(&mut self) -> CrateNum {
        CrateNum::from_u32(self.read_u32())
    }

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

    fn decode_attr_id(&mut self) -> AttrId {
        panic!("cannot decode `AttrId` with `MemDecoder`");
    }
}

impl<D: SpanDecoder> Decodable<D> for Span {
    fn decode(s: &mut D) -> Span {
        s.decode_span()
    }
}

impl<D: BlobDecoder> Decodable<D> for Symbol {
    fn decode(s: &mut D) -> Symbol {
        s.decode_symbol()
    }
}

impl<D: BlobDecoder> Decodable<D> for ByteSymbol {
    fn decode(s: &mut D) -> ByteSymbol {
        s.decode_byte_symbol()
    }
}

impl<D: SpanDecoder> Decodable<D> for ExpnId {
    fn decode(s: &mut D) -> ExpnId {
        s.decode_expn_id()
    }
}

impl<D: SpanDecoder> Decodable<D> for SyntaxContext {
    fn decode(s: &mut D) -> SyntaxContext {
        s.decode_syntax_context()
    }
}

impl<D: SpanDecoder> Decodable<D> for CrateNum {
    fn decode(s: &mut D) -> CrateNum {
        s.decode_crate_num()
    }
}

impl<D: BlobDecoder> Decodable<D> for DefIndex {
    fn decode(s: &mut D) -> DefIndex {
        s.decode_def_index()
    }
}

impl<D: SpanDecoder> Decodable<D> for DefId {
    fn decode(s: &mut D) -> DefId {
        s.decode_def_id()
    }
}

impl<D: SpanDecoder> Decodable<D> for AttrId {
    fn decode(s: &mut D) -> AttrId {
        s.decode_attr_id()
    }
}

impl fmt::Debug for Span {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Use the global `SourceMap` to print the span. If that's not
        // available, fall back to printing the raw values.

        fn fallback(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            f.debug_struct("Span")
                .field("lo", &span.lo())
                .field("hi", &span.hi())
                .field("ctxt", &span.ctxt())
                .finish()
        }

        if SESSION_GLOBALS.is_set() {
            with_session_globals(|session_globals| {
                if let Some(source_map) = &session_globals.source_map {
                    write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
                } else {
                    fallback(*self, f)
                }
            })
        } else {
            fallback(*self, f)
        }
    }
}

impl fmt::Debug for SpanData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.span(), f)
    }
}

/// Identifies an offset of a multi-byte character in a `SourceFile`.
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, StableHash)]
pub struct MultiByteChar {
    /// The relative offset of the character in the `SourceFile`.
    pub pos: RelativeBytePos,
    /// The number of bytes, `>= 2`.
    pub bytes: u8,
}

/// Identifies an offset of a character that was normalized away from `SourceFile`.
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, StableHash)]
pub struct NormalizedPos {
    /// The relative offset of the character in the `SourceFile`.
    pub pos: RelativeBytePos,
    /// The difference between original and normalized string at position.
    pub diff: u32,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum ExternalSource {
    /// No external source has to be loaded, since the `SourceFile` represents a local crate.
    Unneeded,
    Foreign {
        kind: ExternalSourceKind,
        /// Index of the file inside metadata.
        metadata_index: u32,
    },
}

/// The state of the lazy external source loading mechanism of a `SourceFile`.
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum ExternalSourceKind {
    /// The external source has been loaded already.
    Present(Arc<String>),
    /// No attempt has been made to load the external source.
    AbsentOk,
    /// A failed attempt has been made to load the external source.
    AbsentErr,
}

impl ExternalSource {
    pub fn get_source(&self) -> Option<&str> {
        match self {
            ExternalSource::Foreign { kind: ExternalSourceKind::Present(src), .. } => Some(src),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub struct OffsetOverflowError;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
#[derive(StableHash)]
pub enum SourceFileHashAlgorithm {
    Md5,
    Sha1,
    Sha256,
    Blake3,
}

impl Display for SourceFileHashAlgorithm {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Self::Md5 => "md5",
            Self::Sha1 => "sha1",
            Self::Sha256 => "sha256",
            Self::Blake3 => "blake3",
        })
    }
}

impl FromStr for SourceFileHashAlgorithm {
    type Err = ();

    fn from_str(s: &str) -> Result<SourceFileHashAlgorithm, ()> {
        match s {
            "md5" => Ok(SourceFileHashAlgorithm::Md5),
            "sha1" => Ok(SourceFileHashAlgorithm::Sha1),
            "sha256" => Ok(SourceFileHashAlgorithm::Sha256),
            "blake3" => Ok(SourceFileHashAlgorithm::Blake3),
            _ => Err(()),
        }
    }
}

/// The hash of the on-disk source file used for debug info and cargo freshness checks.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[derive(StableHash, Encodable, Decodable)]
pub struct SourceFileHash {
    pub kind: SourceFileHashAlgorithm,
    value: [u8; 32],
}

impl Display for SourceFileHash {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}=", self.kind)?;
        for byte in self.value[0..self.hash_len()].into_iter() {
            write!(f, "{byte:02x}")?;
        }
        Ok(())
    }
}

impl SourceFileHash {
    pub fn new_in_memory(kind: SourceFileHashAlgorithm, src: impl AsRef<[u8]>) -> SourceFileHash {
        let mut hash = SourceFileHash { kind, value: Default::default() };
        let len = hash.hash_len();
        let value = &mut hash.value[..len];
        let data = src.as_ref();
        match kind {
            SourceFileHashAlgorithm::Md5 => {
                value.copy_from_slice(&Md5::digest(data));
            }
            SourceFileHashAlgorithm::Sha1 => {
                value.copy_from_slice(&Sha1::digest(data));
            }
            SourceFileHashAlgorithm::Sha256 => {
                value.copy_from_slice(&Sha256::digest(data));
            }
            SourceFileHashAlgorithm::Blake3 => value.copy_from_slice(blake3::hash(data).as_bytes()),
        };
        hash
    }

    pub fn new(kind: SourceFileHashAlgorithm, src: impl Read) -> Result<SourceFileHash, io::Error> {
        let mut hash = SourceFileHash { kind, value: Default::default() };
        let len = hash.hash_len();
        let value = &mut hash.value[..len];
        // Buffer size is the recommended amount to fully leverage SIMD instructions on AVX-512 as per
        // blake3 documentation.
        let mut buf = vec![0; 16 * 1024];

        fn digest<T>(
            mut hasher: T,
            mut update: impl FnMut(&mut T, &[u8]),
            finish: impl FnOnce(T, &mut [u8]),
            mut src: impl Read,
            buf: &mut [u8],
            value: &mut [u8],
        ) -> Result<(), io::Error> {
            loop {
                let bytes_read = src.read(buf)?;
                if bytes_read == 0 {
                    break;
                }
                update(&mut hasher, &buf[0..bytes_read]);
            }
            finish(hasher, value);
            Ok(())
        }

        match kind {
            SourceFileHashAlgorithm::Sha256 => {
                digest(
                    Sha256::new(),
                    |h, b| {
                        h.update(b);
                    },
                    |h, out| out.copy_from_slice(&h.finalize()),
                    src,
                    &mut buf,
                    value,
                )?;
            }
            SourceFileHashAlgorithm::Sha1 => {
                digest(
                    Sha1::new(),
                    |h, b| {
                        h.update(b);
                    },
                    |h, out| out.copy_from_slice(&h.finalize()),
                    src,
                    &mut buf,
                    value,
                )?;
            }
            SourceFileHashAlgorithm::Md5 => {
                digest(
                    Md5::new(),
                    |h, b| {
                        h.update(b);
                    },
                    |h, out| out.copy_from_slice(&h.finalize()),
                    src,
                    &mut buf,
                    value,
                )?;
            }
            SourceFileHashAlgorithm::Blake3 => {
                digest(
                    blake3::Hasher::new(),
                    |h, b| {
                        h.update(b);
                    },
                    |h, out| out.copy_from_slice(h.finalize().as_bytes()),
                    src,
                    &mut buf,
                    value,
                )?;
            }
        }
        Ok(hash)
    }

    /// Check if the stored hash matches the hash of the string.
    pub fn matches(&self, src: &str) -> bool {
        Self::new_in_memory(self.kind, src.as_bytes()) == *self
    }

    /// The bytes of the hash.
    pub fn hash_bytes(&self) -> &[u8] {
        let len = self.hash_len();
        &self.value[..len]
    }

    fn hash_len(&self) -> usize {
        match self.kind {
            SourceFileHashAlgorithm::Md5 => 16,
            SourceFileHashAlgorithm::Sha1 => 20,
            SourceFileHashAlgorithm::Sha256 | SourceFileHashAlgorithm::Blake3 => 32,
        }
    }
}

#[derive(Clone)]
pub enum SourceFileLines {
    /// The source file lines, in decoded (random-access) form.
    Lines(Vec<RelativeBytePos>),

    /// The source file lines, in undecoded difference list form.
    Diffs(SourceFileDiffs),
}

impl SourceFileLines {
    pub fn is_lines(&self) -> bool {
        matches!(self, SourceFileLines::Lines(_))
    }
}

/// The source file lines in difference list form. This matches the form
/// used within metadata, which saves space by exploiting the fact that the
/// lines list is sorted and individual lines are usually not that long.
///
/// We read it directly from metadata and only decode it into `Lines` form
/// when necessary. This is a significant performance win, especially for
/// small crates where very little of `std`'s metadata is used.
#[derive(Clone)]
pub struct SourceFileDiffs {
    /// Always 1, 2, or 4. Always as small as possible, while being big
    /// enough to hold the length of the longest line in the source file.
    /// The 1 case is by far the most common.
    bytes_per_diff: usize,

    /// The number of diffs encoded in `raw_diffs`. Always one less than
    /// the number of lines in the source file.
    num_diffs: usize,

    /// The diffs in "raw" form. Each segment of `bytes_per_diff` length
    /// encodes one little-endian diff. Note that they aren't LEB128
    /// encoded. This makes for much faster decoding. Besides, the
    /// bytes_per_diff==1 case is by far the most common, and LEB128
    /// encoding has no effect on that case.
    raw_diffs: Vec<u8>,
}

/// A single source in the [`SourceMap`].
pub struct SourceFile {
    /// The name of the file that the source came from. Source that doesn't
    /// originate from files has names between angle brackets by convention
    /// (e.g., `<anon>`).
    pub name: FileName,
    /// The complete source code.
    pub src: Option<Arc<String>>,
    /// The source code's hash.
    pub src_hash: SourceFileHash,
    /// Used to enable cargo to use checksums to check if a crate is fresh rather
    /// than mtimes. This might be the same as `src_hash`, and if the requested algorithm
    /// is identical we won't compute it twice.
    pub checksum_hash: Option<SourceFileHash>,
    /// The external source code (used for external crates, which will have a `None`
    /// value as `self.src`.
    pub external_src: FreezeLock<ExternalSource>,
    /// The start position of this source in the `SourceMap`.
    pub start_pos: BytePos,
    /// The byte length of this source after normalization.
    pub normalized_source_len: RelativeBytePos,
    /// The byte length of this source before normalization.
    pub unnormalized_source_len: u32,
    /// Locations of lines beginnings in the source code.
    pub lines: FreezeLock<SourceFileLines>,
    /// Locations of multi-byte characters in the source code.
    pub multibyte_chars: Vec<MultiByteChar>,
    /// Locations of characters removed during normalization.
    pub normalized_pos: Vec<NormalizedPos>,
    /// A hash of the filename & crate-id, used for uniquely identifying source
    /// files within the crate graph and for speeding up hashing in incremental
    /// compilation.
    pub stable_id: StableSourceFileId,
    /// Indicates which crate this `SourceFile` was imported from.
    pub cnum: CrateNum,
}

impl Clone for SourceFile {
    fn clone(&self) -> Self {
        Self {
            name: self.name.clone(),
            src: self.src.clone(),
            src_hash: self.src_hash,
            checksum_hash: self.checksum_hash,
            external_src: self.external_src.clone(),
            start_pos: self.start_pos,
            normalized_source_len: self.normalized_source_len,
            unnormalized_source_len: self.unnormalized_source_len,
            lines: self.lines.clone(),
            multibyte_chars: self.multibyte_chars.clone(),
            normalized_pos: self.normalized_pos.clone(),
            stable_id: self.stable_id,
            cnum: self.cnum,
        }
    }
}

impl<S: SpanEncoder> Encodable<S> for SourceFile {
    fn encode(&self, s: &mut S) {
        self.name.encode(s);
        self.src_hash.encode(s);
        self.checksum_hash.encode(s);
        // Do not encode `start_pos` as it's global state for this session.
        self.normalized_source_len.encode(s);
        self.unnormalized_source_len.encode(s);

        // We are always in `Lines` form by the time we reach here.
        assert!(self.lines.read().is_lines());
        let lines = self.lines();
        // Store the length.
        s.emit_u32(lines.len() as u32);

        // Compute and store the difference list.
        if lines.len() != 0 {
            let max_line_length = if lines.len() == 1 {
                0
            } else {
                lines
                    .array_windows()
                    .map(|&[fst, snd]| snd - fst)
                    .map(|bp| bp.to_usize())
                    .max()
                    .unwrap()
            };

            let bytes_per_diff: usize = match max_line_length {
                0..=0xFF => 1,
                0x100..=0xFFFF => 2,
                _ => 4,
            };

            // Encode the number of bytes used per diff.
            s.emit_u8(bytes_per_diff as u8);

            // Encode the first element.
            assert_eq!(lines[0], RelativeBytePos(0));

            // Encode the difference list.
            let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst);
            let num_diffs = lines.len() - 1;
            let mut raw_diffs;
            match bytes_per_diff {
                1 => {
                    raw_diffs = Vec::with_capacity(num_diffs);
                    for diff in diff_iter {
                        raw_diffs.push(diff.0 as u8);
                    }
                }
                2 => {
                    raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
                    for diff in diff_iter {
                        raw_diffs.extend_from_slice(&(diff.0 as u16).to_le_bytes());
                    }
                }
                4 => {
                    raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
                    for diff in diff_iter {
                        raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
                    }
                }
                _ => unreachable!(),
            }
            s.emit_raw_bytes(&raw_diffs);
        }

        self.multibyte_chars.encode(s);
        self.stable_id.encode(s);
        self.normalized_pos.encode(s);
        self.cnum.encode(s);
    }
}

impl<D: SpanDecoder> Decodable<D> for SourceFile {
    fn decode(d: &mut D) -> SourceFile {
        let name: FileName = Decodable::decode(d);
        let src_hash: SourceFileHash = Decodable::decode(d);
        let checksum_hash: Option<SourceFileHash> = Decodable::decode(d);
        let normalized_source_len: RelativeBytePos = Decodable::decode(d);
        let unnormalized_source_len = Decodable::decode(d);
        let lines = {
            let num_lines: u32 = Decodable::decode(d);
            if num_lines > 0 {
                // Read the number of bytes used per diff.
                let bytes_per_diff = d.read_u8() as usize;

                // Read the difference list.
                let num_diffs = num_lines as usize - 1;
                let raw_diffs = d.read_raw_bytes(bytes_per_diff * num_diffs).to_vec();
                SourceFileLines::Diffs(SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs })
            } else {
                SourceFileLines::Lines(vec![])
            }
        };
        let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
        let stable_id = Decodable::decode(d);
        let normalized_pos: Vec<NormalizedPos> = Decodable::decode(d);
        let cnum: CrateNum = Decodable::decode(d);
        SourceFile {
            name,
            start_pos: BytePos::from_u32(0),
            normalized_source_len,
            unnormalized_source_len,
            src: None,
            src_hash,
            checksum_hash,
            // Unused - the metadata decoder will construct
            // a new SourceFile, filling in `external_src` properly
            external_src: FreezeLock::frozen(ExternalSource::Unneeded),
            lines: FreezeLock::new(lines),
            multibyte_chars,
            normalized_pos,
            stable_id,
            cnum,
        }
    }
}

impl fmt::Debug for SourceFile {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "SourceFile({:?})", self.name)
    }
}

/// This is a [SourceFile] identifier that is used to correlate source files between
/// subsequent compilation sessions (which is something we need to do during
/// incremental compilation).
///
/// It is a hash value (so we can efficiently consume it when stable-hashing
/// spans) that consists of the `FileName` and the `StableCrateId` of the crate
/// the source file is from. The crate id is needed because sometimes the
/// `FileName` is not unique within the crate graph (think `src/lib.rs`, for
/// example).
///
/// The way the crate-id part is handled is a bit special: source files of the
/// local crate are hashed as `(filename, None)`, while source files from
/// upstream crates have a hash of `(filename, Some(stable_crate_id))`. This
/// is because SourceFiles for the local crate are allocated very early in the
/// compilation process when the `StableCrateId` is not yet known. If, due to
/// some refactoring of the compiler, the `StableCrateId` of the local crate
/// were to become available, it would be better to uniformly make this a
/// hash of `(filename, stable_crate_id)`.
///
/// When `SourceFile`s are exported in crate metadata, the `StableSourceFileId`
/// is updated to incorporate the `StableCrateId` of the exporting crate.
#[derive(
    Debug, Clone, Copy, Hash, PartialEq, Eq, StableHash, Encodable, Decodable, Default, PartialOrd,
    Ord
)]
pub struct StableSourceFileId(Hash128);

impl StableSourceFileId {
    fn from_filename_in_current_crate(filename: &FileName) -> Self {
        Self::from_filename_and_stable_crate_id(filename, None)
    }

    pub fn from_filename_for_export(
        filename: &FileName,
        local_crate_stable_crate_id: StableCrateId,
    ) -> Self {
        Self::from_filename_and_stable_crate_id(filename, Some(local_crate_stable_crate_id))
    }

    fn from_filename_and_stable_crate_id(
        filename: &FileName,
        stable_crate_id: Option<StableCrateId>,
    ) -> Self {
        let mut hasher = StableHasher::new();
        filename.hash(&mut hasher);
        stable_crate_id.hash(&mut hasher);
        StableSourceFileId(hasher.finish())
    }
}

impl SourceFile {
    const MAX_FILE_SIZE: u32 = u32::MAX - 1;

    pub fn new(
        name: FileName,
        mut src: String,
        hash_kind: SourceFileHashAlgorithm,
        checksum_hash_kind: Option<SourceFileHashAlgorithm>,
    ) -> Result<Self, OffsetOverflowError> {
        // Compute the file hash before any normalization.
        let src_hash = SourceFileHash::new_in_memory(hash_kind, src.as_bytes());
        let checksum_hash = checksum_hash_kind.map(|checksum_hash_kind| {
            if checksum_hash_kind == hash_kind {
                src_hash
            } else {
                SourceFileHash::new_in_memory(checksum_hash_kind, src.as_bytes())
            }
        });
        // Capture the original source length before normalization.
        let unnormalized_source_len = u32::try_from(src.len()).map_err(|_| OffsetOverflowError)?;
        if unnormalized_source_len > Self::MAX_FILE_SIZE {
            return Err(OffsetOverflowError);
        }

        let normalized_pos = normalize_src(&mut src);

        let stable_id = StableSourceFileId::from_filename_in_current_crate(&name);
        let normalized_source_len = u32::try_from(src.len()).map_err(|_| OffsetOverflowError)?;
        if normalized_source_len > Self::MAX_FILE_SIZE {
            return Err(OffsetOverflowError);
        }

        let (lines, multibyte_chars) = analyze_source_file::analyze_source_file(&src);

        Ok(SourceFile {
            name,
            src: Some(Arc::new(src)),
            src_hash,
            checksum_hash,
            external_src: FreezeLock::frozen(ExternalSource::Unneeded),
            start_pos: BytePos::from_u32(0),
            normalized_source_len: RelativeBytePos::from_u32(normalized_source_len),
            unnormalized_source_len,
            lines: FreezeLock::frozen(SourceFileLines::Lines(lines)),
            multibyte_chars,
            normalized_pos,
            stable_id,
            cnum: LOCAL_CRATE,
        })
    }

    /// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes
    /// it.
    fn convert_diffs_to_lines_frozen(&self) {
        let mut guard = if let Some(guard) = self.lines.try_write() { guard } else { return };

        let SourceFileDiffs { bytes_per_diff, num_diffs, raw_diffs } = match &*guard {
            SourceFileLines::Diffs(diffs) => diffs,
            SourceFileLines::Lines(..) => {
                FreezeWriteGuard::freeze(guard);
                return;
            }
        };

        // Convert from "diffs" form to "lines" form.
        let num_lines = num_diffs + 1;
        let mut lines = Vec::with_capacity(num_lines);
        let mut line_start = RelativeBytePos(0);
        lines.push(line_start);

        assert_eq!(*num_diffs, raw_diffs.len() / bytes_per_diff);
        match bytes_per_diff {
            1 => {
                lines.extend(raw_diffs.into_iter().map(|&diff| {
                    line_start = line_start + RelativeBytePos(diff as u32);
                    line_start
                }));
            }
            2 => {
                lines.extend((0..*num_diffs).map(|i| {
                    let pos = bytes_per_diff * i;
                    let bytes = [raw_diffs[pos], raw_diffs[pos + 1]];
                    let diff = u16::from_le_bytes(bytes);
                    line_start = line_start + RelativeBytePos(diff as u32);
                    line_start
                }));
            }
            4 => {
                lines.extend((0..*num_diffs).map(|i| {
                    let pos = bytes_per_diff * i;
                    let bytes = [
                        raw_diffs[pos],
                        raw_diffs[pos + 1],
                        raw_diffs[pos + 2],
                        raw_diffs[pos + 3],
                    ];
                    let diff = u32::from_le_bytes(bytes);
                    line_start = line_start + RelativeBytePos(diff);
                    line_start
                }));
            }
            _ => unreachable!(),
        }

        *guard = SourceFileLines::Lines(lines);

        FreezeWriteGuard::freeze(guard);
    }

    pub fn lines(&self) -> &[RelativeBytePos] {
        if let Some(SourceFileLines::Lines(lines)) = self.lines.get() {
            return &lines[..];
        }

        outline(|| {
            self.convert_diffs_to_lines_frozen();
            if let Some(SourceFileLines::Lines(lines)) = self.lines.get() {
                return &lines[..];
            }
            unreachable!()
        })
    }

    /// Returns the `BytePos` of the beginning of the current line.
    pub fn line_begin_pos(&self, pos: BytePos) -> BytePos {
        let pos = self.relative_position(pos);
        let line_index = self.lookup_line(pos).unwrap();
        let line_start_pos = self.lines()[line_index];
        self.absolute_position(line_start_pos)
    }

    /// Add externally loaded source.
    /// If the hash of the input doesn't match or no input is supplied via None,
    /// it is interpreted as an error and the corresponding enum variant is set.
    /// The return value signifies whether some kind of source is present.
    pub fn add_external_src<F>(&self, get_src: F) -> bool
    where
        F: FnOnce() -> Option<String>,
    {
        if !self.external_src.is_frozen() {
            let src = get_src();
            let src = src.and_then(|mut src| {
                // The src_hash needs to be computed on the pre-normalized src.
                self.src_hash.matches(&src).then(|| {
                    normalize_src(&mut src);
                    src
                })
            });

            self.external_src.try_write().map(|mut external_src| {
                if let ExternalSource::Foreign {
                    kind: src_kind @ ExternalSourceKind::AbsentOk,
                    ..
                } = &mut *external_src
                {
                    *src_kind = if let Some(src) = src {
                        ExternalSourceKind::Present(Arc::new(src))
                    } else {
                        ExternalSourceKind::AbsentErr
                    };
                } else {
                    panic!("unexpected state {:?}", *external_src)
                }

                // Freeze this so we don't try to load the source again.
                FreezeWriteGuard::freeze(external_src)
            });
        }

        self.src.is_some() || self.external_src.read().get_source().is_some()
    }

    /// Gets a line from the list of pre-computed line-beginnings.
    /// The line number here is 0-based.
    pub fn get_line(&self, line_number: usize) -> Option<Cow<'_, str>> {
        fn get_until_newline(src: &str, begin: usize) -> &str {
            // We can't use `lines.get(line_number+1)` because we might
            // be parsing when we call this function and thus the current
            // line is the last one we have line info for.
            let slice = &src[begin..];
            match slice.find('\n') {
                Some(e) => &slice[..e],
                None => slice,
            }
        }

        let begin = {
            let line = self.lines().get(line_number).copied()?;
            line.to_usize()
        };

        if let Some(ref src) = self.src {
            Some(Cow::from(get_until_newline(src, begin)))
        } else {
            self.external_src
                .borrow()
                .get_source()
                .map(|src| Cow::Owned(String::from(get_until_newline(src, begin))))
        }
    }

    pub fn is_real_file(&self) -> bool {
        self.name.is_real()
    }

    #[inline]
    pub fn is_imported(&self) -> bool {
        self.src.is_none()
    }

    pub fn count_lines(&self) -> usize {
        self.lines().len()
    }

    #[inline]
    pub fn absolute_position(&self, pos: RelativeBytePos) -> BytePos {
        BytePos::from_u32(pos.to_u32() + self.start_pos.to_u32())
    }

    #[inline]
    pub fn relative_position(&self, pos: BytePos) -> RelativeBytePos {
        RelativeBytePos::from_u32(pos.to_u32() - self.start_pos.to_u32())
    }

    #[inline]
    pub fn end_position(&self) -> BytePos {
        self.absolute_position(self.normalized_source_len)
    }

    /// Finds the line containing the given position. The return value is the
    /// index into the `lines` array of this `SourceFile`, not the 1-based line
    /// number. If the source_file is empty or the position is located before the
    /// first line, `None` is returned.
    pub fn lookup_line(&self, pos: RelativeBytePos) -> Option<usize> {
        self.lines().partition_point(|x| x <= &pos).checked_sub(1)
    }

    pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
        if self.is_empty() {
            return self.start_pos..self.start_pos;
        }

        let lines = self.lines();
        assert!(line_index < lines.len());
        if line_index == (lines.len() - 1) {
            self.absolute_position(lines[line_index])..self.end_position()
        } else {
            self.absolute_position(lines[line_index])..self.absolute_position(lines[line_index + 1])
        }
    }

    /// Returns whether or not the file contains the given `SourceMap` byte
    /// position. The position one past the end of the file is considered to be
    /// contained by the file. This implies that files for which `is_empty`
    /// returns true still contain one byte position according to this function.
    #[inline]
    pub fn contains(&self, byte_pos: BytePos) -> bool {
        byte_pos >= self.start_pos && byte_pos <= self.end_position()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.normalized_source_len.to_u32() == 0
    }

    /// Calculates the original byte position relative to the start of the file
    /// based on the given byte position.
    pub fn original_relative_byte_pos(&self, pos: BytePos) -> RelativeBytePos {
        let pos = self.relative_position(pos);

        // Diff before any records is 0. Otherwise use the previously recorded
        // diff as that applies to the following characters until a new diff
        // is recorded.
        let diff = match self.normalized_pos.binary_search_by(|np| np.pos.cmp(&pos)) {
            Ok(i) => self.normalized_pos[i].diff,
            Err(0) => 0,
            Err(i) => self.normalized_pos[i - 1].diff,
        };

        RelativeBytePos::from_u32(pos.0 + diff)
    }

    /// Calculates a normalized byte position from a byte offset relative to the
    /// start of the file.
    ///
    /// When we get an inline assembler error from LLVM during codegen, we
    /// import the expanded assembly code as a new `SourceFile`, which can then
    /// be used for error reporting with spans. However the byte offsets given
    /// to us by LLVM are relative to the start of the original buffer, not the
    /// normalized one. Hence we need to convert those offsets to the normalized
    /// form when constructing spans.
    pub fn normalized_byte_pos(&self, offset: u32) -> BytePos {
        let diff =
            match self.normalized_pos.binary_search_by(|np| (np.pos.0 + np.diff).cmp(&offset)) {
                Ok(i) => self.normalized_pos[i].diff,
                Err(0) => 0,
                Err(i) => self.normalized_pos[i - 1].diff,
            };

        BytePos::from_u32(self.start_pos.0 + offset - diff)
    }

    /// Converts an relative `RelativeBytePos` to a `CharPos` relative to the `SourceFile`.
    fn bytepos_to_file_charpos(&self, bpos: RelativeBytePos) -> CharPos {
        // The number of extra bytes due to multibyte chars in the `SourceFile`.
        let mut total_extra_bytes = 0;

        for mbc in self.multibyte_chars.iter() {
            debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
            if mbc.pos < bpos {
                // Every character is at least one byte, so we only
                // count the actual extra bytes.
                total_extra_bytes += mbc.bytes as u32 - 1;
                // We should never see a byte position in the middle of a
                // character.
                assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
            } else {
                break;
            }
        }

        assert!(total_extra_bytes <= bpos.to_u32());
        CharPos(bpos.to_usize() - total_extra_bytes as usize)
    }

    /// Looks up the file's (1-based) line number and (0-based `CharPos`) column offset, for a
    /// given `RelativeBytePos`.
    fn lookup_file_pos(&self, pos: RelativeBytePos) -> (usize, CharPos) {
        let chpos = self.bytepos_to_file_charpos(pos);
        match self.lookup_line(pos) {
            Some(a) => {
                let line = a + 1; // Line numbers start at 1
                let linebpos = self.lines()[a];
                let linechpos = self.bytepos_to_file_charpos(linebpos);
                let col = chpos - linechpos;
                debug!("byte pos {:?} is on the line at byte pos {:?}", pos, linebpos);
                debug!("char pos {:?} is on the line at char pos {:?}", chpos, linechpos);
                debug!("byte is on line: {}", line);
                assert!(chpos >= linechpos);
                (line, col)
            }
            None => (0, chpos),
        }
    }

    /// Looks up the file's (1-based) line number, (0-based `CharPos`) column offset, and (0-based)
    /// column offset when displayed, for a given `BytePos`.
    pub fn lookup_file_pos_with_col_display(&self, pos: BytePos) -> (usize, CharPos, usize) {
        let pos = self.relative_position(pos);
        let (line, col_or_chpos) = self.lookup_file_pos(pos);
        if line > 0 {
            let Some(code) = self.get_line(line - 1) else {
                // If we don't have the code available, it is ok as a fallback to return the bytepos
                // instead of the "display" column, which is only used to properly show underlines
                // in the terminal.
                // FIXME: we'll want better handling of this in the future for the sake of tools
                // that want to use the display col instead of byte offsets to modify Rust code, but
                // that is a problem for another day, the previous code was already incorrect for
                // both displaying *and* third party tools using the json output naïvely.
                tracing::info!("couldn't find line {line} {:?}", self.name);
                return (line, col_or_chpos, col_or_chpos.0);
            };
            let display_col = code.chars().take(col_or_chpos.0).map(|ch| char_width(ch)).sum();
            (line, col_or_chpos, display_col)
        } else {
            // This is never meant to happen?
            (0, col_or_chpos, col_or_chpos.0)
        }
    }
}

pub fn char_width(ch: char) -> usize {
    // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now,
    // just accept that sometimes the code line will be longer than desired.
    match ch {
        '\t' => 4,
        // Keep the following list in sync with `rustc_errors::emitter::OUTPUT_REPLACEMENTS`. These
        // are control points that we replace before printing with a visible codepoint for the sake
        // of being able to point at them with underlines.
        '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}'
        | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}'
        | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}'
        | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}'
        | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}'
        | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}'
        | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1,
        _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1),
    }
}

pub fn str_width(s: &str) -> usize {
    s.chars().map(char_width).sum()
}

/// Normalizes the source code and records the normalizations.
fn normalize_src(src: &mut String) -> Vec<NormalizedPos> {
    let mut normalized_pos = vec![];
    remove_bom(src, &mut normalized_pos);
    normalize_newlines(src, &mut normalized_pos);
    normalized_pos
}

/// Removes UTF-8 BOM, if any.
fn remove_bom(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
    if src.starts_with('\u{feff}') {
        src.drain(..3);
        normalized_pos.push(NormalizedPos { pos: RelativeBytePos(0), diff: 3 });
    }
}

/// Replaces `\r\n` with `\n` in-place in `src`.
///
/// Leaves any occurrences of lone `\r` unchanged.
fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
    if !src.as_bytes().contains(&b'\r') {
        return;
    }

    // We replace `\r\n` with `\n` in-place, which doesn't break utf-8 encoding.
    // While we *can* call `as_mut_vec` and do surgery on the live string
    // directly, let's rather steal the contents of `src`. This makes the code
    // safe even if a panic occurs.

    let mut buf = std::mem::take(src).into_bytes();
    let mut gap_len = 0;
    let mut tail = buf.as_mut_slice();
    let mut cursor = 0;
    let original_gap = normalized_pos.last().map_or(0, |l| l.diff);
    loop {
        let idx = match find_crlf(&tail[gap_len..]) {
            None => tail.len(),
            Some(idx) => idx + gap_len,
        };
        tail.copy_within(gap_len..idx, 0);
        tail = &mut tail[idx - gap_len..];
        if tail.len() == gap_len {
            break;
        }
        cursor += idx - gap_len;
        gap_len += 1;
        normalized_pos.push(NormalizedPos {
            pos: RelativeBytePos::from_usize(cursor + 1),
            diff: original_gap + gap_len as u32,
        });
    }

    // Account for removed `\r`.
    // After `set_len`, `buf` is guaranteed to contain utf-8 again.
    let new_len = buf.len() - gap_len;
    unsafe {
        buf.set_len(new_len);
        *src = String::from_utf8_unchecked(buf);
    }

    fn find_crlf(src: &[u8]) -> Option<usize> {
        let mut search_idx = 0;
        while let Some(idx) = find_cr(&src[search_idx..]) {
            if src[search_idx..].get(idx + 1) != Some(&b'\n') {
                search_idx += idx + 1;
                continue;
            }
            return Some(search_idx + idx);
        }
        None
    }

    fn find_cr(src: &[u8]) -> Option<usize> {
        src.iter().position(|&b| b == b'\r')
    }
}

// _____________________________________________________________________________
// Pos, BytePos, CharPos
//

pub trait Pos {
    fn from_usize(n: usize) -> Self;
    fn to_usize(&self) -> usize;
    fn from_u32(n: u32) -> Self;
    fn to_u32(&self) -> u32;
}

macro_rules! impl_pos {
    (
        $(
            $(#[$attr:meta])*
            $vis:vis struct $ident:ident($inner_vis:vis $inner_ty:ty);
        )*
    ) => {
        $(
            $(#[$attr])*
            $vis struct $ident($inner_vis $inner_ty);

            impl Pos for $ident {
                #[inline(always)]
                fn from_usize(n: usize) -> $ident {
                    $ident(n as $inner_ty)
                }

                #[inline(always)]
                fn to_usize(&self) -> usize {
                    self.0 as usize
                }

                #[inline(always)]
                fn from_u32(n: u32) -> $ident {
                    $ident(n as $inner_ty)
                }

                #[inline(always)]
                fn to_u32(&self) -> u32 {
                    self.0 as u32
                }
            }

            impl Add for $ident {
                type Output = $ident;

                #[inline(always)]
                fn add(self, rhs: $ident) -> $ident {
                    $ident(self.0 + rhs.0)
                }
            }

            impl Sub for $ident {
                type Output = $ident;

                #[inline(always)]
                fn sub(self, rhs: $ident) -> $ident {
                    $ident(self.0 - rhs.0)
                }
            }
        )*
    };
}

impl_pos! {
    /// A byte offset.
    ///
    /// Keep this small (currently 32-bits), as AST contains a lot of them.
    #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
    pub struct BytePos(pub u32);

    /// A byte offset relative to file beginning.
    #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, StableHash)]
    pub struct RelativeBytePos(pub u32);

    /// A character offset.
    ///
    /// Because of multibyte UTF-8 characters, a byte offset
    /// is not equivalent to a character offset. The [`SourceMap`] will convert [`BytePos`]
    /// values to `CharPos` values as necessary.
    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
    pub struct CharPos(pub usize);
}

impl<S: Encoder> Encodable<S> for BytePos {
    fn encode(&self, s: &mut S) {
        s.emit_u32(self.0);
    }
}

impl<D: Decoder> Decodable<D> for BytePos {
    fn decode(d: &mut D) -> BytePos {
        BytePos(d.read_u32())
    }
}

impl<S: Encoder> Encodable<S> for RelativeBytePos {
    fn encode(&self, s: &mut S) {
        s.emit_u32(self.0);
    }
}

impl<D: Decoder> Decodable<D> for RelativeBytePos {
    fn decode(d: &mut D) -> RelativeBytePos {
        RelativeBytePos(d.read_u32())
    }
}

// _____________________________________________________________________________
// Loc, SourceFileAndLine, SourceFileAndBytePos
//

/// A source code location used for error reporting.
#[derive(Debug, Clone)]
pub struct Loc {
    /// Information about the original source.
    pub file: Arc<SourceFile>,
    /// The (1-based) line number.
    pub line: usize,
    /// The (0-based) column offset.
    pub col: CharPos,
    /// The (0-based) column offset when displayed.
    pub col_display: usize,
}

// Used to be structural records.
#[derive(Debug)]
pub struct SourceFileAndLine {
    pub sf: Arc<SourceFile>,
    /// Index of line, starting from 0.
    pub line: usize,
}
#[derive(Debug)]
pub struct SourceFileAndBytePos {
    pub sf: Arc<SourceFile>,
    pub pos: BytePos,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LineInfo {
    /// Index of line, starting from 0.
    pub line_index: usize,

    /// Column in line where span begins, starting from 0.
    pub start_col: CharPos,

    /// Column in line where span ends, starting from 0, exclusive.
    pub end_col: CharPos,
}

pub struct FileLines {
    pub file: Arc<SourceFile>,
    pub lines: Vec<LineInfo>,
}

pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));

// _____________________________________________________________________________
// SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
//

pub type FileLinesResult = Result<FileLines, SpanLinesError>;

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum SpanLinesError {
    DistinctSources(Box<DistinctSources>),
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum SpanSnippetError {
    IllFormedSpan(Span),
    DistinctSources(Box<DistinctSources>),
    MalformedForSourcemap(MalformedSourceMapPositions),
    SourceNotAvailable { filename: FileName },
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct DistinctSources {
    pub begin: (FileName, BytePos),
    pub end: (FileName, BytePos),
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct MalformedSourceMapPositions {
    pub name: FileName,
    pub source_len: usize,
    pub begin_pos: BytePos,
    pub end_pos: BytePos,
}

/// Range inside of a `Span` used for diagnostics when we only have access to relative positions.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct InnerSpan {
    pub start: usize,
    pub end: usize,
}

impl InnerSpan {
    pub fn new(start: usize, end: usize) -> InnerSpan {
        InnerSpan { start, end }
    }
}

impl StableHash for Span {
    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
        // `stable_hash_span` does all the work.
        hcx.stable_hash_span(self.to_raw_span(), hasher)
    }
}

/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
///
/// The `()` field is necessary: it is non-`pub`, which means values of this
/// type cannot be constructed outside of this crate.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(StableHash)]
pub struct ErrorGuaranteed(());

impl ErrorGuaranteed {
    /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`!
    #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"]
    pub fn unchecked_error_guaranteed() -> Self {
        ErrorGuaranteed(())
    }

    pub fn raise_fatal(self) -> ! {
        FatalError.raise()
    }
}

impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
    #[inline]
    fn encode(&self, _e: &mut E) {
        panic!(
            "should never serialize an `ErrorGuaranteed`, as we do not write metadata or \
            incremental caches in case errors occurred"
        )
    }
}
impl<D: rustc_serialize::Decoder> Decodable<D> for ErrorGuaranteed {
    #[inline]
    fn decode(_d: &mut D) -> ErrorGuaranteed {
        panic!(
            "`ErrorGuaranteed` should never have been serialized to metadata or incremental caches"
        )
    }
}
