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