Skip to main content

sway_core/decl_engine/
engine.rs

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