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