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(Box<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) => {
1209                TypeCached::Snapshot(Box::new(TypeIdCached::new(type_id, ctx)))
1210            }
1211            TypeLongId::GenericParameter(generic_param_id) => TypeCached::GenericParameter(
1212                GenericParamCached::new(generic_param_id, &mut ctx.defs_ctx),
1213            ),
1214            TypeLongId::ImplType(impl_type_id) => {
1215                TypeCached::ImplType(ImplTypeCached::new(impl_type_id, ctx))
1216            }
1217            TypeLongId::FixedSizeArray { type_id, size } => TypeCached::FixedSizeArray(
1218                TypeIdCached::new(type_id, ctx),
1219                ConstValueCached::new(size.long(ctx.db).clone(), ctx),
1220            ),
1221            TypeLongId::Closure(closure_ty) => {
1222                TypeCached::ClosureType(ClosureTypeCached::new(closure_ty, ctx))
1223            }
1224            TypeLongId::Coupon(func_id) => {
1225                TypeCached::Coupon(SemanticFunctionIdCached::new(func_id, ctx))
1226            }
1227            TypeLongId::Var(_) | TypeLongId::Missing(_) => {
1228                unreachable!("type {:?} is not supported for caching", type_id.debug(ctx.db))
1229            }
1230        }
1231    }
1232    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TypeLongId<'db> {
1233        match self {
1234            TypeCached::Concrete(concrete_type) => TypeLongId::Concrete(concrete_type.embed(ctx)),
1235            TypeCached::Tuple(vec) => {
1236                TypeLongId::Tuple(vec.into_iter().map(|ty| ty.embed(ctx)).collect())
1237            }
1238            TypeCached::Snapshot(type_id) => TypeLongId::Snapshot(type_id.embed(ctx)),
1239            TypeCached::GenericParameter(generic_param) => TypeLongId::GenericParameter(
1240                generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1241            ),
1242            TypeCached::ImplType(impl_type) => TypeLongId::ImplType(impl_type.embed(ctx)),
1243            TypeCached::FixedSizeArray(type_id, size) => TypeLongId::FixedSizeArray {
1244                type_id: type_id.embed(ctx),
1245                size: size.embed(ctx).intern(ctx.db),
1246            },
1247            TypeCached::ClosureType(closure_ty) => TypeLongId::Closure(closure_ty.embed(ctx)),
1248            TypeCached::Coupon(coupon) => TypeLongId::Coupon(coupon.embed(ctx)),
1249        }
1250    }
1251}
1252
1253#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1254pub struct TypeIdCached(usize);
1255
1256impl TypeIdCached {
1257    pub fn new<'db>(ty: TypeId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1258        if let Some(id) = ctx.type_ids.get(&ty) {
1259            return *id;
1260        }
1261        let ty_long = TypeCached::new(ty.long(ctx.db).clone(), ctx);
1262        let id = TypeIdCached(ctx.type_ids_lookup.len());
1263        ctx.type_ids_lookup.push(ty_long);
1264        ctx.type_ids.insert(ty, id);
1265        id
1266    }
1267    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TypeId<'db> {
1268        if let Some(type_id) = ctx.type_ids.get(&self) {
1269            return *type_id;
1270        }
1271
1272        let ty = ctx.type_ids_lookup[self.0].clone();
1273        let ty = ty.embed(ctx).intern(ctx.db);
1274        ctx.type_ids.insert(self, ty);
1275        ty
1276    }
1277    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> TypeId<'db> {
1278        data.type_ids[&self]
1279    }
1280}
1281
1282#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1283enum ConcreteTypeCached {
1284    Struct(ConcreteStructCached),
1285    Enum(ConcreteEnumCached),
1286    Extern(ConcreteExternTypeCached),
1287}
1288
1289impl ConcreteTypeCached {
1290    fn new<'db>(
1291        concrete_type_id: ConcreteTypeId<'db>,
1292        ctx: &mut SemanticCacheSavingContext<'db>,
1293    ) -> Self {
1294        match concrete_type_id {
1295            ConcreteTypeId::Struct(id) => {
1296                ConcreteTypeCached::Struct(ConcreteStructCached::new(id, ctx))
1297            }
1298            ConcreteTypeId::Enum(id) => ConcreteTypeCached::Enum(ConcreteEnumCached::new(id, ctx)),
1299            ConcreteTypeId::Extern(id) => {
1300                ConcreteTypeCached::Extern(ConcreteExternTypeCached::new(id, ctx))
1301            }
1302        }
1303    }
1304    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteTypeId<'db> {
1305        match self {
1306            ConcreteTypeCached::Struct(s) => ConcreteTypeId::Struct(s.embed(ctx)),
1307            ConcreteTypeCached::Enum(e) => ConcreteTypeId::Enum(e.embed(ctx)),
1308            ConcreteTypeCached::Extern(e) => ConcreteTypeId::Extern(e.embed(ctx)),
1309        }
1310    }
1311}
1312
1313#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1314struct ImplTypeCached {
1315    impl_id: ImplIdCached,
1316    trait_type: TraitTypeCached,
1317}
1318impl ImplTypeCached {
1319    fn new<'db>(impl_type_id: ImplTypeId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1320        Self {
1321            impl_id: ImplIdCached::new(impl_type_id.impl_id(), ctx),
1322            trait_type: TraitTypeCached::new(impl_type_id.ty(), ctx),
1323        }
1324    }
1325    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplTypeId<'db> {
1326        let impl_id = self.impl_id.embed(ctx);
1327        let ty = self.trait_type.embed(ctx);
1328        ImplTypeId::new(impl_id, ty, ctx.db)
1329    }
1330}
1331#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1332struct ClosureTypeCached {
1333    param_tys: Vec<TypeIdCached>,
1334    ret_ty: TypeIdCached,
1335    captured_types: Vec<TypeIdCached>,
1336    parent_function: SemanticFunctionIdCached,
1337    params_location: SyntaxStablePtrIdCached,
1338}
1339
1340impl ClosureTypeCached {
1341    fn new<'db>(
1342        closure_type_id: ClosureTypeLongId<'db>,
1343        ctx: &mut SemanticCacheSavingContext<'db>,
1344    ) -> Self {
1345        Self {
1346            param_tys: closure_type_id
1347                .param_tys
1348                .iter()
1349                .map(|ty| TypeIdCached::new(*ty, ctx))
1350                .collect(),
1351            ret_ty: TypeIdCached::new(closure_type_id.ret_ty, ctx),
1352            captured_types: closure_type_id
1353                .captured_types
1354                .iter()
1355                .map(|ty| TypeIdCached::new(*ty, ctx))
1356                .collect(),
1357            parent_function: SemanticFunctionIdCached::new(
1358                closure_type_id.parent_function.unwrap(),
1359                ctx,
1360            ),
1361            params_location: SyntaxStablePtrIdCached::new(
1362                closure_type_id.params_location.stable_ptr(),
1363                &mut ctx.defs_ctx,
1364            ),
1365        }
1366    }
1367    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ClosureTypeLongId<'db> {
1368        ClosureTypeLongId {
1369            param_tys: self.param_tys.into_iter().map(|ty| ty.embed(ctx)).collect(),
1370            ret_ty: self.ret_ty.embed(ctx),
1371            captured_types: self.captured_types.into_iter().map(|ty| ty.embed(ctx)).collect(),
1372            parent_function: Ok(self.parent_function.embed(ctx)),
1373            params_location: StableLocation::new(
1374                self.params_location.get_embedded(&ctx.defs_loading_data),
1375            ),
1376        }
1377    }
1378}
1379
1380#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
1381struct TraitTypeCached {
1382    language_element: LanguageElementCached,
1383}
1384impl TraitTypeCached {
1385    fn new<'db>(
1386        trait_type_id: TraitTypeId<'db>,
1387        ctx: &mut SemanticCacheSavingContext<'db>,
1388    ) -> Self {
1389        Self { language_element: LanguageElementCached::new(trait_type_id, &mut ctx.defs_ctx) }
1390    }
1391    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TraitTypeId<'db> {
1392        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1393        TraitTypeLongId(module_id, TraitItemTypePtr(stable_ptr)).intern(ctx.db)
1394    }
1395}
1396
1397#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1398enum ImplCached {
1399    Concrete(ConcreteImplCached),
1400    GenericParameter(GenericParamCached),
1401    ImplImpl(ImplImplCached),
1402    GeneratedImpl(GeneratedImplCached),
1403    SelfImpl(ConcreteTraitCached),
1404}
1405impl ImplCached {
1406    fn new<'db>(impl_id: ImplLongId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1407        match impl_id {
1408            ImplLongId::Concrete(concrete_impl) => {
1409                ImplCached::Concrete(ConcreteImplCached::new(concrete_impl, ctx))
1410            }
1411            ImplLongId::GenericParameter(generic_param_id) => ImplCached::GenericParameter(
1412                GenericParamCached::new(generic_param_id, &mut ctx.defs_ctx),
1413            ),
1414            ImplLongId::GeneratedImpl(generated_impl) => {
1415                ImplCached::GeneratedImpl(GeneratedImplCached::new(generated_impl, ctx))
1416            }
1417            ImplLongId::ImplImpl(impl_impl) => {
1418                ImplCached::ImplImpl(ImplImplCached::new(impl_impl, ctx))
1419            }
1420            ImplLongId::SelfImpl(concrete_trait) => {
1421                ImplCached::SelfImpl(ConcreteTraitCached::new(concrete_trait, ctx))
1422            }
1423            ImplLongId::ImplVar(_) => {
1424                unreachable!("impl {:?} is not supported for caching", impl_id.debug(ctx.db))
1425            }
1426        }
1427    }
1428    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplLongId<'db> {
1429        match self {
1430            ImplCached::Concrete(concrete_impl) => ImplLongId::Concrete(concrete_impl.embed(ctx)),
1431            ImplCached::ImplImpl(impl_impl) => ImplLongId::ImplImpl(impl_impl.embed(ctx)),
1432            ImplCached::GenericParameter(generic_param) => ImplLongId::GenericParameter(
1433                generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1434            ),
1435            ImplCached::GeneratedImpl(generated_impl) => {
1436                ImplLongId::GeneratedImpl(generated_impl.embed(ctx))
1437            }
1438            ImplCached::SelfImpl(concrete_trait) => ImplLongId::SelfImpl(concrete_trait.embed(ctx)),
1439        }
1440    }
1441}
1442#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1443pub struct ImplIdCached(usize);
1444
1445impl ImplIdCached {
1446    pub fn new<'db>(impl_id: ImplId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1447        if let Some(id) = ctx.impl_ids.get(&impl_id) {
1448            return *id;
1449        }
1450        let imp = ImplCached::new(impl_id.long(ctx.db).clone(), ctx);
1451        let id = ImplIdCached(ctx.impl_ids_lookup.len());
1452        ctx.impl_ids_lookup.push(imp);
1453        ctx.impl_ids.insert(impl_id, id);
1454        id
1455    }
1456    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplId<'db> {
1457        if let Some(impl_id) = ctx.impl_ids.get(&self) {
1458            return *impl_id;
1459        }
1460
1461        let imp = ctx.impl_ids_lookup[self.0].clone();
1462        let imp = imp.embed(ctx).intern(ctx.db);
1463        ctx.impl_ids.insert(self, imp);
1464        imp
1465    }
1466    pub fn get_embedded<'db>(self, data: &Arc<SemanticCacheLoadingData<'db>>) -> ImplId<'db> {
1467        data.impl_ids[&self]
1468    }
1469}
1470
1471#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1472struct ConcreteImplCached {
1473    impl_def_id: ImplDefIdCached,
1474    generic_args: Vec<GenericArgumentCached>,
1475}
1476impl ConcreteImplCached {
1477    fn new<'db>(
1478        concrete_impl: ConcreteImplId<'db>,
1479        ctx: &mut SemanticCacheSavingContext<'db>,
1480    ) -> Self {
1481        let long_id = concrete_impl.long(ctx.db);
1482        Self {
1483            impl_def_id: ImplDefIdCached::new(long_id.impl_def_id, &mut ctx.defs_ctx),
1484            generic_args: long_id
1485                .generic_args
1486                .clone()
1487                .into_iter()
1488                .map(|arg| GenericArgumentCached::new(arg, ctx))
1489                .collect(),
1490        }
1491    }
1492    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteImplId<'db> {
1493        let impl_def_id = self.impl_def_id.get_embedded(&ctx.defs_loading_data);
1494        let long_id = ConcreteImplLongId {
1495            impl_def_id,
1496            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1497        };
1498        long_id.intern(ctx.db)
1499    }
1500    pub fn get_embedded<'db>(
1501        self,
1502        data: &Arc<SemanticCacheLoadingData<'db>>,
1503        db: &'db dyn Database,
1504    ) -> ConcreteImplId<'db> {
1505        let impl_def_id = self.impl_def_id.get_embedded(&data.defs_loading_data);
1506        let long_id = ConcreteImplLongId {
1507            impl_def_id,
1508            generic_args: self
1509                .generic_args
1510                .into_iter()
1511                .map(|arg| arg.get_embedded(data, db))
1512                .collect(),
1513        };
1514        long_id.intern(db)
1515    }
1516}
1517
1518#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1519struct ImplImplCached {
1520    impl_id: ImplIdCached,
1521    trait_impl_id: TraitImplCached,
1522}
1523impl ImplImplCached {
1524    fn new<'db>(impl_impl_id: ImplImplId<'db>, ctx: &mut SemanticCacheSavingContext<'db>) -> Self {
1525        Self {
1526            impl_id: ImplIdCached::new(impl_impl_id.impl_id(), ctx),
1527            trait_impl_id: TraitImplCached::new(impl_impl_id.trait_impl_id(), ctx),
1528        }
1529    }
1530    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ImplImplId<'db> {
1531        let impl_id = self.impl_id.embed(ctx);
1532        let trait_impl_id = self.trait_impl_id.embed(ctx);
1533        ImplImplId::new(impl_id, trait_impl_id, ctx.db)
1534    }
1535}
1536
1537#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1538struct TraitImplCached {
1539    language_element: LanguageElementCached,
1540}
1541impl TraitImplCached {
1542    fn new<'db>(
1543        trait_impl_id: TraitImplId<'db>,
1544        ctx: &mut SemanticCacheSavingContext<'db>,
1545    ) -> Self {
1546        Self { language_element: LanguageElementCached::new(trait_impl_id, &mut ctx.defs_ctx) }
1547    }
1548    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> TraitImplId<'db> {
1549        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1550        TraitImplLongId(module_id, TraitItemImplPtr(stable_ptr)).intern(ctx.db)
1551    }
1552}
1553
1554#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1555struct GeneratedImplCached {
1556    pub concrete_trait: ConcreteTraitCached,
1557    pub generic_params: Vec<SemanticGenericParamCached>,
1558    pub impl_items: OrderedHashMap<TraitTypeCached, TypeIdCached>,
1559}
1560impl GeneratedImplCached {
1561    fn new<'db>(
1562        generated_impl: GeneratedImplId<'db>,
1563        ctx: &mut SemanticCacheSavingContext<'db>,
1564    ) -> Self {
1565        let generated_impl = generated_impl.long(ctx.db);
1566        Self {
1567            concrete_trait: ConcreteTraitCached::new(generated_impl.concrete_trait, ctx),
1568            generic_params: generated_impl
1569                .generic_params
1570                .clone()
1571                .into_iter()
1572                .map(|param| SemanticGenericParamCached::new(param, ctx))
1573                .collect(),
1574            impl_items: generated_impl
1575                .impl_items
1576                .0
1577                .clone()
1578                .into_iter()
1579                .map(|(k, v)| (TraitTypeCached::new(k, ctx), TypeIdCached::new(v, ctx)))
1580                .collect(),
1581        }
1582    }
1583    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GeneratedImplId<'db> {
1584        GeneratedImplLongId {
1585            concrete_trait: self.concrete_trait.embed(ctx),
1586            generic_params: self.generic_params.into_iter().map(|param| param.embed(ctx)).collect(),
1587            impl_items: GeneratedImplItems(
1588                self.impl_items.into_iter().map(|(k, v)| (k.embed(ctx), v.embed(ctx))).collect(),
1589            ),
1590        }
1591        .intern(ctx.db)
1592    }
1593}
1594
1595#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1596enum NegativeImplCached {
1597    Solved(ConcreteTraitCached),
1598    GenericParameter(GenericParamCached),
1599}
1600impl NegativeImplCached {
1601    fn new<'db>(
1602        negative_impl_id: NegativeImplLongId<'db>,
1603        ctx: &mut SemanticCacheSavingContext<'db>,
1604    ) -> Self {
1605        match negative_impl_id {
1606            NegativeImplLongId::Solved(concrete_trait_id) => {
1607                NegativeImplCached::Solved(ConcreteTraitCached::new(concrete_trait_id, ctx))
1608            }
1609            NegativeImplLongId::GenericParameter(generic_param_id) => {
1610                NegativeImplCached::GenericParameter(GenericParamCached::new(
1611                    generic_param_id,
1612                    &mut ctx.defs_ctx,
1613                ))
1614            }
1615            NegativeImplLongId::NegativeImplVar(_) => {
1616                unreachable!("negative impl var is not supported for caching",)
1617            }
1618        }
1619    }
1620    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> NegativeImplLongId<'db> {
1621        match self {
1622            NegativeImplCached::Solved(concrete_trait) => {
1623                NegativeImplLongId::Solved(concrete_trait.embed(ctx))
1624            }
1625            NegativeImplCached::GenericParameter(generic_param) => {
1626                NegativeImplLongId::GenericParameter(
1627                    generic_param.get_embedded(&ctx.defs_loading_data, ctx.db),
1628                )
1629            }
1630        }
1631    }
1632}
1633
1634#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1635struct NegativeImplIdCached(usize);
1636
1637impl NegativeImplIdCached {
1638    fn new<'db>(
1639        negative_impl_id: NegativeImplId<'db>,
1640        ctx: &mut SemanticCacheSavingContext<'db>,
1641    ) -> Self {
1642        if let Some(id) = ctx.negative_impl_ids.get(&negative_impl_id) {
1643            return *id;
1644        }
1645        let imp = NegativeImplCached::new(negative_impl_id.long(ctx.db).clone(), ctx);
1646        let id = NegativeImplIdCached(ctx.negative_impl_ids_lookup.len());
1647        ctx.negative_impl_ids_lookup.push(imp);
1648        ctx.negative_impl_ids.insert(negative_impl_id, id);
1649        id
1650    }
1651    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> NegativeImplId<'db> {
1652        if let Some(negative_impl_id) = ctx.negative_impl_ids.get(&self) {
1653            return *negative_impl_id;
1654        }
1655
1656        let imp = ctx.negative_impl_ids_lookup[self.0].clone();
1657        let imp = imp.embed(ctx).intern(ctx.db);
1658        ctx.negative_impl_ids.insert(self, imp);
1659        imp
1660    }
1661    pub fn get_embedded<'db>(
1662        self,
1663        data: &Arc<SemanticCacheLoadingData<'db>>,
1664    ) -> NegativeImplId<'db> {
1665        data.negative_impl_ids[&self]
1666    }
1667}
1668
1669#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1670enum SemanticGenericParamCached {
1671    Type(GenericParamTypeCached),
1672    Const(GenericParamConstCached),
1673    Impl(GenericParamImplCached),
1674    NegImpl(GenericParamImplCached),
1675}
1676impl SemanticGenericParamCached {
1677    fn new<'db>(
1678        generic_param_id: GenericParam<'db>,
1679        ctx: &mut SemanticCacheSavingContext<'db>,
1680    ) -> Self {
1681        match generic_param_id {
1682            GenericParam::Type(generic_param) => {
1683                SemanticGenericParamCached::Type(GenericParamTypeCached::new(generic_param, ctx))
1684            }
1685            GenericParam::Const(generic_param) => {
1686                SemanticGenericParamCached::Const(GenericParamConstCached::new(generic_param, ctx))
1687            }
1688            GenericParam::Impl(generic_param) => {
1689                SemanticGenericParamCached::Impl(GenericParamImplCached::new(generic_param, ctx))
1690            }
1691            GenericParam::NegImpl(generic_param) => {
1692                SemanticGenericParamCached::NegImpl(GenericParamImplCached::new(generic_param, ctx))
1693            }
1694        }
1695    }
1696    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParam<'db> {
1697        match self {
1698            SemanticGenericParamCached::Type(generic_param) => {
1699                GenericParam::Type(generic_param.embed(ctx))
1700            }
1701            SemanticGenericParamCached::Const(generic_param) => {
1702                GenericParam::Const(generic_param.embed(ctx))
1703            }
1704            SemanticGenericParamCached::Impl(generic_param) => {
1705                GenericParam::Impl(generic_param.embed(ctx))
1706            }
1707            SemanticGenericParamCached::NegImpl(generic_param) => {
1708                GenericParam::NegImpl(generic_param.embed(ctx))
1709            }
1710        }
1711    }
1712}
1713
1714#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1715struct GenericParamTypeCached {
1716    id: GenericParamCached,
1717}
1718
1719impl GenericParamTypeCached {
1720    fn new<'db>(
1721        generic_param: GenericParamType<'db>,
1722        ctx: &mut SemanticCacheSavingContext<'db>,
1723    ) -> Self {
1724        Self { id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx) }
1725    }
1726    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamType<'db> {
1727        GenericParamType { id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db) }
1728    }
1729}
1730
1731#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1732struct GenericParamConstCached {
1733    id: GenericParamCached,
1734    ty: TypeIdCached,
1735}
1736
1737impl GenericParamConstCached {
1738    fn new<'db>(
1739        generic_param: GenericParamConst<'db>,
1740        ctx: &mut SemanticCacheSavingContext<'db>,
1741    ) -> Self {
1742        Self {
1743            id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx),
1744            ty: TypeIdCached::new(generic_param.ty, ctx),
1745        }
1746    }
1747    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamConst<'db> {
1748        GenericParamConst {
1749            id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db),
1750            ty: self.ty.embed(ctx),
1751        }
1752    }
1753}
1754
1755#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1756struct GenericParamImplCached {
1757    id: GenericParamCached,
1758    concrete_trait: ConcreteTraitCached,
1759    type_constraints: OrderedHashMap<TraitTypeCached, TypeIdCached>,
1760}
1761
1762impl GenericParamImplCached {
1763    fn new<'db>(
1764        generic_param: GenericParamImpl<'db>,
1765        ctx: &mut SemanticCacheSavingContext<'db>,
1766    ) -> Self {
1767        Self {
1768            id: GenericParamCached::new(generic_param.id, &mut ctx.defs_ctx),
1769            concrete_trait: ConcreteTraitCached::new(generic_param.concrete_trait.unwrap(), ctx),
1770
1771            type_constraints: generic_param
1772                .type_constraints
1773                .into_iter()
1774                .map(|(k, v)| (TraitTypeCached::new(k, ctx), TypeIdCached::new(v, ctx)))
1775                .collect(),
1776        }
1777    }
1778    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> GenericParamImpl<'db> {
1779        GenericParamImpl {
1780            id: self.id.get_embedded(&ctx.defs_loading_data, ctx.db),
1781            concrete_trait: Ok(self.concrete_trait.embed(ctx)),
1782            type_constraints: self
1783                .type_constraints
1784                .into_iter()
1785                .map(|(k, v)| (k.embed(ctx), v.embed(ctx)))
1786                .collect(),
1787        }
1788    }
1789}
1790
1791#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1792pub struct ConcreteVariantCached {
1793    concrete_enum_id: ConcreteEnumCached,
1794    id: LanguageElementCached,
1795    ty: TypeIdCached,
1796    idx: usize,
1797}
1798impl ConcreteVariantCached {
1799    pub fn new<'db>(
1800        concrete_variant: ConcreteVariant<'db>,
1801        ctx: &mut SemanticCacheSavingContext<'db>,
1802    ) -> Self {
1803        Self {
1804            concrete_enum_id: ConcreteEnumCached::new(concrete_variant.concrete_enum_id, ctx),
1805            id: LanguageElementCached::new(concrete_variant.id, &mut ctx.defs_ctx),
1806            ty: TypeIdCached::new(concrete_variant.ty, ctx),
1807            idx: concrete_variant.idx,
1808        }
1809    }
1810    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteVariant<'db> {
1811        let concrete_enum_id = self.concrete_enum_id.embed(ctx);
1812        let ty = self.ty.embed(ctx);
1813        let (module_id, stable_ptr) = self.id.get_embedded(&ctx.defs_loading_data);
1814
1815        let id = VariantLongId(module_id, VariantPtr(stable_ptr)).intern(ctx.db);
1816        ConcreteVariant { concrete_enum_id, id, ty, idx: self.idx }
1817    }
1818    pub fn get_embedded<'db>(
1819        self,
1820        data: &Arc<SemanticCacheLoadingData<'db>>,
1821        db: &'db dyn Database,
1822    ) -> ConcreteVariant<'db> {
1823        let concrete_enum_id = self.concrete_enum_id.get_embedded(data, db);
1824        let ty = self.ty.get_embedded(data);
1825        let (module_id, stable_ptr) = self.id.get_embedded(&data.defs_loading_data);
1826        let id = VariantLongId(module_id, VariantPtr(stable_ptr)).intern(db);
1827        ConcreteVariant { concrete_enum_id, id, ty, idx: self.idx }
1828    }
1829}
1830
1831#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1832pub struct ConcreteEnumCached {
1833    enum_id: LanguageElementCached,
1834    generic_args: Vec<GenericArgumentCached>,
1835}
1836
1837impl ConcreteEnumCached {
1838    pub fn new<'db>(
1839        concrete_enum: ConcreteEnumId<'db>,
1840        ctx: &mut SemanticCacheSavingContext<'db>,
1841    ) -> Self {
1842        let long_id = concrete_enum.long(ctx.db);
1843        Self {
1844            enum_id: LanguageElementCached::new(long_id.enum_id, &mut ctx.defs_ctx),
1845            generic_args: long_id
1846                .generic_args
1847                .clone()
1848                .into_iter()
1849                .map(|arg| GenericArgumentCached::new(arg, ctx))
1850                .collect(),
1851        }
1852    }
1853    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteEnumId<'db> {
1854        let (module_id, stable_ptr) = self.enum_id.get_embedded(&ctx.defs_loading_data);
1855
1856        let long_id = ConcreteEnumLongId {
1857            enum_id: EnumLongId(module_id, ItemEnumPtr(stable_ptr)).intern(ctx.db),
1858            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1859        };
1860        long_id.intern(ctx.db)
1861    }
1862    pub fn get_embedded<'db>(
1863        self,
1864        data: &Arc<SemanticCacheLoadingData<'db>>,
1865        db: &'db dyn Database,
1866    ) -> ConcreteEnumId<'db> {
1867        let (module_id, stable_ptr) = self.enum_id.get_embedded(&data.defs_loading_data);
1868        let id = EnumLongId(module_id, ItemEnumPtr(stable_ptr)).intern(db);
1869        ConcreteEnumLongId {
1870            enum_id: id,
1871            generic_args: self
1872                .generic_args
1873                .into_iter()
1874                .map(|arg| arg.get_embedded(data, db))
1875                .collect(),
1876        }
1877        .intern(db)
1878    }
1879}
1880
1881#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1882pub struct ConcreteStructCached {
1883    struct_id: LanguageElementCached,
1884    generic_args: Vec<GenericArgumentCached>,
1885}
1886impl ConcreteStructCached {
1887    fn new<'db>(
1888        concrete_struct: ConcreteStructId<'db>,
1889        ctx: &mut SemanticCacheSavingContext<'db>,
1890    ) -> Self {
1891        let long_id = concrete_struct.long(ctx.db);
1892        Self {
1893            struct_id: LanguageElementCached::new(long_id.struct_id, &mut ctx.defs_ctx),
1894            generic_args: long_id
1895                .generic_args
1896                .clone()
1897                .into_iter()
1898                .map(|arg| GenericArgumentCached::new(arg, ctx))
1899                .collect(),
1900        }
1901    }
1902    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteStructId<'db> {
1903        let (module_id, stable_ptr) = self.struct_id.get_embedded(&ctx.defs_loading_data);
1904
1905        let long_id = ConcreteStructLongId {
1906            struct_id: StructLongId(module_id, ItemStructPtr(stable_ptr)).intern(ctx.db),
1907            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1908        };
1909        long_id.intern(ctx.db)
1910    }
1911    pub fn get_embedded<'db>(
1912        self,
1913        data: &Arc<SemanticCacheLoadingData<'db>>,
1914        db: &'db dyn Database,
1915    ) -> ConcreteStructId<'db> {
1916        let (module_id, stable_ptr) = self.struct_id.get_embedded(&data.defs_loading_data);
1917        let long_id = ConcreteStructLongId {
1918            struct_id: StructLongId(module_id, ItemStructPtr(stable_ptr)).intern(db),
1919            generic_args: self
1920                .generic_args
1921                .into_iter()
1922                .map(|arg| arg.get_embedded(data, db))
1923                .collect(),
1924        };
1925        long_id.intern(db)
1926    }
1927}
1928
1929#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1930struct ConcreteExternTypeCached {
1931    language_element: LanguageElementCached,
1932    generic_args: Vec<GenericArgumentCached>,
1933}
1934impl ConcreteExternTypeCached {
1935    fn new<'db>(
1936        concrete_extern_type: ConcreteExternTypeId<'db>,
1937        ctx: &mut SemanticCacheSavingContext<'db>,
1938    ) -> Self {
1939        let long_id = concrete_extern_type.long(ctx.db);
1940        Self {
1941            language_element: LanguageElementCached::new(long_id.extern_type_id, &mut ctx.defs_ctx),
1942            generic_args: long_id
1943                .generic_args
1944                .clone()
1945                .into_iter()
1946                .map(|arg| GenericArgumentCached::new(arg, ctx))
1947                .collect(),
1948        }
1949    }
1950    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteExternTypeId<'db> {
1951        let (module_id, stable_ptr) = self.language_element.get_embedded(&ctx.defs_loading_data);
1952
1953        let long_id = ConcreteExternTypeLongId {
1954            extern_type_id: ExternTypeLongId(module_id, ItemExternTypePtr(stable_ptr))
1955                .intern(ctx.db),
1956            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1957        };
1958        long_id.intern(ctx.db)
1959    }
1960}
1961
1962#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1963struct ConcreteTraitCached {
1964    trait_id: LanguageElementCached,
1965    generic_args: Vec<GenericArgumentCached>,
1966}
1967
1968impl ConcreteTraitCached {
1969    fn new<'db>(
1970        concrete_trait: ConcreteTraitId<'db>,
1971        ctx: &mut SemanticCacheSavingContext<'db>,
1972    ) -> Self {
1973        let long_id = concrete_trait.long(ctx.db);
1974        Self {
1975            trait_id: LanguageElementCached::new(long_id.trait_id, &mut ctx.defs_ctx),
1976            generic_args: long_id
1977                .generic_args
1978                .clone()
1979                .into_iter()
1980                .map(|arg| GenericArgumentCached::new(arg, ctx))
1981                .collect(),
1982        }
1983    }
1984    fn embed<'db>(self, ctx: &mut SemanticCacheLoadingContext<'db>) -> ConcreteTraitId<'db> {
1985        let (module_id, stable_ptr) = self.trait_id.get_embedded(&ctx.defs_loading_data);
1986
1987        let long_id = ConcreteTraitLongId {
1988            trait_id: TraitLongId(module_id, ItemTraitPtr(stable_ptr)).intern(ctx.db),
1989            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1990        };
1991        long_id.intern(ctx.db)
1992    }
1993    pub fn get_embedded<'db>(
1994        self,
1995        data: &Arc<SemanticCacheLoadingData<'db>>,
1996        db: &'db dyn Database,
1997    ) -> ConcreteTraitId<'db> {
1998        let (module_id, stable_ptr) = self.trait_id.get_embedded(&data.defs_loading_data);
1999        let long_id = ConcreteTraitLongId {
2000            trait_id: TraitLongId(module_id, ItemTraitPtr(stable_ptr)).intern(db),
2001            generic_args: self
2002                .generic_args
2003                .into_iter()
2004                .map(|arg| arg.get_embedded(data, db))
2005                .collect(),
2006        };
2007        long_id.intern(db)
2008    }
2009}