Skip to main content

rustc_span/
hygiene.rs

1//! Machinery for hygienic macros.
2//!
3//! Inspired by Matthew Flatt et al., “Macros That Work Together: Compile-Time Bindings, Partial
4//! Expansion, and Definition Contexts,” *Journal of Functional Programming* 22, no. 2
5//! (March 1, 2012): 181–216, <https://doi.org/10.1017/S0956796812000093>.
6
7// Hygiene data is stored in a global variable and accessed via TLS, which
8// means that accesses are somewhat expensive. (`HygieneData::with`
9// encapsulates a single access.) Therefore, on hot code paths it is worth
10// ensuring that multiple HygieneData accesses are combined into a single
11// `HygieneData::with`.
12//
13// This explains why `HygieneData`, `SyntaxContext` and `ExpnId` have interfaces
14// with a certain amount of redundancy in them. For example,
15// `SyntaxContext::outer_expn_data` combines `SyntaxContext::outer` and
16// `ExpnId::expn_data` so that two `HygieneData` accesses can be performed within
17// a single `HygieneData::with` call.
18//
19// It also explains why many functions appear in `HygieneData` and again in
20// `SyntaxContext` or `ExpnId`. For example, `HygieneData::outer` and
21// `SyntaxContext::outer` do the same thing, but the former is for use within a
22// `HygieneData::with` call while the latter is for use outside such a call.
23// When modifying this file it is important to understand this distinction,
24// because getting it wrong can lead to nested `HygieneData::with` calls that
25// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
26
27use std::cell::RefCell;
28use std::hash::{Hash, Hasher};
29use std::marker::PhantomData;
30use std::sync::Arc;
31use std::{fmt, iter, mem};
32
33use rustc_data_structures::fingerprint::Fingerprint;
34use rustc_data_structures::fx::{FxHashMap, FxHashSet};
35use rustc_data_structures::stable_hash::{
36    StableHash, StableHashCtxt, StableHasher, ToStableHashKey,
37};
38use rustc_data_structures::sync::Lock;
39use rustc_data_structures::unhash::UnhashMap;
40use rustc_hashes::Hash64;
41use rustc_index::IndexVec;
42use rustc_macros::{Decodable, Encodable, StableHash};
43use rustc_serialize::{ContextOrd, Decodable, Decoder, Encodable};
44use tracing::{debug, trace};
45
46use crate::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, ModId, StableCrateId};
47use crate::edition::Edition;
48use crate::source_map::SourceMap;
49use crate::symbol::{Symbol, kw, sym};
50use crate::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, with_session_globals};
51
52#[automatically_derived]impl ::core::marker::Copy for SyntaxContext { }
impl SyntaxContext {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0x1FFF_FFFF;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0x1FFF_FFFF);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0x1FFF_FFFF as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0x1FFF_FFFF as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0x1FFF_FFFF) {
            ::core::panicking::panic("assertion failed: value <= 0x1FFF_FFFF")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0x1FFF_FFFF) {
            ::core::panicking::panic("assertion failed: value <= 0x1FFF_FFFF")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for SyntaxContext {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for SyntaxContext {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for SyntaxContext {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl std::default::Default for SyntaxContext {
    #[inline]
    fn default() -> Self { Self::ZERO }
}
impl From<SyntaxContext> for u32 {
    #[inline]
    fn from(v: SyntaxContext) -> u32 { v.as_u32() }
}
impl From<SyntaxContext> for usize {
    #[inline]
    fn from(v: SyntaxContext) -> usize { v.as_usize() }
}
impl From<usize> for SyntaxContext {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for SyntaxContext {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for SyntaxContext {}
impl ::std::cmp::PartialEq for SyntaxContext {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for SyntaxContext {}
impl ::std::hash::Hash for SyntaxContext {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl ::std::fmt::Debug for SyntaxContext {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("#{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
53    /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
54    ///
55    /// See <https://rustc-dev-guide.rust-lang.org/macro-expansion.html> for more explanation.
56    #[max = 0x1FFF_FFFF] // `u32::MAX` >> 3, as `SyntaxContext` should be fit in 29 bits (see `span_encoding`).
57    #[debug_format = "#{}"]
58    #[default]
59    pub struct SyntaxContext {}
60}
61
62// To ensure correctness of incremental compilation,
63// `SyntaxContext` must not implement `Ord` or `PartialOrd`.
64// See https://github.com/rust-lang/rust/issues/90317.
65impl !Ord for SyntaxContext {}
66impl !PartialOrd for SyntaxContext {}
67
68/// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal.
69/// The other fields are only for caching.
70pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
71
72#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for SyntaxContextData {
}
#[automatically_derived]impl ::core::clone::Clone for SyntaxContextData {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<ExpnId>;
        let _: ::core::clone::AssertParamIsClone<Transparency>;
        let _: ::core::clone::AssertParamIsClone<SyntaxContext>;
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for SyntaxContextData { }Copy, #[automatically_derived]impl ::core::fmt::Debug for SyntaxContextData {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            "SyntaxContextData outer_expn outer_transparency parent opaque opaque_and_semiopaque dollar_crate_name";
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.outer_expn, &self.outer_transparency, &self.parent,
                        &self.opaque, &self.opaque_and_semiopaque,
                        &&self.dollar_crate_name];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, names, values)
    }
}Debug)]
73struct SyntaxContextData {
74    /// The last macro expansion in the chain.
75    /// (Here we say the most deeply nested macro expansion is the "outermost" expansion.)
76    outer_expn: ExpnId,
77    /// Transparency of the last macro expansion
78    outer_transparency: Transparency,
79    parent: SyntaxContext,
80    /// This context, but with all transparent and semi-opaque expansions filtered away.
81    opaque: SyntaxContext,
82    /// This context, but with all transparent expansions filtered away.
83    opaque_and_semiopaque: SyntaxContext,
84    /// Name of the crate to which `$crate` with this context would resolve.
85    dollar_crate_name: Symbol,
86}
87
88impl SyntaxContextData {
89    fn root() -> SyntaxContextData {
90        SyntaxContextData {
91            outer_expn: ExpnId::root(),
92            outer_transparency: Transparency::Opaque,
93            parent: SyntaxContext::root(),
94            opaque: SyntaxContext::root(),
95            opaque_and_semiopaque: SyntaxContext::root(),
96            dollar_crate_name: kw::DollarCrate,
97        }
98    }
99
100    fn key(&self) -> SyntaxContextKey {
101        (self.parent, self.outer_expn, self.outer_transparency)
102    }
103}
104
105#[automatically_derived]impl ::core::marker::Copy for ExpnIndex { }
impl ExpnIndex {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0xFFFF_FF00 as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for ExpnIndex {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for ExpnIndex {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for ExpnIndex {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for ExpnIndex {
    #[inline]
    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
        <usize as
                ::std::iter::Step>::steps_between(&Self::index(*start),
            &Self::index(*end))
    }
    #[inline]
    fn forward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_add(u).map(Self::from_usize)
    }
    #[inline]
    fn backward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_sub(u).map(Self::from_usize)
    }
    #[inline]
    fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_add(u);
        (Self::from_usize(s), o)
    }
    #[inline]
    fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_sub(u);
        (Self::from_usize(s), o)
    }
}
impl ::std::cmp::Ord for ExpnIndex {
    #[inline]
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_u32().cmp(&other.as_u32())
    }
}
impl ::std::cmp::PartialOrd for ExpnIndex {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl From<ExpnIndex> for u32 {
    #[inline]
    fn from(v: ExpnIndex) -> u32 { v.as_u32() }
}
impl From<ExpnIndex> for usize {
    #[inline]
    fn from(v: ExpnIndex) -> usize { v.as_usize() }
}
impl From<usize> for ExpnIndex {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for ExpnIndex {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for ExpnIndex {}
impl ::std::cmp::PartialEq for ExpnIndex {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for ExpnIndex {}
impl ::std::hash::Hash for ExpnIndex {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl ::std::fmt::Debug for ExpnIndex {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
106    /// A unique ID associated with a macro invocation and expansion.
107    #[orderable]
108    pub struct ExpnIndex {}
109}
110
111/// A unique ID associated with a macro invocation and expansion.
112#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExpnId {
}
#[automatically_derived]impl ::core::clone::Clone for ExpnId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<CrateNum>;
        let _: ::core::clone::AssertParamIsClone<ExpnIndex>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for ExpnId { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for ExpnId {
}
#[automatically_derived]impl ::core::cmp::PartialEq for ExpnId {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.krate == other.krate && self.local_id == other.local_id
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ExpnId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<CrateNum>;
        let _: ::core::cmp::AssertParamIsEq<ExpnIndex>;
    }
}Eq, #[automatically_derived]impl ::core::hash::Hash for ExpnId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.krate, state);
        ::core::hash::Hash::hash(&self.local_id, state)
    }
}Hash)]
113pub struct ExpnId {
114    pub krate: CrateNum,
115    pub local_id: ExpnIndex,
116}
117
118impl fmt::Debug for ExpnId {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        // Generate crate_::{{expn_}}.
121        f.write_fmt(format_args!("{0:?}::{{{{expn{1}}}}}", self.krate,
        self.local_id.as_u32()))write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.as_u32())
122    }
123}
124
125#[automatically_derived]impl ::core::marker::Copy for LocalExpnId { }
impl LocalExpnId {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0xFFFF_FF00 as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for LocalExpnId {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for LocalExpnId {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for LocalExpnId {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl std::default::Default for LocalExpnId {
    #[inline]
    fn default() -> Self { Self::ZERO }
}
impl From<LocalExpnId> for u32 {
    #[inline]
    fn from(v: LocalExpnId) -> u32 { v.as_u32() }
}
impl From<LocalExpnId> for usize {
    #[inline]
    fn from(v: LocalExpnId) -> usize { v.as_usize() }
}
impl From<usize> for LocalExpnId {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for LocalExpnId {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for LocalExpnId {}
impl ::std::cmp::PartialEq for LocalExpnId {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for LocalExpnId {}
impl ::std::hash::Hash for LocalExpnId {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl ::std::fmt::Debug for LocalExpnId {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("expn{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
126    /// A unique ID associated with a macro invocation and expansion.
127    #[debug_format = "expn{}"]
128    #[default]
129    pub struct LocalExpnId {}
130}
131
132// To ensure correctness of incremental compilation,
133// `LocalExpnId` must not implement `Ord` or `PartialOrd`.
134// See https://github.com/rust-lang/rust/issues/90317.
135impl !Ord for LocalExpnId {}
136impl !PartialOrd for LocalExpnId {}
137
138/// A unique hash value associated to an expansion.
139#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExpnHash {
}
#[automatically_derived]impl ::core::clone::Clone for ExpnHash {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Fingerprint>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for ExpnHash { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for ExpnHash
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for ExpnHash {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ExpnHash {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Fingerprint>;
    }
}Eq, #[automatically_derived]impl ::core::hash::Hash for ExpnHash {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]impl ::core::fmt::Debug for ExpnHash {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "ExpnHash",
            &&self.0)
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for ExpnHash {
            fn encode(&self, __encoder: &mut __E) {
                let ExpnHash(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for ExpnHash {
            fn decode(__decoder: &mut __D) -> Self {
                ExpnHash(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ExpnHash {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ExpnHash(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
140pub struct ExpnHash(Fingerprint);
141
142impl<E> ContextOrd<E> for ExpnHash {
143    fn stable_cmp_with_context(_context: E) -> impl FnMut(&Self, &Self) -> std::cmp::Ordering {
144        |h1, h2| h1.0.cmp(&h2.0)
145    }
146}
147
148impl ExpnHash {
149    /// Returns the [StableCrateId] identifying the crate this [ExpnHash]
150    /// originates from.
151    #[inline]
152    pub fn stable_crate_id(self) -> StableCrateId {
153        StableCrateId(self.0.split().0)
154    }
155
156    /// Returns the crate-local part of the [ExpnHash].
157    ///
158    /// Used for assertions.
159    #[inline]
160    pub fn local_hash(self) -> Hash64 {
161        self.0.split().1
162    }
163
164    #[inline]
165    pub fn is_root(self) -> bool {
166        self.0 == Fingerprint::ZERO
167    }
168
169    /// Builds a new [ExpnHash] with the given [StableCrateId] and
170    /// `local_hash`, where `local_hash` must be unique within its crate.
171    fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> ExpnHash {
172        ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
173    }
174}
175
176/// A property of a macro expansion that determines how identifiers
177/// produced by that expansion are resolved.
178#[derive(#[automatically_derived]impl ::core::marker::Copy for Transparency { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Transparency {
}
#[automatically_derived]impl ::core::clone::Clone for Transparency {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    Transparency {
}
#[automatically_derived]impl ::core::cmp::PartialEq for Transparency {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for Transparency { }Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for Transparency {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self),
            &::core::intrinsics::discriminant_value(other))
    }
}PartialOrd, #[automatically_derived]impl ::core::hash::Hash for Transparency {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state)
    }
}Hash, #[automatically_derived]impl ::core::fmt::Debug for Transparency {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Transparency::Transparent => "Transparent",
                Transparency::SemiOpaque => "SemiOpaque",
                Transparency::Opaque => "Opaque",
            })
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Transparency {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Transparency::Transparent => { 0usize }
                        Transparency::SemiOpaque => { 1usize }
                        Transparency::Opaque => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Transparency {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Transparency::Transparent }
                    1usize => { Transparency::SemiOpaque }
                    2usize => { Transparency::Opaque }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Transparency`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
179#[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Transparency
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    Transparency::Transparent =>
                        0u8.stable_hash(__hcx, __hasher),
                    Transparency::SemiOpaque =>
                        1u8.stable_hash(__hcx, __hasher),
                    Transparency::Opaque => 2u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    Transparency::Transparent => {}
                    Transparency::SemiOpaque => {}
                    Transparency::Opaque => {}
                }
            }
        }
    };StableHash)]
180pub enum Transparency {
181    /// Identifier produced by a transparent expansion is always resolved at call-site.
182    /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
183    Transparent,
184    /// Identifier produced by a semi-opaque expansion may be resolved
185    /// either at call-site or at definition-site.
186    /// If it's a local variable, label or `$crate` then it's resolved at def-site.
187    /// Otherwise it's resolved at call-site.
188    /// `macro_rules` macros behave like this, built-in macros currently behave like this too,
189    /// but that's an implementation detail.
190    SemiOpaque,
191    /// Identifier produced by an opaque expansion is always resolved at definition-site.
192    /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
193    Opaque,
194}
195
196impl Transparency {
197    pub fn fallback(macro_rules: bool) -> Self {
198        if macro_rules { Transparency::SemiOpaque } else { Transparency::Opaque }
199    }
200}
201
202impl LocalExpnId {
203    /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
204    pub const ROOT: LocalExpnId = LocalExpnId::ZERO;
205
206    #[inline]
207    fn from_raw(idx: ExpnIndex) -> LocalExpnId {
208        LocalExpnId::from_u32(idx.as_u32())
209    }
210
211    #[inline]
212    pub fn as_raw(self) -> ExpnIndex {
213        ExpnIndex::from_u32(self.as_u32())
214    }
215
216    pub fn fresh_empty() -> LocalExpnId {
217        HygieneData::with(|data| {
218            let expn_id = data.local_expn_data.push(None);
219            let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO));
220            if true {
    {
        match (&expn_id, &_eid) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(expn_id, _eid);
221            expn_id
222        })
223    }
224
225    pub fn fresh(mut expn_data: ExpnData, hcx: impl StableHashCtxt) -> LocalExpnId {
226        if true {
    {
        match (&expn_data.parent.krate, &LOCAL_CRATE) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
227        let expn_hash = update_disambiguator(&mut expn_data, hcx);
228        HygieneData::with(|data| {
229            let expn_id = data.local_expn_data.push(Some(expn_data));
230            let _eid = data.local_expn_hashes.push(expn_hash);
231            if true {
    {
        match (&expn_id, &_eid) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(expn_id, _eid);
232            let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id());
233            if true {
    if !_old_id.is_none() {
        ::core::panicking::panic("assertion failed: _old_id.is_none()")
    };
};debug_assert!(_old_id.is_none());
234            expn_id
235        })
236    }
237
238    #[inline]
239    pub fn expn_data(self) -> ExpnData {
240        HygieneData::with(|data| data.local_expn_data(self).clone())
241    }
242
243    #[inline]
244    pub fn to_expn_id(self) -> ExpnId {
245        ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() }
246    }
247
248    #[inline]
249    pub fn set_expn_data(self, mut expn_data: ExpnData, hcx: impl StableHashCtxt) {
250        if true {
    {
        match (&expn_data.parent.krate, &LOCAL_CRATE) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
251        let expn_hash = update_disambiguator(&mut expn_data, hcx);
252        HygieneData::with(|data| {
253            let old_expn_data = &mut data.local_expn_data[self];
254            if !old_expn_data.is_none() {
    {
        ::core::panicking::panic_fmt(format_args!("expansion data is reset for an expansion ID"));
    }
};assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
255            *old_expn_data = Some(expn_data);
256            if true {
    {
        match (&data.local_expn_hashes[self].0, &Fingerprint::ZERO) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO);
257            data.local_expn_hashes[self] = expn_hash;
258            let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id());
259            if true {
    if !_old_id.is_none() {
        ::core::panicking::panic("assertion failed: _old_id.is_none()")
    };
};debug_assert!(_old_id.is_none());
260        });
261    }
262
263    #[inline]
264    pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool {
265        self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
266    }
267
268    /// Returns span for the macro which originally caused this expansion to happen.
269    ///
270    /// Stops backtracing at include! boundary.
271    #[inline]
272    pub fn expansion_cause(self) -> Option<Span> {
273        self.to_expn_id().expansion_cause()
274    }
275}
276
277impl ExpnId {
278    /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
279    /// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0.
280    pub const fn root() -> ExpnId {
281        ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::ZERO }
282    }
283
284    #[inline]
285    pub fn expn_hash(self) -> ExpnHash {
286        HygieneData::with(|data| data.expn_hash(self))
287    }
288
289    #[inline]
290    pub fn from_hash(hash: ExpnHash) -> Option<ExpnId> {
291        HygieneData::with(|data| data.expn_hash_to_expn_id.get(&hash).copied())
292    }
293
294    #[inline]
295    pub fn as_local(self) -> Option<LocalExpnId> {
296        if self.krate == LOCAL_CRATE { Some(LocalExpnId::from_raw(self.local_id)) } else { None }
297    }
298
299    #[inline]
300    #[track_caller]
301    pub fn expect_local(self) -> LocalExpnId {
302        self.as_local().unwrap()
303    }
304
305    #[inline]
306    pub fn expn_data(self) -> ExpnData {
307        HygieneData::with(|data| data.expn_data(self).clone())
308    }
309
310    #[inline]
311    pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
312        // a few "fast path" cases to avoid locking HygieneData
313        if ancestor == ExpnId::root() || ancestor == self {
314            return true;
315        }
316        if ancestor.krate != self.krate {
317            return false;
318        }
319        HygieneData::with(|data| data.is_descendant_of(self, ancestor))
320    }
321
322    /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
323    /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
324    #[inline]
325    pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
326        // fast path to avoid locking: everything is a descendant of the root context's
327        // outer expansion
328        if ctxt.is_root() {
329            return true;
330        }
331        HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt)))
332    }
333
334    /// Returns span for the macro which originally caused this expansion to happen.
335    ///
336    /// Stops backtracing at include! boundary.
337    pub fn expansion_cause(mut self) -> Option<Span> {
338        let mut last_macro = None;
339        loop {
340            // Fast path to avoid locking.
341            if self == ExpnId::root() {
342                break;
343            }
344            let expn_data = self.expn_data();
345            // Stop going up the backtrace once include! is encountered
346            if expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include) {
347                break;
348            }
349            self = expn_data.call_site.ctxt().outer_expn();
350            last_macro = Some(expn_data.call_site);
351        }
352        last_macro
353    }
354}
355
356#[derive(#[automatically_derived]impl<TKey: ::core::default::Default,
    TRemappedKey: ::core::default::Default> ::core::default::Default for
    HygieneRemappingResults<TKey, TRemappedKey> {
    #[inline]
    fn default() -> Self {
        HygieneRemappingResults {
            remapping: ::core::default::Default::default(),
            first_non_det_index: ::core::default::Default::default(),
            data: ::core::default::Default::default(),
        }
    }
}Default)]
357pub struct HygieneRemappingResults<TKey, TRemappedKey> {
358    remapping: FxHashMap<u32, u32>,
359    first_non_det_index: u32,
360    data: PhantomData<(TKey, TRemappedKey)>,
361}
362
363pub trait RemappableIdx = Hash + Eq + Copy;
364impl<TKey: RemappableIdx + Into<u32>, TRemappedKey: RemappableIdx + From<u32>>
365    HygieneRemappingResults<TKey, TRemappedKey>
366{
367    #[inline]
368    pub fn map_id(&self, idx: TKey) -> TRemappedKey {
369        let raw_idx: u32 = idx.into();
370        let remapped_idx = if raw_idx < self.first_non_det_index {
371            raw_idx
372        } else {
373            self.remapping.get(&raw_idx).copied().unwrap_or(raw_idx)
374        };
375
376        TRemappedKey::from(remapped_idx)
377    }
378}
379
380/// Includes common logic for remapping both expansion ids and syntax contexts.
381/// FIXME: this solution does not take into account syntax contexts and expansion ids
382/// that are allocated during metadata encoding, if we will have non-determinism there
383/// this remapping will not help as it is constructed before metadata encoding.
384pub trait HygieneRemapper<T> {
385    fn stable_hash(&self, t: T, hcx: &mut impl StableHashCtxt, hasher: &mut StableHasher);
386    fn len(&self) -> usize;
387    fn first_non_det_index_mut(&mut self) -> &mut Option<T>;
388    fn first_non_det_index(&self) -> u32;
389
390    fn commit_end_of_determinism(&mut self)
391    where
392        T: From<u32>,
393    {
394        let len = self.len() as u32;
395
396        let prev = self.first_non_det_index_mut().replace(T::from(len));
397        if !prev.is_none() {
    {
        ::core::panicking::panic_fmt(format_args!("this function can be called only once"));
    }
}assert!(prev.is_none(), "this function can be called only once")
398    }
399
400    fn remapping_results<TRemappedKey>(
401        &self,
402        hcx: &mut impl StableHashCtxt,
403    ) -> HygieneRemappingResults<T, TRemappedKey>
404    where
405        T: RemappableIdx + From<u32>,
406    {
407        let start = self.first_non_det_index();
408        let range = start..self.len() as u32;
409
410        let mut indices_to_remap = range.collect::<Vec<_>>();
411        indices_to_remap.sort_by_cached_key(|&key| {
412            let hasher = &mut StableHasher::new();
413            self.stable_hash(T::from(key), hcx, hasher);
414
415            hasher.finish()
416        });
417
418        let mut remapping = FxHashMap::default();
419
420        for (idx, key) in indices_to_remap.into_iter().enumerate() {
421            let from = key;
422            let to = start + idx as u32;
423
424            if from != to {
425                remapping.insert(from, to);
426            }
427        }
428
429        HygieneRemappingResults { remapping, first_non_det_index: start, data: PhantomData }
430    }
431}
432
433pub struct SyntaxContextRemapper<'a>(&'a mut HygieneData);
434impl SyntaxContextRemapper<'_> {
435    pub fn with<T>(f: impl FnOnce(SyntaxContextRemapper<'_>) -> T) -> T {
436        HygieneData::with(|data| f(SyntaxContextRemapper(data)))
437    }
438}
439
440pub struct LocalExpnIdRemapper<'a>(&'a mut HygieneData);
441impl LocalExpnIdRemapper<'_> {
442    pub fn with<T>(f: impl FnOnce(LocalExpnIdRemapper<'_>) -> T) -> T {
443        HygieneData::with(|data| f(LocalExpnIdRemapper(data)))
444    }
445}
446
447impl HygieneRemapper<SyntaxContext> for SyntaxContextRemapper<'_> {
448    #[inline]
449    fn len(&self) -> usize {
450        self.0.syntax_context_data.len()
451    }
452
453    #[inline]
454    fn first_non_det_index_mut(&mut self) -> &mut Option<SyntaxContext> {
455        &mut self.0.first_non_det_syntax_context
456    }
457
458    #[inline]
459    fn first_non_det_index(&self) -> u32 {
460        self.0.first_non_det_syntax_context.map(|s| s.as_u32()).expect("must be set at this point")
461    }
462
463    #[inline]
464    fn stable_hash(
465        &self,
466        ctxt: SyntaxContext,
467        hcx: &mut impl StableHashCtxt,
468        hasher: &mut StableHasher,
469    ) {
470        ctxt.stable_hash_internal(Some(self.0), hcx, hasher);
471    }
472}
473
474impl HygieneRemapper<LocalExpnId> for LocalExpnIdRemapper<'_> {
475    #[inline]
476    fn len(&self) -> usize {
477        self.0.local_expn_data.len()
478    }
479
480    #[inline]
481    fn first_non_det_index_mut(&mut self) -> &mut Option<LocalExpnId> {
482        &mut self.0.first_non_det_local_expn_id
483    }
484
485    #[inline]
486    fn first_non_det_index(&self) -> u32 {
487        self.0.first_non_det_local_expn_id.map(|l| l.as_u32()).expect("must be set at this point")
488    }
489
490    #[inline]
491    fn stable_hash(
492        &self,
493        local_expn_id: LocalExpnId,
494        hcx: &mut impl StableHashCtxt,
495        hasher: &mut StableHasher,
496    ) {
497        local_expn_id.to_expn_id().stable_hash_internal(Some(self.0), hcx, hasher);
498    }
499}
500
501#[derive(#[automatically_derived]impl ::core::fmt::Debug for HygieneData {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            "HygieneData local_expn_data local_expn_hashes foreign_expn_data foreign_expn_hashes expn_hash_to_expn_id syntax_context_data first_non_det_syntax_context first_non_det_local_expn_id syntax_context_map expn_data_disambiguators";
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.local_expn_data, &self.local_expn_hashes,
                        &self.foreign_expn_data, &self.foreign_expn_hashes,
                        &self.expn_hash_to_expn_id, &self.syntax_context_data,
                        &self.first_non_det_syntax_context,
                        &self.first_non_det_local_expn_id, &self.syntax_context_map,
                        &&self.expn_data_disambiguators];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, names, values)
    }
}Debug)]
502pub(crate) struct HygieneData {
503    /// Each expansion should have an associated expansion data, but sometimes there's a delay
504    /// between creation of an expansion ID and obtaining its data (e.g. macros are collected
505    /// first and then resolved later), so we use an `Option` here.
506    local_expn_data: IndexVec<LocalExpnId, Option<ExpnData>>,
507    local_expn_hashes: IndexVec<LocalExpnId, ExpnHash>,
508    /// Data and hash information from external crates. We may eventually want to remove these
509    /// maps, and fetch the information directly from the other crate's metadata like DefIds do.
510    foreign_expn_data: FxHashMap<ExpnId, ExpnData>,
511    foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
512    expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
513    syntax_context_data: IndexVec<SyntaxContext, SyntaxContextData>,
514    first_non_det_syntax_context: Option<SyntaxContext>,
515    first_non_det_local_expn_id: Option<LocalExpnId>,
516    syntax_context_map: FxHashMap<SyntaxContextKey, SyntaxContext>,
517    /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
518    /// This is used by `update_disambiguator` to keep track of which `ExpnData`s
519    /// would have collisions without a disambiguator.
520    /// The keys of this map are always computed with `ExpnData.disambiguator`
521    /// set to 0.
522    expn_data_disambiguators: UnhashMap<Hash64, u32>,
523}
524
525impl HygieneData {
526    pub(crate) fn new(edition: Edition) -> Self {
527        let root_data = ExpnData::default(
528            ExpnKind::Root,
529            DUMMY_SP,
530            edition,
531            Some(CRATE_DEF_ID.to_def_id()),
532            None,
533        );
534
535        // Index 0 is the root context, and nothing but its `dollar_crate_name` is ever
536        // mutated afterwards. The lock-free root paths on `SyntaxContext` rely on that.
537        let root_ctxt_data = SyntaxContextData::root();
538        HygieneData {
539            local_expn_data: IndexVec::from_elem_n(Some(root_data), 1),
540            local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1),
541            foreign_expn_data: FxHashMap::default(),
542            foreign_expn_hashes: FxHashMap::default(),
543            expn_hash_to_expn_id: iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
544                .collect(),
545            syntax_context_data: IndexVec::from_elem_n(root_ctxt_data, 1),
546            syntax_context_map: iter::once((root_ctxt_data.key(), SyntaxContext::root())).collect(),
547            expn_data_disambiguators: UnhashMap::default(),
548            first_non_det_syntax_context: None,
549            first_non_det_local_expn_id: None,
550        }
551    }
552
553    #[inline]
554    fn with<R>(f: impl FnOnce(&mut HygieneData) -> R) -> R {
555        with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
556    }
557
558    #[inline]
559    fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
560        match expn_id.as_local() {
561            Some(expn_id) => self.local_expn_hashes[expn_id],
562            None => self.foreign_expn_hashes[&expn_id],
563        }
564    }
565
566    #[inline]
567    fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
568        self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
569    }
570
571    fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
572        if let Some(expn_id) = expn_id.as_local() {
573            self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
574        } else {
575            &self.foreign_expn_data[&expn_id]
576        }
577    }
578
579    fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
580        // a couple "fast path" cases to avoid traversing parents in the loop below
581        if ancestor == ExpnId::root() {
582            return true;
583        }
584        if expn_id.krate != ancestor.krate {
585            return false;
586        }
587        loop {
588            if expn_id == ancestor {
589                return true;
590            }
591            if expn_id == ExpnId::root() {
592                return false;
593            }
594            expn_id = self.expn_data(expn_id).parent;
595        }
596    }
597
598    #[inline]
599    fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
600        self.syntax_context_data[ctxt].opaque
601    }
602
603    #[inline]
604    fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
605        self.syntax_context_data[ctxt].opaque_and_semiopaque
606    }
607
608    /// See [`SyntaxContextData::outer_expn`]
609    #[inline]
610    fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
611        self.syntax_context_data[ctxt].outer_expn
612    }
613
614    /// The last macro expansion and its Transparency
615    #[inline]
616    fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
617        let data = &self.syntax_context_data[ctxt];
618        (data.outer_expn, data.outer_transparency)
619    }
620
621    #[inline]
622    fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
623        self.syntax_context_data[ctxt].parent
624    }
625
626    fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) {
627        let outer_mark = self.outer_mark(*ctxt);
628        *ctxt = self.parent_ctxt(*ctxt);
629        outer_mark
630    }
631
632    fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
633        let mut marks = Vec::new();
634        while !ctxt.is_root() {
635            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:635",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(635u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("marks: getting parent of {0:?}",
                                                    ctxt) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("marks: getting parent of {:?}", ctxt);
636            marks.push(self.outer_mark(ctxt));
637            ctxt = self.parent_ctxt(ctxt);
638        }
639        marks.reverse();
640        marks
641    }
642
643    fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
644        let orig_span = span;
645        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:645",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(645u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain({0:?}, {1:?})",
                                                    span, to) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain({:?}, {:?})", span, to);
646        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:646",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(646u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain: span ctxt = {0:?}",
                                                    span.ctxt()) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain: span ctxt = {:?}", span.ctxt());
647        while span.ctxt() != to && span.from_expansion() {
648            let outer_expn = self.outer_expn(span.ctxt());
649            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:649",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(649u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain({0:?}): outer_expn={1:?}",
                                                    span, outer_expn) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
650            let expn_data = self.expn_data(outer_expn);
651            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:651",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(651u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain({0:?}): expn_data={1:?}",
                                                    span, expn_data) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
652            span = expn_data.call_site;
653        }
654        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:654",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(654u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain: for span {0:?} >>> return span = {1:?}",
                                                    orig_span, span) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain: for span {:?} >>> return span = {:?}", orig_span, span);
655        span
656    }
657
658    fn walk_chain_collapsed(&self, mut span: Span, to: Span) -> Span {
659        let orig_span = span;
660        let mut ret_span = span;
661        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:661",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(661u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain_collapsed({0:?}, {1:?})",
                                                    span, to) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain_collapsed({:?}, {:?})", span, to);
662        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:662",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(662u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain_collapsed: span ctxt = {0:?}",
                                                    span.ctxt()) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
663        while let ctxt = span.ctxt()
664            && !ctxt.is_root()
665            && ctxt != to.ctxt()
666        {
667            let outer_expn = self.outer_expn(ctxt);
668            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:668",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(668u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain_collapsed({0:?}): outer_expn={1:?}",
                                                    span, outer_expn) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
669            let expn_data = self.expn_data(outer_expn);
670            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:670",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(670u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain_collapsed({0:?}): expn_data={1:?}",
                                                    span, expn_data) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
671            span = expn_data.call_site;
672            if expn_data.collapse_debuginfo {
673                ret_span = span;
674            }
675        }
676        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:676",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(676u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("walk_chain_collapsed: for span {0:?} >>> return span = {1:?}",
                                                    orig_span, ret_span) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("walk_chain_collapsed: for span {:?} >>> return span = {:?}", orig_span, ret_span);
677        ret_span
678    }
679
680    fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
681        let mut scope = None;
682        while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
683            scope = Some(self.remove_mark(ctxt).0);
684        }
685        scope
686    }
687
688    fn apply_mark(
689        &mut self,
690        ctxt: SyntaxContext,
691        expn_id: ExpnId,
692        transparency: Transparency,
693    ) -> SyntaxContext {
694        {
    match (&expn_id, &ExpnId::root()) {
        (left_val, right_val) => {
            if *left_val == *right_val {
                let kind = ::core::panicking::AssertKind::Ne;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_ne!(expn_id, ExpnId::root());
695        if transparency == Transparency::Opaque {
696            return self.alloc_ctxt(ctxt, expn_id, transparency);
697        }
698
699        let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
700        let mut call_site_ctxt = if transparency == Transparency::SemiOpaque {
701            self.normalize_to_macros_2_0(call_site_ctxt)
702        } else {
703            self.normalize_to_macro_rules(call_site_ctxt)
704        };
705
706        if call_site_ctxt.is_root() {
707            return self.alloc_ctxt(ctxt, expn_id, transparency);
708        }
709
710        // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
711        // macros 2.0 expansion, i.e., a macros 1.0 invocation is in a macros 2.0 definition.
712        //
713        // In this case, the tokens from the macros 1.0 definition inherit the hygiene
714        // at their invocation. That is, we pretend that the macros 1.0 definition
715        // was defined at its invocation (i.e., inside the macros 2.0 definition)
716        // so that the macros 2.0 definition remains hygienic.
717        //
718        // See the example at `test/ui/hygiene/legacy_interaction.rs`.
719        for (expn_id, transparency) in self.marks(ctxt) {
720            call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
721        }
722        self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
723    }
724
725    /// Allocate a new context with the given key, or retrieve it from cache if the given key
726    /// already exists. The auxiliary fields are calculated from the key.
727    fn alloc_ctxt(
728        &mut self,
729        parent: SyntaxContext,
730        expn_id: ExpnId,
731        transparency: Transparency,
732    ) -> SyntaxContext {
733        // Look into the cache first.
734        let key = (parent, expn_id, transparency);
735        if let Some(ctxt) = self.syntax_context_map.get(&key) {
736            return *ctxt;
737        }
738
739        // Reserve a new syntax context.
740        // The inserted dummy data can only be potentially accessed by nested `alloc_ctxt` calls,
741        // the assert below ensures that it doesn't happen.
742        let ctxt = self
743            .syntax_context_data
744            .push(SyntaxContextData { dollar_crate_name: sym::dummy, ..SyntaxContextData::root() });
745
746        self.syntax_context_map.insert(key, ctxt);
747
748        // Opaque and semi-opaque versions of the parent. Note that they may be equal to the
749        // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
750        // and `parent_opaque_and_semiopaque` == `parent` if the expn contains only (semi-)opaques.
751        let parent_data = &self.syntax_context_data[parent];
752        {
    match (&parent_data.dollar_crate_name, &sym::dummy) {
        (left_val, right_val) => {
            if *left_val == *right_val {
                let kind = ::core::panicking::AssertKind::Ne;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_ne!(parent_data.dollar_crate_name, sym::dummy);
753        let parent_opaque = parent_data.opaque;
754        let parent_opaque_and_semiopaque = parent_data.opaque_and_semiopaque;
755
756        // Evaluate opaque and semi-opaque versions of the new syntax context.
757        let (opaque, opaque_and_semiopaque) = match transparency {
758            Transparency::Transparent => (parent_opaque, parent_opaque_and_semiopaque),
759            Transparency::SemiOpaque => (
760                parent_opaque,
761                // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques.
762                self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency),
763            ),
764            Transparency::Opaque => (
765                // Will be the same as `ctxt` if the expn chain contains only opaques.
766                self.alloc_ctxt(parent_opaque, expn_id, transparency),
767                // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques.
768                self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency),
769            ),
770        };
771
772        // Fill the full data, now that we have it.
773        self.syntax_context_data[ctxt] = SyntaxContextData {
774            outer_expn: expn_id,
775            outer_transparency: transparency,
776            parent,
777            opaque,
778            opaque_and_semiopaque,
779            dollar_crate_name: kw::DollarCrate,
780        };
781        ctxt
782    }
783}
784
785pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
786    HygieneData::with(|data| data.walk_chain(span, to))
787}
788
789/// In order to have good line stepping behavior in debugger, for the given span we return its
790/// outermost macro call site that still has a `#[collapse_debuginfo(yes)]` property on it.
791/// We also stop walking call sites at the function body level because no line stepping can occur
792/// at the level above that.
793/// The returned span can then be used in emitted debuginfo.
794pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
795    HygieneData::with(|data| data.walk_chain_collapsed(span, to))
796}
797
798pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
799    // The new contexts that need updating are at the end of the list and have `$crate` as a name.
800    let mut to_update = ::alloc::vec::Vec::new()vec![];
801    HygieneData::with(|data| {
802        for (idx, scdata) in data.syntax_context_data.iter_enumerated().rev() {
803            if scdata.dollar_crate_name == kw::DollarCrate {
804                to_update.push((idx, kw::DollarCrate));
805            } else {
806                break;
807            }
808        }
809    });
810    // The callback must be called from outside of the `HygieneData` lock,
811    // since it will try to acquire it too.
812    for (ctxt, name) in &mut to_update {
813        *name = get_name(*ctxt);
814    }
815    HygieneData::with(|data| {
816        for (ctxt, name) in to_update {
817            data.syntax_context_data[ctxt].dollar_crate_name = name;
818        }
819    })
820}
821
822pub fn debug_hygiene_data(verbose: bool) -> String {
823    HygieneData::with(|data| {
824        if verbose {
825            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:#?}", data))
    })format!("{data:#?}")
826        } else {
827            let mut s = String::from("Expansions:");
828            let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| {
829                s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\n{0:?}: parent: {1:?}, call_site_ctxt: {2:?}, def_site_ctxt: {3:?}, kind: {4:?}",
                id, expn_data.parent, expn_data.call_site.ctxt(),
                expn_data.def_site.ctxt(), expn_data.kind))
    })format!(
830                    "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
831                    id,
832                    expn_data.parent,
833                    expn_data.call_site.ctxt(),
834                    expn_data.def_site.ctxt(),
835                    expn_data.kind,
836                ))
837            };
838            data.local_expn_data.iter_enumerated().for_each(|(id, expn_data)| {
839                let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID");
840                debug_expn_data((&id.to_expn_id(), expn_data))
841            });
842
843            // Sort the hash map for more reproducible output.
844            // Because of this, it is fine to rely on the unstable iteration order of the map.
845            #[allow(rustc::potential_query_instability)]
846            let mut foreign_expn_data: Vec<_> = data.foreign_expn_data.iter().collect();
847            foreign_expn_data.sort_by_key(|(id, _)| (id.krate, id.local_id));
848            foreign_expn_data.into_iter().for_each(debug_expn_data);
849            s.push_str("\n\nSyntaxContexts:");
850            data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
851                s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\n#{0}: parent: {1:?}, outer_mark: ({2:?}, {3:?})",
                id, ctxt.parent, ctxt.outer_expn, ctxt.outer_transparency))
    })format!(
852                    "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
853                    id, ctxt.parent, ctxt.outer_expn, ctxt.outer_transparency,
854                ));
855            });
856            s
857        }
858    })
859}
860
861impl SyntaxContext {
862    #[inline(always)]
863    pub const fn root() -> SyntaxContext {
864        SyntaxContext::from_u32(0)
865    }
866
867    #[inline]
868    pub const fn is_root(self) -> bool {
869        self.as_u32() == SyntaxContext::root().as_u32()
870    }
871
872    /// Extend a syntax context with a given expansion and transparency.
873    #[inline]
874    pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
875        HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
876    }
877
878    /// Pulls a single mark off of the syntax context. This effectively moves the
879    /// context up one macro definition level. That is, if we have a nested macro
880    /// definition as follows:
881    ///
882    /// ```ignore (illustrative)
883    /// macro_rules! f {
884    ///    macro_rules! g {
885    ///        ...
886    ///    }
887    /// }
888    /// ```
889    ///
890    /// and we have a SyntaxContext that is referring to something declared by an invocation
891    /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
892    /// invocation of f that created g1.
893    /// Returns the mark that was removed.
894    #[inline]
895    pub fn remove_mark(&mut self) -> ExpnId {
896        HygieneData::with(|data| data.remove_mark(self).0)
897    }
898
899    #[inline]
900    pub fn marks(self) -> Vec<(ExpnId, Transparency)> {
901        HygieneData::with(|data| data.marks(self))
902    }
903
904    /// Adjust this context for resolution in a scope created by the given expansion.
905    /// For example, consider the following three resolutions of `f`:
906    ///
907    /// ```rust
908    /// #![feature(decl_macro)]
909    /// mod foo {
910    ///     pub fn f() {} // `f`'s `SyntaxContext` is empty.
911    /// }
912    /// m!(f);
913    /// macro m($f:ident) {
914    ///     mod bar {
915    ///         pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
916    ///         pub fn $f() {} // `$f`'s `SyntaxContext` is empty.
917    ///     }
918    ///     foo::f(); // `f`'s `SyntaxContext` has a single `ExpnId` from `m`
919    ///     //^ Since `mod foo` is outside this expansion, `adjust` removes the mark from `f`,
920    ///     //| and it resolves to `::foo::f`.
921    ///     bar::f(); // `f`'s `SyntaxContext` has a single `ExpnId` from `m`
922    ///     //^ Since `mod bar` not outside this expansion, `adjust` does not change `f`,
923    ///     //| and it resolves to `::bar::f`.
924    ///     bar::$f(); // `f`'s `SyntaxContext` is empty.
925    ///     //^ Since `mod bar` is not outside this expansion, `adjust` does not change `$f`,
926    ///     //| and it resolves to `::bar::$f`.
927    /// }
928    /// ```
929    /// This returns the expansion whose definition scope we use to privacy check the resolution,
930    /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
931    #[inline]
932    pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
933        HygieneData::with(|data| data.adjust(self, expn_id))
934    }
935
936    /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
937    #[inline]
938    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
939        HygieneData::with(|data| {
940            *self = data.normalize_to_macros_2_0(*self);
941            data.adjust(self, expn_id)
942        })
943    }
944
945    /// Adjust this context for resolution in a scope created by the given expansion
946    /// via a glob import with the given `SyntaxContext`.
947    /// For example:
948    ///
949    /// ```compile_fail,E0425
950    /// #![feature(decl_macro)]
951    /// m!(f);
952    /// macro m($i:ident) {
953    ///     mod foo {
954    ///         pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
955    ///         pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
956    ///     }
957    ///     n!(f);
958    ///     macro n($j:ident) {
959    ///         use foo::*;
960    ///         f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
961    ///         //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::f`.
962    ///         $i(); // `$i`'s `SyntaxContext` has a mark from `n`
963    ///         //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::$i`.
964    ///         $j(); // `$j`'s `SyntaxContext` has a mark from `m`
965    ///         //^ This cannot be glob-adjusted, so this is a resolution error.
966    ///     }
967    /// }
968    /// ```
969    /// This returns `None` if the context cannot be glob-adjusted.
970    /// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
971    pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
972        HygieneData::with(|data| {
973            let mut scope = None;
974            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
975            while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
976                scope = Some(data.remove_mark(&mut glob_ctxt).0);
977                if data.remove_mark(self).0 != scope.unwrap() {
978                    return None;
979                }
980            }
981            if data.adjust(self, expn_id).is_some() {
982                return None;
983            }
984            Some(scope)
985        })
986    }
987
988    /// Undo `glob_adjust` if possible:
989    ///
990    /// ```ignore (illustrative)
991    /// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) {
992    ///     assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
993    /// }
994    /// ```
995    pub fn reverse_glob_adjust(
996        &mut self,
997        expn_id: ExpnId,
998        glob_span: Span,
999    ) -> Option<Option<ExpnId>> {
1000        HygieneData::with(|data| {
1001            if data.adjust(self, expn_id).is_some() {
1002                return None;
1003            }
1004
1005            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
1006            let mut marks = Vec::new();
1007            while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
1008                marks.push(data.remove_mark(&mut glob_ctxt));
1009            }
1010
1011            let scope = marks.last().map(|mark| mark.0);
1012            while let Some((expn_id, transparency)) = marks.pop() {
1013                *self = data.apply_mark(*self, expn_id, transparency);
1014            }
1015            Some(scope)
1016        })
1017    }
1018
1019    pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool {
1020        HygieneData::with(|data| {
1021            let mut self_normalized = data.normalize_to_macros_2_0(self);
1022            data.adjust(&mut self_normalized, expn_id);
1023            self_normalized == data.normalize_to_macros_2_0(other)
1024        })
1025    }
1026
1027    #[inline]
1028    pub fn normalize_to_macros_2_0(self) -> SyntaxContext {
1029        // fast path to avoid locking: the root context normalizes to itself
1030        if self.is_root() {
1031            return self;
1032        }
1033        HygieneData::with(|data| data.normalize_to_macros_2_0(self))
1034    }
1035
1036    #[inline]
1037    pub fn normalize_to_macro_rules(self) -> SyntaxContext {
1038        // fast path to avoid locking: the root context normalizes to itself
1039        if self.is_root() {
1040            return self;
1041        }
1042        HygieneData::with(|data| data.normalize_to_macro_rules(self))
1043    }
1044
1045    /// See [`SyntaxContextData::outer_expn`]
1046    #[inline]
1047    pub fn outer_expn(self) -> ExpnId {
1048        HygieneData::with(|data| data.outer_expn(self))
1049    }
1050
1051    /// `ctxt.outer_expn_data()` is equivalent to but faster than
1052    /// `ctxt.outer_expn().expn_data()`.
1053    #[inline]
1054    pub fn outer_expn_data(self) -> ExpnData {
1055        HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
1056    }
1057
1058    #[inline]
1059    pub(crate) fn dollar_crate_name(self) -> Symbol {
1060        HygieneData::with(|data| data.syntax_context_data[self].dollar_crate_name)
1061    }
1062
1063    #[inline]
1064    pub fn edition(self) -> Edition {
1065        HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
1066    }
1067
1068    /// Returns whether this context originates in a foreign crate's external macro.
1069    ///
1070    /// This is used to test whether a lint should not even begin to figure out whether it should
1071    /// be reported on the current node.
1072    pub fn in_external_macro(self, sm: &SourceMap) -> bool {
1073        // fast path to avoid locking/expn-data read: the root context is not in a macro
1074        if self.is_root() {
1075            return false;
1076        }
1077        let expn_data = self.outer_expn_data();
1078        match expn_data.kind {
1079            ExpnKind::Root
1080            | ExpnKind::Desugaring(
1081                DesugaringKind::ForLoop
1082                | DesugaringKind::WhileLoop
1083                | DesugaringKind::OpaqueTy
1084                | DesugaringKind::Async
1085                | DesugaringKind::Await,
1086            ) => false,
1087            ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
1088            ExpnKind::Macro(MacroKind::Bang, _) => {
1089                // Dummy span for the `def_site` means it's an external macro.
1090                expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site)
1091            }
1092            ExpnKind::Macro { .. } => true, // definitely a plugin
1093        }
1094    }
1095}
1096
1097impl Span {
1098    /// Reuses the span but adds information like the kind of the desugaring and features that are
1099    /// allowed inside this span.
1100    pub fn mark_with_reason(
1101        self,
1102        allow_internal_unstable: Option<Arc<[Symbol]>>,
1103        reason: DesugaringKind,
1104        edition: Edition,
1105        hcx: impl StableHashCtxt,
1106    ) -> Span {
1107        let expn_data = ExpnData {
1108            allow_internal_unstable,
1109            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None)
1110        };
1111        let expn_id = LocalExpnId::fresh(expn_data, hcx);
1112        self.apply_mark(expn_id.to_expn_id(), Transparency::Transparent)
1113    }
1114}
1115
1116/// A subset of properties from both macro definition and macro call available through global data.
1117/// Avoid using this if you have access to the original definition or call structures.
1118#[derive(#[automatically_derived]impl ::core::clone::Clone for ExpnData {
    #[inline]
    fn clone(&self) -> Self {
        ExpnData {
            kind: ::core::clone::Clone::clone(&self.kind),
            parent: ::core::clone::Clone::clone(&self.parent),
            call_site: ::core::clone::Clone::clone(&self.call_site),
            disambiguator: ::core::clone::Clone::clone(&self.disambiguator),
            def_site: ::core::clone::Clone::clone(&self.def_site),
            allow_internal_unstable: ::core::clone::Clone::clone(&self.allow_internal_unstable),
            edition: ::core::clone::Clone::clone(&self.edition),
            macro_def_id: ::core::clone::Clone::clone(&self.macro_def_id),
            parent_module: ::core::clone::Clone::clone(&self.parent_module),
            allow_internal_unsafe: ::core::clone::Clone::clone(&self.allow_internal_unsafe),
            local_inner_macros: ::core::clone::Clone::clone(&self.local_inner_macros),
            collapse_debuginfo: ::core::clone::Clone::clone(&self.collapse_debuginfo),
            diagnostic_opaque: ::core::clone::Clone::clone(&self.diagnostic_opaque),
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for ExpnData {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            "ExpnData kind parent call_site disambiguator def_site allow_internal_unstable edition macro_def_id parent_module allow_internal_unsafe local_inner_macros collapse_debuginfo diagnostic_opaque";
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.kind, &self.parent, &self.call_site, &self.disambiguator,
                        &self.def_site, &self.allow_internal_unstable,
                        &self.edition, &self.macro_def_id, &self.parent_module,
                        &self.allow_internal_unsafe, &self.local_inner_macros,
                        &self.collapse_debuginfo, &&self.diagnostic_opaque];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, names, values)
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for ExpnData {
            fn encode(&self, __encoder: &mut __E) {
                let ExpnData {
                        kind: ref __binding_0,
                        parent: ref __binding_1,
                        call_site: ref __binding_2,
                        disambiguator: ref __binding_3,
                        def_site: ref __binding_4,
                        allow_internal_unstable: ref __binding_5,
                        edition: ref __binding_6,
                        macro_def_id: ref __binding_7,
                        parent_module: ref __binding_8,
                        allow_internal_unsafe: ref __binding_9,
                        local_inner_macros: ref __binding_10,
                        collapse_debuginfo: ref __binding_11,
                        diagnostic_opaque: ref __binding_12 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_4,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_5,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_6,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_7,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_8,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_9,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_10,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_11,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_12,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for ExpnData {
            fn decode(__decoder: &mut __D) -> Self {
                ExpnData {
                    kind: ::rustc_serialize::Decodable::decode(__decoder),
                    parent: ::rustc_serialize::Decodable::decode(__decoder),
                    call_site: ::rustc_serialize::Decodable::decode(__decoder),
                    disambiguator: ::rustc_serialize::Decodable::decode(__decoder),
                    def_site: ::rustc_serialize::Decodable::decode(__decoder),
                    allow_internal_unstable: ::rustc_serialize::Decodable::decode(__decoder),
                    edition: ::rustc_serialize::Decodable::decode(__decoder),
                    macro_def_id: ::rustc_serialize::Decodable::decode(__decoder),
                    parent_module: ::rustc_serialize::Decodable::decode(__decoder),
                    allow_internal_unsafe: ::rustc_serialize::Decodable::decode(__decoder),
                    local_inner_macros: ::rustc_serialize::Decodable::decode(__decoder),
                    collapse_debuginfo: ::rustc_serialize::Decodable::decode(__decoder),
                    diagnostic_opaque: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ExpnData {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ExpnData {
                        kind: ref __binding_0,
                        parent: ref __binding_1,
                        call_site: ref __binding_2,
                        disambiguator: ref __binding_3,
                        def_site: ref __binding_4,
                        allow_internal_unstable: ref __binding_5,
                        edition: ref __binding_6,
                        macro_def_id: ref __binding_7,
                        parent_module: ref __binding_8,
                        allow_internal_unsafe: ref __binding_9,
                        local_inner_macros: ref __binding_10,
                        collapse_debuginfo: ref __binding_11,
                        diagnostic_opaque: ref __binding_12 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                        { __binding_4.stable_hash(__hcx, __hasher); }
                        { __binding_5.stable_hash(__hcx, __hasher); }
                        { __binding_6.stable_hash(__hcx, __hasher); }
                        { __binding_7.stable_hash(__hcx, __hasher); }
                        { __binding_8.stable_hash(__hcx, __hasher); }
                        { __binding_9.stable_hash(__hcx, __hasher); }
                        { __binding_10.stable_hash(__hcx, __hasher); }
                        { __binding_11.stable_hash(__hcx, __hasher); }
                        { __binding_12.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
1119pub struct ExpnData {
1120    // --- The part unique to each expansion.
1121    pub kind: ExpnKind,
1122    /// The expansion that contains the definition of the macro for this expansion.
1123    pub parent: ExpnId,
1124    /// The span of the macro call which produced this expansion.
1125    ///
1126    /// This span will typically have a different `ExpnData` and `call_site`.
1127    /// This recursively traces back through any macro calls which expanded into further
1128    /// macro calls, until the "source call-site" is reached at the root SyntaxContext.
1129    /// For example, if `food!()` expands to `fruit!()` which then expands to `grape`,
1130    /// then the call-site of `grape` is `fruit!()` and the call-site of `fruit!()`
1131    /// is `food!()`.
1132    ///
1133    /// For a desugaring expansion, this is the span of the expression or node that was
1134    /// desugared.
1135    pub call_site: Span,
1136    /// Used to force two `ExpnData`s to have different `Fingerprint`s.
1137    /// Due to macro expansion, it's possible to end up with two `ExpnId`s
1138    /// that have identical `ExpnData`s. This violates the contract of `StableHash`
1139    /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal
1140    /// (since the numerical `ExpnId` value is not considered by the `StableHash`
1141    /// implementation).
1142    ///
1143    /// The `disambiguator` field is set by `update_disambiguator` when two distinct
1144    /// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes
1145    /// a `krate` field, this value only needs to be unique within a single crate.
1146    disambiguator: u32,
1147
1148    // --- The part specific to the macro/desugaring definition.
1149    // --- It may be reasonable to share this part between expansions with the same definition,
1150    // --- but such sharing is known to bring some minor inconveniences without also bringing
1151    // --- noticeable perf improvements (PR #62898).
1152    /// The span of the macro definition (possibly dummy).
1153    /// This span serves only informational purpose and is not used for resolution.
1154    pub def_site: Span,
1155    /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
1156    /// internally without forcing the whole crate to opt-in
1157    /// to them.
1158    pub allow_internal_unstable: Option<Arc<[Symbol]>>,
1159    /// Edition of the crate in which the macro is defined.
1160    pub edition: Edition,
1161    /// The `DefId` of the macro being invoked,
1162    /// if this `ExpnData` corresponds to a macro invocation
1163    pub macro_def_id: Option<DefId>,
1164    /// The normal module (`mod`) in which the expanded macro was defined.
1165    pub parent_module: Option<ModId>,
1166    /// Suppresses the `unsafe_code` lint for code produced by this macro.
1167    pub(crate) allow_internal_unsafe: bool,
1168    /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
1169    pub local_inner_macros: bool,
1170    /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
1171    /// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
1172    pub(crate) collapse_debuginfo: bool,
1173    /// When true, we prevent diagnostics pointing into this macro, if it is one, and we do not
1174    /// display the note telling people to use the `-Zmacro-backtrace` flag.
1175    pub diagnostic_opaque: bool,
1176}
1177
1178impl !PartialEq for ExpnData {}
1179impl !Hash for ExpnData {}
1180
1181impl ExpnData {
1182    pub fn new(
1183        kind: ExpnKind,
1184        parent: ExpnId,
1185        call_site: Span,
1186        def_site: Span,
1187        allow_internal_unstable: Option<Arc<[Symbol]>>,
1188        edition: Edition,
1189        macro_def_id: Option<DefId>,
1190        parent_module: Option<ModId>,
1191        allow_internal_unsafe: bool,
1192        local_inner_macros: bool,
1193        collapse_debuginfo: bool,
1194        diagnostic_opaque: bool,
1195    ) -> ExpnData {
1196        ExpnData {
1197            kind,
1198            parent,
1199            call_site,
1200            def_site,
1201            allow_internal_unstable,
1202            edition,
1203            macro_def_id,
1204            parent_module,
1205            disambiguator: 0,
1206            allow_internal_unsafe,
1207            local_inner_macros,
1208            collapse_debuginfo,
1209            diagnostic_opaque,
1210        }
1211    }
1212
1213    /// Constructs expansion data with default properties.
1214    pub fn default(
1215        kind: ExpnKind,
1216        call_site: Span,
1217        edition: Edition,
1218        macro_def_id: Option<DefId>,
1219        parent_module: Option<ModId>,
1220    ) -> ExpnData {
1221        ExpnData {
1222            kind,
1223            parent: ExpnId::root(),
1224            call_site,
1225            def_site: DUMMY_SP,
1226            allow_internal_unstable: None,
1227            edition,
1228            macro_def_id,
1229            parent_module,
1230            disambiguator: 0,
1231            allow_internal_unsafe: false,
1232            local_inner_macros: false,
1233            collapse_debuginfo: false,
1234            diagnostic_opaque: false,
1235        }
1236    }
1237
1238    pub fn allow_unstable(
1239        kind: ExpnKind,
1240        call_site: Span,
1241        edition: Edition,
1242        allow_internal_unstable: Arc<[Symbol]>,
1243        macro_def_id: Option<DefId>,
1244        parent_module: Option<ModId>,
1245    ) -> ExpnData {
1246        ExpnData {
1247            allow_internal_unstable: Some(allow_internal_unstable),
1248            ..ExpnData::default(kind, call_site, edition, macro_def_id, parent_module)
1249        }
1250    }
1251
1252    #[inline]
1253    pub fn is_root(&self) -> bool {
1254        #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    ExpnKind::Root => true,
    _ => false,
}matches!(self.kind, ExpnKind::Root)
1255    }
1256
1257    #[inline]
1258    fn hash_expn(&self, hcx: &mut impl StableHashCtxt) -> Hash64 {
1259        let mut hasher = StableHasher::new();
1260        self.stable_hash(hcx, &mut hasher);
1261        hasher.finish()
1262    }
1263}
1264
1265/// Expansion kind.
1266#[derive(#[automatically_derived]impl ::core::clone::Clone for ExpnKind {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Root => ExpnKind::Root,
            Self::Macro(__self_0, __self_1) =>
                ExpnKind::Macro(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
            Self::AstPass(__self_0) =>
                ExpnKind::AstPass(::core::clone::Clone::clone(__self_0)),
            Self::Desugaring(__self_0) =>
                ExpnKind::Desugaring(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for ExpnKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Root => ::core::fmt::Formatter::write_str(f, "Root"),
            Self::Macro(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Macro",
                    __self_0, &__self_1),
            Self::AstPass(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "AstPass", &__self_0),
            Self::Desugaring(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Desugaring", &__self_0),
        }
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for ExpnKind
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for ExpnKind {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Macro(__self_0, __self_1),
                    Self::Macro(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (Self::AstPass(__self_0), Self::AstPass(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::Desugaring(__self_0), Self::Desugaring(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for ExpnKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        ExpnKind::Root => { 0usize }
                        ExpnKind::Macro(ref __binding_0, ref __binding_1) => {
                            1usize
                        }
                        ExpnKind::AstPass(ref __binding_0) => { 2usize }
                        ExpnKind::Desugaring(ref __binding_0) => { 3usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    ExpnKind::Root => {}
                    ExpnKind::Macro(ref __binding_0, ref __binding_1) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    ExpnKind::AstPass(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    ExpnKind::Desugaring(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for ExpnKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { ExpnKind::Root }
                    1usize => {
                        ExpnKind::Macro(::rustc_serialize::Decodable::decode(__decoder),
                            ::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => {
                        ExpnKind::AstPass(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => {
                        ExpnKind::Desugaring(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `ExpnKind`, expected 0..4, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ExpnKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ExpnKind::Root => 0u8.stable_hash(__hcx, __hasher),
                    ExpnKind::Macro(ref __binding_0, ref __binding_1) =>
                        1u8.stable_hash(__hcx, __hasher),
                    ExpnKind::AstPass(ref __binding_0) =>
                        2u8.stable_hash(__hcx, __hasher),
                    ExpnKind::Desugaring(ref __binding_0) =>
                        3u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    ExpnKind::Root => {}
                    ExpnKind::Macro(ref __binding_0, ref __binding_1) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    ExpnKind::AstPass(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    ExpnKind::Desugaring(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
1267pub enum ExpnKind {
1268    /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
1269    Root,
1270    /// Expansion produced by a macro.
1271    Macro(MacroKind, Symbol),
1272    /// Transform done by the compiler on the AST.
1273    AstPass(AstPass),
1274    /// Desugaring done by the compiler during AST lowering.
1275    Desugaring(DesugaringKind),
1276}
1277
1278impl ExpnKind {
1279    pub fn descr(&self) -> String {
1280        match *self {
1281            ExpnKind::Root => kw::PathRoot.to_string(),
1282            ExpnKind::Macro(macro_kind, name) => match macro_kind {
1283                MacroKind::Bang => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}!", name))
    })format!("{name}!"),
1284                MacroKind::Attr => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[{0}]", name))
    })format!("#[{name}]"),
1285                MacroKind::Derive => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[derive({0})]", name))
    })format!("#[derive({name})]"),
1286            },
1287            ExpnKind::AstPass(kind) => kind.descr().to_string(),
1288            ExpnKind::Desugaring(kind) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("desugaring of {0}", kind.descr()))
    })format!("desugaring of {}", kind.descr()),
1289        }
1290    }
1291}
1292
1293/// The kind of macro invocation or definition.
1294#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for MacroKind {
}
#[automatically_derived]impl ::core::clone::Clone for MacroKind {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for MacroKind { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for MacroKind
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for MacroKind {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for MacroKind { }Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for MacroKind {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for MacroKind {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
            &::core::intrinsics::discriminant_value(other))
    }
}Ord, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for MacroKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        MacroKind::Bang => { 0usize }
                        MacroKind::Attr => { 1usize }
                        MacroKind::Derive => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for MacroKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { MacroKind::Bang }
                    1usize => { MacroKind::Attr }
                    2usize => { MacroKind::Derive }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `MacroKind`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable, #[automatically_derived]impl ::core::hash::Hash for MacroKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state)
    }
}Hash, #[automatically_derived]impl ::core::fmt::Debug for MacroKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                MacroKind::Bang => "Bang",
                MacroKind::Attr => "Attr",
                MacroKind::Derive => "Derive",
            })
    }
}Debug)]
1295#[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for MacroKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    MacroKind::Bang => 0u8.stable_hash(__hcx, __hasher),
                    MacroKind::Attr => 1u8.stable_hash(__hcx, __hasher),
                    MacroKind::Derive => 2u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    MacroKind::Bang => {}
                    MacroKind::Attr => {}
                    MacroKind::Derive => {}
                }
            }
        }
    };StableHash)]
1296pub enum MacroKind {
1297    /// A bang macro `foo!()`.
1298    Bang,
1299    /// An attribute macro `#[foo]`.
1300    Attr,
1301    /// A derive macro `#[derive(Foo)]`
1302    Derive,
1303}
1304
1305impl MacroKind {
1306    pub fn descr(self) -> &'static str {
1307        match self {
1308            MacroKind::Bang => "macro",
1309            MacroKind::Attr => "attribute macro",
1310            MacroKind::Derive => "derive macro",
1311        }
1312    }
1313
1314    pub fn descr_expected(self) -> &'static str {
1315        match self {
1316            MacroKind::Attr => "attribute",
1317            _ => self.descr(),
1318        }
1319    }
1320
1321    pub fn article(self) -> &'static str {
1322        match self {
1323            MacroKind::Attr => "an",
1324            _ => "a",
1325        }
1326    }
1327}
1328
1329/// The kind of AST transform.
1330#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for AstPass {
}
#[automatically_derived]impl ::core::clone::Clone for AstPass {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for AstPass { }Copy, #[automatically_derived]impl ::core::fmt::Debug for AstPass {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                AstPass::StdImports => "StdImports",
                AstPass::TestHarness => "TestHarness",
                AstPass::ProcMacroHarness => "ProcMacroHarness",
            })
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for AstPass {
}
#[automatically_derived]impl ::core::cmp::PartialEq for AstPass {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AstPass {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AstPass::StdImports => { 0usize }
                        AstPass::TestHarness => { 1usize }
                        AstPass::ProcMacroHarness => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AstPass {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AstPass::StdImports }
                    1usize => { AstPass::TestHarness }
                    2usize => { AstPass::ProcMacroHarness }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AstPass`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AstPass {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AstPass::StdImports => 0u8.stable_hash(__hcx, __hasher),
                    AstPass::TestHarness => 1u8.stable_hash(__hcx, __hasher),
                    AstPass::ProcMacroHarness =>
                        2u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    AstPass::StdImports => {}
                    AstPass::TestHarness => {}
                    AstPass::ProcMacroHarness => {}
                }
            }
        }
    };StableHash)]
1331pub enum AstPass {
1332    StdImports,
1333    TestHarness,
1334    ProcMacroHarness,
1335}
1336
1337impl AstPass {
1338    pub fn descr(self) -> &'static str {
1339        match self {
1340            AstPass::StdImports => "standard library imports",
1341            AstPass::TestHarness => "test harness",
1342            AstPass::ProcMacroHarness => "proc macro harness",
1343        }
1344    }
1345}
1346
1347/// The kind of compiler desugaring.
1348#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for DesugaringKind {
}
#[automatically_derived]impl ::core::clone::Clone for DesugaringKind {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for DesugaringKind { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    DesugaringKind {
}
#[automatically_derived]impl ::core::cmp::PartialEq for DesugaringKind {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::FormatLiteral { source: __self_0 },
                    Self::FormatLiteral { source: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]impl ::core::fmt::Debug for DesugaringKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::QuestionMark =>
                ::core::fmt::Formatter::write_str(f, "QuestionMark"),
            Self::TryBlock =>
                ::core::fmt::Formatter::write_str(f, "TryBlock"),
            Self::YeetExpr =>
                ::core::fmt::Formatter::write_str(f, "YeetExpr"),
            Self::OpaqueTy =>
                ::core::fmt::Formatter::write_str(f, "OpaqueTy"),
            Self::Async => ::core::fmt::Formatter::write_str(f, "Async"),
            Self::Await => ::core::fmt::Formatter::write_str(f, "Await"),
            Self::ForLoop => ::core::fmt::Formatter::write_str(f, "ForLoop"),
            Self::WhileLoop =>
                ::core::fmt::Formatter::write_str(f, "WhileLoop"),
            Self::BoundModifier =>
                ::core::fmt::Formatter::write_str(f, "BoundModifier"),
            Self::Contract =>
                ::core::fmt::Formatter::write_str(f, "Contract"),
            Self::PatTyRange =>
                ::core::fmt::Formatter::write_str(f, "PatTyRange"),
            Self::FormatLiteral { source: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "FormatLiteral source", &__self_0),
            Self::RangeExpr =>
                ::core::fmt::Formatter::write_str(f, "RangeExpr"),
        }
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DesugaringKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        DesugaringKind::QuestionMark => { 0usize }
                        DesugaringKind::TryBlock => { 1usize }
                        DesugaringKind::YeetExpr => { 2usize }
                        DesugaringKind::OpaqueTy => { 3usize }
                        DesugaringKind::Async => { 4usize }
                        DesugaringKind::Await => { 5usize }
                        DesugaringKind::ForLoop => { 6usize }
                        DesugaringKind::WhileLoop => { 7usize }
                        DesugaringKind::BoundModifier => { 8usize }
                        DesugaringKind::Contract => { 9usize }
                        DesugaringKind::PatTyRange => { 10usize }
                        DesugaringKind::FormatLiteral { source: ref __binding_0 } =>
                            {
                            11usize
                        }
                        DesugaringKind::RangeExpr => { 12usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    DesugaringKind::QuestionMark => {}
                    DesugaringKind::TryBlock => {}
                    DesugaringKind::YeetExpr => {}
                    DesugaringKind::OpaqueTy => {}
                    DesugaringKind::Async => {}
                    DesugaringKind::Await => {}
                    DesugaringKind::ForLoop => {}
                    DesugaringKind::WhileLoop => {}
                    DesugaringKind::BoundModifier => {}
                    DesugaringKind::Contract => {}
                    DesugaringKind::PatTyRange => {}
                    DesugaringKind::FormatLiteral { source: ref __binding_0 } =>
                        {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    DesugaringKind::RangeExpr => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DesugaringKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { DesugaringKind::QuestionMark }
                    1usize => { DesugaringKind::TryBlock }
                    2usize => { DesugaringKind::YeetExpr }
                    3usize => { DesugaringKind::OpaqueTy }
                    4usize => { DesugaringKind::Async }
                    5usize => { DesugaringKind::Await }
                    6usize => { DesugaringKind::ForLoop }
                    7usize => { DesugaringKind::WhileLoop }
                    8usize => { DesugaringKind::BoundModifier }
                    9usize => { DesugaringKind::Contract }
                    10usize => { DesugaringKind::PatTyRange }
                    11usize => {
                        DesugaringKind::FormatLiteral {
                            source: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    12usize => { DesugaringKind::RangeExpr }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DesugaringKind`, expected 0..13, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            DesugaringKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    DesugaringKind::QuestionMark =>
                        0u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::TryBlock =>
                        1u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::YeetExpr =>
                        2u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::OpaqueTy =>
                        3u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::Async => 4u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::Await => 5u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::ForLoop => 6u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::WhileLoop =>
                        7u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::BoundModifier =>
                        8u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::Contract =>
                        9u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::PatTyRange =>
                        10u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::FormatLiteral { source: ref __binding_0 } =>
                        11u8.stable_hash(__hcx, __hasher),
                    DesugaringKind::RangeExpr =>
                        12u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    DesugaringKind::QuestionMark => {}
                    DesugaringKind::TryBlock => {}
                    DesugaringKind::YeetExpr => {}
                    DesugaringKind::OpaqueTy => {}
                    DesugaringKind::Async => {}
                    DesugaringKind::Await => {}
                    DesugaringKind::ForLoop => {}
                    DesugaringKind::WhileLoop => {}
                    DesugaringKind::BoundModifier => {}
                    DesugaringKind::Contract => {}
                    DesugaringKind::PatTyRange => {}
                    DesugaringKind::FormatLiteral { source: ref __binding_0 } =>
                        {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    DesugaringKind::RangeExpr => {}
                }
            }
        }
    };StableHash)]
1349pub enum DesugaringKind {
1350    QuestionMark,
1351    TryBlock,
1352    YeetExpr,
1353    /// Desugaring of an `impl Trait` in return type position
1354    /// to an `type Foo = impl Trait;` and replacing the
1355    /// `impl Trait` with `Foo`.
1356    OpaqueTy,
1357    Async,
1358    Await,
1359    ForLoop,
1360    WhileLoop,
1361    /// `async Fn()` bound modifier
1362    BoundModifier,
1363    /// Calls to contract checks (`#[requires]` to precond, `#[ensures]` to postcond)
1364    Contract,
1365    /// A pattern type range start/end
1366    PatTyRange,
1367    /// A format literal.
1368    FormatLiteral {
1369        /// Was this format literal written in the source?
1370        /// - `format!("boo")` => Yes,
1371        /// - `format!(concat!("b", "o", "o"))` => No,
1372        /// - `format!(include_str!("boo.txt"))` => No,
1373        ///
1374        /// If it wasn't written in the source then we have to be careful with suggestions about
1375        /// rewriting it.
1376        source: bool,
1377    },
1378    RangeExpr,
1379}
1380
1381impl DesugaringKind {
1382    /// The description wording should combine well with "desugaring of {}".
1383    pub fn descr(self) -> &'static str {
1384        match self {
1385            DesugaringKind::Async => "`async` block or function",
1386            DesugaringKind::Await => "`await` expression",
1387            DesugaringKind::QuestionMark => "operator `?`",
1388            DesugaringKind::TryBlock => "`try` block",
1389            DesugaringKind::YeetExpr => "`do yeet` expression",
1390            DesugaringKind::OpaqueTy => "`impl Trait`",
1391            DesugaringKind::ForLoop => "`for` loop",
1392            DesugaringKind::WhileLoop => "`while` loop",
1393            DesugaringKind::BoundModifier => "trait bound modifier",
1394            DesugaringKind::Contract => "contract check",
1395            DesugaringKind::PatTyRange => "pattern type",
1396            DesugaringKind::FormatLiteral { source: true } => "format string literal",
1397            DesugaringKind::FormatLiteral { source: false } => {
1398                "expression that expanded into a format string literal"
1399            }
1400            DesugaringKind::RangeExpr => "range expression",
1401        }
1402    }
1403
1404    /// For use with `rustc_unimplemented` to support conditions
1405    /// like `from_desugaring = "QuestionMark"`
1406    pub fn matches(&self, value: &str) -> bool {
1407        match self {
1408            DesugaringKind::Async => value == "Async",
1409            DesugaringKind::Await => value == "Await",
1410            DesugaringKind::QuestionMark => value == "QuestionMark",
1411            DesugaringKind::TryBlock => value == "TryBlock",
1412            DesugaringKind::YeetExpr => value == "YeetExpr",
1413            DesugaringKind::OpaqueTy => value == "OpaqueTy",
1414            DesugaringKind::ForLoop => value == "ForLoop",
1415            DesugaringKind::WhileLoop => value == "WhileLoop",
1416            DesugaringKind::BoundModifier => value == "BoundModifier",
1417            DesugaringKind::Contract => value == "Contract",
1418            DesugaringKind::PatTyRange => value == "PatTyRange",
1419            DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
1420            DesugaringKind::RangeExpr => value == "RangeExpr",
1421        }
1422    }
1423}
1424
1425pub struct HygieneEncodeContext {
1426    /// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata.
1427    serialized_ctxts: FxHashSet<SyntaxContext>,
1428    latest_ctxts: Vec<SyntaxContext>,
1429
1430    serialized_expns: FxHashSet<ExpnId>,
1431    latest_expns: Vec<ExpnId>,
1432}
1433
1434impl Default for HygieneEncodeContext {
1435    fn default() -> HygieneEncodeContext {
1436        HygieneEncodeContext {
1437            serialized_ctxts: Default::default(),
1438            latest_ctxts: Default::default(),
1439            serialized_expns: Default::default(),
1440            latest_expns: Default::default(),
1441        }
1442    }
1443}
1444
1445impl HygieneEncodeContext {
1446    /// Record the fact that we need to serialize the corresponding `ExpnData`.
1447    #[inline]
1448    pub fn schedule_expn_data_for_encoding(&mut self, expn: ExpnId) {
1449        if self.serialized_expns.insert(expn) {
1450            self.latest_expns.push(expn);
1451        }
1452    }
1453
1454    pub fn encode<T>(
1455        h_ctxt: &RefCell<HygieneEncodeContext>,
1456        encoder: &mut T,
1457        mut encode_ctxt: impl FnMut(&mut T, SyntaxContext, &SyntaxContextKey),
1458        mut encode_expn: impl FnMut(&mut T, ExpnId, Option<&ExpnData>, ExpnHash),
1459    ) {
1460        // When we serialize a `SyntaxContextData`, we may end up serializing
1461        // a `SyntaxContext` that we haven't seen before
1462        while {
1463            let h_ctxt = h_ctxt.borrow();
1464            !h_ctxt.latest_ctxts.is_empty() || !h_ctxt.latest_expns.is_empty()
1465        } {
1466            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:1466",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(1466u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encode_hygiene: Serializing a round of {0:?} SyntaxContextData: {1:?}",
                                                    h_ctxt.borrow().latest_ctxts.len(),
                                                    h_ctxt.borrow().latest_ctxts) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(
1467                "encode_hygiene: Serializing a round of {:?} SyntaxContextData: {:?}",
1468                h_ctxt.borrow().latest_ctxts.len(),
1469                h_ctxt.borrow().latest_ctxts
1470            );
1471
1472            // Consume the current round of syntax contexts.
1473            // It's fine to iterate over a HashSet, because the serialization of the table
1474            // that we insert data into doesn't depend on insertion order.
1475            #[allow(rustc::potential_query_instability)]
1476            let latest_contexts = { mem::take(&mut h_ctxt.borrow_mut().latest_ctxts) }.into_iter();
1477
1478            for ctxt in latest_contexts {
1479                let key = HygieneData::with(|data| data.syntax_context_data[ctxt].key());
1480                encode_ctxt(encoder, ctxt, &key);
1481            }
1482
1483            // Same as above, but for expansions instead of syntax contexts.
1484            #[allow(rustc::potential_query_instability)]
1485            let latest_expns = { mem::take(&mut h_ctxt.borrow_mut().latest_expns) }.into_iter();
1486
1487            for expn in latest_expns {
1488                let (data, hash) = HygieneData::with(|data| {
1489                    // We need `data` only for local expansions, so don't clone `data` for non-local
1490                    // expansions.
1491                    // FIXME: completely remove this clone
1492                    let expn_data = expn.as_local().map(|id| data.local_expn_data(id).clone());
1493                    (expn_data, data.expn_hash(expn))
1494                });
1495
1496                encode_expn(encoder, expn, data.as_ref(), hash);
1497            }
1498        }
1499
1500        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:1500",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(1500u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encode_hygiene: Done serializing SyntaxContextData")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("encode_hygiene: Done serializing SyntaxContextData");
1501    }
1502
1503    #[inline]
1504    pub fn enqueue_syntax_context_for_encoding(&mut self, ctxt: SyntaxContext) {
1505        if self.serialized_ctxts.insert(ctxt) {
1506            self.latest_ctxts.push(ctxt);
1507        }
1508    }
1509}
1510
1511/// Additional information used to assist in decoding hygiene data
1512#[derive(#[automatically_derived]impl ::core::default::Default for HygieneDecodeContext
    {
    #[inline]
    fn default() -> Self {
        HygieneDecodeContext {
            remapped_ctxts: ::core::default::Default::default(),
        }
    }
}Default)]
1513pub struct HygieneDecodeContext {
1514    // A cache mapping raw serialized per-crate syntax context ids to corresponding decoded
1515    // `SyntaxContext`s in the current global `HygieneData`.
1516    remapped_ctxts: Lock<IndexVec<DecodedSyntaxContext, Option<SyntaxContext>>>,
1517}
1518
1519/// Register an expansion which has been decoded from the on-disk-cache for the local crate.
1520pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId {
1521    HygieneData::with(|hygiene_data| {
1522        let expn_id = hygiene_data.local_expn_data.next_index();
1523        hygiene_data.local_expn_data.push(Some(data));
1524        let _eid = hygiene_data.local_expn_hashes.push(hash);
1525        if true {
    {
        match (&expn_id, &_eid) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(expn_id, _eid);
1526
1527        let expn_id = expn_id.to_expn_id();
1528
1529        let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
1530        if true {
    if !_old_id.is_none() {
        ::core::panicking::panic("assertion failed: _old_id.is_none()")
    };
};debug_assert!(_old_id.is_none());
1531        expn_id
1532    })
1533}
1534
1535/// Register an expansion which has been decoded from the metadata of a foreign crate.
1536pub fn register_expn_id(
1537    krate: CrateNum,
1538    local_id: ExpnIndex,
1539    data: ExpnData,
1540    hash: ExpnHash,
1541) -> ExpnId {
1542    if true {
    if !(data.parent == ExpnId::root() || krate == data.parent.krate) {
        ::core::panicking::panic("assertion failed: data.parent == ExpnId::root() || krate == data.parent.krate")
    };
};debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate);
1543    let expn_id = ExpnId { krate, local_id };
1544    HygieneData::with(|hygiene_data| {
1545        let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
1546        let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash);
1547        if true {
    if !(_old_hash.is_none() || _old_hash == Some(hash)) {
        ::core::panicking::panic("assertion failed: _old_hash.is_none() || _old_hash == Some(hash)")
    };
};debug_assert!(_old_hash.is_none() || _old_hash == Some(hash));
1548        let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
1549        if true {
    if !(_old_id.is_none() || _old_id == Some(expn_id)) {
        ::core::panicking::panic("assertion failed: _old_id.is_none() || _old_id == Some(expn_id)")
    };
};debug_assert!(_old_id.is_none() || _old_id == Some(expn_id));
1550    });
1551    expn_id
1552}
1553
1554/// Decode an expansion from the metadata of a foreign crate.
1555pub fn decode_expn_id(
1556    krate: CrateNum,
1557    index: u32,
1558    decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash),
1559) -> ExpnId {
1560    if index == 0 {
1561        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:1561",
                        "rustc_span::hygiene", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(1561u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decode_expn_id: deserialized root")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decode_expn_id: deserialized root");
1562        return ExpnId::root();
1563    }
1564
1565    let index = ExpnIndex::from_u32(index);
1566
1567    // This function is used to decode metadata, so it cannot decode information about LOCAL_CRATE.
1568    if true {
    {
        match (&krate, &LOCAL_CRATE) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    let kind = ::core::panicking::AssertKind::Ne;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_ne!(krate, LOCAL_CRATE);
1569    let expn_id = ExpnId { krate, local_id: index };
1570
1571    // Fast path if the expansion has already been decoded.
1572    if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) {
1573        return expn_id;
1574    }
1575
1576    // Don't decode the data inside `HygieneData::with`, since we need to recursively decode
1577    // other ExpnIds
1578    let (expn_data, hash) = decode_data(expn_id);
1579
1580    register_expn_id(krate, index, expn_data, hash)
1581}
1582
1583#[automatically_derived]impl ::core::marker::Copy for DecodedSyntaxContext { }
impl DecodedSyntaxContext {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0x1FFF_FFFF;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0x1FFF_FFFF);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0x1FFF_FFFF as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0x1FFF_FFFF as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0x1FFF_FFFF) {
            ::core::panicking::panic("assertion failed: value <= 0x1FFF_FFFF")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0x1FFF_FFFF) {
            ::core::panicking::panic("assertion failed: value <= 0x1FFF_FFFF")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for DecodedSyntaxContext {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for DecodedSyntaxContext {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for DecodedSyntaxContext {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl From<DecodedSyntaxContext> for u32 {
    #[inline]
    fn from(v: DecodedSyntaxContext) -> u32 { v.as_u32() }
}
impl From<DecodedSyntaxContext> for usize {
    #[inline]
    fn from(v: DecodedSyntaxContext) -> usize { v.as_usize() }
}
impl From<usize> for DecodedSyntaxContext {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for DecodedSyntaxContext {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for DecodedSyntaxContext {}
impl ::std::cmp::PartialEq for DecodedSyntaxContext {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for DecodedSyntaxContext {}
impl ::std::hash::Hash for DecodedSyntaxContext {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for
    DecodedSyntaxContext {
    fn decode(d: &mut D) -> Self { Self::from_u32(d.read_u32()) }
}
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for
    DecodedSyntaxContext {
    fn encode(&self, e: &mut E) { e.emit_u32(self.as_u32()); }
}
impl ::std::fmt::Debug for DecodedSyntaxContext {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("#decoded{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
1584    /// A syntax context that is obtained from metadata of an external crate and
1585    /// was not yet remapped to local `SyntaxContext`.
1586    #[encodable]
1587    #[max = 0x1FFF_FFFF] // `u32::MAX` >> 3, as `SyntaxContext` should be fit in 29 bits (see `span_encoding`).
1588    #[debug_format = "#decoded{}"]
1589    pub struct DecodedSyntaxContext {}
1590}
1591
1592impl DecodedSyntaxContext {
1593    #[inline(always)]
1594    fn is_root(self) -> bool {
1595        self.as_u32() == 0
1596    }
1597}
1598
1599// Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
1600// to track which `SyntaxContext`s we have already decoded.
1601// The provided closure will be invoked to deserialize a `SyntaxContextData`
1602// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1603pub fn decode_syntax_context<D: Decoder>(
1604    d: &mut D,
1605    context: &HygieneDecodeContext,
1606    decode_data: impl FnOnce(&mut D, DecodedSyntaxContext) -> SyntaxContextKey,
1607) -> SyntaxContext {
1608    let decoded_ctxt: DecodedSyntaxContext = Decodable::decode(d);
1609    if decoded_ctxt.is_root() {
1610        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:1610",
                        "rustc_span::hygiene", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(1610u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decode_syntax_context: deserialized root")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decode_syntax_context: deserialized root");
1611        // The root is special
1612        return SyntaxContext::root();
1613    }
1614
1615    // Look into the cache first.
1616    // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
1617    // raw ids from different crate metadatas.
1618    if let Some(Some(ctxt)) = context.remapped_ctxts.lock().get(decoded_ctxt) {
1619        return *ctxt;
1620    }
1621
1622    // Don't try to decode data while holding the lock, since we need to
1623    // be able to recursively decode a SyntaxContext
1624    let (parent, expn_id, transparency) = decode_data(d, decoded_ctxt);
1625    let remapped_ctxt =
1626        HygieneData::with(|hygiene_data| hygiene_data.alloc_ctxt(parent, expn_id, transparency));
1627
1628    context.remapped_ctxts.lock().insert(decoded_ctxt, remapped_ctxt);
1629
1630    remapped_ctxt
1631}
1632
1633impl<E: SpanEncoder> Encodable<E> for LocalExpnId {
1634    fn encode(&self, e: &mut E) {
1635        self.to_expn_id().encode(e);
1636    }
1637}
1638
1639impl<D: SpanDecoder> Decodable<D> for LocalExpnId {
1640    fn decode(d: &mut D) -> Self {
1641        ExpnId::expect_local(ExpnId::decode(d))
1642    }
1643}
1644
1645/// Updates the `disambiguator` field of the corresponding `ExpnData`
1646/// such that the `Fingerprint` of the `ExpnData` does not collide with
1647/// any other `ExpnIds`.
1648///
1649/// This method is called only when an `ExpnData` is first associated
1650/// with an `ExpnId` (when the `ExpnId` is initially constructed, or via
1651/// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
1652/// from another crate's metadata - since `ExpnHash` includes the stable crate id,
1653/// collisions are only possible between `ExpnId`s within the same crate.
1654fn update_disambiguator(expn_data: &mut ExpnData, mut hcx: impl StableHashCtxt) -> ExpnHash {
1655    // This disambiguator should not have been set yet.
1656    {
    match (&expn_data.disambiguator, &0) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("Already set disambiguator for ExpnData: {0:?}",
                            expn_data)));
            }
        }
    }
};assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}");
1657    hcx.assert_default_stable_hash_controls("ExpnData (disambiguator)");
1658    let mut expn_hash = expn_data.hash_expn(&mut hcx);
1659
1660    let disambiguator = HygieneData::with(|data| {
1661        // If this is the first ExpnData with a given hash, then keep our
1662        // disambiguator at 0 (the default u32 value)
1663        let disambig = data.expn_data_disambiguators.entry(expn_hash).or_default();
1664        let disambiguator = *disambig;
1665        *disambig += 1;
1666        disambiguator
1667    });
1668
1669    if disambiguator != 0 {
1670        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs:1670",
                        "rustc_span::hygiene", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_span/src/hygiene.rs"),
                        ::tracing_core::__macro_support::Option::Some(1670u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_span::hygiene"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Set disambiguator for expn_data={0:?} expn_hash={1:?}",
                                                    expn_data, expn_hash) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash);
1671
1672        expn_data.disambiguator = disambiguator;
1673        expn_hash = expn_data.hash_expn(&mut hcx);
1674
1675        // Verify that the new disambiguator makes the hash unique
1676        #[cfg(debug_assertions)]
1677        HygieneData::with(|data| {
1678            {
    match (&data.expn_data_disambiguators.get(&expn_hash), &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("Hash collision after disambiguator update!")));
            }
        }
    }
};assert_eq!(
1679                data.expn_data_disambiguators.get(&expn_hash),
1680                None,
1681                "Hash collision after disambiguator update!",
1682            );
1683        });
1684    }
1685
1686    ExpnHash::new(LOCAL_CRATE.as_def_id().to_stable_hash_key(&mut hcx).stable_crate_id(), expn_hash)
1687}
1688
1689impl SyntaxContext {
1690    fn stable_hash_internal(
1691        self,
1692        data: Option<&HygieneData>,
1693        hcx: &mut impl StableHashCtxt,
1694        hasher: &mut StableHasher,
1695    ) {
1696        const TAG_EXPANSION: u8 = 0;
1697        const TAG_NO_EXPANSION: u8 = 1;
1698
1699        if self.is_root() {
1700            TAG_NO_EXPANSION.stable_hash(hcx, hasher);
1701        } else {
1702            TAG_EXPANSION.stable_hash(hcx, hasher);
1703            // This duplicates `ExpnId::stable_hash`, but reads the outer mark and
1704            // expansion hash in a single `HygieneData::with` call to avoid extra locking.
1705            hcx.assert_default_stable_hash_controls("ExpnId");
1706
1707            let get_hashing_data = |data: &HygieneData| {
1708                let (expn_id, transparency) = data.outer_mark(self);
1709                (data.expn_hash(expn_id).0, transparency)
1710            };
1711
1712            let (hash, transparency) = match data {
1713                Some(data) => get_hashing_data(data),
1714                None => HygieneData::with(|data| get_hashing_data(data)),
1715            };
1716
1717            hash.stable_hash(hcx, hasher);
1718            transparency.stable_hash(hcx, hasher);
1719        }
1720    }
1721}
1722
1723impl StableHash for SyntaxContext {
1724    #[inline]
1725    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
1726        self.stable_hash_internal(None, hcx, hasher);
1727    }
1728}
1729
1730impl ExpnId {
1731    fn stable_hash_internal(
1732        self,
1733        data: Option<&HygieneData>,
1734        hcx: &mut impl StableHashCtxt,
1735        hasher: &mut StableHasher,
1736    ) {
1737        hcx.assert_default_stable_hash_controls("ExpnId");
1738        let hash = if self == ExpnId::root() {
1739            // Avoid fetching TLS storage for a trivial often-used value.
1740            Fingerprint::ZERO
1741        } else {
1742            let get_hashing_data = |data: &HygieneData| data.expn_hash(self).0;
1743
1744            match data {
1745                Some(data) => get_hashing_data(data),
1746                None => HygieneData::with(|data| get_hashing_data(data)),
1747            }
1748        };
1749
1750        hash.stable_hash(hcx, hasher);
1751    }
1752}
1753
1754impl StableHash for ExpnId {
1755    #[inline]
1756    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
1757        self.stable_hash_internal(None, hcx, hasher)
1758    }
1759}
1760
1761impl StableHash for LocalExpnId {
1762    #[inline]
1763    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
1764        self.to_expn_id().stable_hash_internal(None, hcx, hasher);
1765    }
1766}