Skip to main content

rustc_span/
def_id.rs

1use std::fmt;
2use std::hash::{BuildHasherDefault, Hash, Hasher};
3
4use rustc_data_structures::AtomicRef;
5use rustc_data_structures::fingerprint::Fingerprint;
6use rustc_data_structures::stable_hash::{
7    RawDefId, StableHash, StableHashCtxt, StableHasher, StableOrd, ToStableHashKey,
8};
9use rustc_data_structures::unhash::Unhasher;
10use rustc_hashes::Hash64;
11use rustc_index::Idx;
12use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash};
13use rustc_serialize::{ContextOrd, Decodable, Encodable};
14
15use crate::{BlobDecoder, SpanEncoder, Symbol};
16
17pub type StableCrateIdMap =
18    indexmap::IndexMap<StableCrateId, CrateNum, BuildHasherDefault<Unhasher>>;
19
20#[automatically_derived]impl ::core::marker::Copy for CrateNum { }
impl CrateNum {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0xFFFF_FF00 as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for CrateNum {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for CrateNum {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for CrateNum {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for CrateNum {
    #[inline]
    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
        <usize as
                ::std::iter::Step>::steps_between(&Self::index(*start),
            &Self::index(*end))
    }
    #[inline]
    fn forward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_add(u).map(Self::from_usize)
    }
    #[inline]
    fn backward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_sub(u).map(Self::from_usize)
    }
    #[inline]
    fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_add(u);
        (Self::from_usize(s), o)
    }
    #[inline]
    fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_sub(u);
        (Self::from_usize(s), o)
    }
}
impl ::std::cmp::Ord for CrateNum {
    #[inline]
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_u32().cmp(&other.as_u32())
    }
}
impl ::std::cmp::PartialOrd for CrateNum {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl From<CrateNum> for u32 {
    #[inline]
    fn from(v: CrateNum) -> u32 { v.as_u32() }
}
impl From<CrateNum> for usize {
    #[inline]
    fn from(v: CrateNum) -> usize { v.as_usize() }
}
impl From<usize> for CrateNum {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for CrateNum {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for CrateNum {}
impl ::std::cmp::PartialEq for CrateNum {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for CrateNum {}
impl ::std::hash::Hash for CrateNum {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl ::std::fmt::Debug for CrateNum {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("crate{0}", self.as_u32()))
    }
}rustc_index::newtype_index! {
21    #[orderable]
22    #[debug_format = "crate{}"]
23    pub struct CrateNum {}
24}
25
26impl<E: SpanEncoder> ContextOrd<&E> for CrateNum {
27    fn stable_cmp_with_context(context: &E) -> impl FnMut(&Self, &Self) -> std::cmp::Ordering {
28        let hasher = context.def_path_hasher();
29        move |id1, id2| hasher(id1.as_def_id()).cmp(&hasher(id2.as_def_id()))
30    }
31}
32
33/// Item definitions in the currently-compiled crate would have the `CrateNum`
34/// `LOCAL_CRATE` in their `DefId`.
35pub const LOCAL_CRATE: CrateNum = CrateNum::ZERO;
36
37impl CrateNum {
38    #[inline]
39    pub fn new(x: usize) -> CrateNum {
40        CrateNum::from_usize(x)
41    }
42
43    // FIXME(typed_def_id): Replace this with `as_mod_def_id`.
44    #[inline]
45    pub fn as_def_id(self) -> DefId {
46        DefId { krate: self, index: CRATE_DEF_INDEX }
47    }
48
49    #[inline]
50    pub fn as_mod_id(self) -> ModId {
51        ModId::new_unchecked(DefId { krate: self, index: CRATE_DEF_INDEX })
52    }
53}
54
55impl fmt::Display for CrateNum {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        fmt::Display::fmt(&self.as_u32(), f)
58    }
59}
60
61/// A `DefPathHash` is a fixed-size representation of a `DefPath` that is
62/// stable across crate and compilation session boundaries. It consists of two
63/// separate 64-bit hashes. The first uniquely identifies the crate this
64/// `DefPathHash` originates from (see [StableCrateId]), and the second
65/// uniquely identifies the corresponding `DefPath` within that crate. Together
66/// they form a unique identifier within an entire crate graph.
67///
68/// There is a very small chance of hash collisions, which would mean that two
69/// different `DefPath`s map to the same `DefPathHash`. Proceeding compilation
70/// with such a hash collision would very probably lead to an ICE, and in the
71/// worst case lead to a silent mis-compilation. The compiler therefore actively
72/// and exhaustively checks for such hash collisions and aborts compilation if
73/// it finds one.
74///
75/// `DefPathHash` uses 64-bit hashes for both the crate-id part and the
76/// crate-internal part, even though it is likely that there are many more
77/// `LocalDefId`s in a single crate than there are individual crates in a crate
78/// graph. Since we use the same number of bits in both cases, the collision
79/// probability for the crate-local part will be quite a bit higher (though
80/// still very small).
81///
82/// This imbalance is not by accident: A hash collision in the
83/// crate-local part of a `DefPathHash` will be detected and reported while
84/// compiling the crate in question. Such a collision does not depend on
85/// outside factors and can be easily fixed by the crate maintainer (e.g. by
86/// renaming the item in question or by bumping the crate version in a harmless
87/// way).
88///
89/// A collision between crate-id hashes on the other hand is harder to fix
90/// because it depends on the set of crates in the entire crate graph of a
91/// compilation session. Again, using the same crate with a different version
92/// number would fix the issue with a high probability -- but that might be
93/// easier said than done if the crates in questions are dependencies of
94/// third-party crates.
95///
96/// That being said, given a high quality hash function, the collision
97/// probabilities in question are very small. For example, for a big crate like
98/// `rustc_middle` (with ~50000 `LocalDefId`s as of the time of writing) there
99/// is a probability of roughly 1 in 14,750,000,000 of a crate-internal
100/// collision occurring. For a big crate graph with 1000 crates in it, there is
101/// a probability of 1 in 36,890,000,000,000 of a `StableCrateId` collision.
102#[derive(#[automatically_derived]impl ::core::marker::Copy for DefPathHash { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for DefPathHash {
}
#[automatically_derived]impl ::core::clone::Clone for DefPathHash {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Fingerprint>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::hash::Hash for DefPathHash {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    DefPathHash {
}
#[automatically_derived]impl ::core::cmp::PartialEq for DefPathHash {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for DefPathHash {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Fingerprint>;
    }
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for DefPathHash {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for DefPathHash {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.0, &other.0)
    }
}Ord, #[automatically_derived]impl ::core::fmt::Debug for DefPathHash {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "DefPathHash",
            &&self.0)
    }
}Debug)]
103#[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for DefPathHash
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    DefPathHash(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DefPathHash {
            fn encode(&self, __encoder: &mut __E) {
                let DefPathHash(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DefPathHash {
            fn decode(__decoder: &mut __D) -> Self {
                DefPathHash(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable)]
104pub struct DefPathHash(pub Fingerprint);
105
106impl DefPathHash {
107    /// Returns the [StableCrateId] identifying the crate this [DefPathHash]
108    /// originates from.
109    #[inline]
110    pub fn stable_crate_id(&self) -> StableCrateId {
111        StableCrateId(self.0.split().0)
112    }
113
114    /// Returns the crate-local part of the [DefPathHash].
115    #[inline]
116    pub fn local_hash(&self) -> Hash64 {
117        self.0.split().1
118    }
119
120    /// Builds a new [DefPathHash] with the given [StableCrateId] and
121    /// `local_hash`, where `local_hash` must be unique within its crate.
122    #[inline]
123    pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash {
124        DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash))
125    }
126}
127
128impl Default for DefPathHash {
129    fn default() -> Self {
130        DefPathHash(Fingerprint::ZERO)
131    }
132}
133
134impl StableOrd for DefPathHash {
135    const CAN_USE_UNSTABLE_SORT: bool = true;
136
137    // `DefPathHash` sort order is not affected by (de)serialization.
138    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
139}
140
141/// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all
142/// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to
143/// [`DefId`]. It is stable across compilation sessions.
144///
145/// Since the ID is a hash value, there is a small chance that two crates
146/// end up with the same [`StableCrateId`]. The compiler will check for such
147/// collisions when loading crates and abort compilation in order to avoid
148/// further trouble.
149///
150/// For more information on the possibility of hash collisions in rustc,
151/// see the discussion in [`DefId`].
152#[derive(#[automatically_derived]impl ::core::marker::Copy for StableCrateId { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for StableCrateId {
}
#[automatically_derived]impl ::core::clone::Clone for StableCrateId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Hash64>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    StableCrateId {
}
#[automatically_derived]impl ::core::cmp::PartialEq for StableCrateId {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for StableCrateId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Hash64>;
    }
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for StableCrateId {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for StableCrateId {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.0, &other.0)
    }
}Ord, #[automatically_derived]impl ::core::fmt::Debug for StableCrateId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "StableCrateId",
            &&self.0)
    }
}Debug)]
153#[derive(#[automatically_derived]impl ::core::hash::Hash for StableCrateId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            StableCrateId {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    StableCrateId(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for StableCrateId {
            fn encode(&self, __encoder: &mut __E) {
                let StableCrateId(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
            for StableCrateId {
            fn decode(__decoder: &mut __D) -> Self {
                StableCrateId(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };BlobDecodable)]
154pub struct StableCrateId(pub(crate) Hash64);
155
156impl StableCrateId {
157    /// Computes the stable ID for a crate with the given name and
158    /// `-Cmetadata` arguments.
159    pub fn new(
160        crate_name: Symbol,
161        is_exe: bool,
162        mut metadata: Vec<String>,
163        cfg_version: &'static str,
164    ) -> StableCrateId {
165        let mut hasher = StableHasher::new();
166        // We must hash the string text of the crate name, not the id, as the id is not stable
167        // across builds.
168        crate_name.as_str().hash(&mut hasher);
169
170        // We don't want the stable crate ID to depend on the order of
171        // -C metadata arguments, so sort them:
172        metadata.sort();
173        // Every distinct -C metadata value is only incorporated once:
174        metadata.dedup();
175
176        hasher.write(b"metadata");
177        for s in &metadata {
178            // Also incorporate the length of a metadata string, so that we generate
179            // different values for `-Cmetadata=ab -Cmetadata=c` and
180            // `-Cmetadata=a -Cmetadata=bc`
181            hasher.write_usize(s.len());
182            hasher.write(s.as_bytes());
183        }
184
185        // Also incorporate crate type, so that we don't get symbol conflicts when
186        // linking against a library of the same name, if this is an executable.
187        hasher.write(if is_exe { b"exe" } else { b"lib" });
188
189        // Also incorporate the rustc version. Otherwise, with -Zsymbol-mangling-version=v0
190        // and no -Cmetadata, symbols from the same crate compiled with different versions of
191        // rustc are named the same.
192        //
193        // RUSTC_FORCE_RUSTC_VERSION is used to inject rustc version information
194        // during testing.
195        if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
196            hasher.write(val.to_string_lossy().into_owned().as_bytes())
197        } else {
198            hasher.write(cfg_version.as_bytes())
199        }
200
201        StableCrateId(hasher.finish())
202    }
203
204    #[inline]
205    pub fn as_hash(self) -> Hash64 {
206        self.0
207    }
208
209    #[inline]
210    pub fn as_u64(self) -> u64 {
211        self.0.as_u64()
212    }
213}
214
215impl fmt::LowerHex for StableCrateId {
216    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217        fmt::LowerHex::fmt(&self.0, f)
218    }
219}
220
221#[automatically_derived]impl ::core::marker::Copy for DefIndex { }
#[doc = " The crate root is always assigned index 0 by the AST Map code,"]
#[doc = " thanks to `NodeCollector::new`."]
pub const CRATE_DEF_INDEX: DefIndex = DefIndex::from_u32(0);
impl DefIndex {
    #[doc = r" Maximum value the index can take, as a `u32`."]
    pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
    #[doc = r" Maximum value the index can take."]
    pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
    #[doc = r" Zero value of the index."]
    pub const ZERO: Self = Self::from_u32(0);
    #[doc = r" Creates a new index from a given `usize`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_usize(value: usize) -> Self {
        if !(value <= (0xFFFF_FF00 as usize)) {
            ::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
        };
        unsafe { Self::from_u32_unchecked(value as u32) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u32(value: u32) -> Self {
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u16`."]
    #[doc = r""]
    #[doc = r" # Panics"]
    #[doc = r""]
    #[doc = r" Will panic if `value` exceeds `MAX`."]
    #[inline]
    pub const fn from_u16(value: u16) -> Self {
        let value = value as u32;
        if !(value <= 0xFFFF_FF00) {
            ::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
        };
        unsafe { Self::from_u32_unchecked(value) }
    }
    #[doc = r" Creates a new index from a given `u32`."]
    #[doc = r""]
    #[doc = r" # Safety"]
    #[doc = r""]
    #[doc =
    r" The provided value must be less than or equal to the maximum value for the newtype."]
    #[doc =
    r" Providing a value outside this range is undefined due to layout restrictions."]
    #[doc = r""]
    #[doc = r" Prefer using `from_u32`."]
    #[inline]
    pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
        Self {
            private_use_as_methods_instead: unsafe {
                std::mem::transmute(value)
            },
        }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn index(self) -> usize { self.as_usize() }
    #[doc = r" Extracts the value of this index as a `u32`."]
    #[inline]
    pub const fn as_u32(self) -> u32 {
        unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
    }
    #[doc = r" Extracts the value of this index as a `usize`."]
    #[inline]
    pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for DefIndex {
    type Output = Self;
    #[inline]
    fn add(self, other: usize) -> Self {
        Self::from_usize(self.index() + other)
    }
}
impl std::ops::AddAssign<usize> for DefIndex {
    #[inline]
    fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for DefIndex {
    #[inline]
    fn new(value: usize) -> Self { Self::from_usize(value) }
    #[inline]
    fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for DefIndex {
    #[inline]
    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
        <usize as
                ::std::iter::Step>::steps_between(&Self::index(*start),
            &Self::index(*end))
    }
    #[inline]
    fn forward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_add(u).map(Self::from_usize)
    }
    #[inline]
    fn backward_checked(start: Self, u: usize) -> Option<Self> {
        Self::index(start).checked_sub(u).map(Self::from_usize)
    }
    #[inline]
    fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_add(u);
        (Self::from_usize(s), o)
    }
    #[inline]
    fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
        let (s, o) = Self::index(start).overflowing_sub(u);
        (Self::from_usize(s), o)
    }
}
impl ::std::cmp::Ord for DefIndex {
    #[inline]
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_u32().cmp(&other.as_u32())
    }
}
impl ::std::cmp::PartialOrd for DefIndex {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl From<DefIndex> for u32 {
    #[inline]
    fn from(v: DefIndex) -> u32 { v.as_u32() }
}
impl From<DefIndex> for usize {
    #[inline]
    fn from(v: DefIndex) -> usize { v.as_usize() }
}
impl From<usize> for DefIndex {
    #[inline]
    fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for DefIndex {
    #[inline]
    fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for DefIndex {}
impl ::std::cmp::PartialEq for DefIndex {
    fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for DefIndex {}
impl ::std::hash::Hash for DefIndex {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.as_u32().hash(state)
    }
}
impl ::std::fmt::Debug for DefIndex {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("DefIndex({0})", self.as_u32()))
    }
}rustc_index::newtype_index! {
222    /// A DefIndex is an index into the hir-map for a crate, identifying a
223    /// particular definition. It should really be considered an interned
224    /// shorthand for a particular DefPath.
225    #[orderable]
226    #[debug_format = "DefIndex({})"]
227    pub struct DefIndex {
228        /// The crate root is always assigned index 0 by the AST Map code,
229        /// thanks to `NodeCollector::new`.
230        const CRATE_DEF_INDEX = 0;
231    }
232}
233
234/// A `DefId` identifies a particular *definition*, by combining a crate
235/// index and a def index.
236///
237/// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
238#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for DefId {
}
#[automatically_derived]impl ::core::clone::Clone for DefId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<DefIndex>;
        let _: ::core::clone::AssertParamIsClone<CrateNum>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for DefId { }
#[automatically_derived]impl ::core::cmp::PartialEq for DefId {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.index == other.index && self.krate == other.krate
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for DefId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<DefIndex>;
        let _: ::core::cmp::AssertParamIsEq<CrateNum>;
    }
}Eq, #[automatically_derived]impl ::core::marker::Copy for DefId { }Copy)]
239// On below-64 bit systems we can simply use the derived `Hash` impl
240#[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
241#[repr(C)]
242#[rustc_pass_by_value]
243// We guarantee field order. Note that the order is essential here, see below why.
244pub struct DefId {
245    // cfg-ing the order of fields so that the `DefIndex` which is high entropy always ends up in
246    // the lower bits no matter the endianness. This allows the compiler to turn that `Hash` impl
247    // into a direct call to `u64::hash(_)`.
248    #[cfg(not(all(target_pointer_width = "64", target_endian = "big")))]
249    pub index: DefIndex,
250    pub krate: CrateNum,
251    #[cfg(all(target_pointer_width = "64", target_endian = "big"))]
252    pub index: DefIndex,
253}
254
255// To ensure correctness of incremental compilation,
256// `DefId` must not implement `Ord` or `PartialOrd`.
257// See https://github.com/rust-lang/rust/issues/90317.
258impl !Ord for DefId {}
259impl !PartialOrd for DefId {}
260
261// On 64-bit systems, we can hash the whole `DefId` as one `u64` instead of two `u32`s. This
262// improves performance without impairing `FxHash` quality. So the below code gets compiled to a
263// noop on little endian systems because the memory layout of `DefId` is as follows:
264//
265// ```
266//     +-1--------------31-+-32-------------63-+
267//     ! index             ! krate             !
268//     +-------------------+-------------------+
269// ```
270//
271// The order here has direct impact on `FxHash` quality because we have far more `DefIndex` per
272// crate than we have `Crate`s within one compilation. Or in other words, this arrangement puts
273// more entropy in the low bits than the high bits. The reason this matters is that `FxHash`, which
274// is used throughout rustc, has problems distributing the entropy from the high bits, so reversing
275// the order would lead to a large number of collisions and thus far worse performance.
276//
277// On 64-bit big-endian systems, this compiles to a 64-bit rotation by 32 bits, which is still
278// faster than another `FxHash` round.
279#[cfg(target_pointer_width = "64")]
280impl Hash for DefId {
281    fn hash<H: Hasher>(&self, h: &mut H) {
282        (((self.krate.as_u32() as u64) << 32) | (self.index.as_u32() as u64)).hash(h)
283    }
284}
285
286impl DefId {
287    /// Makes a local `DefId` from the given `DefIndex`.
288    #[inline]
289    pub fn local(index: DefIndex) -> DefId {
290        DefId { krate: LOCAL_CRATE, index }
291    }
292
293    /// Returns whether the item is defined in the crate currently being compiled.
294    #[inline]
295    pub fn is_local(self) -> bool {
296        self.krate == LOCAL_CRATE
297    }
298
299    #[inline]
300    pub fn as_local(self) -> Option<LocalDefId> {
301        self.is_local().then(|| LocalDefId { local_def_index: self.index })
302    }
303
304    #[inline]
305    #[track_caller]
306    pub fn expect_local(self) -> LocalDefId {
307        // NOTE: `match` below is required to apply `#[track_caller]`,
308        // i.e. don't use closures.
309        match self.as_local() {
310            Some(local_def_id) => local_def_id,
311            None => {
    ::core::panicking::panic_fmt(format_args!("DefId::expect_local: `{0:?}` isn\'t local",
            self));
}panic!("DefId::expect_local: `{self:?}` isn't local"),
312        }
313    }
314
315    #[inline]
316    pub fn is_crate_root(self) -> bool {
317        self.index == CRATE_DEF_INDEX
318    }
319
320    #[inline]
321    pub fn as_crate_root(self) -> Option<CrateNum> {
322        self.is_crate_root().then_some(self.krate)
323    }
324
325    #[inline]
326    pub fn is_top_level_module(self) -> bool {
327        self.is_local() && self.is_crate_root()
328    }
329
330    #[inline]
331    pub fn to_raw_def_id(self) -> RawDefId {
332        // Field order must match `from_raw_def_id`.
333        RawDefId(self.krate.as_u32(), self.index.as_u32())
334    }
335
336    #[inline]
337    pub fn from_raw_def_id(RawDefId(a, b): RawDefId) -> DefId {
338        // Field order must match `to_raw_def_id`.
339        DefId { krate: a.into(), index: b.into() }
340    }
341}
342
343impl From<LocalDefId> for DefId {
344    fn from(local: LocalDefId) -> DefId {
345        local.to_def_id()
346    }
347}
348
349pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350    f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
351}
352
353pub static DEF_ID_DEBUG: AtomicRef<fn(DefId, &mut fmt::Formatter<'_>) -> fmt::Result> =
354    AtomicRef::new(&(default_def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
355
356impl fmt::Debug for DefId {
357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358        (*DEF_ID_DEBUG)(*self, f)
359    }
360}
361
362pub type DefIdMap<T> = ::rustc_data_structures::unord::UnordMap<DefId, T>;
pub type DefIdSet = ::rustc_data_structures::unord::UnordSet<DefId>;
pub type DefIdMapEntry<'a, T> =
    ::rustc_data_structures::fx::StdEntry<'a, DefId, T>;rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefIdMapEntry, DefId);
363
364/// A `LocalDefId` is equivalent to a `DefId` with `krate == LOCAL_CRATE`. Since
365/// we encode this information in the type, we can ensure at compile time that
366/// no `DefId`s from upstream crates get thrown into the mix. There are quite a
367/// few cases where we know that only `DefId`s from the local crate are expected;
368/// a `DefId` from a different crate would signify a bug somewhere. This
369/// is when `LocalDefId` comes in handy.
370#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for LocalDefId {
}
#[automatically_derived]impl ::core::clone::Clone for LocalDefId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<DefIndex>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for LocalDefId { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    LocalDefId {
}
#[automatically_derived]impl ::core::cmp::PartialEq for LocalDefId {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.local_def_index == other.local_def_index
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for LocalDefId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<DefIndex>;
    }
}Eq, #[automatically_derived]impl ::core::hash::Hash for LocalDefId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.local_def_index, state)
    }
}Hash)]
371pub struct LocalDefId {
372    pub local_def_index: DefIndex,
373}
374
375// To ensure correctness of incremental compilation,
376// `LocalDefId` must not implement `Ord` or `PartialOrd`.
377// See https://github.com/rust-lang/rust/issues/90317.
378impl !Ord for LocalDefId {}
379impl !PartialOrd for LocalDefId {}
380
381pub const CRATE_DEF_ID: LocalDefId = LocalDefId { local_def_index: CRATE_DEF_INDEX };
382pub const CRATE_MOD_ID: LocalModId = LocalModId::new_unchecked(CRATE_DEF_ID);
383
384impl Idx for LocalDefId {
385    #[inline]
386    fn new(idx: usize) -> Self {
387        LocalDefId { local_def_index: Idx::new(idx) }
388    }
389    #[inline]
390    fn index(self) -> usize {
391        self.local_def_index.index()
392    }
393}
394
395impl LocalDefId {
396    #[inline]
397    pub fn to_def_id(self) -> DefId {
398        DefId { krate: LOCAL_CRATE, index: self.local_def_index }
399    }
400
401    #[inline]
402    pub fn is_top_level_module(self) -> bool {
403        self == CRATE_DEF_ID
404    }
405}
406
407impl fmt::Debug for LocalDefId {
408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409        self.to_def_id().fmt(f)
410    }
411}
412
413impl<E: SpanEncoder> Encodable<E> for LocalDefId {
414    fn encode(&self, e: &mut E) {
415        e.encode_local_def_id(*self);
416    }
417}
418
419impl<D: BlobDecoder> Decodable<D> for LocalDefId {
420    fn decode(d: &mut D) -> LocalDefId {
421        d.decode_local_def_id()
422    }
423}
424
425impl<E: SpanEncoder> ContextOrd<&E> for LocalDefId {
426    fn stable_cmp_with_context(context: &E) -> impl FnMut(&Self, &Self) -> std::cmp::Ordering {
427        let hasher = context.def_path_hasher();
428        move |id1, id2| hasher(id1.to_def_id()).cmp(&hasher(id2.to_def_id()))
429    }
430}
431
432pub type LocalDefIdMap<T> =
    ::rustc_data_structures::unord::UnordMap<LocalDefId, T>;
pub type LocalDefIdSet = ::rustc_data_structures::unord::UnordSet<LocalDefId>;
pub type LocalDefIdMapEntry<'a, T> =
    ::rustc_data_structures::fx::StdEntry<'a, LocalDefId, T>;rustc_data_structures::define_id_collections!(
433    LocalDefIdMap,
434    LocalDefIdSet,
435    LocalDefIdMapEntry,
436    LocalDefId
437);
438
439impl<E: SpanEncoder> ContextOrd<&E> for DefId {
440    fn stable_cmp_with_context(context: &E) -> impl FnMut(&Self, &Self) -> std::cmp::Ordering {
441        let hasher = context.def_path_hasher();
442        move |id1, id2| hasher(*id1).cmp(&hasher(*id2))
443    }
444}
445
446impl StableHash for DefId {
447    #[inline]
448    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
449        self.to_stable_hash_key(hcx).stable_hash(hcx, hasher);
450    }
451}
452
453impl StableHash for LocalDefId {
454    #[inline]
455    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
456        self.to_stable_hash_key(hcx).local_hash().stable_hash(hcx, hasher);
457    }
458}
459
460impl StableHash for CrateNum {
461    #[inline]
462    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
463        self.as_def_id().to_stable_hash_key(hcx).stable_crate_id().stable_hash(hcx, hasher);
464    }
465}
466
467impl ToStableHashKey for DefId {
468    type KeyType = DefPathHash;
469
470    #[inline]
471    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> DefPathHash {
472        DefPathHash(hcx.def_path_hash(self.to_raw_def_id()))
473    }
474}
475
476impl ToStableHashKey for LocalDefId {
477    type KeyType = DefPathHash;
478
479    #[inline]
480    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> DefPathHash {
481        self.to_def_id().to_stable_hash_key(hcx)
482    }
483}
484
485#[derive(#[automatically_derived]impl ::core::fmt::Debug for ModId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "ModId",
            &&self.0)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ModId {
}
#[automatically_derived]impl ::core::clone::Clone for ModId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<DefId>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for ModId { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for ModId { }
#[automatically_derived]impl ::core::cmp::PartialEq for ModId {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ModId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<DefId>;
    }
}Eq, #[automatically_derived]impl ::core::hash::Hash for ModId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for ModId {
            fn encode(&self, __encoder: &mut __E) {
                let ModId(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for ModId {
            fn decode(__decoder: &mut __D) -> Self {
                ModId(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ModId {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ModId(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
486pub struct ModId(DefId);
487
488impl ModId {
489    #[inline]
490    pub const fn new_unchecked(def_id: DefId) -> Self {
491        Self(def_id)
492    }
493
494    #[inline]
495    pub fn to_def_id(self) -> DefId {
496        self.into()
497    }
498
499    #[inline]
500    pub fn is_local(self) -> bool {
501        self.0.is_local()
502    }
503
504    #[inline]
505    pub fn as_local(self) -> Option<LocalModId> {
506        self.0.as_local().map(LocalModId::new_unchecked)
507    }
508
509    pub fn expect_local(self) -> LocalModId {
510        LocalModId::new_unchecked(self.0.expect_local())
511    }
512
513    pub fn is_crate_root(self) -> bool {
514        self.0.is_crate_root()
515    }
516
517    pub fn is_top_level_module(self) -> bool {
518        self.0.is_top_level_module()
519    }
520}
521
522impl From<LocalModId> for ModId {
523    #[inline]
524    fn from(local: LocalModId) -> Self {
525        Self(local.0.to_def_id())
526    }
527}
528
529impl From<ModId> for DefId {
530    #[inline]
531    fn from(typed: ModId) -> Self {
532        typed.0
533    }
534}
535
536#[derive(#[automatically_derived]impl ::core::fmt::Debug for LocalModId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "LocalModId",
            &&self.0)
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for LocalModId {
}
#[automatically_derived]impl ::core::clone::Clone for LocalModId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<LocalDefId>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for LocalModId { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    LocalModId {
}
#[automatically_derived]impl ::core::cmp::PartialEq for LocalModId {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for LocalModId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<LocalDefId>;
    }
}Eq, #[automatically_derived]impl ::core::hash::Hash for LocalModId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for LocalModId {
            fn encode(&self, __encoder: &mut __E) {
                let LocalModId(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for LocalModId {
            fn decode(__decoder: &mut __D) -> Self {
                LocalModId(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for LocalModId {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    LocalModId(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
537pub struct LocalModId(LocalDefId);
538
539impl !Ord for LocalModId {}
540impl !PartialOrd for LocalModId {}
541
542impl LocalModId {
543    #[inline]
544    pub const fn new_unchecked(def_id: LocalDefId) -> Self {
545        Self(def_id)
546    }
547
548    pub fn is_top_level_module(self) -> bool {
549        self.0.is_top_level_module()
550    }
551
552    #[inline]
553    pub fn to_def_id(self) -> DefId {
554        self.0.into()
555    }
556
557    pub fn to_mod_id(self) -> ModId {
558        ModId::new_unchecked(self.0.to_def_id())
559    }
560
561    #[inline]
562    pub fn to_local_def_id(self) -> LocalDefId {
563        self.0
564    }
565}
566
567impl From<LocalModId> for LocalDefId {
568    #[inline]
569    fn from(typed: LocalModId) -> Self {
570        typed.0
571    }
572}
573
574impl From<LocalModId> for DefId {
575    #[inline]
576    fn from(typed: LocalModId) -> Self {
577        typed.0.into()
578    }
579}