Skip to main content

cairo_lang_semantic/cache/
mod.rs

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