sway_core/decl_engine/
engine.rs

1use parking_lot::RwLock;
2use std::{
3    collections::{HashMap, HashSet, VecDeque},
4    fmt::Write,
5    sync::Arc,
6};
7
8use sway_types::{Named, ProgramId, SourceId, Spanned};
9
10use crate::{
11    concurrent_slab::ConcurrentSlab,
12    decl_engine::{parsed_id::ParsedDeclId, *},
13    engine_threading::*,
14    language::{
15        parsed::{
16            AbiDeclaration, ConfigurableDeclaration, ConstGenericDeclaration, ConstantDeclaration,
17            Declaration, EnumDeclaration, FunctionDeclaration, ImplSelfOrTrait, StorageDeclaration,
18            StructDeclaration, TraitDeclaration, TraitFn, TraitTypeDeclaration,
19            TypeAliasDeclaration,
20        },
21        ty::{
22            self, TyAbiDecl, TyConfigurableDecl, TyConstGenericDecl, TyConstantDecl,
23            TyDeclParsedType, TyEnumDecl, TyFunctionDecl, TyImplSelfOrTrait, TyStorageDecl,
24            TyStructDecl, TyTraitDecl, TyTraitFn, TyTraitType, TyTypeAliasDecl,
25        },
26    },
27};
28
29/// Used inside of type inference to store declarations.
30#[derive(Debug, Default)]
31pub struct DeclEngine {
32    function_slab: ConcurrentSlab<TyFunctionDecl>,
33    trait_slab: ConcurrentSlab<TyTraitDecl>,
34    trait_fn_slab: ConcurrentSlab<TyTraitFn>,
35    trait_type_slab: ConcurrentSlab<TyTraitType>,
36    impl_self_or_trait_slab: ConcurrentSlab<TyImplSelfOrTrait>,
37    struct_slab: ConcurrentSlab<TyStructDecl>,
38    storage_slab: ConcurrentSlab<TyStorageDecl>,
39    abi_slab: ConcurrentSlab<TyAbiDecl>,
40    constant_slab: ConcurrentSlab<TyConstantDecl>,
41    configurable_slab: ConcurrentSlab<TyConfigurableDecl>,
42    const_generics_slab: ConcurrentSlab<TyConstGenericDecl>,
43    enum_slab: ConcurrentSlab<TyEnumDecl>,
44    type_alias_slab: ConcurrentSlab<TyTypeAliasDecl>,
45
46    function_parsed_decl_id_map:
47        RwLock<HashMap<DeclId<TyFunctionDecl>, ParsedDeclId<FunctionDeclaration>>>,
48    trait_parsed_decl_id_map: RwLock<HashMap<DeclId<TyTraitDecl>, ParsedDeclId<TraitDeclaration>>>,
49    trait_fn_parsed_decl_id_map: RwLock<HashMap<DeclId<TyTraitFn>, ParsedDeclId<TraitFn>>>,
50    trait_type_parsed_decl_id_map:
51        RwLock<HashMap<DeclId<TyTraitType>, ParsedDeclId<TraitTypeDeclaration>>>,
52    impl_self_or_trait_parsed_decl_id_map:
53        RwLock<HashMap<DeclId<TyImplSelfOrTrait>, ParsedDeclId<ImplSelfOrTrait>>>,
54    struct_parsed_decl_id_map:
55        RwLock<HashMap<DeclId<TyStructDecl>, ParsedDeclId<StructDeclaration>>>,
56    storage_parsed_decl_id_map:
57        RwLock<HashMap<DeclId<TyStorageDecl>, ParsedDeclId<StorageDeclaration>>>,
58    abi_parsed_decl_id_map: RwLock<HashMap<DeclId<TyAbiDecl>, ParsedDeclId<AbiDeclaration>>>,
59    constant_parsed_decl_id_map:
60        RwLock<HashMap<DeclId<TyConstantDecl>, ParsedDeclId<ConstantDeclaration>>>,
61    const_generic_parsed_decl_id_map:
62        RwLock<HashMap<DeclId<TyConstGenericDecl>, ParsedDeclId<ConstGenericDeclaration>>>,
63    configurable_parsed_decl_id_map:
64        RwLock<HashMap<DeclId<TyConfigurableDecl>, ParsedDeclId<ConfigurableDeclaration>>>,
65    const_generics_parsed_decl_id_map:
66        RwLock<HashMap<DeclId<TyConstGenericDecl>, ParsedDeclId<ConstGenericDeclaration>>>,
67    enum_parsed_decl_id_map: RwLock<HashMap<DeclId<TyEnumDecl>, ParsedDeclId<EnumDeclaration>>>,
68    type_alias_parsed_decl_id_map:
69        RwLock<HashMap<DeclId<TyTypeAliasDecl>, ParsedDeclId<TypeAliasDeclaration>>>,
70
71    parents: RwLock<HashMap<AssociatedItemDeclId, Vec<AssociatedItemDeclId>>>,
72}
73
74impl Clone for DeclEngine {
75    fn clone(&self) -> Self {
76        DeclEngine {
77            function_slab: self.function_slab.clone(),
78            trait_slab: self.trait_slab.clone(),
79            trait_fn_slab: self.trait_fn_slab.clone(),
80            trait_type_slab: self.trait_type_slab.clone(),
81            impl_self_or_trait_slab: self.impl_self_or_trait_slab.clone(),
82            struct_slab: self.struct_slab.clone(),
83            storage_slab: self.storage_slab.clone(),
84            abi_slab: self.abi_slab.clone(),
85            constant_slab: self.constant_slab.clone(),
86            configurable_slab: self.configurable_slab.clone(),
87            const_generics_slab: self.const_generics_slab.clone(),
88            enum_slab: self.enum_slab.clone(),
89            type_alias_slab: self.type_alias_slab.clone(),
90            function_parsed_decl_id_map: RwLock::new(
91                self.function_parsed_decl_id_map.read().clone(),
92            ),
93            trait_parsed_decl_id_map: RwLock::new(self.trait_parsed_decl_id_map.read().clone()),
94            trait_fn_parsed_decl_id_map: RwLock::new(
95                self.trait_fn_parsed_decl_id_map.read().clone(),
96            ),
97            trait_type_parsed_decl_id_map: RwLock::new(
98                self.trait_type_parsed_decl_id_map.read().clone(),
99            ),
100            impl_self_or_trait_parsed_decl_id_map: RwLock::new(
101                self.impl_self_or_trait_parsed_decl_id_map.read().clone(),
102            ),
103            struct_parsed_decl_id_map: RwLock::new(self.struct_parsed_decl_id_map.read().clone()),
104            storage_parsed_decl_id_map: RwLock::new(self.storage_parsed_decl_id_map.read().clone()),
105            abi_parsed_decl_id_map: RwLock::new(self.abi_parsed_decl_id_map.read().clone()),
106            constant_parsed_decl_id_map: RwLock::new(
107                self.constant_parsed_decl_id_map.read().clone(),
108            ),
109            const_generic_parsed_decl_id_map: RwLock::new(
110                self.const_generic_parsed_decl_id_map.read().clone(),
111            ),
112            configurable_parsed_decl_id_map: RwLock::new(
113                self.configurable_parsed_decl_id_map.read().clone(),
114            ),
115            const_generics_parsed_decl_id_map: RwLock::new(
116                self.const_generics_parsed_decl_id_map.read().clone(),
117            ),
118            enum_parsed_decl_id_map: RwLock::new(self.enum_parsed_decl_id_map.read().clone()),
119            type_alias_parsed_decl_id_map: RwLock::new(
120                self.type_alias_parsed_decl_id_map.read().clone(),
121            ),
122            parents: RwLock::new(self.parents.read().clone()),
123        }
124    }
125}
126
127pub trait DeclEngineGet<I, U> {
128    fn get(&self, index: &I) -> Arc<U>;
129    fn map<R>(&self, index: &I, f: impl FnOnce(&U) -> R) -> R;
130}
131
132pub trait DeclEngineGetParsedDeclId<T>
133where
134    T: TyDeclParsedType,
135{
136    fn get_parsed_decl_id(&self, decl_id: &DeclId<T>) -> Option<ParsedDeclId<T::ParsedType>>;
137}
138
139pub trait DeclEngineGetParsedDecl<T>
140where
141    T: TyDeclParsedType,
142{
143    fn get_parsed_decl(&self, decl_id: &DeclId<T>) -> Option<Declaration>;
144}
145
146pub trait DeclEngineInsert<T>
147where
148    T: Named + Spanned + TyDeclParsedType,
149{
150    fn insert(
151        &self,
152        decl: T,
153        parsed_decl_id: Option<&ParsedDeclId<T::ParsedType>>,
154    ) -> DeclRef<DeclId<T>>;
155}
156
157pub trait DeclEngineInsertArc<T>
158where
159    T: Named + Spanned + TyDeclParsedType,
160{
161    fn insert_arc(
162        &self,
163        decl: Arc<T>,
164        parsed_decl_id: Option<&ParsedDeclId<T::ParsedType>>,
165    ) -> DeclRef<DeclId<T>>;
166}
167
168pub trait DeclEngineReplace<T> {
169    fn replace(&self, index: DeclId<T>, decl: T);
170}
171
172pub trait DeclEngineIndex<T>: DeclEngineGet<DeclId<T>, T> + DeclEngineReplace<T>
173where
174    T: Named + Spanned,
175{
176}
177
178macro_rules! decl_engine_get {
179    ($slab:ident, $decl:ty) => {
180        impl DeclEngineGet<DeclId<$decl>, $decl> for DeclEngine {
181            fn get(&self, index: &DeclId<$decl>) -> Arc<$decl> {
182                self.$slab.get(index.inner())
183            }
184
185            fn map<R>(&self, index: &DeclId<$decl>, f: impl FnOnce(&$decl) -> R) -> R {
186                self.$slab.map(index.inner(), f)
187            }
188        }
189
190        impl DeclEngineGet<DeclRef<DeclId<$decl>>, $decl> for DeclEngine {
191            fn get(&self, index: &DeclRef<DeclId<$decl>>) -> Arc<$decl> {
192                self.$slab.get(index.id().inner())
193            }
194
195            fn map<R>(&self, index: &DeclRef<DeclId<$decl>>, f: impl FnOnce(&$decl) -> R) -> R {
196                self.$slab.map(index.id().inner(), f)
197            }
198        }
199    };
200}
201decl_engine_get!(function_slab, ty::TyFunctionDecl);
202decl_engine_get!(trait_slab, ty::TyTraitDecl);
203decl_engine_get!(trait_fn_slab, ty::TyTraitFn);
204decl_engine_get!(trait_type_slab, ty::TyTraitType);
205decl_engine_get!(impl_self_or_trait_slab, ty::TyImplSelfOrTrait);
206decl_engine_get!(struct_slab, ty::TyStructDecl);
207decl_engine_get!(storage_slab, ty::TyStorageDecl);
208decl_engine_get!(abi_slab, ty::TyAbiDecl);
209decl_engine_get!(constant_slab, ty::TyConstantDecl);
210decl_engine_get!(configurable_slab, ty::TyConfigurableDecl);
211decl_engine_get!(const_generics_slab, ty::TyConstGenericDecl);
212decl_engine_get!(enum_slab, ty::TyEnumDecl);
213decl_engine_get!(type_alias_slab, ty::TyTypeAliasDecl);
214
215macro_rules! decl_engine_insert {
216    ($slab:ident, $parsed_slab:ident, $decl:ty) => {
217        impl DeclEngineInsert<$decl> for DeclEngine {
218            fn insert(
219                &self,
220                decl: $decl,
221                parsed_decl_id: Option<&ParsedDeclId<<$decl as TyDeclParsedType>::ParsedType>>,
222            ) -> DeclRef<DeclId<$decl>> {
223                let span = decl.span();
224                let decl_name = decl.name().clone();
225                let decl_id = DeclId::new(self.$slab.insert(decl));
226                if let Some(parsed_decl_id) = parsed_decl_id {
227                    self.$parsed_slab
228                        .write()
229                        .insert(decl_id, parsed_decl_id.clone());
230                }
231                DeclRef::new(decl_name, decl_id, span)
232            }
233        }
234        impl DeclEngineInsertArc<$decl> for DeclEngine {
235            fn insert_arc(
236                &self,
237                decl: Arc<$decl>,
238                parsed_decl_id: Option<&ParsedDeclId<<$decl as TyDeclParsedType>::ParsedType>>,
239            ) -> DeclRef<DeclId<$decl>> {
240                let span = decl.span();
241                let decl_name = decl.name().clone();
242                let decl_id = DeclId::new(self.$slab.insert_arc(decl));
243                if let Some(parsed_decl_id) = parsed_decl_id {
244                    self.$parsed_slab
245                        .write()
246                        .insert(decl_id, parsed_decl_id.clone());
247                }
248                DeclRef::new(decl_name, decl_id, span)
249            }
250        }
251    };
252}
253decl_engine_insert!(
254    function_slab,
255    function_parsed_decl_id_map,
256    ty::TyFunctionDecl
257);
258decl_engine_insert!(trait_slab, trait_parsed_decl_id_map, ty::TyTraitDecl);
259decl_engine_insert!(trait_fn_slab, trait_fn_parsed_decl_id_map, ty::TyTraitFn);
260decl_engine_insert!(
261    trait_type_slab,
262    trait_type_parsed_decl_id_map,
263    ty::TyTraitType
264);
265decl_engine_insert!(
266    impl_self_or_trait_slab,
267    impl_self_or_trait_parsed_decl_id_map,
268    ty::TyImplSelfOrTrait
269);
270decl_engine_insert!(struct_slab, struct_parsed_decl_id_map, ty::TyStructDecl);
271decl_engine_insert!(storage_slab, storage_parsed_decl_id_map, ty::TyStorageDecl);
272decl_engine_insert!(abi_slab, abi_parsed_decl_id_map, ty::TyAbiDecl);
273decl_engine_insert!(
274    constant_slab,
275    constant_parsed_decl_id_map,
276    ty::TyConstantDecl
277);
278decl_engine_insert!(
279    configurable_slab,
280    configurable_parsed_decl_id_map,
281    ty::TyConfigurableDecl
282);
283decl_engine_insert!(
284    const_generics_slab,
285    const_generics_parsed_decl_id_map,
286    ty::TyConstGenericDecl
287);
288decl_engine_insert!(enum_slab, enum_parsed_decl_id_map, ty::TyEnumDecl);
289decl_engine_insert!(
290    type_alias_slab,
291    type_alias_parsed_decl_id_map,
292    ty::TyTypeAliasDecl
293);
294
295macro_rules! decl_engine_parsed_decl_id {
296    ($slab:ident, $decl:ty) => {
297        impl DeclEngineGetParsedDeclId<$decl> for DeclEngine {
298            fn get_parsed_decl_id(
299                &self,
300                decl_id: &DeclId<$decl>,
301            ) -> Option<ParsedDeclId<<$decl as TyDeclParsedType>::ParsedType>> {
302                let parsed_decl_id_map = self.$slab.read();
303                if let Some(parsed_decl_id) = parsed_decl_id_map.get(&decl_id) {
304                    return Some(parsed_decl_id.clone());
305                } else {
306                    None
307                }
308            }
309        }
310    };
311}
312
313decl_engine_parsed_decl_id!(function_parsed_decl_id_map, ty::TyFunctionDecl);
314decl_engine_parsed_decl_id!(trait_parsed_decl_id_map, ty::TyTraitDecl);
315decl_engine_parsed_decl_id!(trait_fn_parsed_decl_id_map, ty::TyTraitFn);
316decl_engine_parsed_decl_id!(trait_type_parsed_decl_id_map, ty::TyTraitType);
317decl_engine_parsed_decl_id!(impl_self_or_trait_parsed_decl_id_map, ty::TyImplSelfOrTrait);
318decl_engine_parsed_decl_id!(struct_parsed_decl_id_map, ty::TyStructDecl);
319decl_engine_parsed_decl_id!(storage_parsed_decl_id_map, ty::TyStorageDecl);
320decl_engine_parsed_decl_id!(abi_parsed_decl_id_map, ty::TyAbiDecl);
321decl_engine_parsed_decl_id!(constant_parsed_decl_id_map, ty::TyConstantDecl);
322decl_engine_parsed_decl_id!(const_generic_parsed_decl_id_map, ty::TyConstGenericDecl);
323decl_engine_parsed_decl_id!(configurable_parsed_decl_id_map, ty::TyConfigurableDecl);
324decl_engine_parsed_decl_id!(enum_parsed_decl_id_map, ty::TyEnumDecl);
325decl_engine_parsed_decl_id!(type_alias_parsed_decl_id_map, ty::TyTypeAliasDecl);
326
327macro_rules! decl_engine_parsed_decl {
328    ($slab:ident, $decl:ty, $ctor:expr) => {
329        impl DeclEngineGetParsedDecl<$decl> for DeclEngine {
330            fn get_parsed_decl(&self, decl_id: &DeclId<$decl>) -> Option<Declaration> {
331                let parsed_decl_id_map = self.$slab.read();
332                if let Some(parsed_decl_id) = parsed_decl_id_map.get(&decl_id) {
333                    return Some($ctor(parsed_decl_id.clone()));
334                } else {
335                    None
336                }
337            }
338        }
339    };
340}
341
342decl_engine_parsed_decl!(
343    function_parsed_decl_id_map,
344    ty::TyFunctionDecl,
345    Declaration::FunctionDeclaration
346);
347decl_engine_parsed_decl!(
348    trait_parsed_decl_id_map,
349    ty::TyTraitDecl,
350    Declaration::TraitDeclaration
351);
352decl_engine_parsed_decl!(
353    trait_fn_parsed_decl_id_map,
354    ty::TyTraitFn,
355    Declaration::TraitFnDeclaration
356);
357decl_engine_parsed_decl!(
358    trait_type_parsed_decl_id_map,
359    ty::TyTraitType,
360    Declaration::TraitTypeDeclaration
361);
362decl_engine_parsed_decl!(
363    impl_self_or_trait_parsed_decl_id_map,
364    ty::TyImplSelfOrTrait,
365    Declaration::ImplSelfOrTrait
366);
367decl_engine_parsed_decl!(
368    struct_parsed_decl_id_map,
369    ty::TyStructDecl,
370    Declaration::StructDeclaration
371);
372decl_engine_parsed_decl!(
373    storage_parsed_decl_id_map,
374    ty::TyStorageDecl,
375    Declaration::StorageDeclaration
376);
377decl_engine_parsed_decl!(
378    abi_parsed_decl_id_map,
379    ty::TyAbiDecl,
380    Declaration::AbiDeclaration
381);
382decl_engine_parsed_decl!(
383    constant_parsed_decl_id_map,
384    ty::TyConstantDecl,
385    Declaration::ConstantDeclaration
386);
387decl_engine_parsed_decl!(
388    const_generic_parsed_decl_id_map,
389    ty::TyConstGenericDecl,
390    Declaration::ConstGenericDeclaration
391);
392decl_engine_parsed_decl!(
393    configurable_parsed_decl_id_map,
394    ty::TyConfigurableDecl,
395    Declaration::ConfigurableDeclaration
396);
397decl_engine_parsed_decl!(
398    enum_parsed_decl_id_map,
399    ty::TyEnumDecl,
400    Declaration::EnumDeclaration
401);
402decl_engine_parsed_decl!(
403    type_alias_parsed_decl_id_map,
404    ty::TyTypeAliasDecl,
405    Declaration::TypeAliasDeclaration
406);
407
408macro_rules! decl_engine_replace {
409    ($slab:ident, $decl:ty) => {
410        impl DeclEngineReplace<$decl> for DeclEngine {
411            fn replace(&self, index: DeclId<$decl>, decl: $decl) {
412                self.$slab.replace(index.inner(), decl);
413            }
414        }
415    };
416}
417decl_engine_replace!(function_slab, ty::TyFunctionDecl);
418decl_engine_replace!(trait_slab, ty::TyTraitDecl);
419decl_engine_replace!(trait_fn_slab, ty::TyTraitFn);
420decl_engine_replace!(trait_type_slab, ty::TyTraitType);
421decl_engine_replace!(impl_self_or_trait_slab, ty::TyImplSelfOrTrait);
422decl_engine_replace!(struct_slab, ty::TyStructDecl);
423decl_engine_replace!(storage_slab, ty::TyStorageDecl);
424decl_engine_replace!(abi_slab, ty::TyAbiDecl);
425decl_engine_replace!(constant_slab, ty::TyConstantDecl);
426decl_engine_replace!(configurable_slab, ty::TyConfigurableDecl);
427decl_engine_replace!(enum_slab, ty::TyEnumDecl);
428decl_engine_replace!(type_alias_slab, ty::TyTypeAliasDecl);
429
430macro_rules! decl_engine_index {
431    ($slab:ident, $decl:ty) => {
432        impl DeclEngineIndex<$decl> for DeclEngine {}
433    };
434}
435decl_engine_index!(function_slab, ty::TyFunctionDecl);
436decl_engine_index!(trait_slab, ty::TyTraitDecl);
437decl_engine_index!(trait_fn_slab, ty::TyTraitFn);
438decl_engine_index!(trait_type_slab, ty::TyTraitType);
439decl_engine_index!(impl_self_or_trait_slab, ty::TyImplSelfOrTrait);
440decl_engine_index!(struct_slab, ty::TyStructDecl);
441decl_engine_index!(storage_slab, ty::TyStorageDecl);
442decl_engine_index!(abi_slab, ty::TyAbiDecl);
443decl_engine_index!(constant_slab, ty::TyConstantDecl);
444decl_engine_index!(configurable_slab, ty::TyConfigurableDecl);
445decl_engine_index!(enum_slab, ty::TyEnumDecl);
446decl_engine_index!(type_alias_slab, ty::TyTypeAliasDecl);
447
448macro_rules! decl_engine_clear_program {
449    ($($slab:ident, $decl:ty);* $(;)?) => {
450        impl DeclEngine {
451            pub fn clear_program(&mut self, program_id: &ProgramId) {
452                self.parents.write().retain(|key, _| {
453                    match key {
454                        AssociatedItemDeclId::TraitFn(decl_id) => {
455                            self.get_trait_fn(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
456                        },
457                        AssociatedItemDeclId::Function(decl_id) => {
458                            self.get_function(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
459                        },
460                        AssociatedItemDeclId::Type(decl_id) => {
461                            self.get_type(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
462                        },
463                        AssociatedItemDeclId::Constant(decl_id) => {
464                            self.get_constant(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
465                        },
466                    }
467                });
468
469                $(
470                    self.$slab.retain(|_k, ty| match ty.span().source_id() {
471                        Some(source_id) => &source_id.program_id() != program_id,
472                        None => true,
473                    });
474                )*
475            }
476        }
477    };
478}
479
480decl_engine_clear_program!(
481    function_slab, ty::TyFunctionDecl;
482    trait_slab, ty::TyTraitDecl;
483    trait_fn_slab, ty::TyTraitFn;
484    trait_type_slab, ty::TyTraitType;
485    impl_self_or_trait_slab, ty::TyImplTrait;
486    struct_slab, ty::TyStructDecl;
487    storage_slab, ty::TyStorageDecl;
488    abi_slab, ty::TyAbiDecl;
489    constant_slab, ty::TyConstantDecl;
490    configurable_slab, ty::TyConfigurableDecl;
491    enum_slab, ty::TyEnumDecl;
492    type_alias_slab, ty::TyTypeAliasDecl;
493);
494
495macro_rules! decl_engine_clear_module {
496    ($($slab:ident, $decl:ty);* $(;)?) => {
497        impl DeclEngine {
498            pub fn clear_module(&mut self, source_id: &SourceId) {
499                self.parents.write().retain(|key, _| {
500                    match key {
501                        AssociatedItemDeclId::TraitFn(decl_id) => {
502                            self.get_trait_fn(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
503                        },
504                        AssociatedItemDeclId::Function(decl_id) => {
505                            self.get_function(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
506                        },
507                        AssociatedItemDeclId::Type(decl_id) => {
508                            self.get_type(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
509                        },
510                        AssociatedItemDeclId::Constant(decl_id) => {
511                            self.get_constant(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
512                        },
513                    }
514                });
515
516                $(
517                    self.$slab.retain(|_k, ty| match ty.span().source_id() {
518                        Some(src_id) => src_id != source_id,
519                        None => true,
520                    });
521                )*
522            }
523        }
524    };
525}
526
527decl_engine_clear_module!(
528    function_slab, ty::TyFunctionDecl;
529    trait_slab, ty::TyTraitDecl;
530    trait_fn_slab, ty::TyTraitFn;
531    trait_type_slab, ty::TyTraitType;
532    impl_self_or_trait_slab, ty::TyImplTrait;
533    struct_slab, ty::TyStructDecl;
534    storage_slab, ty::TyStorageDecl;
535    abi_slab, ty::TyAbiDecl;
536    constant_slab, ty::TyConstantDecl;
537    configurable_slab, ty::TyConfigurableDecl;
538    enum_slab, ty::TyEnumDecl;
539    type_alias_slab, ty::TyTypeAliasDecl;
540);
541
542impl DeclEngine {
543    /// Given a [DeclRef] `index`, finds all the parents of `index` and all the
544    /// recursive parents of those parents, and so on. Does not perform
545    /// duplicated computation---if the parents of a [DeclRef] have already been
546    /// found, we do not find them again.
547    #[allow(clippy::map_entry)]
548    pub(crate) fn find_all_parents<'a, T>(
549        &self,
550        engines: &Engines,
551        index: &'a T,
552    ) -> Vec<AssociatedItemDeclId>
553    where
554        AssociatedItemDeclId: From<&'a T>,
555    {
556        let index: AssociatedItemDeclId = AssociatedItemDeclId::from(index);
557        let parents = self.parents.read();
558        let mut acc_parents: HashMap<AssociatedItemDeclId, AssociatedItemDeclId> = HashMap::new();
559        let mut already_checked: HashSet<AssociatedItemDeclId> = HashSet::new();
560        let mut left_to_check: VecDeque<AssociatedItemDeclId> = VecDeque::from([index]);
561        while let Some(curr) = left_to_check.pop_front() {
562            if !already_checked.insert(curr.clone()) {
563                continue;
564            }
565            if let Some(curr_parents) = parents.get(&curr) {
566                for curr_parent in curr_parents.iter() {
567                    if !acc_parents.contains_key(curr_parent) {
568                        acc_parents.insert(curr_parent.clone(), curr_parent.clone());
569                    }
570                    if !left_to_check.iter().any(|x| match (x, curr_parent) {
571                        (
572                            AssociatedItemDeclId::TraitFn(x_id),
573                            AssociatedItemDeclId::TraitFn(curr_parent_id),
574                        ) => self.get(x_id).eq(
575                            &self.get(curr_parent_id),
576                            &PartialEqWithEnginesContext::new(engines),
577                        ),
578                        (
579                            AssociatedItemDeclId::Function(x_id),
580                            AssociatedItemDeclId::Function(curr_parent_id),
581                        ) => self.get(x_id).eq(
582                            &self.get(curr_parent_id),
583                            &PartialEqWithEnginesContext::new(engines),
584                        ),
585                        _ => false,
586                    }) {
587                        left_to_check.push_back(curr_parent.clone());
588                    }
589                }
590            }
591        }
592        acc_parents.values().cloned().collect()
593    }
594
595    pub(crate) fn register_parent<I>(
596        &self,
597        index: AssociatedItemDeclId,
598        parent: AssociatedItemDeclId,
599    ) where
600        AssociatedItemDeclId: From<DeclId<I>>,
601    {
602        let mut parents = self.parents.write();
603        parents
604            .entry(index)
605            .and_modify(|e| e.push(parent.clone()))
606            .or_insert_with(|| vec![parent]);
607    }
608
609    /// Friendly helper method for calling the `get` method from the
610    /// implementation of [DeclEngineGet] for [DeclEngine]
611    ///
612    /// Calling [DeclEngine][get] directly is equivalent to this method, but
613    /// this method adds additional syntax that some users may find helpful.
614    pub fn get_function<I>(&self, index: &I) -> Arc<ty::TyFunctionDecl>
615    where
616        DeclEngine: DeclEngineGet<I, ty::TyFunctionDecl>,
617    {
618        self.get(index)
619    }
620
621    /// Friendly helper method for calling the `get` method from the
622    /// implementation of [DeclEngineGet] for [DeclEngine]
623    ///
624    /// Calling [DeclEngine][get] directly is equivalent to this method, but
625    /// this method adds additional syntax that some users may find helpful.
626    pub fn get_trait<I>(&self, index: &I) -> Arc<ty::TyTraitDecl>
627    where
628        DeclEngine: DeclEngineGet<I, ty::TyTraitDecl>,
629    {
630        self.get(index)
631    }
632
633    /// Returns all the [ty::TyTraitDecl]s whose name is the same as `trait_name`.
634    ///
635    /// The method does a linear search over all the declared traits and is meant
636    /// to be used only for diagnostic purposes.
637    pub fn get_traits_by_name(&self, trait_name: &Ident) -> Vec<ty::TyTraitDecl> {
638        let mut vec = vec![];
639        for trait_decl in self.trait_slab.values() {
640            if trait_decl.name == *trait_name {
641                vec.push((*trait_decl).clone())
642            }
643        }
644        vec
645    }
646
647    /// Friendly helper method for calling the `get` method from the
648    /// implementation of [DeclEngineGet] for [DeclEngine]
649    ///
650    /// Calling [DeclEngine][get] directly is equivalent to this method, but
651    /// this method adds additional syntax that some users may find helpful.
652    pub fn get_trait_fn<I>(&self, index: &I) -> Arc<ty::TyTraitFn>
653    where
654        DeclEngine: DeclEngineGet<I, ty::TyTraitFn>,
655    {
656        self.get(index)
657    }
658
659    /// Friendly helper method for calling the `get` method from the
660    /// implementation of [DeclEngineGet] for [DeclEngine]
661    ///
662    /// Calling [DeclEngine][get] directly is equivalent to this method, but
663    /// this method adds additional syntax that some users may find helpful.
664    pub fn get_impl_self_or_trait<I>(&self, index: &I) -> Arc<ty::TyImplSelfOrTrait>
665    where
666        DeclEngine: DeclEngineGet<I, ty::TyImplSelfOrTrait>,
667    {
668        self.get(index)
669    }
670
671    /// Friendly helper method for calling the `get` method from the
672    /// implementation of [DeclEngineGet] for [DeclEngine]
673    ///
674    /// Calling [DeclEngine][get] directly is equivalent to this method, but
675    /// this method adds additional syntax that some users may find helpful.
676    pub fn get_struct<I>(&self, index: &I) -> Arc<ty::TyStructDecl>
677    where
678        DeclEngine: DeclEngineGet<I, ty::TyStructDecl>,
679    {
680        self.get(index)
681    }
682
683    /// Friendly helper method for calling the `get` method from the
684    /// implementation of [DeclEngineGet] for [DeclEngine].
685    ///
686    /// Calling [DeclEngine][get] directly is equivalent to this method, but
687    /// this method adds additional syntax that some users may find helpful.
688    pub fn get_storage<I>(&self, index: &I) -> Arc<ty::TyStorageDecl>
689    where
690        DeclEngine: DeclEngineGet<I, ty::TyStorageDecl>,
691    {
692        self.get(index)
693    }
694
695    /// Friendly helper method for calling the `get` method from the
696    /// implementation of [DeclEngineGet] for [DeclEngine]
697    ///
698    /// Calling [DeclEngine][get] directly is equivalent to this method, but
699    /// this method adds additional syntax that some users may find helpful.
700    pub fn get_abi<I>(&self, index: &I) -> Arc<ty::TyAbiDecl>
701    where
702        DeclEngine: DeclEngineGet<I, ty::TyAbiDecl>,
703    {
704        self.get(index)
705    }
706
707    /// Friendly helper method for calling the `get` method from the
708    /// implementation of [DeclEngineGet] for [DeclEngine]
709    ///
710    /// Calling [DeclEngine][get] directly is equivalent to this method, but
711    /// this method adds additional syntax that some users may find helpful.
712    pub fn get_constant<I>(&self, index: &I) -> Arc<ty::TyConstantDecl>
713    where
714        DeclEngine: DeclEngineGet<I, ty::TyConstantDecl>,
715    {
716        self.get(index)
717    }
718
719    /// Friendly helper method for calling the `get` method from the
720    /// implementation of [DeclEngineGet] for [DeclEngine]
721    ///
722    /// Calling [DeclEngine][get] directly is equivalent to this method, but
723    /// this method adds additional syntax that some users may find helpful.
724    pub fn get_configurable<I>(&self, index: &I) -> Arc<ty::TyConfigurableDecl>
725    where
726        DeclEngine: DeclEngineGet<I, ty::TyConfigurableDecl>,
727    {
728        self.get(index)
729    }
730
731    /// Friendly helper method for calling the `get` method from the
732    /// implementation of [DeclEngineGet] for [DeclEngine]
733    ///
734    /// Calling [DeclEngine][get] directly is equivalent to this method, but
735    /// this method adds additional syntax that some users may find helpful.
736    pub fn get_const_generic<I>(&self, index: &I) -> Arc<ty::TyConstGenericDecl>
737    where
738        DeclEngine: DeclEngineGet<I, ty::TyConstGenericDecl>,
739    {
740        self.get(index)
741    }
742
743    /// Friendly helper method for calling the `get` method from the
744    /// implementation of [DeclEngineGet] for [DeclEngine]
745    ///
746    /// Calling [DeclEngine][get] directly is equivalent to this method, but
747    /// this method adds additional syntax that some users may find helpful.
748    pub fn get_type<I>(&self, index: &I) -> Arc<ty::TyTraitType>
749    where
750        DeclEngine: DeclEngineGet<I, ty::TyTraitType>,
751    {
752        self.get(index)
753    }
754
755    /// Friendly helper method for calling the `get` method from the
756    /// implementation of [DeclEngineGet] for [DeclEngine]
757    ///
758    /// Calling [DeclEngine][get] directly is equivalent to this method, but
759    /// this method adds additional syntax that some users may find helpful.
760    pub fn get_enum<I>(&self, index: &I) -> Arc<ty::TyEnumDecl>
761    where
762        DeclEngine: DeclEngineGet<I, ty::TyEnumDecl>,
763    {
764        self.get(index)
765    }
766
767    /// Friendly helper method for calling the `get` method from the
768    /// implementation of [DeclEngineGet] for [DeclEngine]
769    ///
770    /// Calling [DeclEngine][get] directly is equivalent to this method, but
771    /// this method adds additional syntax that some users may find helpful.
772    pub fn get_type_alias<I>(&self, index: &I) -> Arc<ty::TyTypeAliasDecl>
773    where
774        DeclEngine: DeclEngineGet<I, ty::TyTypeAliasDecl>,
775    {
776        self.get(index)
777    }
778
779    /// Pretty print method for printing the [DeclEngine]. This method is
780    /// manually implemented to avoid implementation overhead regarding using
781    /// [DisplayWithEngines].
782    pub fn pretty_print(&self, engines: &Engines) -> String {
783        let mut builder = String::new();
784        let mut list = String::with_capacity(1024 * 1024);
785        let funcs = self.function_slab.values();
786        for (i, func) in funcs.iter().enumerate() {
787            list.push_str(&format!("{i} - {:?}\n", engines.help_out(func)));
788        }
789        write!(builder, "DeclEngine {{\n{list}\n}}").unwrap();
790        builder
791    }
792}