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