cairo_lang_semantic/cache/
mod.rs

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