Skip to main content

cairo_lang_semantic/cache/
mod.rs

1use std::ops::{Deref, DerefMut};
2use std::sync::Arc;
3
4use cairo_lang_debug::DebugWithDb;
5use cairo_lang_defs::cache::{
6    CrateDefCache, DefCacheLoadingData, DefCacheSavingContext, GenericParamCached,
7    GlobalUseIdCached, ImplAliasIdCached, ImplDefIdCached, LanguageElementCached, ModuleDataCached,
8    ModuleIdCached, ModuleItemIdCached, SyntaxStablePtrIdCached,
9};
10use cairo_lang_defs::db::DefsGroup;
11use cairo_lang_defs::diagnostic_utils::StableLocation;
12use cairo_lang_defs::ids::{
13    EnumLongId, ExternFunctionLongId, ExternTypeLongId, FreeFunctionLongId, ImplFunctionLongId,
14    LocalVarId, LocalVarLongId, MemberLongId, ModuleId, ParamId, ParamLongId, StatementConstLongId,
15    StatementItemId, StatementUseLongId, StructLongId, TraitConstantId, TraitConstantLongId,
16    TraitFunctionLongId, TraitImplId, TraitImplLongId, TraitLongId, TraitTypeId, TraitTypeLongId,
17    VarId, VariantLongId,
18};
19use cairo_lang_diagnostics::{Diagnostics, Maybe};
20use cairo_lang_filesystem::db::FilesGroup;
21use cairo_lang_filesystem::ids::CrateId;
22use cairo_lang_syntax::node::TypedStablePtr;
23use cairo_lang_syntax::node::ast::{
24    ExprPtr, FunctionWithBodyPtr, ItemConstantPtr, ItemEnumPtr, ItemExternFunctionPtr,
25    ItemExternTypePtr, ItemStructPtr, ItemTraitPtr, MemberPtr, ParamPtr, TerminalIdentifierPtr,
26    TraitItemConstantPtr, TraitItemFunctionPtr, TraitItemImplPtr, TraitItemTypePtr, UsePathLeafPtr,
27    VariantPtr,
28};
29use cairo_lang_utils::Intern;
30use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
31use cairo_lang_utils::smol_str::SmolStr;
32use num_bigint::BigInt;
33use salsa::Database;
34use serde::{Deserialize, Serialize};
35
36use crate::db::ModuleSemanticDataCacheAndLoadingData;
37use crate::items::constant::{ConstValue, ConstValueId, ImplConstantId};
38use crate::items::feature_kind::FeatureKind;
39use crate::items::functions::{
40    ConcreteFunctionWithBody, GenericFunctionId, GenericFunctionWithBodyId, ImplFunctionBodyId,
41    ImplGenericFunctionId, ImplGenericFunctionWithBodyId,
42};
43use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
44use crate::items::imp::{
45    GeneratedImplId, GeneratedImplItems, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
46    NegativeImplId, NegativeImplLongId,
47};
48use crate::items::impl_alias::ImplAliasSemantic;
49use crate::items::macro_call::MacroCallSemantic;
50use crate::items::module::{ModuleItemInfo, ModuleSemantic, ModuleSemanticData};
51use crate::items::trt::ConcreteTraitGenericFunctionLongId;
52use crate::items::visibility::Visibility;
53use crate::types::{
54    ClosureTypeLongId, ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId,
55    ImplTypeId,
56};
57use crate::{
58    ConcreteEnumId, ConcreteExternTypeId, ConcreteFunction, ConcreteFunctionWithBodyId,
59    ConcreteImplId, ConcreteImplLongId, ConcreteStructId, ConcreteTraitId, ConcreteTraitLongId,
60    ConcreteTypeId, ConcreteVariant, ExprVar, ExprVarMemberPath, FunctionId, FunctionLongId,
61    GenericArgumentId, GenericParam, MatchArmSelector, TypeId, TypeLongId, ValueSelectorArm,
62};
63
64type SemanticCache<'db> = (CrateSemanticCache, SemanticCacheLookups);
65
66/// Load the cached semantic of a crate if it has a cache file configuration.
67pub fn load_cached_crate_modules_semantic<'db>(
68    db: &'db dyn Database,
69    crate_id: CrateId<'db>,
70) -> Option<ModuleSemanticDataCacheAndLoadingData<'db>> {
71    let def_loading_data = db.cached_crate_modules(crate_id)?.1;
72
73    let blob_id = db.crate_config(crate_id)?.cache_file?;
74    let Some(content) = db.blob_content(blob_id) else {
75        return Default::default();
76    };
77
78    let def_size = usize::from_be_bytes(content[..8].try_into().unwrap());
79
80    let semantic_start = 8 + def_size;
81    let semantic_size =
82        usize::from_be_bytes(content[semantic_start..semantic_start + 8].try_into().unwrap());
83
84    let content = &content[semantic_start + 8..semantic_start + 8 + semantic_size];
85
86    let (module_data, semantic_lookups): SemanticCache<'_> = postcard::from_bytes(content)
87        .unwrap_or_else(|e| {
88            panic!(
89                "failed to deserialize modules cache for crate `{}`: {e}",
90                crate_id.long(db).name().long(db),
91            )
92        });
93
94    let mut ctx = SemanticCacheLoadingContext::new(db, semantic_lookups, def_loading_data);
95    Some(ModuleSemanticDataCacheAndLoadingData {
96        modules_semantic_data: module_data
97            .modules
98            .into_iter()
99            .map(|(module_id, module_data)| {
100                let module_id = module_id.get_embedded(&ctx.defs_loading_data);
101
102                let module_data = module_data.embed(&mut ctx);
103                (module_id, module_data)
104            })
105            .collect::<OrderedHashMap<_, _>>()
106            .into(),
107        impl_aliases_resolved_impls: module_data
108            .impl_aliases
109            .into_iter()
110            .map(|(impl_alias_id, impl_id)| {
111                let impl_alias_id = impl_alias_id.get_embedded(&ctx.defs_loading_data);
112                let impl_id = impl_id.embed(&mut ctx);
113                (impl_alias_id, impl_id)
114            })
115            .collect::<OrderedHashMap<_, _>>()
116            .into(),
117        loading_data: ctx.data.into(),
118    })
119}
120
121/// Cache the module_data of each module in the crate and returns the cache and the context.
122pub fn generate_crate_def_cache<'db>(
123    db: &'db dyn Database,
124    crate_id: cairo_lang_filesystem::ids::CrateId<'db>,
125    ctx: &mut DefCacheSavingContext<'db>,
126) -> Maybe<CrateDefCache<'db>> {
127    Ok(CrateDefCache::new(
128        all_crate_modules_for_cache(db, crate_id)
129            .into_iter()
130            .map(|module_id| {
131                Ok((
132                    ModuleIdCached::new(module_id, ctx),
133                    ModuleDataCached::new(db, module_id.module_data(db)?, ctx),
134                ))
135            })
136            .collect::<Maybe<_>>()?,
137    ))
138}
139
140/// Semantic items in the semantic cache.
141#[derive(Serialize, Deserialize)]
142pub struct CrateSemanticCache {
143    /// Semantic data of the modules in the crate.
144    modules: Vec<(ModuleIdCached, ModuleSemanticDataCached)>,
145    /// Resolved implementations of the impl aliases in the crate.
146    impl_aliases: Vec<(ImplAliasIdCached, ImplIdCached)>,
147}
148
149/// Generate semantic cache for a crate.
150pub fn generate_crate_semantic_cache<'db>(
151    crate_id: CrateId<'db>,
152    ctx: &mut SemanticCacheSavingContext<'db>,
153) -> Maybe<CrateSemanticCache> {
154    let all_modules = all_crate_modules_for_cache(ctx.db, crate_id);
155
156    let modules_data = all_modules
157        .iter()
158        .map(|module_id| {
159            Ok((
160                ModuleIdCached::new(*module_id, &mut ctx.defs_ctx),
161                ModuleSemanticDataCached::new(
162                    ctx.db.priv_module_semantic_data(*module_id)?.clone(),
163                    ctx,
164                ),
165            ))
166        })
167        .collect::<Maybe<_>>()?;
168
169    Ok(CrateSemanticCache {
170        modules: modules_data,
171        impl_aliases: all_modules
172            .iter()
173            .flat_map(|id| match ctx.db.module_impl_aliases_ids(*id) {
174                Err(err) => vec![Err(err)],
175                Ok(impl_aliases) => impl_aliases
176                    .iter()
177                    .map(|id| {
178                        Ok((
179                            ImplAliasIdCached::new(*id, &mut ctx.defs_ctx),
180                            ImplIdCached::new(ctx.db.impl_alias_resolved_impl(*id)?, ctx),
181                        ))
182                    })
183                    .collect::<Vec<_>>(),
184            })
185            .collect::<Maybe<Vec<_>>>()?,
186    })
187}
188
189/// Context for loading cache into the database.
190struct SemanticCacheLoadingContext<'db> {
191    db: &'db dyn Database,
192    data: SemanticCacheLoadingData<'db>,
193}
194
195impl<'db> Deref for SemanticCacheLoadingContext<'db> {
196    type Target = SemanticCacheLoadingData<'db>;
197
198    fn deref(&self) -> &Self::Target {
199        &self.data
200    }
201}
202impl<'db> DerefMut for SemanticCacheLoadingContext<'db> {
203    fn deref_mut(&mut self) -> &mut Self::Target {
204        &mut self.data
205    }
206}
207
208impl<'db> SemanticCacheLoadingContext<'db> {
209    pub fn new(
210        db: &'db dyn Database,
211        lookups: SemanticCacheLookups,
212        defs_loading_data: Arc<DefCacheLoadingData<'db>>,
213    ) -> Self {
214        let mut res = Self { db, data: SemanticCacheLoadingData::new(lookups, defs_loading_data) };
215        res.embed_lookups();
216        res
217    }
218    fn embed_lookups(&mut self) {
219        for id in 0..self.lookups.function_ids_lookup.len() {
220            SemanticFunctionIdCached(id).embed(self);
221        }
222        for id in 0..self.lookups.type_ids_lookup.len() {
223            TypeIdCached(id).embed(self);
224        }
225        for id in 0..self.lookups.impl_ids_lookup.len() {
226            ImplIdCached(id).embed(self);
227        }
228        for id in 0..self.lookups.negative_impl_ids_lookup.len() {
229            NegativeImplIdCached(id).embed(self);
230        }
231        for id in 0..self.lookups.const_value_ids_lookup.len() {
232            ConstValueIdCached(id).embed(self);
233        }
234    }
235}
236
237/// Data for loading cache into the database.
238#[derive(PartialEq, Eq, salsa::Update)]
239pub struct SemanticCacheLoadingData<'db> {
240    pub defs_loading_data: Arc<DefCacheLoadingData<'db>>,
241
242    function_ids: OrderedHashMap<SemanticFunctionIdCached, FunctionId<'db>>,
243    type_ids: OrderedHashMap<TypeIdCached, TypeId<'db>>,
244    impl_ids: OrderedHashMap<ImplIdCached, ImplId<'db>>,
245    negative_impl_ids: OrderedHashMap<NegativeImplIdCached, NegativeImplId<'db>>,
246    const_value_ids: OrderedHashMap<ConstValueIdCached, ConstValueId<'db>>,
247    lookups: SemanticCacheLookups,
248}
249
250impl<'db> SemanticCacheLoadingData<'db> {
251    fn new(
252        lookups: SemanticCacheLookups,
253        defs_loading_data: Arc<DefCacheLoadingData<'db>>,
254    ) -> Self {
255        Self {
256            defs_loading_data,
257            function_ids: OrderedHashMap::default(),
258            type_ids: OrderedHashMap::default(),
259            impl_ids: OrderedHashMap::default(),
260            negative_impl_ids: OrderedHashMap::default(),
261            const_value_ids: OrderedHashMap::default(),
262            lookups,
263        }
264    }
265}
266
267impl<'db> Deref for SemanticCacheLoadingData<'db> {
268    type Target = SemanticCacheLookups;
269
270    fn deref(&self) -> &Self::Target {
271        &self.lookups
272    }
273}
274impl<'db> DerefMut for SemanticCacheLoadingData<'db> {
275    fn deref_mut(&mut self) -> &mut Self::Target {
276        &mut self.lookups
277    }
278}
279
280/// Context for saving cache from the database.
281pub struct SemanticCacheSavingContext<'db> {
282    pub db: &'db dyn Database,
283    pub data: SemanticCacheSavingData<'db>,
284    pub defs_ctx: DefCacheSavingContext<'db>,
285}
286impl<'db> Deref for SemanticCacheSavingContext<'db> {
287    type Target = SemanticCacheSavingData<'db>;
288
289    fn deref(&self) -> &Self::Target {
290        &self.data
291    }
292}
293impl<'db> DerefMut for SemanticCacheSavingContext<'db> {
294    fn deref_mut(&mut self) -> &mut Self::Target {
295        &mut self.data
296    }
297}
298
299/// Data for saving cache from the database.
300#[derive(Default)]
301pub struct SemanticCacheSavingData<'db> {
302    function_ids: OrderedHashMap<FunctionId<'db>, SemanticFunctionIdCached>,
303    type_ids: OrderedHashMap<TypeId<'db>, TypeIdCached>,
304    impl_ids: OrderedHashMap<ImplId<'db>, ImplIdCached>,
305    negative_impl_ids: OrderedHashMap<NegativeImplId<'db>, NegativeImplIdCached>,
306    const_value_ids: OrderedHashMap<ConstValueId<'db>, ConstValueIdCached>,
307    pub lookups: SemanticCacheLookups,
308}
309
310impl<'db> Deref for SemanticCacheSavingData<'db> {
311    type Target = SemanticCacheLookups;
312
313    fn deref(&self) -> &Self::Target {
314        &self.lookups
315    }
316}
317impl<'db> DerefMut for SemanticCacheSavingData<'db> {
318    fn deref_mut(&mut self) -> &mut Self::Target {
319        &mut self.lookups
320    }
321}
322
323/// Saved interned items for the cache.
324#[derive(Serialize, Deserialize, Default, PartialEq, Eq, salsa::Update)]
325pub struct SemanticCacheLookups {
326    function_ids_lookup: Vec<SemanticFunctionCached>,
327    type_ids_lookup: Vec<TypeCached>,
328    impl_ids_lookup: Vec<ImplCached>,
329    negative_impl_ids_lookup: Vec<NegativeImplCached>,
330    const_value_ids_lookup: Vec<ConstValueCached>,
331}
332
333#[derive(Serialize, Deserialize)]
334enum VisibilityCached {
335    Public,
336    PublicInCrate,
337    Private,
338}
339impl VisibilityCached {
340    fn new(visibility: Visibility) -> Self {
341        match visibility {
342            Visibility::Public => VisibilityCached::Public,
343            Visibility::PublicInCrate => VisibilityCached::PublicInCrate,
344            Visibility::Private => VisibilityCached::Private,
345        }
346    }
347    fn embed(self) -> Visibility {
348        match self {
349            VisibilityCached::Public => Visibility::Public,
350            VisibilityCached::PublicInCrate => Visibility::PublicInCrate,
351            VisibilityCached::Private => Visibility::Private,
352        }
353    }
354}
355
356#[derive(Serialize, Deserialize)]
357struct ModuleSemanticDataCached {
358    items: OrderedHashMap<SmolStr, ModuleItemInfoCached>,
359    global_uses: OrderedHashMap<GlobalUseIdCached, VisibilityCached>,
360}
361
362impl ModuleSemanticDataCached {
363    fn new<'db>(
364        module_semantic_data: ModuleSemanticData<'db>,
365        ctx: &mut SemanticCacheSavingContext<'db>,
366    ) -> Self {
367        Self {
368            items: module_semantic_data
369                .items
370                .into_iter()
371                .map(|(item_id, item_info)| {
372                    (item_id.long(ctx.db).clone(), ModuleItemInfoCached::new(item_info, ctx))
373                })
374                .collect(),
375            global_uses: module_semantic_data
376                .global_uses
377                .into_iter()
378                .map(|(global_use_id, visibility)| {
379                    (
380                        GlobalUseIdCached::new(global_use_id, &mut ctx.defs_ctx),
381                        VisibilityCached::new(visibility),
382                    )
383                })
384                .collect(),
385        }
386    }
387    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ModuleSemanticData<'db> {
388        ModuleSemanticData {
389            items: self
390                .items
391                .into_iter()
392                .map(|(item_id, item_info)| (item_id.intern(ctx.db), item_info.embed(ctx)))
393                .collect(),
394            global_uses: self
395                .global_uses
396                .into_iter()
397                .map(|(global_use_id, visibility)| {
398                    (global_use_id.get_embedded(&ctx.defs_loading_data), visibility.embed())
399                })
400                .collect(),
401            diagnostics: Diagnostics::default(),
402        }
403    }
404}
405
406#[derive(Serialize, Deserialize)]
407struct ModuleItemInfoCached {
408    item_id: ModuleItemIdCached,
409    visibility: VisibilityCached,
410    feature_kind: FeatureKindCached,
411}
412
413impl ModuleItemInfoCached {
414    fn new<'db>(
415        module_item_info: ModuleItemInfo<'db>,
416        ctx: &mut SemanticCacheSavingContext<'db>,
417    ) -> Self {
418        Self {
419            item_id: ModuleItemIdCached::new(module_item_info.item_id, &mut ctx.defs_ctx),
420            visibility: VisibilityCached::new(module_item_info.visibility),
421            feature_kind: FeatureKindCached::new(module_item_info.feature_kind, ctx),
422        }
423    }
424    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ModuleItemInfo<'db> {
425        ModuleItemInfo {
426            item_id: self.item_id.get_embedded(&ctx.defs_loading_data),
427            visibility: self.visibility.embed(),
428            feature_kind: self.feature_kind.embed(ctx),
429        }
430    }
431}
432
433/// The kind of a feature for an item.
434#[derive(Serialize, Deserialize)]
435pub enum FeatureKindCached {
436    Stable,
437    Unstable { feature: SmolStr, note: Option<SmolStr> },
438    Deprecated { feature: SmolStr, note: Option<SmolStr> },
439    Internal { feature: SmolStr, note: Option<SmolStr> },
440}
441
442impl FeatureKindCached {
443    fn new<'db>(feature_kind: FeatureKind<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
444        match feature_kind {
445            FeatureKind::Stable => FeatureKindCached::Stable,
446            FeatureKind::Unstable { feature, note } => FeatureKindCached::Unstable {
447                feature: feature.long(ctx.db).clone(),
448                note: note.map(|note| note.long(ctx.db).clone()),
449            },
450            FeatureKind::Deprecated { feature, note } => FeatureKindCached::Deprecated {
451                feature: feature.long(ctx.db).clone(),
452                note: note.map(|note| note.long(ctx.db).clone()),
453            },
454            FeatureKind::Internal { feature, note } => FeatureKindCached::Internal {
455                feature: feature.long(ctx.db).clone(),
456                note: note.map(|note| note.long(ctx.db).clone()),
457            },
458        }
459    }
460    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> FeatureKind<'db> {
461        match self {
462            FeatureKindCached::Stable => FeatureKind::Stable,
463            FeatureKindCached::Unstable { feature, note } => FeatureKind::Unstable {
464                feature: feature.intern(ctx.db),
465                note: note.map(|note| note.intern(ctx.db)),
466            },
467            FeatureKindCached::Deprecated { feature, note } => FeatureKind::Deprecated {
468                feature: feature.intern(ctx.db),
469                note: note.map(|note| note.intern(ctx.db)),
470            },
471            FeatureKindCached::Internal { feature, note } => FeatureKind::Internal {
472                feature: feature.intern(ctx.db),
473                note: note.map(|note| note.intern(ctx.db)),
474            },
475        }
476    }
477}
478
479#[derive(Serialize, Deserialize)]
480pub enum ExprVarMemberPathCached {
481    Var(ExprVarCached),
482    Member {
483        parent: Box<ExprVarMemberPathCached>,
484        member_id: LanguageElementCached,
485        concrete_struct_id: ConcreteStructCached,
486        stable_ptr: SyntaxStablePtrIdCached,
487        ty: TypeIdCached,
488    },
489}
490impl ExprVarMemberPathCached {
491    pub fn new<'db>(
492        expr_var_member_path: ExprVarMemberPath<'db>,
493        ctx: &mut SemanticCacheSavingContext<'db>,
494    ) -> Self {
495        match expr_var_member_path {
496            ExprVarMemberPath::Var(var) => {
497                ExprVarMemberPathCached::Var(ExprVarCached::new(var, ctx))
498            }
499            ExprVarMemberPath::Member { parent, member_id, concrete_struct_id, stable_ptr, ty } => {
500                ExprVarMemberPathCached::Member {
501                    parent: Box::new(ExprVarMemberPathCached::new(*parent, ctx)),
502                    member_id: LanguageElementCached::new(member_id, &mut ctx.defs_ctx),
503                    concrete_struct_id: ConcreteStructCached::new(concrete_struct_id, ctx),
504                    stable_ptr: SyntaxStablePtrIdCached::new(
505                        stable_ptr.untyped(),
506                        &mut ctx.defs_ctx,
507                    ),
508                    ty: TypeIdCached::new(ty, ctx),
509                }
510            }
511        }
512    }
513    pub fn get_embedded<'db>(
514        self,
515        data: &Arc<SemanticCacheLoadingData<'db>>,
516        db: &'db dyn Database,
517    ) -> ExprVarMemberPath<'db> {
518        match self {
519            ExprVarMemberPathCached::Var(var) => ExprVarMemberPath::Var(var.get_embedded(data, db)),
520            ExprVarMemberPathCached::Member {
521                parent,
522                member_id,
523                concrete_struct_id,
524                stable_ptr,
525                ty,
526            } => {
527                let parent = Box::new(parent.get_embedded(data, db));
528                let (module_id, member_stable_ptr) =
529                    member_id.get_embedded(&data.defs_loading_data);
530                let member_id = MemberLongId(module_id, MemberPtr(member_stable_ptr)).intern(db);
531                ExprVarMemberPath::Member {
532                    parent,
533                    member_id,
534                    concrete_struct_id: concrete_struct_id.get_embedded(data, db),
535                    stable_ptr: ExprPtr(stable_ptr.get_embedded(&data.defs_loading_data)),
536                    ty: ty.get_embedded(data),
537                }
538            }
539        }
540    }
541}
542
543#[derive(Serialize, Deserialize)]
544pub struct ExprVarCached {
545    var: SemanticVarIdCached,
546    ty: TypeIdCached,
547    stable_ptr: SyntaxStablePtrIdCached,
548}
549impl ExprVarCached {
550    fn new<'db>(expr_var: ExprVar<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
551        Self {
552            var: SemanticVarIdCached::new(expr_var.var, ctx),
553            ty: TypeIdCached::new(expr_var.ty, ctx),
554            stable_ptr: SyntaxStablePtrIdCached::new(
555                expr_var.stable_ptr.untyped(),
556                &mut ctx.defs_ctx,
557            ),
558        }
559    }
560    pub fn get_embedded<'db>(
561        self,
562        data: &Arc<SemanticCacheLoadingData<'db>>,
563        db: &'db dyn Database,
564    ) -> ExprVar<'db> {
565        ExprVar {
566            var: self.var.get_embedded(data, db),
567            ty: self.ty.get_embedded(data),
568            stable_ptr: ExprPtr(self.stable_ptr.get_embedded(&data.defs_loading_data)),
569        }
570    }
571}
572
573#[derive(Serialize, Deserialize)]
574enum SemanticVarIdCached {
575    Param(SemanticParamIdCached),
576    Local(SemanticLocalVarIdCached),
577    Item(SemanticStatementItemIdCached),
578}
579impl SemanticVarIdCached {
580    fn new<'db>(var_id: VarId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
581        match var_id {
582            VarId::Param(id) => SemanticVarIdCached::Param(SemanticParamIdCached::new(id, ctx)),
583            VarId::Local(id) => SemanticVarIdCached::Local(SemanticLocalVarIdCached::new(id, ctx)),
584            VarId::Item(id) => {
585                SemanticVarIdCached::Item(SemanticStatementItemIdCached::new(id, ctx))
586            }
587        }
588    }
589    pub fn get_embedded<'db>(
590        self,
591        data: &Arc<SemanticCacheLoadingData<'db>>,
592        db: &'db dyn Database,
593    ) -> VarId<'db> {
594        match self {
595            SemanticVarIdCached::Param(id) => VarId::Param(id.get_embedded(data, db)),
596            SemanticVarIdCached::Local(id) => VarId::Local(id.get_embedded(data, db)),
597            SemanticVarIdCached::Item(id) => VarId::Item(id.get_embedded(data, db)),
598        }
599    }
600}
601
602#[derive(Serialize, Deserialize)]
603struct SemanticParamIdCached {
604    language_element: LanguageElementCached,
605}
606impl SemanticParamIdCached {
607    fn new<'db>(param_id: ParamId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
608        Self { language_element: LanguageElementCached::new(param_id, &mut ctx.defs_ctx) }
609    }
610    pub fn get_embedded<'db>(
611        self,
612        data: &Arc<SemanticCacheLoadingData<'db>>,
613        db: &'db dyn Database,
614    ) -> ParamId<'db> {
615        let (module_id, stable_ptr) = self.language_element.get_embedded(&data.defs_loading_data);
616        ParamLongId(module_id, ParamPtr(stable_ptr)).intern(db)
617    }
618}
619
620#[derive(Serialize, Deserialize)]
621struct SemanticLocalVarIdCached {
622    language_element: LanguageElementCached,
623}
624impl SemanticLocalVarIdCached {
625    fn new<'db>(local_var_id: LocalVarId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
626        Self { language_element: LanguageElementCached::new(local_var_id, &mut ctx.defs_ctx) }
627    }
628    pub fn get_embedded<'db>(
629        self,
630        data: &Arc<SemanticCacheLoadingData<'db>>,
631        db: &'db dyn Database,
632    ) -> LocalVarId<'db> {
633        let (module_id, stable_ptr) = self.language_element.get_embedded(&data.defs_loading_data);
634        LocalVarLongId(module_id, TerminalIdentifierPtr(stable_ptr)).intern(db)
635    }
636}
637
638#[derive(Serialize, Deserialize)]
639enum SemanticStatementItemIdCached {
640    Constant(LanguageElementCached),
641    Use(LanguageElementCached),
642}
643
644impl SemanticStatementItemIdCached {
645    fn new<'db>(item_id: StatementItemId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
646        match item_id {
647            StatementItemId::Constant(id) => SemanticStatementItemIdCached::Constant(
648                LanguageElementCached::new(id, &mut ctx.defs_ctx),
649            ),
650            StatementItemId::Use(id) => SemanticStatementItemIdCached::Use(
651                LanguageElementCached::new(id, &mut ctx.defs_ctx),
652            ),
653        }
654    }
655    pub fn get_embedded<'db>(
656        self,
657        data: &Arc<SemanticCacheLoadingData<'db>>,
658        db: &'db dyn Database,
659    ) -> StatementItemId<'db> {
660        match self {
661            SemanticStatementItemIdCached::Constant(id) => {
662                let (module_id, stable_ptr) = id.get_embedded(&data.defs_loading_data);
663                StatementItemId::Constant(
664                    StatementConstLongId(module_id, ItemConstantPtr(stable_ptr)).intern(db),
665                )
666            }
667            SemanticStatementItemIdCached::Use(id) => {
668                let (module_id, stable_ptr) = id.get_embedded(&data.defs_loading_data);
669                StatementItemId::Use(
670                    StatementUseLongId(module_id, UsePathLeafPtr(stable_ptr)).intern(db),
671                )
672            }
673        }
674    }
675}
676
677#[derive(Serialize, Deserialize)]
678pub enum MatchArmSelectorCached {
679    VariantId(ConcreteVariantCached),
680    Value(usize),
681}
682
683impl MatchArmSelectorCached {
684    pub fn new<'db>(
685        match_arm_selector: MatchArmSelector<'db>,
686        ctx: &mut SemanticCacheSavingContext<'db>,
687    ) -> Self {
688        match match_arm_selector {
689            MatchArmSelector::VariantId(variant_id) => {
690                MatchArmSelectorCached::VariantId(ConcreteVariantCached::new(variant_id, ctx))
691            }
692            MatchArmSelector::Value(value) => MatchArmSelectorCached::Value(value.value),
693        }
694    }
695    pub fn get_embedded<'db>(
696        self,
697        data: &Arc<SemanticCacheLoadingData<'db>>,
698        db: &'db dyn Database,
699    ) -> MatchArmSelector<'db> {
700        match self {
701            MatchArmSelectorCached::VariantId(variant_id) => {
702                MatchArmSelector::VariantId(variant_id.get_embedded(data, db))
703            }
704            MatchArmSelectorCached::Value(value) => {
705                MatchArmSelector::Value(ValueSelectorArm { value })
706            }
707        }
708    }
709}
710
711#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
712enum ConstValueCached {
713    Int(BigInt, TypeIdCached),
714    Struct(Vec<ConstValueIdCached>, TypeIdCached),
715    Enum(ConcreteVariantCached, ConstValueIdCached),
716    NonZero(ConstValueIdCached),
717    Generic(GenericParamCached),
718    ImplConstant(ImplConstantCached),
719}
720impl ConstValueCached {
721    fn new<'db>(const_value: ConstValue<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
722        match const_value {
723            ConstValue::Int(value, ty) => ConstValueCached::Int(value, TypeIdCached::new(ty, ctx)),
724            ConstValue::Struct(values, ty) => ConstValueCached::Struct(
725                values.into_iter().map(|v| ConstValueIdCached::new(v, ctx)).collect(),
726                TypeIdCached::new(ty, ctx),
727            ),
728            ConstValue::Enum(variant, value) => ConstValueCached::Enum(
729                ConcreteVariantCached::new(variant, ctx),
730                ConstValueIdCached::new(value, ctx),
731            ),
732            ConstValue::NonZero(value) => {
733                ConstValueCached::NonZero(ConstValueIdCached::new(value, ctx))
734            }
735            ConstValue::Generic(generic_param) => {
736                ConstValueCached::Generic(GenericParamCached::new(generic_param, &mut ctx.defs_ctx))
737            }
738            ConstValue::ImplConstant(impl_constant_id) => {
739                ConstValueCached::ImplConstant(ImplConstantCached::new(impl_constant_id, ctx))
740            }
741            ConstValue::Var(_, _) | ConstValue::Missing(_) => {
742                unreachable!("Const {:#?} is not supported for caching", const_value.debug(ctx.db))
743            }
744        }
745    }
746    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConstValue<'db> {
747        match self {
748            ConstValueCached::Int(value, ty) => ConstValue::Int(value, ty.embed(ctx)),
749            ConstValueCached::Struct(values, ty) => ConstValue::Struct(
750                values.into_iter().map(|v| v.embed(ctx)).collect(),
751                ty.embed(ctx),
752            ),
753            ConstValueCached::Enum(variant, value) => {
754                ConstValue::Enum(variant.embed(ctx), value.embed(ctx))
755            }
756            ConstValueCached::NonZero(value) => ConstValue::NonZero(value.embed(ctx)),
757            ConstValueCached::Generic(generic_param) => {
758                ConstValue::Generic(generic_param.get_embedded(&ctx.defs_loading_data, ctx.db))
759            }
760            ConstValueCached::ImplConstant(impl_constant_id) => {
761                ConstValue::ImplConstant(impl_constant_id.embed(ctx))
762            }
763        }
764    }
765}
766
767#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
768pub struct ConstValueIdCached(usize);
769
770impl ConstValueIdCached {
771    pub fn new<'db>(
772        const_value_id: ConstValueId<'db>,
773        ctx: &mut SemanticCacheSavingContext<'db>,
774    ) -> Self {
775        if let Some(id) = ctx.const_value_ids.get(&const_value_id) {
776            return *id;
777        }
778        let cached = ConstValueCached::new(const_value_id.long(ctx.db).clone(), ctx);
779        let id = Self(ctx.const_value_ids_lookup.len());
780        ctx.const_value_ids_lookup.push(cached);
781        ctx.const_value_ids.insert(const_value_id, id);
782        id
783    }
784    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConstValueId<'db> {
785        if let Some(const_value_id) = ctx.const_value_ids.get(&self) {
786            return *const_value_id;
787        }
788
789        let cached = ctx.const_value_ids_lookup[self.0].clone();
790        let id = cached.embed(ctx).intern(ctx.db);
791        ctx.const_value_ids.insert(self, id);
792        id
793    }
794    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> ConstValueId<'db> {
795        data.const_value_ids[&self]
796    }
797}
798
799#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
800struct ImplConstantCached {
801    impl_id: ImplIdCached,
802    trait_constant: TraitConstantCached,
803}
804impl ImplConstantCached {
805    fn new<'db>(
806        impl_constant_id: ImplConstantId<'db>,
807        ctx: &mut SemanticCacheSavingContext<'db>,
808    ) -> Self {
809        Self {
810            impl_id: ImplIdCached::new(impl_constant_id.impl_id(), ctx),
811            trait_constant: TraitConstantCached::new(impl_constant_id.trait_constant_id(), ctx),
812        }
813    }
814    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplConstantId<'db> {
815        ImplConstantId::new(self.impl_id.embed(ctx), self.trait_constant.embed(ctx), ctx.db)
816    }
817}
818
819#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
820struct TraitConstantCached {
821    language_element: LanguageElementCached,
822}
823impl TraitConstantCached {
824    fn new<'db>(
825        trait_constant_id: TraitConstantId<'db>,
826        ctx: &mut SemanticCacheSavingContext<'db>,
827    ) -> Self {
828        Self { language_element: LanguageElementCached::new(trait_constant_id, &mut ctx.defs_ctx) }
829    }
830    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TraitConstantId<'db> {
831        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
832        TraitConstantLongId(module_id, TraitItemConstantPtr(stable_ptr)).intern(ctx.db)
833    }
834}
835
836#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
837struct SemanticFunctionCached {
838    generic_function: GenericFunctionCached,
839
840    generic_args: Vec<GenericArgumentCached>,
841}
842impl SemanticFunctionCached {
843    fn new<'db>(
844        function_id: FunctionLongId<'db>,
845        ctx: &mut SemanticCacheSavingContext<'db>,
846    ) -> Self {
847        let function = function_id.function;
848        Self {
849            generic_function: GenericFunctionCached::new(function.generic_function, ctx),
850            generic_args: function
851                .generic_args
852                .into_iter()
853                .map(|arg| GenericArgumentCached::new(arg, ctx))
854                .collect(),
855        }
856    }
857    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> FunctionLongId<'db> {
858        FunctionLongId {
859            function: ConcreteFunction {
860                generic_function: self.generic_function.embed(ctx),
861                generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
862            },
863        }
864    }
865}
866#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
867pub struct SemanticFunctionIdCached(usize);
868impl SemanticFunctionIdCached {
869    pub fn new<'db>(
870        function_id: FunctionId<'db>,
871        ctx: &mut SemanticCacheSavingContext<'db>,
872    ) -> Self {
873        if let Some(id) = ctx.function_ids.get(&function_id) {
874            return *id;
875        }
876        let function = SemanticFunctionCached::new(function_id.long(ctx.db).clone(), ctx);
877        let id = SemanticFunctionIdCached(ctx.function_ids_lookup.len());
878        ctx.function_ids_lookup.push(function);
879        ctx.function_ids.insert(function_id, id);
880        id
881    }
882    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> FunctionId<'db> {
883        if let Some(function_id) = ctx.function_ids.get(&self) {
884            return *function_id;
885        }
886
887        let function = ctx.function_ids_lookup[self.0].clone();
888        let function_id = function.embed(ctx).intern(ctx.db);
889        ctx.function_ids.insert(self, function_id);
890        function_id
891    }
892    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> FunctionId<'db> {
893        data.function_ids[&self]
894    }
895}
896
897#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
898enum GenericFunctionCached {
899    Free(LanguageElementCached),
900    Extern(LanguageElementCached),
901    Impl(ImplIdCached, LanguageElementCached),
902}
903impl GenericFunctionCached {
904    fn new<'db>(
905        generic_function: GenericFunctionId<'db>,
906        ctx: &mut SemanticCacheSavingContext<'db>,
907    ) -> Self {
908        match generic_function {
909            GenericFunctionId::Free(id) => {
910                GenericFunctionCached::Free(LanguageElementCached::new(id, &mut ctx.defs_ctx))
911            }
912            GenericFunctionId::Extern(id) => {
913                GenericFunctionCached::Extern(LanguageElementCached::new(id, &mut ctx.defs_ctx))
914            }
915            GenericFunctionId::Impl(id) => GenericFunctionCached::Impl(
916                ImplIdCached::new(id.impl_id, ctx),
917                LanguageElementCached::new(id.function, &mut ctx.defs_ctx),
918            ),
919        }
920    }
921    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericFunctionId<'db> {
922        match self {
923            GenericFunctionCached::Free(id) => {
924                let (module_id, stable_ptr) = id.get_embedded(&ctx.defs_loading_data);
925                let id =
926                    FreeFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr)).intern(ctx.db);
927                GenericFunctionId::Free(id)
928            }
929            GenericFunctionCached::Extern(id) => {
930                let (module_id, stable_ptr) = id.get_embedded(&ctx.defs_loading_data);
931                let id = ExternFunctionLongId(module_id, ItemExternFunctionPtr(stable_ptr))
932                    .intern(ctx.db);
933                GenericFunctionId::Extern(id)
934            }
935            GenericFunctionCached::Impl(id, name) => {
936                let impl_id = id.embed(ctx);
937                let (module_id, stable_ptr) = name.get_embedded(&ctx.defs_loading_data);
938                let trait_function_id =
939                    TraitFunctionLongId(module_id, TraitItemFunctionPtr(stable_ptr)).intern(ctx.db);
940
941                GenericFunctionId::Impl(ImplGenericFunctionId {
942                    impl_id,
943                    function: trait_function_id,
944                })
945            }
946        }
947    }
948}
949
950#[derive(Serialize, Deserialize, Clone)]
951pub struct SemanticConcreteFunctionWithBodyCached {
952    generic_function: GenericFunctionWithBodyCached,
953    generic_args: Vec<GenericArgumentCached>,
954}
955impl SemanticConcreteFunctionWithBodyCached {
956    pub fn new<'db>(
957        function_id: ConcreteFunctionWithBodyId<'db>,
958        ctx: &mut SemanticCacheSavingContext<'db>,
959    ) -> Self {
960        Self {
961            generic_function: GenericFunctionWithBodyCached::new(
962                function_id.generic_function(ctx.db),
963                ctx,
964            ),
965            generic_args: function_id
966                .long(ctx.db)
967                .generic_args
968                .clone()
969                .into_iter()
970                .map(|arg| GenericArgumentCached::new(arg, ctx))
971                .collect(),
972        }
973    }
974    pub fn get_embedded<'db>(
975        self,
976        data: &Arc<SemanticCacheLoadingData<'db>>,
977        db: &'db dyn Database,
978    ) -> ConcreteFunctionWithBodyId<'db> {
979        let generic_function = self.generic_function.get_embedded(data, db);
980        let generic_args =
981            self.generic_args.into_iter().map(|arg| arg.get_embedded(data, db)).collect();
982        ConcreteFunctionWithBody { generic_function, generic_args }.intern(db)
983    }
984}
985
986#[derive(Serialize, Deserialize, Clone)]
987enum GenericFunctionWithBodyCached {
988    Free(LanguageElementCached),
989    Impl(ConcreteImplCached, ImplFunctionBodyCached),
990    Trait(ConcreteTraitCached, LanguageElementCached),
991}
992
993impl GenericFunctionWithBodyCached {
994    fn new<'db>(
995        generic_function: GenericFunctionWithBodyId<'db>,
996        ctx: &mut SemanticCacheSavingContext<'db>,
997    ) -> Self {
998        match generic_function {
999            GenericFunctionWithBodyId::Free(id) => GenericFunctionWithBodyCached::Free(
1000                LanguageElementCached::new(id, &mut ctx.defs_ctx),
1001            ),
1002            GenericFunctionWithBodyId::Impl(id) => GenericFunctionWithBodyCached::Impl(
1003                ConcreteImplCached::new(id.concrete_impl_id, ctx),
1004                ImplFunctionBodyCached::new(id.function_body, ctx),
1005            ),
1006            GenericFunctionWithBodyId::Trait(id) => GenericFunctionWithBodyCached::Trait(
1007                ConcreteTraitCached::new(id.concrete_trait(ctx.db), ctx),
1008                LanguageElementCached::new(id.trait_function(ctx.db), &mut ctx.defs_ctx),
1009            ),
1010        }
1011    }
1012    pub fn get_embedded<'db>(
1013        self,
1014        data: &Arc<SemanticCacheLoadingData<'db>>,
1015        db: &'db dyn Database,
1016    ) -> GenericFunctionWithBodyId<'db> {
1017        match self {
1018            GenericFunctionWithBodyCached::Free(id) => {
1019                let (module_id, stable_ptr) = id.get_embedded(&data.defs_loading_data);
1020                GenericFunctionWithBodyId::Free(
1021                    FreeFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr)).intern(db),
1022                )
1023            }
1024            GenericFunctionWithBodyCached::Impl(id, function_body) => {
1025                GenericFunctionWithBodyId::Impl(ImplGenericFunctionWithBodyId {
1026                    concrete_impl_id: id.get_embedded(data, db),
1027                    function_body: function_body.get_embedded(data, db),
1028                })
1029            }
1030            GenericFunctionWithBodyCached::Trait(id, name) => {
1031                let (module_id, stable_ptr) = name.get_embedded(&data.defs_loading_data);
1032                GenericFunctionWithBodyId::Trait(
1033                    ConcreteTraitGenericFunctionLongId::new(
1034                        db,
1035                        id.get_embedded(data, db),
1036                        TraitFunctionLongId(module_id, TraitItemFunctionPtr(stable_ptr)).intern(db),
1037                    )
1038                    .intern(db),
1039                )
1040            }
1041        }
1042    }
1043}
1044
1045#[derive(Serialize, Deserialize, Clone)]
1046enum ImplFunctionBodyCached {
1047    Impl(LanguageElementCached),
1048    Trait(LanguageElementCached),
1049}
1050impl ImplFunctionBodyCached {
1051    fn new<'db>(
1052        function_body: ImplFunctionBodyId<'db>,
1053        ctx: &mut SemanticCacheSavingContext<'db>,
1054    ) -> Self {
1055        match function_body {
1056            ImplFunctionBodyId::Impl(id) => {
1057                ImplFunctionBodyCached::Impl(LanguageElementCached::new(id, &mut ctx.defs_ctx))
1058            }
1059            ImplFunctionBodyId::Trait(id) => {
1060                ImplFunctionBodyCached::Trait(LanguageElementCached::new(id, &mut ctx.defs_ctx))
1061            }
1062        }
1063    }
1064    pub fn get_embedded<'db>(
1065        self,
1066        data: &Arc<SemanticCacheLoadingData<'db>>,
1067        db: &'db dyn Database,
1068    ) -> ImplFunctionBodyId<'db> {
1069        match self {
1070            ImplFunctionBodyCached::Impl(id) => {
1071                let (module_id, stable_ptr) = id.get_embedded(&data.defs_loading_data);
1072                ImplFunctionBodyId::Impl(
1073                    ImplFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr)).intern(db),
1074                )
1075            }
1076            ImplFunctionBodyCached::Trait(id) => {
1077                let (module_id, stable_ptr) = id.get_embedded(&data.defs_loading_data);
1078                ImplFunctionBodyId::Trait(
1079                    TraitFunctionLongId(module_id, TraitItemFunctionPtr(stable_ptr)).intern(db),
1080                )
1081            }
1082        }
1083    }
1084}
1085
1086#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1087enum GenericArgumentCached {
1088    Type(TypeIdCached),
1089    Value(ConstValueIdCached),
1090    Impl(ImplIdCached),
1091    NegImpl(NegativeImplIdCached),
1092}
1093
1094impl GenericArgumentCached {
1095    fn new<'db>(
1096        generic_argument_id: GenericArgumentId<'db>,
1097        ctx: &mut SemanticCacheSavingContext<'db>,
1098    ) -> Self {
1099        match generic_argument_id {
1100            GenericArgumentId::Type(type_id) => {
1101                GenericArgumentCached::Type(TypeIdCached::new(type_id, ctx))
1102            }
1103            GenericArgumentId::Constant(const_value_id) => {
1104                GenericArgumentCached::Value(ConstValueIdCached::new(const_value_id, ctx))
1105            }
1106            GenericArgumentId::Impl(impl_id) => {
1107                GenericArgumentCached::Impl(ImplIdCached::new(impl_id, ctx))
1108            }
1109            GenericArgumentId::NegImpl(negative_impl) => {
1110                GenericArgumentCached::NegImpl(NegativeImplIdCached::new(negative_impl, ctx))
1111            }
1112        }
1113    }
1114    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericArgumentId<'db> {
1115        match self {
1116            GenericArgumentCached::Type(ty) => GenericArgumentId::Type(ty.embed(ctx)),
1117            GenericArgumentCached::Value(value) => GenericArgumentId::Constant(value.embed(ctx)),
1118            GenericArgumentCached::Impl(imp) => GenericArgumentId::Impl(imp.embed(ctx)),
1119            GenericArgumentCached::NegImpl(negative_impl) => {
1120                GenericArgumentId::NegImpl(negative_impl.embed(ctx))
1121            }
1122        }
1123    }
1124    pub fn get_embedded<'db>(
1125        self,
1126        data: &Arc<SemanticCacheLoadingData<'db>>,
1127        _db: &'db dyn Database,
1128    ) -> GenericArgumentId<'db> {
1129        match self {
1130            GenericArgumentCached::Type(ty) => GenericArgumentId::Type(ty.get_embedded(data)),
1131            GenericArgumentCached::Value(value) => {
1132                GenericArgumentId::Constant(value.get_embedded(data))
1133            }
1134            GenericArgumentCached::Impl(imp) => GenericArgumentId::Impl(imp.get_embedded(data)),
1135            GenericArgumentCached::NegImpl(negative_impl) => {
1136                GenericArgumentId::NegImpl(negative_impl.get_embedded(data))
1137            }
1138        }
1139    }
1140}
1141
1142#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1143enum TypeCached {
1144    Concrete(ConcreteTypeCached),
1145    Tuple(Vec<TypeIdCached>),
1146    Snapshot(TypeIdCached),
1147    GenericParameter(GenericParamCached),
1148    ImplType(ImplTypeCached),
1149    FixedSizeArray(TypeIdCached, ConstValueIdCached),
1150    ClosureType(ClosureTypeCached),
1151    Coupon(SemanticFunctionIdCached),
1152}
1153
1154impl TypeCached {
1155    fn new<'db>(type_id: TypeLongId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1156        match type_id {
1157            TypeLongId::Concrete(concrete_type_id) => {
1158                TypeCached::Concrete(ConcreteTypeCached::new(concrete_type_id, ctx))
1159            }
1160            TypeLongId::Tuple(vec) => {
1161                TypeCached::Tuple(vec.into_iter().map(|ty| TypeIdCached::new(ty, ctx)).collect())
1162            }
1163            TypeLongId::Snapshot(type_id) => TypeCached::Snapshot(TypeIdCached::new(type_id, ctx)),
1164            TypeLongId::GenericParameter(generic_param_id) => TypeCached::GenericParameter(
1165                GenericParamCached::new(generic_param_id, &mut ctx.defs_ctx),
1166            ),
1167            TypeLongId::ImplType(impl_type_id) => {
1168                TypeCached::ImplType(ImplTypeCached::new(impl_type_id, ctx))
1169            }
1170            TypeLongId::FixedSizeArray { type_id, size } => TypeCached::FixedSizeArray(
1171                TypeIdCached::new(type_id, ctx),
1172                ConstValueIdCached::new(size, ctx),
1173            ),
1174            TypeLongId::Closure(closure_ty) => {
1175                TypeCached::ClosureType(ClosureTypeCached::new(closure_ty, ctx))
1176            }
1177            TypeLongId::Coupon(func_id) => {
1178                TypeCached::Coupon(SemanticFunctionIdCached::new(func_id, ctx))
1179            }
1180            TypeLongId::Var(_) | TypeLongId::NumericLiteral(_) | TypeLongId::Missing(_) => {
1181                unreachable!("type {:?} is not supported for caching", type_id.debug(ctx.db))
1182            }
1183        }
1184    }
1185    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TypeLongId<'db> {
1186        match self {
1187            TypeCached::Concrete(concrete_type) => TypeLongId::Concrete(concrete_type.embed(ctx)),
1188            TypeCached::Tuple(vec) => {
1189                TypeLongId::Tuple(vec.into_iter().map(|ty| ty.embed(ctx)).collect())
1190            }
1191            TypeCached::Snapshot(type_id) => TypeLongId::Snapshot(type_id.embed(ctx)),
1192            TypeCached::GenericParameter(generic_param) => TypeLongId::GenericParameter(
1193                generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1194            ),
1195            TypeCached::ImplType(impl_type) => TypeLongId::ImplType(impl_type.embed(ctx)),
1196            TypeCached::FixedSizeArray(type_id, size) => {
1197                TypeLongId::FixedSizeArray { type_id: type_id.embed(ctx), size: size.embed(ctx) }
1198            }
1199            TypeCached::ClosureType(closure_ty) => TypeLongId::Closure(closure_ty.embed(ctx)),
1200            TypeCached::Coupon(coupon) => TypeLongId::Coupon(coupon.embed(ctx)),
1201        }
1202    }
1203}
1204
1205#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1206pub struct TypeIdCached(usize);
1207
1208impl TypeIdCached {
1209    pub fn new<'db>(ty: TypeId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1210        if let Some(id) = ctx.type_ids.get(&ty) {
1211            return *id;
1212        }
1213        let ty_long = TypeCached::new(ty.long(ctx.db).clone(), ctx);
1214        let id = TypeIdCached(ctx.type_ids_lookup.len());
1215        ctx.type_ids_lookup.push(ty_long);
1216        ctx.type_ids.insert(ty, id);
1217        id
1218    }
1219    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TypeId<'db> {
1220        if let Some(type_id) = ctx.type_ids.get(&self) {
1221            return *type_id;
1222        }
1223
1224        let ty = ctx.type_ids_lookup[self.0].clone();
1225        let ty = ty.embed(ctx).intern(ctx.db);
1226        ctx.type_ids.insert(self, ty);
1227        ty
1228    }
1229    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> TypeId<'db> {
1230        data.type_ids[&self]
1231    }
1232}
1233
1234#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1235enum ConcreteTypeCached {
1236    Struct(ConcreteStructCached),
1237    Enum(ConcreteEnumCached),
1238    Extern(ConcreteExternTypeCached),
1239}
1240
1241impl ConcreteTypeCached {
1242    fn new<'db>(
1243        concrete_type_id: ConcreteTypeId<'db>,
1244        ctx: &mut SemanticCacheSavingContext<'db>,
1245    ) -> Self {
1246        match concrete_type_id {
1247            ConcreteTypeId::Struct(id) => {
1248                ConcreteTypeCached::Struct(ConcreteStructCached::new(id, ctx))
1249            }
1250            ConcreteTypeId::Enum(id) => ConcreteTypeCached::Enum(ConcreteEnumCached::new(id, ctx)),
1251            ConcreteTypeId::Extern(id) => {
1252                ConcreteTypeCached::Extern(ConcreteExternTypeCached::new(id, ctx))
1253            }
1254        }
1255    }
1256    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteTypeId<'db> {
1257        match self {
1258            ConcreteTypeCached::Struct(s) => ConcreteTypeId::Struct(s.embed(ctx)),
1259            ConcreteTypeCached::Enum(e) => ConcreteTypeId::Enum(e.embed(ctx)),
1260            ConcreteTypeCached::Extern(e) => ConcreteTypeId::Extern(e.embed(ctx)),
1261        }
1262    }
1263}
1264
1265#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1266struct ImplTypeCached {
1267    impl_id: ImplIdCached,
1268    trait_type: TraitTypeCached,
1269}
1270impl ImplTypeCached {
1271    fn new<'db>(impl_type_id: ImplTypeId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1272        Self {
1273            impl_id: ImplIdCached::new(impl_type_id.impl_id(), ctx),
1274            trait_type: TraitTypeCached::new(impl_type_id.ty(), ctx),
1275        }
1276    }
1277    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplTypeId<'db> {
1278        let impl_id = self.impl_id.embed(ctx);
1279        let ty = self.trait_type.embed(ctx);
1280        ImplTypeId::new(impl_id, ty, ctx.db)
1281    }
1282}
1283#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1284struct ClosureTypeCached {
1285    param_tys: Vec<TypeIdCached>,
1286    ret_ty: TypeIdCached,
1287    captured_types: Vec<TypeIdCached>,
1288    parent_function: SemanticFunctionIdCached,
1289    params_location: SyntaxStablePtrIdCached,
1290}
1291
1292impl ClosureTypeCached {
1293    fn new<'db>(
1294        closure_type_id: ClosureTypeLongId<'db>,
1295        ctx: &mut SemanticCacheSavingContext<'db>,
1296    ) -> Self {
1297        Self {
1298            param_tys: closure_type_id
1299                .param_tys
1300                .iter()
1301                .map(|ty| TypeIdCached::new(*ty, ctx))
1302                .collect(),
1303            ret_ty: TypeIdCached::new(closure_type_id.ret_ty, ctx),
1304            captured_types: closure_type_id
1305                .captured_types
1306                .iter()
1307                .map(|ty| TypeIdCached::new(*ty, ctx))
1308                .collect(),
1309            parent_function: SemanticFunctionIdCached::new(
1310                closure_type_id.parent_function.unwrap(),
1311                ctx,
1312            ),
1313            params_location: SyntaxStablePtrIdCached::new(
1314                closure_type_id.params_location.stable_ptr(),
1315                &mut ctx.defs_ctx,
1316            ),
1317        }
1318    }
1319    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ClosureTypeLongId<'db> {
1320        ClosureTypeLongId {
1321            param_tys: self.param_tys.into_iter().map(|ty| ty.embed(ctx)).collect(),
1322            ret_ty: self.ret_ty.embed(ctx),
1323            captured_types: self.captured_types.into_iter().map(|ty| ty.embed(ctx)).collect(),
1324            parent_function: Ok(self.parent_function.embed(ctx)),
1325            params_location: StableLocation::new(
1326                self.params_location.get_embedded(&ctx.defs_loading_data),
1327            ),
1328        }
1329    }
1330}
1331
1332#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
1333struct TraitTypeCached {
1334    language_element: LanguageElementCached,
1335}
1336impl TraitTypeCached {
1337    fn new<'db>(
1338        trait_type_id: TraitTypeId<'db>,
1339        ctx: &mut SemanticCacheSavingContext<'db>,
1340    ) -> Self {
1341        Self { language_element: LanguageElementCached::new(trait_type_id, &mut ctx.defs_ctx) }
1342    }
1343    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TraitTypeId<'db> {
1344        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1345        TraitTypeLongId(module_id, TraitItemTypePtr(stable_ptr)).intern(ctx.db)
1346    }
1347}
1348
1349#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1350enum ImplCached {
1351    Concrete(ConcreteImplCached),
1352    GenericParameter(GenericParamCached),
1353    ImplImpl(ImplImplCached),
1354    GeneratedImpl(GeneratedImplCached),
1355    SelfImpl(ConcreteTraitCached),
1356}
1357impl ImplCached {
1358    fn new<'db>(impl_id: ImplLongId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1359        match impl_id {
1360            ImplLongId::Concrete(concrete_impl) => {
1361                ImplCached::Concrete(ConcreteImplCached::new(concrete_impl, ctx))
1362            }
1363            ImplLongId::GenericParameter(generic_param_id) => ImplCached::GenericParameter(
1364                GenericParamCached::new(generic_param_id, &mut ctx.defs_ctx),
1365            ),
1366            ImplLongId::GeneratedImpl(generated_impl) => {
1367                ImplCached::GeneratedImpl(GeneratedImplCached::new(generated_impl, ctx))
1368            }
1369            ImplLongId::ImplImpl(impl_impl) => {
1370                ImplCached::ImplImpl(ImplImplCached::new(impl_impl, ctx))
1371            }
1372            ImplLongId::SelfImpl(concrete_trait) => {
1373                ImplCached::SelfImpl(ConcreteTraitCached::new(concrete_trait, ctx))
1374            }
1375            ImplLongId::ImplVar(_) => {
1376                unreachable!("impl {:?} is not supported for caching", impl_id.debug(ctx.db))
1377            }
1378        }
1379    }
1380    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplLongId<'db> {
1381        match self {
1382            ImplCached::Concrete(concrete_impl) => ImplLongId::Concrete(concrete_impl.embed(ctx)),
1383            ImplCached::ImplImpl(impl_impl) => ImplLongId::ImplImpl(impl_impl.embed(ctx)),
1384            ImplCached::GenericParameter(generic_param) => ImplLongId::GenericParameter(
1385                generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1386            ),
1387            ImplCached::GeneratedImpl(generated_impl) => {
1388                ImplLongId::GeneratedImpl(generated_impl.embed(ctx))
1389            }
1390            ImplCached::SelfImpl(concrete_trait) => ImplLongId::SelfImpl(concrete_trait.embed(ctx)),
1391        }
1392    }
1393}
1394#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1395pub struct ImplIdCached(usize);
1396
1397impl ImplIdCached {
1398    pub fn new<'db>(impl_id: ImplId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1399        if let Some(id) = ctx.impl_ids.get(&impl_id) {
1400            return *id;
1401        }
1402        let imp = ImplCached::new(impl_id.long(ctx.db).clone(), ctx);
1403        let id = ImplIdCached(ctx.impl_ids_lookup.len());
1404        ctx.impl_ids_lookup.push(imp);
1405        ctx.impl_ids.insert(impl_id, id);
1406        id
1407    }
1408    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplId<'db> {
1409        if let Some(impl_id) = ctx.impl_ids.get(&self) {
1410            return *impl_id;
1411        }
1412
1413        let imp = ctx.impl_ids_lookup[self.0].clone();
1414        let imp = imp.embed(ctx).intern(ctx.db);
1415        ctx.impl_ids.insert(self, imp);
1416        imp
1417    }
1418    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> ImplId<'db> {
1419        data.impl_ids[&self]
1420    }
1421}
1422
1423#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1424struct ConcreteImplCached {
1425    impl_def_id: ImplDefIdCached,
1426    generic_args: Vec<GenericArgumentCached>,
1427}
1428impl ConcreteImplCached {
1429    fn new<'db>(
1430        concrete_impl: ConcreteImplId<'db>,
1431        ctx: &mut SemanticCacheSavingContext<'db>,
1432    ) -> Self {
1433        let long_id = concrete_impl.long(ctx.db);
1434        Self {
1435            impl_def_id: ImplDefIdCached::new(long_id.impl_def_id, &mut ctx.defs_ctx),
1436            generic_args: long_id
1437                .generic_args
1438                .clone()
1439                .into_iter()
1440                .map(|arg| GenericArgumentCached::new(arg, ctx))
1441                .collect(),
1442        }
1443    }
1444    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteImplId<'db> {
1445        let impl_def_id = self.impl_def_id.get_embedded(&ctx.defs_loading_data);
1446        let long_id = ConcreteImplLongId {
1447            impl_def_id,
1448            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1449        };
1450        long_id.intern(ctx.db)
1451    }
1452    pub fn get_embedded<'db>(
1453        self,
1454        data: &Arc<SemanticCacheLoadingData<'db>>,
1455        db: &'db dyn Database,
1456    ) -> ConcreteImplId<'db> {
1457        let impl_def_id = self.impl_def_id.get_embedded(&data.defs_loading_data);
1458        let long_id = ConcreteImplLongId {
1459            impl_def_id,
1460            generic_args: self
1461                .generic_args
1462                .into_iter()
1463                .map(|arg| arg.get_embedded(data, db))
1464                .collect(),
1465        };
1466        long_id.intern(db)
1467    }
1468}
1469
1470#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1471struct ImplImplCached {
1472    impl_id: ImplIdCached,
1473    trait_impl_id: TraitImplCached,
1474}
1475impl ImplImplCached {
1476    fn new<'db>(impl_impl_id: ImplImplId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1477        Self {
1478            impl_id: ImplIdCached::new(impl_impl_id.impl_id(), ctx),
1479            trait_impl_id: TraitImplCached::new(impl_impl_id.trait_impl_id(), ctx),
1480        }
1481    }
1482    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplImplId<'db> {
1483        let impl_id = self.impl_id.embed(ctx);
1484        let trait_impl_id = self.trait_impl_id.embed(ctx);
1485        ImplImplId::new(impl_id, trait_impl_id, ctx.db)
1486    }
1487}
1488
1489#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1490struct TraitImplCached {
1491    language_element: LanguageElementCached,
1492}
1493impl TraitImplCached {
1494    fn new<'db>(
1495        trait_impl_id: TraitImplId<'db>,
1496        ctx: &mut SemanticCacheSavingContext<'db>,
1497    ) -> Self {
1498        Self { language_element: LanguageElementCached::new(trait_impl_id, &mut ctx.defs_ctx) }
1499    }
1500    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TraitImplId<'db> {
1501        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1502        TraitImplLongId(module_id, TraitItemImplPtr(stable_ptr)).intern(ctx.db)
1503    }
1504}
1505
1506#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1507struct GeneratedImplCached {
1508    pub concrete_trait: ConcreteTraitCached,
1509    pub generic_params: Vec<SemanticGenericParamCached>,
1510    pub impl_items: OrderedHashMap<TraitTypeCached, TypeIdCached>,
1511}
1512impl GeneratedImplCached {
1513    fn new<'db>(
1514        generated_impl: GeneratedImplId<'db>,
1515        ctx: &mut SemanticCacheSavingContext<'db>,
1516    ) -> Self {
1517        let generated_impl = generated_impl.long(ctx.db);
1518        Self {
1519            concrete_trait: ConcreteTraitCached::new(generated_impl.concrete_trait, ctx),
1520            generic_params: generated_impl
1521                .generic_params
1522                .clone()
1523                .into_iter()
1524                .map(|param| SemanticGenericParamCached::new(param, ctx))
1525                .collect(),
1526            impl_items: generated_impl
1527                .impl_items
1528                .0
1529                .clone()
1530                .into_iter()
1531                .map(|(k, v)| (TraitTypeCached::new(k, ctx), TypeIdCached::new(v, ctx)))
1532                .collect(),
1533        }
1534    }
1535    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GeneratedImplId<'db> {
1536        GeneratedImplLongId {
1537            concrete_trait: self.concrete_trait.embed(ctx),
1538            generic_params: self.generic_params.into_iter().map(|param| param.embed(ctx)).collect(),
1539            impl_items: GeneratedImplItems(
1540                self.impl_items.into_iter().map(|(k, v)| (k.embed(ctx), v.embed(ctx))).collect(),
1541            ),
1542        }
1543        .intern(ctx.db)
1544    }
1545}
1546
1547#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1548enum NegativeImplCached {
1549    Solved(ConcreteTraitCached),
1550    GenericParameter(GenericParamCached),
1551}
1552impl NegativeImplCached {
1553    fn new<'db>(
1554        negative_impl_id: NegativeImplLongId<'db>,
1555        ctx: &mut SemanticCacheSavingContext<'db>,
1556    ) -> Self {
1557        match negative_impl_id {
1558            NegativeImplLongId::Solved(concrete_trait_id) => {
1559                NegativeImplCached::Solved(ConcreteTraitCached::new(concrete_trait_id, ctx))
1560            }
1561            NegativeImplLongId::GenericParameter(generic_param_id) => {
1562                NegativeImplCached::GenericParameter(GenericParamCached::new(
1563                    generic_param_id,
1564                    &mut ctx.defs_ctx,
1565                ))
1566            }
1567            NegativeImplLongId::NegativeImplVar(_) => {
1568                unreachable!("negative impl var is not supported for caching",)
1569            }
1570        }
1571    }
1572    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> NegativeImplLongId<'db> {
1573        match self {
1574            NegativeImplCached::Solved(concrete_trait) => {
1575                NegativeImplLongId::Solved(concrete_trait.embed(ctx))
1576            }
1577            NegativeImplCached::GenericParameter(generic_param) => {
1578                NegativeImplLongId::GenericParameter(
1579                    generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1580                )
1581            }
1582        }
1583    }
1584}
1585
1586#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1587struct NegativeImplIdCached(usize);
1588
1589impl NegativeImplIdCached {
1590    fn new<'db>(
1591        negative_impl_id: NegativeImplId<'db>,
1592        ctx: &mut SemanticCacheSavingContext<'db>,
1593    ) -> Self {
1594        if let Some(id) = ctx.negative_impl_ids.get(&negative_impl_id) {
1595            return *id;
1596        }
1597        let imp = NegativeImplCached::new(negative_impl_id.long(ctx.db).clone(), ctx);
1598        let id = NegativeImplIdCached(ctx.negative_impl_ids_lookup.len());
1599        ctx.negative_impl_ids_lookup.push(imp);
1600        ctx.negative_impl_ids.insert(negative_impl_id, id);
1601        id
1602    }
1603    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> NegativeImplId<'db> {
1604        if let Some(negative_impl_id) = ctx.negative_impl_ids.get(&self) {
1605            return *negative_impl_id;
1606        }
1607
1608        let imp = ctx.negative_impl_ids_lookup[self.0].clone();
1609        let imp = imp.embed(ctx).intern(ctx.db);
1610        ctx.negative_impl_ids.insert(self, imp);
1611        imp
1612    }
1613    pub fn get_embedded<'db>(
1614        self,
1615        data: &Arc<SemanticCacheLoadingData<'db>>,
1616    ) -> NegativeImplId<'db> {
1617        data.negative_impl_ids[&self]
1618    }
1619}
1620
1621#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1622enum SemanticGenericParamCached {
1623    Type(GenericParamTypeCached),
1624    Const(GenericParamConstCached),
1625    Impl(GenericParamImplCached),
1626    NegImpl(GenericParamImplCached),
1627}
1628impl SemanticGenericParamCached {
1629    fn new<'db>(
1630        generic_param_id: GenericParam<'db>,
1631        ctx: &mut SemanticCacheSavingContext<'db>,
1632    ) -> Self {
1633        match generic_param_id {
1634            GenericParam::Type(generic_param) => {
1635                SemanticGenericParamCached::Type(GenericParamTypeCached::new(generic_param, ctx))
1636            }
1637            GenericParam::Const(generic_param) => {
1638                SemanticGenericParamCached::Const(GenericParamConstCached::new(generic_param, ctx))
1639            }
1640            GenericParam::Impl(generic_param) => {
1641                SemanticGenericParamCached::Impl(GenericParamImplCached::new(generic_param, ctx))
1642            }
1643            GenericParam::NegImpl(generic_param) => {
1644                SemanticGenericParamCached::NegImpl(GenericParamImplCached::new(generic_param, ctx))
1645            }
1646        }
1647    }
1648    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParam<'db> {
1649        match self {
1650            SemanticGenericParamCached::Type(generic_param) => {
1651                GenericParam::Type(generic_param.embed(ctx))
1652            }
1653            SemanticGenericParamCached::Const(generic_param) => {
1654                GenericParam::Const(generic_param.embed(ctx))
1655            }
1656            SemanticGenericParamCached::Impl(generic_param) => {
1657                GenericParam::Impl(generic_param.embed(ctx))
1658            }
1659            SemanticGenericParamCached::NegImpl(generic_param) => {
1660                GenericParam::NegImpl(generic_param.embed(ctx))
1661            }
1662        }
1663    }
1664}
1665
1666#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1667struct GenericParamTypeCached {
1668    id: GenericParamCached,
1669}
1670
1671impl GenericParamTypeCached {
1672    fn new<'db>(
1673        generic_param: GenericParamType<'db>,
1674        ctx: &mut SemanticCacheSavingContext<'db>,
1675    ) -> Self {
1676        Self { id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx) }
1677    }
1678    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamType<'db> {
1679        GenericParamType { id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db) }
1680    }
1681}
1682
1683#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1684struct GenericParamConstCached {
1685    id: GenericParamCached,
1686    ty: TypeIdCached,
1687}
1688
1689impl GenericParamConstCached {
1690    fn new<'db>(
1691        generic_param: GenericParamConst<'db>,
1692        ctx: &mut SemanticCacheSavingContext<'db>,
1693    ) -> Self {
1694        Self {
1695            id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx),
1696            ty: TypeIdCached::new(generic_param.ty, ctx),
1697        }
1698    }
1699    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamConst<'db> {
1700        GenericParamConst {
1701            id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db),
1702            ty: self.ty.embed(ctx),
1703        }
1704    }
1705}
1706
1707#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1708struct GenericParamImplCached {
1709    id: GenericParamCached,
1710    concrete_trait: ConcreteTraitCached,
1711    type_constraints: OrderedHashMap<TraitTypeCached, TypeIdCached>,
1712}
1713
1714impl GenericParamImplCached {
1715    fn new<'db>(
1716        generic_param: GenericParamImpl<'db>,
1717        ctx: &mut SemanticCacheSavingContext<'db>,
1718    ) -> Self {
1719        Self {
1720            id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx),
1721            concrete_trait: ConcreteTraitCached::new(generic_param.concrete_trait.unwrap(), ctx),
1722
1723            type_constraints: generic_param
1724                .type_constraints
1725                .into_iter()
1726                .map(|(k, v)| (TraitTypeCached::new(k, ctx), TypeIdCached::new(v, ctx)))
1727                .collect(),
1728        }
1729    }
1730    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamImpl<'db> {
1731        GenericParamImpl {
1732            id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db),
1733            concrete_trait: Ok(self.concrete_trait.embed(ctx)),
1734            type_constraints: self
1735                .type_constraints
1736                .into_iter()
1737                .map(|(k, v)| (k.embed(ctx), v.embed(ctx)))
1738                .collect(),
1739        }
1740    }
1741}
1742
1743#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1744pub struct ConcreteVariantCached {
1745    concrete_enum_id: ConcreteEnumCached,
1746    id: LanguageElementCached,
1747    ty: TypeIdCached,
1748    idx: usize,
1749}
1750impl ConcreteVariantCached {
1751    pub fn new<'db>(
1752        concrete_variant: ConcreteVariant<'db>,
1753        ctx: &mut SemanticCacheSavingContext<'db>,
1754    ) -> Self {
1755        Self {
1756            concrete_enum_id: ConcreteEnumCached::new(concrete_variant.concrete_enum_id, ctx),
1757            id: LanguageElementCached::new(concrete_variant.id, &mut ctx.defs_ctx),
1758            ty: TypeIdCached::new(concrete_variant.ty, ctx),
1759            idx: concrete_variant.idx,
1760        }
1761    }
1762    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteVariant<'db> {
1763        let concrete_enum_id = self.concrete_enum_id.embed(ctx);
1764        let ty = self.ty.embed(ctx);
1765        let (module_id, stable_ptr) = self.id.get_embedded(&ctx.defs_loading_data);
1766
1767        let id = VariantLongId(module_id, VariantPtr(stable_ptr)).intern(ctx.db);
1768        ConcreteVariant { concrete_enum_id, id, ty, idx: self.idx }
1769    }
1770    pub fn get_embedded<'db>(
1771        self,
1772        data: &Arc<SemanticCacheLoadingData<'db>>,
1773        db: &'db dyn Database,
1774    ) -> ConcreteVariant<'db> {
1775        let concrete_enum_id = self.concrete_enum_id.get_embedded(data, db);
1776        let ty = self.ty.get_embedded(data);
1777        let (module_id, stable_ptr) = self.id.get_embedded(&data.defs_loading_data);
1778        let id = VariantLongId(module_id, VariantPtr(stable_ptr)).intern(db);
1779        ConcreteVariant { concrete_enum_id, id, ty, idx: self.idx }
1780    }
1781}
1782
1783#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1784pub struct ConcreteEnumCached {
1785    enum_id: LanguageElementCached,
1786    generic_args: Vec<GenericArgumentCached>,
1787}
1788
1789impl ConcreteEnumCached {
1790    pub fn new<'db>(
1791        concrete_enum: ConcreteEnumId<'db>,
1792        ctx: &mut SemanticCacheSavingContext<'db>,
1793    ) -> Self {
1794        let long_id = concrete_enum.long(ctx.db);
1795        Self {
1796            enum_id: LanguageElementCached::new(long_id.enum_id, &mut ctx.defs_ctx),
1797            generic_args: long_id
1798                .generic_args
1799                .clone()
1800                .into_iter()
1801                .map(|arg| GenericArgumentCached::new(arg, ctx))
1802                .collect(),
1803        }
1804    }
1805    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteEnumId<'db> {
1806        let (module_id, stable_ptr) = self.enum_id.get_embedded(&ctx.defs_loading_data);
1807
1808        let long_id = ConcreteEnumLongId {
1809            enum_id: EnumLongId(module_id, ItemEnumPtr(stable_ptr)).intern(ctx.db),
1810            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1811        };
1812        long_id.intern(ctx.db)
1813    }
1814    pub fn get_embedded<'db>(
1815        self,
1816        data: &Arc<SemanticCacheLoadingData<'db>>,
1817        db: &'db dyn Database,
1818    ) -> ConcreteEnumId<'db> {
1819        let (module_id, stable_ptr) = self.enum_id.get_embedded(&data.defs_loading_data);
1820        let id = EnumLongId(module_id, ItemEnumPtr(stable_ptr)).intern(db);
1821        ConcreteEnumLongId {
1822            enum_id: id,
1823            generic_args: self
1824                .generic_args
1825                .into_iter()
1826                .map(|arg| arg.get_embedded(data, db))
1827                .collect(),
1828        }
1829        .intern(db)
1830    }
1831}
1832
1833#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1834pub struct ConcreteStructCached {
1835    struct_id: LanguageElementCached,
1836    generic_args: Vec<GenericArgumentCached>,
1837}
1838impl ConcreteStructCached {
1839    fn new<'db>(
1840        concrete_struct: ConcreteStructId<'db>,
1841        ctx: &mut SemanticCacheSavingContext<'db>,
1842    ) -> Self {
1843        let long_id = concrete_struct.long(ctx.db);
1844        Self {
1845            struct_id: LanguageElementCached::new(long_id.struct_id, &mut ctx.defs_ctx),
1846            generic_args: long_id
1847                .generic_args
1848                .clone()
1849                .into_iter()
1850                .map(|arg| GenericArgumentCached::new(arg, ctx))
1851                .collect(),
1852        }
1853    }
1854    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteStructId<'db> {
1855        let (module_id, stable_ptr) = self.struct_id.get_embedded(&ctx.defs_loading_data);
1856
1857        let long_id = ConcreteStructLongId {
1858            struct_id: StructLongId(module_id, ItemStructPtr(stable_ptr)).intern(ctx.db),
1859            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1860        };
1861        long_id.intern(ctx.db)
1862    }
1863    pub fn get_embedded<'db>(
1864        self,
1865        data: &Arc<SemanticCacheLoadingData<'db>>,
1866        db: &'db dyn Database,
1867    ) -> ConcreteStructId<'db> {
1868        let (module_id, stable_ptr) = self.struct_id.get_embedded(&data.defs_loading_data);
1869        let long_id = ConcreteStructLongId {
1870            struct_id: StructLongId(module_id, ItemStructPtr(stable_ptr)).intern(db),
1871            generic_args: self
1872                .generic_args
1873                .into_iter()
1874                .map(|arg| arg.get_embedded(data, db))
1875                .collect(),
1876        };
1877        long_id.intern(db)
1878    }
1879}
1880
1881#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1882struct ConcreteExternTypeCached {
1883    language_element: LanguageElementCached,
1884    generic_args: Vec<GenericArgumentCached>,
1885}
1886impl ConcreteExternTypeCached {
1887    fn new<'db>(
1888        concrete_extern_type: ConcreteExternTypeId<'db>,
1889        ctx: &mut SemanticCacheSavingContext<'db>,
1890    ) -> Self {
1891        let long_id = concrete_extern_type.long(ctx.db);
1892        Self {
1893            language_element: LanguageElementCached::new(long_id.extern_type_id, &mut ctx.defs_ctx),
1894            generic_args: long_id
1895                .generic_args
1896                .clone()
1897                .into_iter()
1898                .map(|arg| GenericArgumentCached::new(arg, ctx))
1899                .collect(),
1900        }
1901    }
1902    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteExternTypeId<'db> {
1903        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1904
1905        let long_id = ConcreteExternTypeLongId {
1906            extern_type_id: ExternTypeLongId(module_id, ItemExternTypePtr(stable_ptr))
1907                .intern(ctx.db),
1908            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1909        };
1910        long_id.intern(ctx.db)
1911    }
1912}
1913
1914#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1915struct ConcreteTraitCached {
1916    trait_id: LanguageElementCached,
1917    generic_args: Vec<GenericArgumentCached>,
1918}
1919
1920impl ConcreteTraitCached {
1921    fn new<'db>(
1922        concrete_trait: ConcreteTraitId<'db>,
1923        ctx: &mut SemanticCacheSavingContext<'db>,
1924    ) -> Self {
1925        let long_id = concrete_trait.long(ctx.db);
1926        Self {
1927            trait_id: LanguageElementCached::new(long_id.trait_id, &mut ctx.defs_ctx),
1928            generic_args: long_id
1929                .generic_args
1930                .clone()
1931                .into_iter()
1932                .map(|arg| GenericArgumentCached::new(arg, ctx))
1933                .collect(),
1934        }
1935    }
1936    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteTraitId<'db> {
1937        let (module_id, stable_ptr) = self.trait_id.get_embedded(&ctx.defs_loading_data);
1938
1939        let long_id = ConcreteTraitLongId {
1940            trait_id: TraitLongId(module_id, ItemTraitPtr(stable_ptr)).intern(ctx.db),
1941            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1942        };
1943        long_id.intern(ctx.db)
1944    }
1945    pub fn get_embedded<'db>(
1946        self,
1947        data: &Arc<SemanticCacheLoadingData<'db>>,
1948        db: &'db dyn Database,
1949    ) -> ConcreteTraitId<'db> {
1950        let (module_id, stable_ptr) = self.trait_id.get_embedded(&data.defs_loading_data);
1951        let long_id = ConcreteTraitLongId {
1952            trait_id: TraitLongId(module_id, ItemTraitPtr(stable_ptr)).intern(db),
1953            generic_args: self
1954                .generic_args
1955                .into_iter()
1956                .map(|arg| arg.get_embedded(data, db))
1957                .collect(),
1958        };
1959        long_id.intern(db)
1960    }
1961}
1962
1963/// Returns all modules reachable from the crate root, following both submodule and macro call
1964/// edges. This ensures that submodules nested inside MacroCall modules are included.
1965pub fn all_crate_modules_for_cache<'db>(
1966    db: &'db dyn Database,
1967    crate_id: CrateId<'db>,
1968) -> Vec<ModuleId<'db>> {
1969    let mut result = vec![ModuleId::CrateRoot(crate_id)];
1970    let mut unprocessed = 0;
1971    while let Some(module_id) = result.get(unprocessed).copied() {
1972        unprocessed += 1;
1973        if let Ok(submodule_ids) = db.module_submodules_ids(module_id) {
1974            result.extend(submodule_ids.iter().map(|id| ModuleId::Submodule(*id)));
1975        }
1976        if let Ok(macro_calls) = db.module_macro_calls_ids(module_id) {
1977            result.extend(macro_calls.iter().flat_map(|id| db.macro_call_module_id(*id)));
1978        }
1979    }
1980    result
1981}