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