1use crate::{
2 decl_engine::*,
3 engine_threading::*,
4 language::ty::{
5 TyConstantDecl, TyDeclParsedType, TyEnumDecl, TyFunctionDecl, TyImplSelfOrTrait,
6 TyStructDecl, TyTraitDecl, TyTraitFn, TyTraitType, TyTypeAliasDecl,
7 },
8 type_system::*,
9 HasChanges,
10};
11use serde::{Deserialize, Serialize};
12use std::{
13 collections::hash_map::DefaultHasher,
14 fmt,
15 hash::{Hash, Hasher},
16 marker::PhantomData,
17};
18use sway_types::{Named, Spanned};
19
20pub type DeclIdIndexType = usize;
21
22pub struct DeclId<T>(DeclIdIndexType, PhantomData<T>);
24
25impl<T> fmt::Debug for DeclId<T> {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.debug_tuple("DeclId").field(&self.0).finish()
28 }
29}
30
31#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)]
32pub struct DeclUniqueId(pub(crate) u64);
33
34impl<T> DeclId<T> {
35 pub(crate) fn inner(&self) -> DeclIdIndexType {
36 self.0
37 }
38
39 pub fn unique_id(&self) -> DeclUniqueId
40 where
41 T: 'static,
42 {
43 let mut hasher = DefaultHasher::default();
44 std::any::TypeId::of::<T>().hash(&mut hasher);
45 self.0.hash(&mut hasher);
46
47 DeclUniqueId(hasher.finish())
48 }
49}
50
51impl<T> Copy for DeclId<T> {}
52impl<T> Clone for DeclId<T> {
53 fn clone(&self) -> Self {
54 *self
55 }
56}
57
58impl<T> Eq for DeclId<T> {}
59impl<T> Hash for DeclId<T> {
60 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
61 self.0.hash(state)
62 }
63}
64impl<T> PartialEq for DeclId<T> {
65 fn eq(&self, other: &Self) -> bool {
66 self.0.eq(&other.0)
67 }
68}
69impl<T> PartialOrd for DeclId<T> {
70 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
71 Some(self.cmp(other))
72 }
73}
74impl<T> Ord for DeclId<T> {
75 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
76 self.0.cmp(&other.0)
77 }
78}
79
80impl<T> DeclId<T> {
81 pub(crate) fn new(id: usize) -> Self {
82 DeclId(id, PhantomData)
83 }
84
85 pub(crate) fn replace_id(&mut self, index: Self) {
86 self.0 = index.0;
87 }
88
89 pub(crate) fn dummy() -> Self {
90 Self(usize::MAX, PhantomData)
92 }
93}
94
95#[allow(clippy::from_over_into)]
96impl<T> Into<usize> for DeclId<T> {
97 fn into(self) -> usize {
98 self.0
99 }
100}
101
102impl<T> DebugWithEngines for DeclId<T>
103where
104 DeclEngine: DeclEngineIndex<T>,
105 T: Named + Spanned + DebugWithEngines,
106{
107 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
108 let decl = engines.de().get(self);
109 DebugWithEngines::fmt(&decl, f, engines)
110 }
111}
112
113impl<T> EqWithEngines for DeclId<T>
114where
115 DeclEngine: DeclEngineIndex<T>,
116 T: Named + Spanned + PartialEqWithEngines + EqWithEngines,
117{
118}
119
120impl<T> PartialEqWithEngines for DeclId<T>
121where
122 DeclEngine: DeclEngineIndex<T>,
123 T: Named + Spanned + PartialEqWithEngines,
124{
125 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
126 let decl_engine = ctx.engines().de();
127 let l_decl = decl_engine.get(self);
128 let r_decl = decl_engine.get(other);
129 l_decl.name() == r_decl.name() && l_decl.eq(&r_decl, ctx)
130 }
131}
132
133impl<T> HashWithEngines for DeclId<T>
134where
135 DeclEngine: DeclEngineIndex<T>,
136 T: Named + Spanned + HashWithEngines,
137{
138 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
139 let decl_engine = engines.de();
140 let decl = decl_engine.get(self);
141 decl.name().hash(state);
142 decl.hash(state, engines);
143 }
144}
145
146impl SubstTypes for DeclId<TyFunctionDecl> {
147 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
148 let decl_engine = ctx.engines.de();
149 let mut decl = (*decl_engine.get(self)).clone();
150 if decl.subst(ctx).has_changes() {
151 decl_engine.replace(*self, decl);
152 HasChanges::Yes
153 } else {
154 HasChanges::No
155 }
156 }
157}
158impl SubstTypes for DeclId<TyTraitDecl> {
159 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
160 let decl_engine = ctx.engines.de();
161 let mut decl = (*decl_engine.get(self)).clone();
162 if decl.subst(ctx).has_changes() {
163 decl_engine.replace(*self, decl);
164 HasChanges::Yes
165 } else {
166 HasChanges::No
167 }
168 }
169}
170impl SubstTypes for DeclId<TyTraitFn> {
171 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
172 let decl_engine = ctx.engines.de();
173 let mut decl = (*decl_engine.get(self)).clone();
174 if decl.subst(ctx).has_changes() {
175 decl_engine.replace(*self, decl);
176 HasChanges::Yes
177 } else {
178 HasChanges::No
179 }
180 }
181}
182impl SubstTypes for DeclId<TyImplSelfOrTrait> {
183 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
184 let decl_engine = ctx.engines.de();
185 let mut decl = (*decl_engine.get(self)).clone();
186 if decl.subst(ctx).has_changes() {
187 decl_engine.replace(*self, decl);
188 HasChanges::Yes
189 } else {
190 HasChanges::No
191 }
192 }
193}
194impl SubstTypes for DeclId<TyStructDecl> {
195 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
196 let decl_engine = ctx.engines.de();
197 let mut decl = (*decl_engine.get(self)).clone();
198 if decl.subst(ctx).has_changes() {
199 decl_engine.replace(*self, decl);
200 HasChanges::Yes
201 } else {
202 HasChanges::No
203 }
204 }
205}
206impl SubstTypes for DeclId<TyEnumDecl> {
207 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
208 let decl_engine = ctx.engines.de();
209 let mut decl = (*decl_engine.get(self)).clone();
210 if decl.subst(ctx).has_changes() {
211 decl_engine.replace(*self, decl);
212 HasChanges::Yes
213 } else {
214 HasChanges::No
215 }
216 }
217}
218impl SubstTypes for DeclId<TyTypeAliasDecl> {
219 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
220 let decl_engine = ctx.engines.de();
221 let mut decl = (*decl_engine.get(self)).clone();
222 if decl.subst(ctx).has_changes() {
223 decl_engine.replace(*self, decl);
224 HasChanges::Yes
225 } else {
226 HasChanges::No
227 }
228 }
229}
230
231impl SubstTypes for DeclId<TyTraitType> {
232 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
233 let decl_engine = ctx.engines.de();
234 let mut decl = (*decl_engine.get(self)).clone();
235 if decl.subst(ctx).has_changes() {
236 decl_engine.replace(*self, decl);
237 HasChanges::Yes
238 } else {
239 HasChanges::No
240 }
241 }
242}
243
244impl SubstTypes for DeclId<TyConstantDecl> {
254 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
255 let decl_engine = ctx.engines.de();
256 let mut decl = (*decl_engine.get(self)).clone();
257 if decl.subst(ctx).has_changes() {
258 *self = *decl_engine
259 .insert(decl, decl_engine.get_parsed_decl_id(self).as_ref())
260 .id();
261 HasChanges::Yes
262 } else {
263 HasChanges::No
264 }
265 }
266}
267
268impl<T> DeclId<T>
269where
270 DeclEngine: DeclEngineIndex<T> + DeclEngineInsert<T> + DeclEngineGetParsedDeclId<T>,
271 T: Named + Spanned + SubstTypes + Clone + TyDeclParsedType,
272{
273 pub(crate) fn subst_types_and_insert_new(
274 &self,
275 ctx: &SubstTypesContext,
276 ) -> Option<DeclRef<Self>> {
277 let decl_engine = ctx.engines.de();
278 let mut decl = (*decl_engine.get(self)).clone();
279 if decl.subst(ctx).has_changes() {
280 Some(decl_engine.insert(decl, decl_engine.get_parsed_decl_id(self).as_ref()))
281 } else {
282 None
283 }
284 }
285}
286
287impl<T> Serialize for DeclId<T> {
288 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
289 where
290 S: serde::Serializer,
291 {
292 self.0.serialize(serializer)
293 }
294}
295
296impl<'de, T> Deserialize<'de> for DeclId<T> {
297 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
298 where
299 D: serde::Deserializer<'de>,
300 {
301 let id = DeclIdIndexType::deserialize(deserializer)?;
302 Ok(DeclId::new(id))
303 }
304}