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    enum_parsed_decl_id_map: RwLock<HashMap<DeclId<TyEnumDecl>, ParsedDeclId<EnumDeclaration>>>,
67    type_alias_parsed_decl_id_map:
68        RwLock<HashMap<DeclId<TyTypeAliasDecl>, ParsedDeclId<TypeAliasDeclaration>>>,
69
70    parents: RwLock<HashMap<AssociatedItemDeclId, Vec<AssociatedItemDeclId>>>,
71}
72
73impl Clone for DeclEngine {
74    fn clone(&self) -> Self {
75        DeclEngine {
76            function_slab: self.function_slab.clone(),
77            trait_slab: self.trait_slab.clone(),
78            trait_fn_slab: self.trait_fn_slab.clone(),
79            trait_type_slab: self.trait_type_slab.clone(),
80            impl_self_or_trait_slab: self.impl_self_or_trait_slab.clone(),
81            struct_slab: self.struct_slab.clone(),
82            storage_slab: self.storage_slab.clone(),
83            abi_slab: self.abi_slab.clone(),
84            constant_slab: self.constant_slab.clone(),
85            configurable_slab: self.configurable_slab.clone(),
86            const_generics_slab: self.const_generics_slab.clone(),
87            enum_slab: self.enum_slab.clone(),
88            type_alias_slab: self.type_alias_slab.clone(),
89            function_parsed_decl_id_map: RwLock::new(
90                self.function_parsed_decl_id_map.read().clone(),
91            ),
92            trait_parsed_decl_id_map: RwLock::new(self.trait_parsed_decl_id_map.read().clone()),
93            trait_fn_parsed_decl_id_map: RwLock::new(
94                self.trait_fn_parsed_decl_id_map.read().clone(),
95            ),
96            trait_type_parsed_decl_id_map: RwLock::new(
97                self.trait_type_parsed_decl_id_map.read().clone(),
98            ),
99            impl_self_or_trait_parsed_decl_id_map: RwLock::new(
100                self.impl_self_or_trait_parsed_decl_id_map.read().clone(),
101            ),
102            struct_parsed_decl_id_map: RwLock::new(self.struct_parsed_decl_id_map.read().clone()),
103            storage_parsed_decl_id_map: RwLock::new(self.storage_parsed_decl_id_map.read().clone()),
104            abi_parsed_decl_id_map: RwLock::new(self.abi_parsed_decl_id_map.read().clone()),
105            constant_parsed_decl_id_map: RwLock::new(
106                self.constant_parsed_decl_id_map.read().clone(),
107            ),
108            const_generic_parsed_decl_id_map: RwLock::new(
109                self.const_generic_parsed_decl_id_map.read().clone(),
110            ),
111            configurable_parsed_decl_id_map: RwLock::new(
112                self.configurable_parsed_decl_id_map.read().clone(),
113            ),
114            enum_parsed_decl_id_map: RwLock::new(self.enum_parsed_decl_id_map.read().clone()),
115            type_alias_parsed_decl_id_map: RwLock::new(
116                self.type_alias_parsed_decl_id_map.read().clone(),
117            ),
118            parents: RwLock::new(self.parents.read().clone()),
119        }
120    }
121}
122
123pub trait DeclEngineGet<I, U> {
124    fn get(&self, index: &I) -> Arc<U>;
125    fn map<R>(&self, index: &I, f: impl FnOnce(&U) -> R) -> R;
126}
127
128pub trait DeclEngineGetParsedDeclId<T>
129where
130    T: TyDeclParsedType,
131{
132    fn get_parsed_decl_id(&self, decl_id: &DeclId<T>) -> Option<ParsedDeclId<T::ParsedType>>;
133}
134
135pub trait DeclEngineGetParsedDecl<T>
136where
137    T: TyDeclParsedType,
138{
139    fn get_parsed_decl(&self, decl_id: &DeclId<T>) -> Option<Declaration>;
140}
141
142pub trait DeclEngineInsert<T>
143where
144    T: Named + Spanned + TyDeclParsedType,
145{
146    /// Inserts a typed declaration `decl` that corresponds to the parsed declaration
147    /// `parsed_decl_it` into the [DeclEngine] for the first time.
148    ///
149    /// This method is meant to be called **only during the initial type checking**,
150    /// when the typed declaration is created for the first time.
151    fn insert(&self, decl: T, parsed_decl_id: ParsedDeclId<T::ParsedType>) -> DeclRef<DeclId<T>>;
152
153    /// Inserts a typed declaration `modified_decl` that represents a modified version of
154    /// an `original_decl`. E.g., during monomorphization, we get an original typed declaration
155    /// from the [DeclEngine], modify it, and insert the `modified_decl` into the [DeclEngine].
156    ///
157    /// The `modified_decl` will have the same corresponding parsed declaration as the `original_decl`.
158    ///
159    /// Panics if the `original_decl` does not exist in the [DeclEngine]
160    /// or if it doesn't have its corresponding parsed declaration.
161    ///
162    /// The only typed declarations that legitimately have no corresponding parsed
163    /// declaration are the trait-interface dummy functions inserted via
164    /// [DeclEngine::insert_dummy_func]. For those, [DeclEngineInsert] is implemented
165    /// manually (see the implementation for [ty::TyFunctionDecl]).
166    fn insert_modified(&self, modified_decl: T, original_decl: DeclId<T>) -> 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: 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                self.$parsed_slab.write().insert(decl_id, parsed_decl_id);
228                DeclRef::new(decl_name, decl_id, span)
229            }
230
231            fn insert_modified(
232                &self,
233                modified_decl: $decl,
234                original_decl: DeclId<$decl>,
235            ) -> DeclRef<DeclId<$decl>> {
236                self.insert(
237                    modified_decl,
238                    self.get_parsed_decl_id(&original_decl)
239                        .expect("`original_decl` must have a corresponding parsed declaration"),
240                )
241            }
242        }
243    };
244}
245
246/// [ty::TyFunctionDecl] is intentionally not implemented via the `decl_engine_insert!`
247/// macro. Unlike all other typed declarations, functions have one legitimate case of not
248/// having a corresponding parsed declaration: the trait-interface dummy functions inserted
249/// via [DeclEngine::insert_dummy_func]. `insert_modified` must therefore tolerate a missing
250/// parsed declaration, but **only for such dummy functions**.
251impl DeclEngineInsert<ty::TyFunctionDecl> for DeclEngine {
252    fn insert(
253        &self,
254        decl: ty::TyFunctionDecl,
255        parsed_decl_id: ParsedDeclId<<ty::TyFunctionDecl as TyDeclParsedType>::ParsedType>,
256    ) -> DeclRef<DeclId<ty::TyFunctionDecl>> {
257        let span = decl.span();
258        let decl_name = decl.name().clone();
259        let decl_id = DeclId::new(self.function_slab.insert(decl));
260        self.function_parsed_decl_id_map
261            .write()
262            .insert(decl_id, parsed_decl_id);
263        DeclRef::new(decl_name, decl_id, span)
264    }
265
266    fn insert_modified(
267        &self,
268        modified_decl: ty::TyFunctionDecl,
269        original_decl: DeclId<ty::TyFunctionDecl>,
270    ) -> DeclRef<DeclId<ty::TyFunctionDecl>> {
271        match self.get_parsed_decl_id(&original_decl) {
272            // The `modified_decl` inherits the parsed declaration of the
273            // `original_decl` it was cloned and modified from.
274            Some(parsed_decl_id) => self.insert(modified_decl, parsed_decl_id),
275            // The only functions that legitimately lack a parsed declaration are the
276            // trait-interface dummy functions. If the `original_decl` had no parsed
277            // declaration and was not a dummy function, that is a bug.
278            None => self.insert_dummy_func(modified_decl),
279        }
280    }
281}
282
283decl_engine_insert!(trait_slab, trait_parsed_decl_id_map, ty::TyTraitDecl);
284decl_engine_insert!(trait_fn_slab, trait_fn_parsed_decl_id_map, ty::TyTraitFn);
285decl_engine_insert!(
286    trait_type_slab,
287    trait_type_parsed_decl_id_map,
288    ty::TyTraitType
289);
290decl_engine_insert!(
291    impl_self_or_trait_slab,
292    impl_self_or_trait_parsed_decl_id_map,
293    ty::TyImplSelfOrTrait
294);
295decl_engine_insert!(struct_slab, struct_parsed_decl_id_map, ty::TyStructDecl);
296decl_engine_insert!(storage_slab, storage_parsed_decl_id_map, ty::TyStorageDecl);
297decl_engine_insert!(abi_slab, abi_parsed_decl_id_map, ty::TyAbiDecl);
298decl_engine_insert!(
299    constant_slab,
300    constant_parsed_decl_id_map,
301    ty::TyConstantDecl
302);
303decl_engine_insert!(
304    configurable_slab,
305    configurable_parsed_decl_id_map,
306    ty::TyConfigurableDecl
307);
308decl_engine_insert!(
309    const_generics_slab,
310    const_generic_parsed_decl_id_map,
311    ty::TyConstGenericDecl
312);
313decl_engine_insert!(enum_slab, enum_parsed_decl_id_map, ty::TyEnumDecl);
314decl_engine_insert!(
315    type_alias_slab,
316    type_alias_parsed_decl_id_map,
317    ty::TyTypeAliasDecl
318);
319
320macro_rules! decl_engine_parsed_decl_id {
321    ($slab:ident, $decl:ty) => {
322        impl DeclEngineGetParsedDeclId<$decl> for DeclEngine {
323            fn get_parsed_decl_id(
324                &self,
325                decl_id: &DeclId<$decl>,
326            ) -> Option<ParsedDeclId<<$decl as TyDeclParsedType>::ParsedType>> {
327                let parsed_decl_id_map = self.$slab.read();
328                if let Some(parsed_decl_id) = parsed_decl_id_map.get(&decl_id) {
329                    return Some(parsed_decl_id.clone());
330                } else {
331                    None
332                }
333            }
334        }
335    };
336}
337
338decl_engine_parsed_decl_id!(function_parsed_decl_id_map, ty::TyFunctionDecl);
339decl_engine_parsed_decl_id!(trait_parsed_decl_id_map, ty::TyTraitDecl);
340decl_engine_parsed_decl_id!(trait_fn_parsed_decl_id_map, ty::TyTraitFn);
341decl_engine_parsed_decl_id!(trait_type_parsed_decl_id_map, ty::TyTraitType);
342decl_engine_parsed_decl_id!(impl_self_or_trait_parsed_decl_id_map, ty::TyImplSelfOrTrait);
343decl_engine_parsed_decl_id!(struct_parsed_decl_id_map, ty::TyStructDecl);
344decl_engine_parsed_decl_id!(storage_parsed_decl_id_map, ty::TyStorageDecl);
345decl_engine_parsed_decl_id!(abi_parsed_decl_id_map, ty::TyAbiDecl);
346decl_engine_parsed_decl_id!(constant_parsed_decl_id_map, ty::TyConstantDecl);
347decl_engine_parsed_decl_id!(const_generic_parsed_decl_id_map, ty::TyConstGenericDecl);
348decl_engine_parsed_decl_id!(configurable_parsed_decl_id_map, ty::TyConfigurableDecl);
349decl_engine_parsed_decl_id!(enum_parsed_decl_id_map, ty::TyEnumDecl);
350decl_engine_parsed_decl_id!(type_alias_parsed_decl_id_map, ty::TyTypeAliasDecl);
351
352macro_rules! decl_engine_parsed_decl {
353    ($slab:ident, $decl:ty, $ctor:expr) => {
354        impl DeclEngineGetParsedDecl<$decl> for DeclEngine {
355            fn get_parsed_decl(&self, decl_id: &DeclId<$decl>) -> Option<Declaration> {
356                let parsed_decl_id_map = self.$slab.read();
357                if let Some(parsed_decl_id) = parsed_decl_id_map.get(&decl_id) {
358                    return Some($ctor(parsed_decl_id.clone()));
359                } else {
360                    None
361                }
362            }
363        }
364    };
365}
366
367decl_engine_parsed_decl!(
368    function_parsed_decl_id_map,
369    ty::TyFunctionDecl,
370    Declaration::FunctionDeclaration
371);
372decl_engine_parsed_decl!(
373    trait_parsed_decl_id_map,
374    ty::TyTraitDecl,
375    Declaration::TraitDeclaration
376);
377decl_engine_parsed_decl!(
378    trait_fn_parsed_decl_id_map,
379    ty::TyTraitFn,
380    Declaration::TraitFnDeclaration
381);
382decl_engine_parsed_decl!(
383    trait_type_parsed_decl_id_map,
384    ty::TyTraitType,
385    Declaration::TraitTypeDeclaration
386);
387decl_engine_parsed_decl!(
388    impl_self_or_trait_parsed_decl_id_map,
389    ty::TyImplSelfOrTrait,
390    Declaration::ImplSelfOrTrait
391);
392decl_engine_parsed_decl!(
393    struct_parsed_decl_id_map,
394    ty::TyStructDecl,
395    Declaration::StructDeclaration
396);
397decl_engine_parsed_decl!(
398    storage_parsed_decl_id_map,
399    ty::TyStorageDecl,
400    Declaration::StorageDeclaration
401);
402decl_engine_parsed_decl!(
403    abi_parsed_decl_id_map,
404    ty::TyAbiDecl,
405    Declaration::AbiDeclaration
406);
407decl_engine_parsed_decl!(
408    constant_parsed_decl_id_map,
409    ty::TyConstantDecl,
410    Declaration::ConstantDeclaration
411);
412decl_engine_parsed_decl!(
413    const_generic_parsed_decl_id_map,
414    ty::TyConstGenericDecl,
415    Declaration::ConstGenericDeclaration
416);
417decl_engine_parsed_decl!(
418    configurable_parsed_decl_id_map,
419    ty::TyConfigurableDecl,
420    Declaration::ConfigurableDeclaration
421);
422decl_engine_parsed_decl!(
423    enum_parsed_decl_id_map,
424    ty::TyEnumDecl,
425    Declaration::EnumDeclaration
426);
427decl_engine_parsed_decl!(
428    type_alias_parsed_decl_id_map,
429    ty::TyTypeAliasDecl,
430    Declaration::TypeAliasDeclaration
431);
432
433macro_rules! decl_engine_replace {
434    ($slab:ident, $decl:ty) => {
435        impl DeclEngineReplace<$decl> for DeclEngine {
436            fn replace(&self, index: DeclId<$decl>, decl: $decl) {
437                self.$slab.replace(index.inner(), decl);
438            }
439        }
440    };
441}
442decl_engine_replace!(function_slab, ty::TyFunctionDecl);
443decl_engine_replace!(trait_slab, ty::TyTraitDecl);
444decl_engine_replace!(trait_fn_slab, ty::TyTraitFn);
445decl_engine_replace!(trait_type_slab, ty::TyTraitType);
446decl_engine_replace!(impl_self_or_trait_slab, ty::TyImplSelfOrTrait);
447decl_engine_replace!(struct_slab, ty::TyStructDecl);
448decl_engine_replace!(storage_slab, ty::TyStorageDecl);
449decl_engine_replace!(abi_slab, ty::TyAbiDecl);
450decl_engine_replace!(constant_slab, ty::TyConstantDecl);
451decl_engine_replace!(configurable_slab, ty::TyConfigurableDecl);
452decl_engine_replace!(enum_slab, ty::TyEnumDecl);
453decl_engine_replace!(type_alias_slab, ty::TyTypeAliasDecl);
454
455macro_rules! decl_engine_index {
456    ($slab:ident, $decl:ty) => {
457        impl DeclEngineIndex<$decl> for DeclEngine {}
458    };
459}
460decl_engine_index!(function_slab, ty::TyFunctionDecl);
461decl_engine_index!(trait_slab, ty::TyTraitDecl);
462decl_engine_index!(trait_fn_slab, ty::TyTraitFn);
463decl_engine_index!(trait_type_slab, ty::TyTraitType);
464decl_engine_index!(impl_self_or_trait_slab, ty::TyImplSelfOrTrait);
465decl_engine_index!(struct_slab, ty::TyStructDecl);
466decl_engine_index!(storage_slab, ty::TyStorageDecl);
467decl_engine_index!(abi_slab, ty::TyAbiDecl);
468decl_engine_index!(constant_slab, ty::TyConstantDecl);
469decl_engine_index!(configurable_slab, ty::TyConfigurableDecl);
470decl_engine_index!(enum_slab, ty::TyEnumDecl);
471decl_engine_index!(type_alias_slab, ty::TyTypeAliasDecl);
472
473macro_rules! decl_engine_clear_program {
474    ($($slab:ident, $decl:ty);* $(;)?) => {
475        impl DeclEngine {
476            pub fn clear_program(&mut self, program_id: &ProgramId) {
477                self.parents.write().retain(|key, _| {
478                    match key {
479                        AssociatedItemDeclId::TraitFn(decl_id) => {
480                            self.get_trait_fn(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
481                        },
482                        AssociatedItemDeclId::Function(decl_id) => {
483                            self.get_function(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
484                        },
485                        AssociatedItemDeclId::Type(decl_id) => {
486                            self.get_type(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
487                        },
488                        AssociatedItemDeclId::Constant(decl_id) => {
489                            self.get_constant(decl_id).span().source_id().map_or(true, |src_id| &src_id.program_id() != program_id)
490                        },
491                    }
492                });
493
494                $(
495                    self.$slab.retain(|_k, ty| match ty.span().source_id() {
496                        Some(source_id) => &source_id.program_id() != program_id,
497                        None => true,
498                    });
499                )*
500            }
501        }
502    };
503}
504
505decl_engine_clear_program!(
506    function_slab, ty::TyFunctionDecl;
507    trait_slab, ty::TyTraitDecl;
508    trait_fn_slab, ty::TyTraitFn;
509    trait_type_slab, ty::TyTraitType;
510    impl_self_or_trait_slab, ty::TyImplTrait;
511    struct_slab, ty::TyStructDecl;
512    storage_slab, ty::TyStorageDecl;
513    abi_slab, ty::TyAbiDecl;
514    constant_slab, ty::TyConstantDecl;
515    configurable_slab, ty::TyConfigurableDecl;
516    enum_slab, ty::TyEnumDecl;
517    type_alias_slab, ty::TyTypeAliasDecl;
518);
519
520macro_rules! decl_engine_clear_module {
521    ($($slab:ident, $decl:ty);* $(;)?) => {
522        impl DeclEngine {
523            pub fn clear_module(&mut self, source_id: &SourceId) {
524                self.parents.write().retain(|key, _| {
525                    match key {
526                        AssociatedItemDeclId::TraitFn(decl_id) => {
527                            self.get_trait_fn(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
528                        },
529                        AssociatedItemDeclId::Function(decl_id) => {
530                            self.get_function(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
531                        },
532                        AssociatedItemDeclId::Type(decl_id) => {
533                            self.get_type(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
534                        },
535                        AssociatedItemDeclId::Constant(decl_id) => {
536                            self.get_constant(decl_id).span().source_id().map_or(true, |src_id| src_id != source_id)
537                        },
538                    }
539                });
540
541                $(
542                    self.$slab.retain(|_k, ty| match ty.span().source_id() {
543                        Some(src_id) => src_id != source_id,
544                        None => true,
545                    });
546                )*
547            }
548        }
549    };
550}
551
552decl_engine_clear_module!(
553    function_slab, ty::TyFunctionDecl;
554    trait_slab, ty::TyTraitDecl;
555    trait_fn_slab, ty::TyTraitFn;
556    trait_type_slab, ty::TyTraitType;
557    impl_self_or_trait_slab, ty::TyImplTrait;
558    struct_slab, ty::TyStructDecl;
559    storage_slab, ty::TyStorageDecl;
560    abi_slab, ty::TyAbiDecl;
561    constant_slab, ty::TyConstantDecl;
562    configurable_slab, ty::TyConfigurableDecl;
563    enum_slab, ty::TyEnumDecl;
564    type_alias_slab, ty::TyTypeAliasDecl;
565);
566
567impl DeclEngine {
568    /// Given a [DeclRef] `index`, finds all the parents of `index` and all the
569    /// recursive parents of those parents, and so on. Does not perform
570    /// duplicated computation---if the parents of a [DeclRef] have already been
571    /// found, we do not find them again.
572    #[allow(clippy::map_entry)]
573    pub(crate) fn find_all_parents<'a, T>(
574        &self,
575        engines: &Engines,
576        index: &'a T,
577    ) -> Vec<AssociatedItemDeclId>
578    where
579        AssociatedItemDeclId: From<&'a T>,
580    {
581        let index: AssociatedItemDeclId = AssociatedItemDeclId::from(index);
582        let parents = self.parents.read();
583        let mut acc_parents: HashMap<AssociatedItemDeclId, AssociatedItemDeclId> = HashMap::new();
584        let mut already_checked: HashSet<AssociatedItemDeclId> = HashSet::new();
585        let mut left_to_check: VecDeque<AssociatedItemDeclId> = VecDeque::from([index]);
586        while let Some(curr) = left_to_check.pop_front() {
587            if !already_checked.insert(curr.clone()) {
588                continue;
589            }
590            if let Some(curr_parents) = parents.get(&curr) {
591                for curr_parent in curr_parents.iter() {
592                    if !acc_parents.contains_key(curr_parent) {
593                        acc_parents.insert(curr_parent.clone(), curr_parent.clone());
594                    }
595                    if !left_to_check.iter().any(|x| match (x, curr_parent) {
596                        (
597                            AssociatedItemDeclId::TraitFn(x_id),
598                            AssociatedItemDeclId::TraitFn(curr_parent_id),
599                        ) => self.get(x_id).eq(
600                            &self.get(curr_parent_id),
601                            &PartialEqWithEnginesContext::new(engines),
602                        ),
603                        (
604                            AssociatedItemDeclId::Function(x_id),
605                            AssociatedItemDeclId::Function(curr_parent_id),
606                        ) => self.get(x_id).eq(
607                            &self.get(curr_parent_id),
608                            &PartialEqWithEnginesContext::new(engines),
609                        ),
610                        _ => false,
611                    }) {
612                        left_to_check.push_back(curr_parent.clone());
613                    }
614                }
615            }
616        }
617        acc_parents.values().cloned().collect()
618    }
619
620    pub(crate) fn register_parent<I>(
621        &self,
622        index: AssociatedItemDeclId,
623        parent: AssociatedItemDeclId,
624    ) where
625        AssociatedItemDeclId: From<DeclId<I>>,
626    {
627        let mut parents = self.parents.write();
628        parents
629            .entry(index)
630            .and_modify(|e| e.push(parent.clone()))
631            .or_insert_with(|| vec![parent]);
632    }
633
634    /// Inserts a trait-interface **dummy function** into the [DeclEngine].
635    ///
636    /// This is a bit of a maverick compared to the regular [DeclEngineInsert::insert].
637    /// It deliberately inserts a [ty::TyFunctionDecl] **without an associated parsed
638    /// declaration**.
639    ///
640    /// Dummy functions are placeholders created from trait interface methods
641    /// (see [ty::TyTraitFn::to_dummy_func]). They allow the trait's
642    /// provided methods to refer to interface methods before an actual implementation
643    /// exists. Their parsed origin is a [TraitFn] (i.e., a parsed trait function), not a
644    /// [FunctionDeclaration], so there is no [FunctionDeclaration] to associate them with.
645    ///
646    /// This is the only semantically valid case of a [ty::TyFunctionDecl] having no
647    /// corresponding parsed declaration. Everything else must go through
648    /// [DeclEngineInsert::insert] or [DeclEngineInsert::insert_modified], which guarantee
649    /// (and, for `insert_modified`, assert) the presence of a parsed declaration.
650    ///
651    /// Panics if the `decl` is not a trait-interface dummy function.
652    pub fn insert_dummy_func(
653        &self,
654        decl: ty::TyFunctionDecl,
655    ) -> DeclRef<DeclId<ty::TyFunctionDecl>> {
656        assert!(
657            decl.is_trait_method_dummy,
658            "`insert_dummy_func` must only be called with trait-interface dummy functions"
659        );
660        let span = decl.span();
661        let decl_name = decl.name().clone();
662        let decl_id = DeclId::new(self.function_slab.insert(decl));
663        DeclRef::new(decl_name, decl_id, span)
664    }
665
666    /// Friendly helper method for calling the `get` method from the
667    /// implementation of [DeclEngineGet] for [DeclEngine]
668    ///
669    /// Calling [DeclEngine][get] directly is equivalent to this method, but
670    /// this method adds additional syntax that some users may find helpful.
671    pub fn get_function<I>(&self, index: &I) -> Arc<ty::TyFunctionDecl>
672    where
673        DeclEngine: DeclEngineGet<I, ty::TyFunctionDecl>,
674    {
675        self.get(index)
676    }
677
678    /// Friendly helper method for calling the `get` method from the
679    /// implementation of [DeclEngineGet] for [DeclEngine]
680    ///
681    /// Calling [DeclEngine][get] directly is equivalent to this method, but
682    /// this method adds additional syntax that some users may find helpful.
683    pub fn get_trait<I>(&self, index: &I) -> Arc<ty::TyTraitDecl>
684    where
685        DeclEngine: DeclEngineGet<I, ty::TyTraitDecl>,
686    {
687        self.get(index)
688    }
689
690    /// Returns all the [ty::TyTraitDecl]s whose name is the same as `trait_name`.
691    ///
692    /// The method does a linear search over all the declared traits and is meant
693    /// to be used only for diagnostic purposes.
694    pub fn get_traits_by_name(&self, trait_name: &Ident) -> Vec<ty::TyTraitDecl> {
695        let mut vec = vec![];
696        for trait_decl in self.trait_slab.values() {
697            if trait_decl.name == *trait_name {
698                vec.push((*trait_decl).clone())
699            }
700        }
701        vec
702    }
703
704    /// Friendly helper method for calling the `get` method from the
705    /// implementation of [DeclEngineGet] for [DeclEngine]
706    ///
707    /// Calling [DeclEngine][get] directly is equivalent to this method, but
708    /// this method adds additional syntax that some users may find helpful.
709    pub fn get_trait_fn<I>(&self, index: &I) -> Arc<ty::TyTraitFn>
710    where
711        DeclEngine: DeclEngineGet<I, ty::TyTraitFn>,
712    {
713        self.get(index)
714    }
715
716    /// Friendly helper method for calling the `get` method from the
717    /// implementation of [DeclEngineGet] for [DeclEngine]
718    ///
719    /// Calling [DeclEngine][get] directly is equivalent to this method, but
720    /// this method adds additional syntax that some users may find helpful.
721    pub fn get_impl_self_or_trait<I>(&self, index: &I) -> Arc<ty::TyImplSelfOrTrait>
722    where
723        DeclEngine: DeclEngineGet<I, ty::TyImplSelfOrTrait>,
724    {
725        self.get(index)
726    }
727
728    /// Friendly helper method for calling the `get` method from the
729    /// implementation of [DeclEngineGet] for [DeclEngine]
730    ///
731    /// Calling [DeclEngine][get] directly is equivalent to this method, but
732    /// this method adds additional syntax that some users may find helpful.
733    pub fn get_struct<I>(&self, index: &I) -> Arc<ty::TyStructDecl>
734    where
735        DeclEngine: DeclEngineGet<I, ty::TyStructDecl>,
736    {
737        self.get(index)
738    }
739
740    /// Friendly helper method for calling the `get` method from the
741    /// implementation of [DeclEngineGet] for [DeclEngine].
742    ///
743    /// Calling [DeclEngine][get] directly is equivalent to this method, but
744    /// this method adds additional syntax that some users may find helpful.
745    pub fn get_storage<I>(&self, index: &I) -> Arc<ty::TyStorageDecl>
746    where
747        DeclEngine: DeclEngineGet<I, ty::TyStorageDecl>,
748    {
749        self.get(index)
750    }
751
752    /// Friendly helper method for calling the `get` method from the
753    /// implementation of [DeclEngineGet] for [DeclEngine]
754    ///
755    /// Calling [DeclEngine][get] directly is equivalent to this method, but
756    /// this method adds additional syntax that some users may find helpful.
757    pub fn get_abi<I>(&self, index: &I) -> Arc<ty::TyAbiDecl>
758    where
759        DeclEngine: DeclEngineGet<I, ty::TyAbiDecl>,
760    {
761        self.get(index)
762    }
763
764    /// Friendly helper method for calling the `get` method from the
765    /// implementation of [DeclEngineGet] for [DeclEngine]
766    ///
767    /// Calling [DeclEngine][get] directly is equivalent to this method, but
768    /// this method adds additional syntax that some users may find helpful.
769    pub fn get_constant<I>(&self, index: &I) -> Arc<ty::TyConstantDecl>
770    where
771        DeclEngine: DeclEngineGet<I, ty::TyConstantDecl>,
772    {
773        self.get(index)
774    }
775
776    /// Friendly helper method for calling the `get` method from the
777    /// implementation of [DeclEngineGet] for [DeclEngine]
778    ///
779    /// Calling [DeclEngine][get] directly is equivalent to this method, but
780    /// this method adds additional syntax that some users may find helpful.
781    pub fn get_configurable<I>(&self, index: &I) -> Arc<ty::TyConfigurableDecl>
782    where
783        DeclEngine: DeclEngineGet<I, ty::TyConfigurableDecl>,
784    {
785        self.get(index)
786    }
787
788    /// Friendly helper method for calling the `get` method from the
789    /// implementation of [DeclEngineGet] for [DeclEngine]
790    ///
791    /// Calling [DeclEngine][get] directly is equivalent to this method, but
792    /// this method adds additional syntax that some users may find helpful.
793    pub fn get_const_generic<I>(&self, index: &I) -> Arc<ty::TyConstGenericDecl>
794    where
795        DeclEngine: DeclEngineGet<I, ty::TyConstGenericDecl>,
796    {
797        self.get(index)
798    }
799
800    /// Friendly helper method for calling the `get` method from the
801    /// implementation of [DeclEngineGet] for [DeclEngine]
802    ///
803    /// Calling [DeclEngine][get] directly is equivalent to this method, but
804    /// this method adds additional syntax that some users may find helpful.
805    pub fn get_type<I>(&self, index: &I) -> Arc<ty::TyTraitType>
806    where
807        DeclEngine: DeclEngineGet<I, ty::TyTraitType>,
808    {
809        self.get(index)
810    }
811
812    /// Friendly helper method for calling the `get` method from the
813    /// implementation of [DeclEngineGet] for [DeclEngine]
814    ///
815    /// Calling [DeclEngine][get] directly is equivalent to this method, but
816    /// this method adds additional syntax that some users may find helpful.
817    pub fn get_enum<I>(&self, index: &I) -> Arc<ty::TyEnumDecl>
818    where
819        DeclEngine: DeclEngineGet<I, ty::TyEnumDecl>,
820    {
821        self.get(index)
822    }
823
824    /// Friendly helper method for calling the `get` method from the
825    /// implementation of [DeclEngineGet] for [DeclEngine]
826    ///
827    /// Calling [DeclEngine][get] directly is equivalent to this method, but
828    /// this method adds additional syntax that some users may find helpful.
829    pub fn get_type_alias<I>(&self, index: &I) -> Arc<ty::TyTypeAliasDecl>
830    where
831        DeclEngine: DeclEngineGet<I, ty::TyTypeAliasDecl>,
832    {
833        self.get(index)
834    }
835
836    /// Pretty print method for printing the [DeclEngine]. This method is
837    /// manually implemented to avoid implementation overhead regarding using
838    /// [DisplayWithEngines].
839    pub fn pretty_print(&self, engines: &Engines) -> String {
840        let mut builder = String::new();
841        let mut list = String::with_capacity(1024 * 1024);
842        let funcs = self.function_slab.values();
843        for (i, func) in funcs.iter().enumerate() {
844            list.push_str(&format!("{i} - {:?}\n", engines.help_out(func)));
845        }
846        write!(builder, "DeclEngine {{\n{list}\n}}").unwrap();
847        builder
848    }
849
850    pub fn metrics(&self) -> DeclEngineMetrics {
851        DeclEngineMetrics {
852            slabs: vec![
853                self.function_slab.metrics("function_slab".into()),
854                self.struct_slab.metrics("struct_slab".into()),
855                self.enum_slab.metrics("enum_slab".into()),
856                self.trait_slab.metrics("trait_slab".into()),
857                self.trait_fn_slab.metrics("trait_fn_slab".into()),
858                self.trait_type_slab.metrics("trait_type_slab".into()),
859                self.impl_self_or_trait_slab
860                    .metrics("impl_self_or_trait_slab".into()),
861                self.storage_slab.metrics("storage_slab".into()),
862                self.abi_slab.metrics("abi_slab".into()),
863                self.constant_slab.metrics("constant_slab".into()),
864                self.configurable_slab.metrics("configurable_slab".into()),
865                self.const_generics_slab
866                    .metrics("const_generics_slab".into()),
867                self.type_alias_slab.metrics("type_alias_slab".into()),
868            ],
869        }
870    }
871}