cairo_lang_semantic/cache/
mod.rs

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