cairo_lang_lowering/cache/
mod.rs

1#[cfg(test)]
2#[path = "test.rs"]
3mod test;
4
5use std::ops::{Deref, DerefMut};
6use std::path::PathBuf;
7use std::sync::Arc;
8
9use cairo_lang_debug::DebugWithDb;
10use cairo_lang_defs::diagnostic_utils::StableLocation;
11use cairo_lang_defs::ids::{
12    EnumLongId, ExternFunctionLongId, ExternTypeLongId, FileIndex, FreeFunctionLongId,
13    FunctionWithBodyId, GenericParamId, GenericParamLongId, ImplDefId, ImplDefLongId,
14    ImplFunctionLongId, LanguageElementId, LocalVarId, LocalVarLongId, MemberLongId, ModuleFileId,
15    ModuleId, ParamLongId, PluginGeneratedFileId, PluginGeneratedFileLongId, StatementConstLongId,
16    StatementItemId, StatementUseLongId, StructLongId, SubmoduleId, SubmoduleLongId,
17    TraitConstantId, TraitConstantLongId, TraitFunctionLongId, TraitTypeId, TraitTypeLongId,
18    VariantLongId,
19};
20use cairo_lang_diagnostics::{Maybe, skip_diagnostic};
21use cairo_lang_filesystem::ids::{
22    CodeMapping, CrateId, CrateLongId, FileId, FileKind, FileLongId, VirtualFile,
23};
24use cairo_lang_filesystem::span::TextWidth;
25use cairo_lang_semantic::db::SemanticGroup;
26use cairo_lang_semantic::expr::inference::InferenceError;
27use cairo_lang_semantic::items::constant::{ConstValue, ImplConstantId};
28use cairo_lang_semantic::items::functions::{
29    ConcreteFunctionWithBody, GenericFunctionId, GenericFunctionWithBodyId, ImplFunctionBodyId,
30    ImplGenericFunctionId, ImplGenericFunctionWithBodyId,
31};
32use cairo_lang_semantic::items::imp::{ImplId, ImplLongId};
33use cairo_lang_semantic::types::{
34    ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId, ImplTypeId,
35};
36use cairo_lang_semantic::{
37    ConcreteFunction, ConcreteImplLongId, MatchArmSelector, TypeId, TypeLongId, ValueSelectorArm,
38};
39use cairo_lang_syntax::node::TypedStablePtr;
40use cairo_lang_syntax::node::ast::{
41    ExprPtr, FunctionWithBodyPtr, GenericParamPtr, ItemConstantPtr, ItemEnumPtr,
42    ItemExternFunctionPtr, ItemExternTypePtr, ItemImplPtr, ItemModulePtr, ItemStructPtr, MemberPtr,
43    ParamPtr, TerminalIdentifierPtr, TraitItemConstantPtr, TraitItemFunctionPtr, TraitItemTypePtr,
44    UsePathLeafPtr, VariantPtr,
45};
46use cairo_lang_syntax::node::green::{GreenNode, GreenNodeDetails};
47use cairo_lang_syntax::node::ids::{GreenId, SyntaxStablePtrId};
48use cairo_lang_syntax::node::kind::SyntaxKind;
49use cairo_lang_syntax::node::stable_ptr::SyntaxStablePtr;
50use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
51use cairo_lang_utils::{Intern, LookupIntern};
52use id_arena::Arena;
53use num_bigint::BigInt;
54use salsa::InternKey;
55use serde::{Deserialize, Serialize};
56use smol_str::SmolStr;
57use {cairo_lang_defs as defs, cairo_lang_semantic as semantic};
58
59use crate::blocks::FlatBlocksBuilder;
60use crate::db::LoweringGroup;
61use crate::ids::{
62    FunctionId, FunctionLongId, GeneratedFunction, GeneratedFunctionKey, LocationId, Signature,
63};
64use crate::lower::MultiLowering;
65use crate::objects::{
66    BlockId, MatchExternInfo, Statement, StatementCall, StatementConst, StatementStructDestructure,
67    VariableId,
68};
69use crate::{
70    FlatBlock, FlatBlockEnd, FlatLowered, Location, MatchArm, MatchEnumInfo, MatchEnumValue,
71    MatchInfo, StatementDesnap, StatementEnumConstruct, StatementSnapshot,
72    StatementStructConstruct, VarRemapping, VarUsage, Variable,
73};
74
75/// Load the cached lowering of a crate if it has a cache file configuration.
76pub fn load_cached_crate_functions(
77    db: &dyn LoweringGroup,
78    crate_id: CrateId,
79) -> Option<Arc<OrderedHashMap<defs::ids::FunctionWithBodyId, MultiLowering>>> {
80    let blob_id = db.crate_config(crate_id)?.cache_file?;
81    let Some(content) = db.blob_content(blob_id) else {
82        return Default::default();
83    };
84    let (lookups, semantic_lookups, lowerings): (
85        CacheLookups,
86        SemanticCacheLookups,
87        Vec<(DefsFunctionWithBodyIdCached, MultiLoweringCached)>,
88    ) = bincode::deserialize(&content).unwrap_or_default();
89    // TODO(tomer): Fail on version, cfg, and dependencies mismatch.
90    let mut ctx = CacheLoadingContext::new(db, lookups, semantic_lookups, crate_id);
91
92    Some(
93        lowerings
94            .into_iter()
95            .map(|(function_id, lowering)| {
96                let function_id = function_id.embed(&mut ctx.semantic_ctx);
97
98                let lowering = lowering.embed(&mut ctx);
99                (function_id, lowering)
100            })
101            .collect::<OrderedHashMap<_, _>>()
102            .into(),
103    )
104}
105
106/// Cache the lowering of each function in the crate into a blob.
107pub fn generate_crate_cache(
108    db: &dyn LoweringGroup,
109    crate_id: cairo_lang_filesystem::ids::CrateId,
110) -> Maybe<Arc<[u8]>> {
111    let modules = db.crate_modules(crate_id);
112    let mut function_ids = Vec::new();
113    for module_id in modules.iter() {
114        for free_func in db.module_free_functions_ids(*module_id)?.iter() {
115            function_ids.push(FunctionWithBodyId::Free(*free_func));
116        }
117        for impl_id in db.module_impls_ids(*module_id)?.iter() {
118            for impl_func in db.impl_functions(*impl_id)?.values() {
119                function_ids.push(FunctionWithBodyId::Impl(*impl_func));
120            }
121        }
122    }
123
124    let mut ctx = CacheSavingContext::new(db, crate_id);
125    let cached = function_ids
126        .iter()
127        .map(|id| {
128            let multi = db.priv_function_with_body_multi_lowering(*id)?;
129            Ok((
130                DefsFunctionWithBodyIdCached::new(*id, &mut ctx.semantic_ctx),
131                MultiLoweringCached::new((*multi).clone(), &mut ctx),
132            ))
133        })
134        .collect::<Maybe<Vec<_>>>()?;
135
136    let artifact = if let Ok(lowered) =
137        bincode::serialize(&(&ctx.lookups, &ctx.semantic_ctx.lookups, cached))
138    {
139        lowered
140    } else {
141        "".into()
142    };
143    Ok(Arc::from(artifact.as_slice()))
144}
145
146/// Context for loading cache into the database.
147struct CacheLoadingContext<'db> {
148    /// The variable ids of the flat lowered that is currently being loaded.
149    flat_lowered_variables_id: Vec<VariableId>,
150    db: &'db dyn LoweringGroup,
151
152    /// data for loading the entire cache into the database.
153    data: CacheLoadingData,
154
155    semantic_ctx: SemanticCacheLoadingContext<'db>,
156}
157
158impl<'db> CacheLoadingContext<'db> {
159    fn new(
160        db: &'db dyn LoweringGroup,
161        lookups: CacheLookups,
162        semantic_lookups: SemanticCacheLookups,
163        self_crate_id: CrateId,
164    ) -> Self {
165        Self {
166            flat_lowered_variables_id: Vec::new(),
167            db,
168            data: CacheLoadingData {
169                function_ids: OrderedHashMap::default(),
170                location_ids: OrderedHashMap::default(),
171                lookups,
172            },
173            semantic_ctx: SemanticCacheLoadingContext::<'db> {
174                db: db.upcast(),
175                data: SemanticCacheLoadingData::new(semantic_lookups, self_crate_id),
176            },
177        }
178    }
179}
180
181impl Deref for CacheLoadingContext<'_> {
182    type Target = CacheLoadingData;
183
184    fn deref(&self) -> &Self::Target {
185        &self.data
186    }
187}
188impl DerefMut for CacheLoadingContext<'_> {
189    fn deref_mut(&mut self) -> &mut Self::Target {
190        &mut self.data
191    }
192}
193
194/// Data for loading cache into the database.
195struct CacheLoadingData {
196    function_ids: OrderedHashMap<FunctionIdCached, FunctionId>,
197    location_ids: OrderedHashMap<LocationIdCached, LocationId>,
198    lookups: CacheLookups,
199}
200impl Deref for CacheLoadingData {
201    type Target = CacheLookups;
202
203    fn deref(&self) -> &Self::Target {
204        &self.lookups
205    }
206}
207impl DerefMut for CacheLoadingData {
208    fn deref_mut(&mut self) -> &mut Self::Target {
209        &mut self.lookups
210    }
211}
212
213/// Context for saving cache from the database.
214struct CacheSavingContext<'db> {
215    db: &'db dyn LoweringGroup,
216    data: CacheSavingData,
217    semantic_ctx: SemanticCacheSavingContext<'db>,
218}
219impl Deref for CacheSavingContext<'_> {
220    type Target = CacheSavingData;
221
222    fn deref(&self) -> &Self::Target {
223        &self.data
224    }
225}
226impl DerefMut for CacheSavingContext<'_> {
227    fn deref_mut(&mut self) -> &mut Self::Target {
228        &mut self.data
229    }
230}
231impl<'db> CacheSavingContext<'db> {
232    fn new(db: &'db dyn LoweringGroup, self_crate_id: CrateId) -> Self {
233        Self {
234            db,
235            data: CacheSavingData::default(),
236            semantic_ctx: SemanticCacheSavingContext {
237                db: db.upcast(),
238                data: SemanticCacheSavingData::default(),
239                self_crate_id,
240            },
241        }
242    }
243}
244
245/// Data for saving cache from the database.
246#[derive(Default)]
247struct CacheSavingData {
248    function_ids: OrderedHashMap<FunctionId, FunctionIdCached>,
249    location_ids: OrderedHashMap<LocationId, LocationIdCached>,
250    lookups: CacheLookups,
251}
252impl Deref for CacheSavingData {
253    type Target = CacheLookups;
254
255    fn deref(&self) -> &Self::Target {
256        &self.lookups
257    }
258}
259impl DerefMut for CacheSavingData {
260    fn deref_mut(&mut self) -> &mut Self::Target {
261        &mut self.lookups
262    }
263}
264
265/// Saved interned items for the cache.
266#[derive(Serialize, Deserialize, Default)]
267struct CacheLookups {
268    function_ids_lookup: Vec<FunctionCached>,
269    location_ids_lookup: Vec<LocationCached>,
270}
271
272/// Context for loading cache into the database.
273struct SemanticCacheLoadingContext<'db> {
274    db: &'db dyn SemanticGroup,
275    data: SemanticCacheLoadingData,
276}
277
278impl Deref for SemanticCacheLoadingContext<'_> {
279    type Target = SemanticCacheLoadingData;
280
281    fn deref(&self) -> &Self::Target {
282        &self.data
283    }
284}
285impl DerefMut for SemanticCacheLoadingContext<'_> {
286    fn deref_mut(&mut self) -> &mut Self::Target {
287        &mut self.data
288    }
289}
290
291/// Data for loading cache into the database.
292struct SemanticCacheLoadingData {
293    function_ids: OrderedHashMap<SemanticFunctionIdCached, semantic::FunctionId>,
294    type_ids: OrderedHashMap<TypeIdCached, TypeId>,
295    impl_ids: OrderedHashMap<ImplIdCached, ImplId>,
296    green_ids: OrderedHashMap<GreenIdCached, GreenId>,
297    syntax_stable_ptr_ids: OrderedHashMap<SyntaxStablePtrIdCached, SyntaxStablePtrId>,
298    crate_ids: OrderedHashMap<CrateIdCached, CrateId>,
299    submodule_ids: OrderedHashMap<SubmoduleIdCached, SubmoduleId>,
300    file_ids: OrderedHashMap<FileIdCached, FileId>,
301    self_crate_id: CrateId,
302    lookups: SemanticCacheLookups,
303}
304
305impl SemanticCacheLoadingData {
306    fn new(lookups: SemanticCacheLookups, self_crate_id: CrateId) -> Self {
307        Self {
308            function_ids: OrderedHashMap::default(),
309            type_ids: OrderedHashMap::default(),
310            impl_ids: OrderedHashMap::default(),
311            green_ids: OrderedHashMap::default(),
312            syntax_stable_ptr_ids: OrderedHashMap::default(),
313            crate_ids: OrderedHashMap::default(),
314            submodule_ids: OrderedHashMap::default(),
315            file_ids: OrderedHashMap::default(),
316            self_crate_id,
317            lookups,
318        }
319    }
320}
321
322impl Deref for SemanticCacheLoadingData {
323    type Target = SemanticCacheLookups;
324
325    fn deref(&self) -> &Self::Target {
326        &self.lookups
327    }
328}
329impl DerefMut for SemanticCacheLoadingData {
330    fn deref_mut(&mut self) -> &mut Self::Target {
331        &mut self.lookups
332    }
333}
334
335/// Context for saving cache from the database.
336struct SemanticCacheSavingContext<'db> {
337    db: &'db dyn SemanticGroup,
338    data: SemanticCacheSavingData,
339    self_crate_id: CrateId,
340}
341impl Deref for SemanticCacheSavingContext<'_> {
342    type Target = SemanticCacheSavingData;
343
344    fn deref(&self) -> &Self::Target {
345        &self.data
346    }
347}
348impl DerefMut for SemanticCacheSavingContext<'_> {
349    fn deref_mut(&mut self) -> &mut Self::Target {
350        &mut self.data
351    }
352}
353
354/// Data for saving cache from the database.
355#[derive(Default)]
356struct SemanticCacheSavingData {
357    function_ids: OrderedHashMap<semantic::FunctionId, SemanticFunctionIdCached>,
358
359    type_ids: OrderedHashMap<TypeId, TypeIdCached>,
360
361    impl_ids: OrderedHashMap<ImplId, ImplIdCached>,
362
363    green_ids: OrderedHashMap<GreenId, GreenIdCached>,
364    crate_ids: OrderedHashMap<CrateId, CrateIdCached>,
365    submodule_ids: OrderedHashMap<SubmoduleId, SubmoduleIdCached>,
366
367    syntax_stable_ptr_ids: OrderedHashMap<SyntaxStablePtrId, SyntaxStablePtrIdCached>,
368    file_ids: OrderedHashMap<FileId, FileIdCached>,
369
370    lookups: SemanticCacheLookups,
371}
372
373impl Deref for SemanticCacheSavingData {
374    type Target = SemanticCacheLookups;
375
376    fn deref(&self) -> &Self::Target {
377        &self.lookups
378    }
379}
380impl DerefMut for SemanticCacheSavingData {
381    fn deref_mut(&mut self) -> &mut Self::Target {
382        &mut self.lookups
383    }
384}
385
386/// Saved interned items for the cache.
387#[derive(Serialize, Deserialize, Default)]
388struct SemanticCacheLookups {
389    function_ids_lookup: Vec<SemanticFunctionCached>,
390    type_ids_lookup: Vec<TypeCached>,
391    impl_ids_lookup: Vec<ImplCached>,
392    green_ids_lookup: Vec<GreenNodeCached>,
393    crate_ids_lookup: Vec<CrateCached>,
394    syntax_stable_ptr_ids_lookup: Vec<SyntaxStablePtrCached>,
395    submodule_ids_lookup: Vec<SubmoduleCached>,
396    file_ids_lookup: Vec<FileCached>,
397}
398
399/// Cached version of [defs::ids::FunctionWithBodyId]
400/// used as a key in the cache for the [MultiLowering] struct.
401#[derive(Serialize, Deserialize, Hash, Eq, PartialEq)]
402enum DefsFunctionWithBodyIdCached {
403    Free(LanguageElementCached),
404    Impl(LanguageElementCached),
405    Trait(LanguageElementCached),
406}
407impl DefsFunctionWithBodyIdCached {
408    fn new(id: defs::ids::FunctionWithBodyId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
409        match id {
410            defs::ids::FunctionWithBodyId::Free(id) => {
411                DefsFunctionWithBodyIdCached::Free(LanguageElementCached::new(id, ctx))
412            }
413            defs::ids::FunctionWithBodyId::Impl(id) => {
414                DefsFunctionWithBodyIdCached::Impl(LanguageElementCached::new(id, ctx))
415            }
416            defs::ids::FunctionWithBodyId::Trait(id) => {
417                DefsFunctionWithBodyIdCached::Trait(LanguageElementCached::new(id, ctx))
418            }
419        }
420    }
421
422    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> defs::ids::FunctionWithBodyId {
423        match self {
424            DefsFunctionWithBodyIdCached::Free(id) => {
425                let (module_file_id, function_stable_ptr) = id.embed(ctx);
426                defs::ids::FunctionWithBodyId::Free(
427                    FreeFunctionLongId(module_file_id, FunctionWithBodyPtr(function_stable_ptr))
428                        .intern(ctx.db),
429                )
430            }
431            DefsFunctionWithBodyIdCached::Impl(id) => {
432                let (module_file_id, function_stable_ptr) = id.embed(ctx);
433                defs::ids::FunctionWithBodyId::Impl(
434                    ImplFunctionLongId(module_file_id, FunctionWithBodyPtr(function_stable_ptr))
435                        .intern(ctx.db),
436                )
437            }
438            DefsFunctionWithBodyIdCached::Trait(id) => {
439                let (module_file_id, function_stable_ptr) = id.embed(ctx);
440                defs::ids::FunctionWithBodyId::Trait(
441                    TraitFunctionLongId(module_file_id, TraitItemFunctionPtr(function_stable_ptr))
442                        .intern(ctx.db),
443                )
444            }
445        }
446    }
447}
448
449/// Cached version of [MultiLowering].
450#[derive(Serialize, Deserialize)]
451struct MultiLoweringCached {
452    main_lowering: FlatLoweredCached,
453    generated_lowerings: Vec<(GeneratedFunctionKeyCached, FlatLoweredCached)>,
454}
455impl MultiLoweringCached {
456    fn new(lowering: MultiLowering, ctx: &mut CacheSavingContext<'_>) -> Self {
457        Self {
458            main_lowering: FlatLoweredCached::new(lowering.main_lowering, ctx),
459            generated_lowerings: lowering
460                .generated_lowerings
461                .into_iter()
462                .map(|(key, flat_lowered)| {
463                    (
464                        GeneratedFunctionKeyCached::new(key, ctx),
465                        FlatLoweredCached::new(flat_lowered, ctx),
466                    )
467                })
468                .collect(),
469        }
470    }
471    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MultiLowering {
472        MultiLowering {
473            main_lowering: self.main_lowering.embed(ctx),
474            generated_lowerings: self
475                .generated_lowerings
476                .into_iter()
477                .map(|(key, flat_lowered)| (key.embed(ctx), flat_lowered.embed(ctx)))
478                .collect(),
479        }
480    }
481}
482
483#[derive(Serialize, Deserialize)]
484struct FlatLoweredCached {
485    /// Function signature.
486    signature: SignatureCached,
487    /// Arena of allocated lowered variables.
488    variables: Vec<VariableCached>,
489    /// Arena of allocated lowered blocks.
490    blocks: Vec<FlatBlockCached>,
491    /// function parameters, including implicits.
492    parameters: Vec<usize>,
493}
494impl FlatLoweredCached {
495    fn new(flat_lowered: FlatLowered, ctx: &mut CacheSavingContext<'_>) -> Self {
496        Self {
497            signature: SignatureCached::new(flat_lowered.signature, ctx),
498            variables: flat_lowered
499                .variables
500                .into_iter()
501                .map(|var| VariableCached::new(var.1, ctx))
502                .collect(),
503            blocks: flat_lowered
504                .blocks
505                .into_iter()
506                .map(|block: (BlockId, &FlatBlock)| FlatBlockCached::new(block.1.clone(), ctx))
507                .collect(),
508            parameters: flat_lowered.parameters.iter().map(|var| var.index()).collect(),
509        }
510    }
511    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> FlatLowered {
512        ctx.flat_lowered_variables_id.clear();
513        let mut variables = Arena::new();
514        for var in self.variables {
515            let id = variables.alloc(var.embed(ctx));
516            ctx.flat_lowered_variables_id.push(id);
517        }
518
519        let mut blocks = FlatBlocksBuilder::new();
520        for block in self.blocks {
521            blocks.alloc(block.embed(ctx));
522        }
523        FlatLowered {
524            diagnostics: Default::default(),
525            signature: self.signature.embed(ctx),
526            variables,
527            blocks: blocks.build().unwrap(),
528            parameters: self
529                .parameters
530                .into_iter()
531                .map(|var_id| ctx.flat_lowered_variables_id[var_id])
532                .collect(),
533        }
534    }
535}
536
537#[derive(Serialize, Deserialize)]
538struct SignatureCached {
539    /// Function parameters.
540    params: Vec<ExprVarMemberPathCached>,
541    /// Extra return values.
542    extra_rets: Vec<ExprVarMemberPathCached>,
543    /// Return type.
544    return_type: TypeIdCached,
545    /// Implicit parameters.
546    implicits: Vec<TypeIdCached>,
547    /// Whether the function is panicable.
548    panicable: bool,
549    location: LocationIdCached,
550}
551impl SignatureCached {
552    fn new(signature: Signature, ctx: &mut CacheSavingContext<'_>) -> Self {
553        Self {
554            params: signature
555                .params
556                .into_iter()
557                .map(|var| ExprVarMemberPathCached::new(var, &mut ctx.semantic_ctx))
558                .collect(),
559            extra_rets: signature
560                .extra_rets
561                .into_iter()
562                .map(|var| ExprVarMemberPathCached::new(var, &mut ctx.semantic_ctx))
563                .collect(),
564
565            return_type: TypeIdCached::new(signature.return_type, &mut ctx.semantic_ctx),
566            implicits: signature
567                .implicits
568                .into_iter()
569                .map(|ty| TypeIdCached::new(ty, &mut ctx.semantic_ctx))
570                .collect(),
571            panicable: signature.panicable,
572            location: LocationIdCached::new(signature.location, ctx),
573        }
574    }
575    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> Signature {
576        Signature {
577            params: self.params.into_iter().map(|var| var.embed(&mut ctx.semantic_ctx)).collect(),
578            extra_rets: self
579                .extra_rets
580                .into_iter()
581                .map(|var| var.embed(&mut ctx.semantic_ctx))
582                .collect(),
583            return_type: self.return_type.embed(&mut ctx.semantic_ctx),
584            implicits: self
585                .implicits
586                .into_iter()
587                .map(|ty| ty.embed(&mut ctx.semantic_ctx))
588                .collect(),
589            panicable: self.panicable,
590            location: self.location.embed(ctx),
591        }
592    }
593}
594
595#[derive(Serialize, Deserialize)]
596enum ExprVarMemberPathCached {
597    Var(ExprVarCached),
598    Member {
599        parent: Box<ExprVarMemberPathCached>,
600        member_id: LanguageElementCached,
601        concrete_struct_id: ConcreteStructCached,
602        stable_ptr: SyntaxStablePtrIdCached,
603        ty: TypeIdCached,
604    },
605}
606impl ExprVarMemberPathCached {
607    fn new(
608        expr_var_member_path: semantic::ExprVarMemberPath,
609        ctx: &mut SemanticCacheSavingContext<'_>,
610    ) -> Self {
611        match expr_var_member_path {
612            semantic::ExprVarMemberPath::Var(var) => {
613                ExprVarMemberPathCached::Var(ExprVarCached::new(var, ctx))
614            }
615            semantic::ExprVarMemberPath::Member {
616                parent,
617                member_id,
618                concrete_struct_id,
619                stable_ptr,
620                ty,
621            } => ExprVarMemberPathCached::Member {
622                parent: Box::new(ExprVarMemberPathCached::new(*parent, ctx)),
623                member_id: LanguageElementCached::new(member_id, ctx),
624                concrete_struct_id: ConcreteStructCached::new(concrete_struct_id, ctx),
625                stable_ptr: SyntaxStablePtrIdCached::new(stable_ptr.untyped(), ctx),
626                ty: TypeIdCached::new(ty, ctx),
627            },
628        }
629    }
630    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ExprVarMemberPath {
631        match self {
632            ExprVarMemberPathCached::Var(var) => semantic::ExprVarMemberPath::Var(var.embed(ctx)),
633            ExprVarMemberPathCached::Member {
634                parent,
635                member_id,
636                concrete_struct_id,
637                stable_ptr,
638                ty,
639            } => {
640                let parent = Box::new(parent.embed(ctx));
641                let (module_file_id, member_stable_ptr) = member_id.embed(ctx);
642                let member_id =
643                    MemberLongId(module_file_id, MemberPtr(member_stable_ptr)).intern(ctx.db);
644                semantic::ExprVarMemberPath::Member {
645                    parent,
646                    member_id,
647                    concrete_struct_id: concrete_struct_id.embed(ctx),
648                    stable_ptr: ExprPtr(stable_ptr.embed(ctx)),
649                    ty: ty.embed(ctx),
650                }
651            }
652        }
653    }
654}
655
656#[derive(Serialize, Deserialize)]
657struct ExprVarCached {
658    var: SemanticVarIdCached,
659    /// Variable type.
660    ty: TypeIdCached,
661    stable_ptr: SyntaxStablePtrIdCached,
662}
663impl ExprVarCached {
664    fn new(expr_var: semantic::ExprVar, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
665        Self {
666            var: SemanticVarIdCached::new(expr_var.var, ctx),
667            ty: TypeIdCached::new(expr_var.ty, ctx),
668            stable_ptr: SyntaxStablePtrIdCached::new(expr_var.stable_ptr.untyped(), ctx),
669        }
670    }
671    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ExprVar {
672        semantic::ExprVar {
673            var: self.var.embed(ctx),
674            ty: self.ty.embed(ctx),
675            stable_ptr: ExprPtr(self.stable_ptr.embed(ctx)),
676        }
677    }
678}
679
680#[derive(Serialize, Deserialize)]
681enum SemanticVarIdCached {
682    Param(SemanticParamIdCached),
683    Local(SemanticLocalVarIdCached),
684    Item(SemanticStatementItemIdCached),
685}
686impl SemanticVarIdCached {
687    fn new(var_id: semantic::VarId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
688        match var_id {
689            semantic::VarId::Param(id) => {
690                SemanticVarIdCached::Param(SemanticParamIdCached::new(id, ctx))
691            }
692            semantic::VarId::Local(id) => {
693                SemanticVarIdCached::Local(SemanticLocalVarIdCached::new(id, ctx))
694            }
695            semantic::VarId::Item(id) => {
696                SemanticVarIdCached::Item(SemanticStatementItemIdCached::new(id, ctx))
697            }
698        }
699    }
700    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::VarId {
701        match self {
702            SemanticVarIdCached::Param(id) => semantic::VarId::Param(id.embed(ctx)),
703            SemanticVarIdCached::Local(id) => semantic::VarId::Local(id.embed(ctx)),
704            SemanticVarIdCached::Item(id) => semantic::VarId::Item(id.embed(ctx)),
705        }
706    }
707}
708
709#[derive(Serialize, Deserialize)]
710struct SemanticParamIdCached {
711    language_element: LanguageElementCached,
712}
713impl SemanticParamIdCached {
714    fn new(param_id: semantic::ParamId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
715        Self { language_element: LanguageElementCached::new(param_id, ctx) }
716    }
717    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ParamId {
718        let (module_id, stable_ptr) = self.language_element.embed(ctx);
719        ParamLongId(module_id, ParamPtr(stable_ptr)).intern(ctx.db)
720    }
721}
722
723#[derive(Serialize, Deserialize)]
724struct SemanticLocalVarIdCached {
725    language_element: LanguageElementCached,
726}
727impl SemanticLocalVarIdCached {
728    fn new(local_var_id: LocalVarId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
729        Self { language_element: LanguageElementCached::new(local_var_id, ctx) }
730    }
731    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> LocalVarId {
732        let (module_id, stable_ptr) = self.language_element.embed(ctx);
733        LocalVarLongId(module_id, TerminalIdentifierPtr(stable_ptr)).intern(ctx.db)
734    }
735}
736
737#[derive(Serialize, Deserialize)]
738enum SemanticStatementItemIdCached {
739    Constant(LanguageElementCached),
740    Use(LanguageElementCached),
741}
742
743impl SemanticStatementItemIdCached {
744    fn new(item_id: StatementItemId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
745        match item_id {
746            StatementItemId::Constant(id) => {
747                SemanticStatementItemIdCached::Constant(LanguageElementCached::new(id, ctx))
748            }
749            StatementItemId::Use(id) => {
750                SemanticStatementItemIdCached::Use(LanguageElementCached::new(id, ctx))
751            }
752        }
753    }
754    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> StatementItemId {
755        match self {
756            SemanticStatementItemIdCached::Constant(id) => {
757                let (module_id, stable_ptr) = id.embed(ctx);
758                StatementItemId::Constant(
759                    StatementConstLongId(module_id, ItemConstantPtr(stable_ptr)).intern(ctx.db),
760                )
761            }
762            SemanticStatementItemIdCached::Use(id) => {
763                let (module_id, stable_ptr) = id.embed(ctx);
764                StatementItemId::Use(
765                    StatementUseLongId(module_id, UsePathLeafPtr(stable_ptr)).intern(ctx.db),
766                )
767            }
768        }
769    }
770}
771
772#[derive(Serialize, Deserialize)]
773struct VariableCached {
774    droppable: Option<ImplIdCached>,
775    /// Can the type be (trivially) copied.
776    copyable: Option<ImplIdCached>,
777    /// A Destruct impl for the type, if found.
778    destruct_impl: Option<ImplIdCached>,
779    /// A PanicDestruct impl for the type, if found.
780    panic_destruct_impl: Option<ImplIdCached>,
781    /// Semantic type of the variable.
782    ty: TypeIdCached,
783    location: LocationIdCached,
784}
785impl VariableCached {
786    fn new(variable: Variable, ctx: &mut CacheSavingContext<'_>) -> Self {
787        Self {
788            droppable: variable
789                .droppable
790                .map(|impl_id| ImplIdCached::new(impl_id, &mut ctx.semantic_ctx))
791                .ok(),
792            copyable: variable
793                .copyable
794                .map(|impl_id| ImplIdCached::new(impl_id, &mut ctx.semantic_ctx))
795                .ok(),
796            destruct_impl: variable
797                .destruct_impl
798                .map(|impl_id| ImplIdCached::new(impl_id, &mut ctx.semantic_ctx))
799                .ok(),
800            panic_destruct_impl: variable
801                .panic_destruct_impl
802                .map(|impl_id| ImplIdCached::new(impl_id, &mut ctx.semantic_ctx))
803                .ok(),
804            ty: TypeIdCached::new(variable.ty, &mut ctx.semantic_ctx),
805            location: LocationIdCached::new(variable.location, ctx),
806        }
807    }
808    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> Variable {
809        Variable {
810            droppable: self
811                .droppable
812                .map(|impl_id| impl_id.embed(&mut ctx.semantic_ctx))
813                .ok_or(InferenceError::Reported(skip_diagnostic())),
814            copyable: self
815                .copyable
816                .map(|impl_id| impl_id.embed(&mut ctx.semantic_ctx))
817                .ok_or(InferenceError::Reported(skip_diagnostic())),
818            destruct_impl: self
819                .destruct_impl
820                .map(|impl_id| impl_id.embed(&mut ctx.semantic_ctx))
821                .ok_or(InferenceError::Reported(skip_diagnostic())),
822            panic_destruct_impl: self
823                .panic_destruct_impl
824                .map(|impl_id| impl_id.embed(&mut ctx.semantic_ctx))
825                .ok_or(InferenceError::Reported(skip_diagnostic())),
826            ty: self.ty.embed(&mut ctx.semantic_ctx),
827            location: self.location.embed(ctx),
828        }
829    }
830}
831
832#[derive(Serialize, Deserialize)]
833struct VarUsageCached {
834    /// Variable id.
835    var_id: usize,
836    /// Location of the usage.
837    location: LocationIdCached,
838}
839
840impl VarUsageCached {
841    fn new(var_usage: VarUsage, ctx: &mut CacheSavingContext<'_>) -> Self {
842        Self {
843            var_id: var_usage.var_id.index(),
844            location: LocationIdCached::new(var_usage.location, ctx),
845        }
846    }
847    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> VarUsage {
848        VarUsage {
849            var_id: ctx.flat_lowered_variables_id[self.var_id],
850            location: self.location.embed(ctx),
851        }
852    }
853}
854
855#[derive(Serialize, Deserialize)]
856struct FlatBlockCached {
857    /// Statements in the block.
858    statements: Vec<StatementCached>,
859    /// Block end.
860    end: FlatBlockEndCached,
861}
862impl FlatBlockCached {
863    fn new(flat_block: FlatBlock, ctx: &mut CacheSavingContext<'_>) -> Self {
864        Self {
865            statements: flat_block
866                .statements
867                .into_iter()
868                .map(|stmt| StatementCached::new(stmt, ctx))
869                .collect(),
870            end: FlatBlockEndCached::new(flat_block.end, ctx),
871        }
872    }
873    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> FlatBlock {
874        FlatBlock {
875            statements: self.statements.into_iter().map(|stmt| stmt.embed(ctx)).collect(),
876            end: self.end.embed(ctx),
877        }
878    }
879}
880#[derive(Serialize, Deserialize)]
881enum FlatBlockEndCached {
882    /// The block was created but still needs to be populated. Block must not be in this state in
883    /// the end of the lowering phase.
884    NotSet,
885    /// This block ends with a `return` statement, exiting the function.
886    Return(Vec<VarUsageCached>, LocationIdCached),
887    /// This block ends with a panic.
888    Panic(VarUsageCached),
889    /// This block ends with a jump to a different block.
890    Goto(usize, VarRemappingCached),
891    Match {
892        info: MatchInfoCached,
893    },
894}
895impl FlatBlockEndCached {
896    fn new(flat_block_end: FlatBlockEnd, ctx: &mut CacheSavingContext<'_>) -> Self {
897        match flat_block_end {
898            FlatBlockEnd::Return(returns, location) => FlatBlockEndCached::Return(
899                returns.iter().map(|var| VarUsageCached::new(*var, ctx)).collect(),
900                LocationIdCached::new(location, ctx),
901            ),
902            FlatBlockEnd::Panic(data) => FlatBlockEndCached::Panic(VarUsageCached::new(data, ctx)),
903            FlatBlockEnd::Goto(block_id, remapping) => {
904                FlatBlockEndCached::Goto(block_id.0, VarRemappingCached::new(remapping, ctx))
905            }
906            FlatBlockEnd::NotSet => FlatBlockEndCached::NotSet,
907            FlatBlockEnd::Match { info } => {
908                FlatBlockEndCached::Match { info: MatchInfoCached::new(info, ctx) }
909            }
910        }
911    }
912    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> FlatBlockEnd {
913        match self {
914            FlatBlockEndCached::Return(returns, location) => FlatBlockEnd::Return(
915                returns.into_iter().map(|var_usage| var_usage.embed(ctx)).collect(),
916                location.embed(ctx),
917            ),
918            FlatBlockEndCached::Panic(var_id) => FlatBlockEnd::Panic(var_id.embed(ctx)),
919            FlatBlockEndCached::Goto(block_id, remapping) => {
920                FlatBlockEnd::Goto(BlockId(block_id), remapping.embed(ctx))
921            }
922            FlatBlockEndCached::NotSet => FlatBlockEnd::NotSet,
923            FlatBlockEndCached::Match { info } => FlatBlockEnd::Match { info: info.embed(ctx) },
924        }
925    }
926}
927
928#[derive(Serialize, Deserialize)]
929struct VarRemappingCached {
930    /// Map from new_var to old_var (since new_var cannot appear twice, but old_var can).
931    remapping: OrderedHashMap<usize, VarUsageCached>,
932}
933impl VarRemappingCached {
934    fn new(var_remapping: VarRemapping, ctx: &mut CacheSavingContext<'_>) -> Self {
935        Self {
936            remapping: var_remapping
937                .iter()
938                .map(|(dst, src)| (dst.index(), VarUsageCached::new(*src, ctx)))
939                .collect(),
940        }
941    }
942    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> VarRemapping {
943        let mut remapping = OrderedHashMap::default();
944        for (dst, src) in self.remapping {
945            remapping.insert(ctx.flat_lowered_variables_id[dst], src.embed(ctx));
946        }
947        VarRemapping { remapping }
948    }
949}
950
951#[derive(Serialize, Deserialize)]
952enum MatchInfoCached {
953    Enum(MatchEnumInfoCached),
954    Extern(MatchExternInfoCached),
955    Value(MatchEnumValueCached),
956}
957impl MatchInfoCached {
958    fn new(match_info: MatchInfo, ctx: &mut CacheSavingContext<'_>) -> Self {
959        match match_info {
960            MatchInfo::Enum(info) => MatchInfoCached::Enum(MatchEnumInfoCached::new(info, ctx)),
961            MatchInfo::Extern(info) => {
962                MatchInfoCached::Extern(MatchExternInfoCached::new(info, ctx))
963            }
964            MatchInfo::Value(info) => MatchInfoCached::Value(MatchEnumValueCached::new(info, ctx)),
965        }
966    }
967    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchInfo {
968        match self {
969            MatchInfoCached::Enum(info) => MatchInfo::Enum(info.embed(ctx)),
970            MatchInfoCached::Extern(info) => MatchInfo::Extern(info.embed(ctx)),
971            MatchInfoCached::Value(info) => MatchInfo::Value(info.embed(ctx)),
972        }
973    }
974}
975
976#[derive(Serialize, Deserialize)]
977struct MatchEnumInfoCached {
978    concrete_enum_id: ConcreteEnumCached,
979    /// A living variable in current scope to match on.
980    input: VarUsageCached,
981    /// Match arms. All blocks should have the same rets.
982    /// Order must be identical to the order in the definition of the enum.
983    arms: Vec<MatchArmCached>,
984    location: LocationIdCached,
985}
986impl MatchEnumInfoCached {
987    fn new(match_enum_info: MatchEnumInfo, ctx: &mut CacheSavingContext<'_>) -> Self {
988        Self {
989            concrete_enum_id: ConcreteEnumCached::new(
990                match_enum_info.concrete_enum_id,
991                &mut ctx.semantic_ctx,
992            ),
993            input: VarUsageCached::new(match_enum_info.input, ctx),
994            arms: match_enum_info
995                .arms
996                .into_iter()
997                .map(|arm| MatchArmCached::new(arm, ctx))
998                .collect(),
999            location: LocationIdCached::new(match_enum_info.location, ctx),
1000        }
1001    }
1002    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchEnumInfo {
1003        MatchEnumInfo {
1004            concrete_enum_id: self.concrete_enum_id.embed(&mut ctx.semantic_ctx),
1005            input: self.input.embed(ctx),
1006            arms: self.arms.into_iter().map(|arm| arm.embed(ctx)).collect(),
1007            location: self.location.embed(ctx),
1008        }
1009    }
1010}
1011
1012#[derive(Serialize, Deserialize)]
1013struct MatchExternInfoCached {
1014    /// A concrete external function to call.
1015    function: FunctionIdCached,
1016    /// Living variables in current scope to move to the function, as arguments.
1017    inputs: Vec<VarUsageCached>,
1018    /// Match arms. All blocks should have the same rets.
1019    /// Order must be identical to the order in the definition of the enum.
1020    arms: Vec<MatchArmCached>,
1021    location: LocationIdCached,
1022}
1023
1024impl MatchExternInfoCached {
1025    fn new(match_extern_info: MatchExternInfo, ctx: &mut CacheSavingContext<'_>) -> Self {
1026        Self {
1027            function: FunctionIdCached::new(match_extern_info.function, ctx),
1028            inputs: match_extern_info
1029                .inputs
1030                .iter()
1031                .map(|var| VarUsageCached::new(*var, ctx))
1032                .collect(),
1033            arms: match_extern_info
1034                .arms
1035                .into_iter()
1036                .map(|arm| MatchArmCached::new(arm, ctx))
1037                .collect(),
1038            location: LocationIdCached::new(match_extern_info.location, ctx),
1039        }
1040    }
1041    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchExternInfo {
1042        MatchExternInfo {
1043            function: self.function.embed(ctx),
1044            inputs: self.inputs.into_iter().map(|var_id| var_id.embed(ctx)).collect(),
1045            arms: self.arms.into_iter().map(|arm| arm.embed(ctx)).collect(),
1046            location: self.location.embed(ctx),
1047        }
1048    }
1049}
1050
1051#[derive(Serialize, Deserialize)]
1052struct MatchEnumValueCached {
1053    num_of_arms: usize,
1054
1055    /// A living variable in current scope to match on.
1056    input: VarUsageCached,
1057    /// Match arms. All blocks should have the same rets.
1058    arms: Vec<MatchArmCached>,
1059    location: LocationIdCached,
1060}
1061
1062impl MatchEnumValueCached {
1063    fn new(match_enum_value: MatchEnumValue, ctx: &mut CacheSavingContext<'_>) -> Self {
1064        Self {
1065            num_of_arms: match_enum_value.num_of_arms,
1066            input: VarUsageCached::new(match_enum_value.input, ctx),
1067            arms: match_enum_value
1068                .arms
1069                .into_iter()
1070                .map(|arm| MatchArmCached::new(arm, ctx))
1071                .collect(),
1072            location: LocationIdCached::new(match_enum_value.location, ctx),
1073        }
1074    }
1075    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchEnumValue {
1076        MatchEnumValue {
1077            num_of_arms: self.num_of_arms,
1078            input: self.input.embed(ctx),
1079            arms: self.arms.into_iter().map(|arm| arm.embed(ctx)).collect(),
1080            location: self.location.embed(ctx),
1081        }
1082    }
1083}
1084/// An arm of a match statement.
1085#[derive(Serialize, Deserialize)]
1086struct MatchArmCached {
1087    /// The selector of the arm.
1088    arm_selector: MatchArmSelectorCached,
1089
1090    /// The block_id where the relevant arm is implemented.
1091    block_id: usize,
1092
1093    /// The list of variable ids introduced in this arm.
1094    var_ids: Vec<usize>,
1095}
1096
1097impl MatchArmCached {
1098    fn new(match_arm: MatchArm, ctx: &mut CacheSavingContext<'_>) -> Self {
1099        Self {
1100            arm_selector: MatchArmSelectorCached::new(
1101                match_arm.arm_selector,
1102                &mut ctx.semantic_ctx,
1103            ),
1104            block_id: match_arm.block_id.0,
1105            var_ids: match_arm.var_ids.iter().map(|var| var.index()).collect(),
1106        }
1107    }
1108    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchArm {
1109        MatchArm {
1110            arm_selector: self.arm_selector.embed(ctx),
1111            block_id: BlockId(self.block_id),
1112            var_ids: self
1113                .var_ids
1114                .into_iter()
1115                .map(|var_id| ctx.flat_lowered_variables_id[var_id])
1116                .collect(),
1117        }
1118    }
1119}
1120
1121#[derive(Serialize, Deserialize)]
1122enum MatchArmSelectorCached {
1123    VariantId(ConcreteVariantCached),
1124    Value(usize),
1125}
1126
1127impl MatchArmSelectorCached {
1128    fn new(match_arm_selector: MatchArmSelector, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1129        match match_arm_selector {
1130            MatchArmSelector::VariantId(variant_id) => {
1131                MatchArmSelectorCached::VariantId(ConcreteVariantCached::new(variant_id, ctx))
1132            }
1133            MatchArmSelector::Value(value) => MatchArmSelectorCached::Value(value.value),
1134        }
1135    }
1136    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> MatchArmSelector {
1137        match self {
1138            MatchArmSelectorCached::VariantId(variant_id) => {
1139                MatchArmSelector::VariantId(variant_id.embed(&mut ctx.semantic_ctx))
1140            }
1141            MatchArmSelectorCached::Value(value) => {
1142                MatchArmSelector::Value(ValueSelectorArm { value })
1143            }
1144        }
1145    }
1146}
1147
1148#[derive(Serialize, Deserialize)]
1149enum StatementCached {
1150    // Values.
1151    Const(StatementConstCached),
1152
1153    // Flow control.
1154    Call(StatementCallCached),
1155
1156    // Structs (including tuples).
1157    StructConstruct(StatementStructConstructCached),
1158    StructDestructure(StatementStructDestructureCached),
1159
1160    // Enums.
1161    EnumConstruct(StatementEnumConstructCached),
1162
1163    Snapshot(StatementSnapshotCached),
1164    Desnap(StatementDesnapCached),
1165}
1166
1167impl StatementCached {
1168    fn new(stmt: Statement, ctx: &mut CacheSavingContext<'_>) -> Self {
1169        match stmt {
1170            Statement::Const(stmt) => StatementCached::Const(StatementConstCached::new(stmt, ctx)),
1171            Statement::Call(stmt) => StatementCached::Call(StatementCallCached::new(stmt, ctx)),
1172            Statement::StructConstruct(stmt) => {
1173                StatementCached::StructConstruct(StatementStructConstructCached::new(stmt, ctx))
1174            }
1175            Statement::StructDestructure(stmt) => {
1176                StatementCached::StructDestructure(StatementStructDestructureCached::new(stmt, ctx))
1177            }
1178            Statement::EnumConstruct(stmt) => {
1179                StatementCached::EnumConstruct(StatementEnumConstructCached::new(stmt, ctx))
1180            }
1181            Statement::Snapshot(stmt) => {
1182                StatementCached::Snapshot(StatementSnapshotCached::new(stmt, ctx))
1183            }
1184            Statement::Desnap(stmt) => {
1185                StatementCached::Desnap(StatementDesnapCached::new(stmt, ctx))
1186            }
1187        }
1188    }
1189    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> Statement {
1190        match self {
1191            StatementCached::Const(stmt) => Statement::Const(stmt.embed(ctx)),
1192            StatementCached::Call(stmt) => Statement::Call(stmt.embed(ctx)),
1193            StatementCached::StructConstruct(stmt) => Statement::StructConstruct(stmt.embed(ctx)),
1194            StatementCached::StructDestructure(stmt) => {
1195                Statement::StructDestructure(stmt.embed(ctx))
1196            }
1197            StatementCached::EnumConstruct(stmt) => Statement::EnumConstruct(stmt.embed(ctx)),
1198            StatementCached::Snapshot(stmt) => Statement::Snapshot(stmt.embed(ctx)),
1199            StatementCached::Desnap(stmt) => Statement::Desnap(stmt.embed(ctx)),
1200        }
1201    }
1202}
1203
1204#[derive(Serialize, Deserialize)]
1205struct StatementConstCached {
1206    /// The value of the const.
1207    value: ConstValueCached,
1208    /// The variable to bind the value to.
1209    output: usize,
1210}
1211impl StatementConstCached {
1212    fn new(stmt: StatementConst, ctx: &mut CacheSavingContext<'_>) -> Self {
1213        Self {
1214            value: ConstValueCached::new(stmt.value, &mut ctx.semantic_ctx),
1215            output: stmt.output.index(),
1216        }
1217    }
1218    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementConst {
1219        StatementConst {
1220            value: self.value.embed(&mut ctx.semantic_ctx),
1221            output: ctx.flat_lowered_variables_id[self.output],
1222        }
1223    }
1224}
1225
1226#[derive(Serialize, Deserialize, Clone)]
1227enum ConstValueCached {
1228    Int(BigInt, TypeIdCached),
1229    Struct(Vec<ConstValueCached>, TypeIdCached),
1230    Enum(ConcreteVariantCached, Box<ConstValueCached>),
1231    NonZero(Box<ConstValueCached>),
1232    Boxed(Box<ConstValueCached>),
1233    Generic(GenericParamCached),
1234    ImplConstant(ImplConstantCached),
1235}
1236impl ConstValueCached {
1237    fn new(const_value_id: ConstValue, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1238        match const_value_id {
1239            ConstValue::Int(value, ty) => ConstValueCached::Int(value, TypeIdCached::new(ty, ctx)),
1240            ConstValue::Struct(values, ty) => ConstValueCached::Struct(
1241                values.into_iter().map(|v| ConstValueCached::new(v, ctx)).collect(),
1242                TypeIdCached::new(ty, ctx),
1243            ),
1244            ConstValue::Enum(variant, value) => ConstValueCached::Enum(
1245                ConcreteVariantCached::new(variant, ctx),
1246                Box::new(ConstValueCached::new(*value, ctx)),
1247            ),
1248            ConstValue::NonZero(value) => {
1249                ConstValueCached::NonZero(Box::new(ConstValueCached::new(*value, ctx)))
1250            }
1251            ConstValue::Boxed(value) => {
1252                ConstValueCached::Boxed(Box::new(ConstValueCached::new(*value, ctx)))
1253            }
1254            ConstValue::Generic(generic_param) => {
1255                ConstValueCached::Generic(GenericParamCached::new(generic_param, ctx))
1256            }
1257            ConstValue::ImplConstant(impl_constant_id) => {
1258                ConstValueCached::ImplConstant(ImplConstantCached::new(impl_constant_id, ctx))
1259            }
1260            ConstValue::Var(_, _) | ConstValue::Missing(_) => {
1261                unreachable!(
1262                    "Const {:#?} is not supported for caching",
1263                    const_value_id.debug(ctx.db.elongate())
1264                )
1265            }
1266        }
1267    }
1268    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ConstValue {
1269        match self {
1270            ConstValueCached::Int(value, ty) => ConstValue::Int(value, ty.embed(ctx)),
1271            ConstValueCached::Struct(values, ty) => ConstValue::Struct(
1272                values.into_iter().map(|v| v.embed(ctx)).collect(),
1273                ty.embed(ctx),
1274            ),
1275            ConstValueCached::Enum(variant, value) => {
1276                ConstValue::Enum(variant.embed(ctx), Box::new(value.embed(ctx)))
1277            }
1278            ConstValueCached::NonZero(value) => ConstValue::NonZero(Box::new(value.embed(ctx))),
1279            ConstValueCached::Boxed(value) => ConstValue::Boxed(Box::new(value.embed(ctx))),
1280            ConstValueCached::Generic(generic_param) => {
1281                ConstValue::Generic(generic_param.embed(ctx))
1282            }
1283            ConstValueCached::ImplConstant(impl_constant_id) => {
1284                ConstValue::ImplConstant(impl_constant_id.embed(ctx))
1285            }
1286        }
1287    }
1288}
1289
1290#[derive(Serialize, Deserialize, Clone)]
1291struct ImplConstantCached {
1292    impl_id: ImplIdCached,
1293    trait_constant: TraitConstantCached,
1294}
1295impl ImplConstantCached {
1296    fn new(impl_constant_id: ImplConstantId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1297        Self {
1298            impl_id: ImplIdCached::new(impl_constant_id.impl_id(), ctx),
1299            trait_constant: TraitConstantCached::new(impl_constant_id.trait_constant_id(), ctx),
1300        }
1301    }
1302    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplConstantId {
1303        ImplConstantId::new(self.impl_id.embed(ctx), self.trait_constant.embed(ctx), ctx.db)
1304    }
1305}
1306
1307#[derive(Serialize, Deserialize, Clone)]
1308struct TraitConstantCached {
1309    language_element: LanguageElementCached,
1310}
1311impl TraitConstantCached {
1312    fn new(trait_constant_id: TraitConstantId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1313        Self { language_element: LanguageElementCached::new(trait_constant_id, ctx) }
1314    }
1315    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> TraitConstantId {
1316        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1317        TraitConstantLongId(module_id, TraitItemConstantPtr(stable_ptr)).intern(ctx.db)
1318    }
1319}
1320
1321#[derive(Serialize, Deserialize)]
1322struct ConstStatementCached {
1323    /// Value of the constant.
1324    value: i32,
1325}
1326
1327#[derive(Serialize, Deserialize)]
1328struct StatementCallCached {
1329    /// A function to "call".
1330    function: FunctionIdCached,
1331    /// Living variables in current scope to move to the function, as arguments.
1332    inputs: Vec<VarUsageCached>,
1333    /// Is the last input a coupon for the function call. See
1334    /// [semantic::ExprFunctionCall::coupon_arg] for more information.
1335    with_coupon: bool,
1336    /// New variables to be introduced into the current scope from the function outputs.
1337    outputs: Vec<usize>,
1338    location: LocationIdCached,
1339}
1340impl StatementCallCached {
1341    fn new(stmt: StatementCall, ctx: &mut CacheSavingContext<'_>) -> Self {
1342        Self {
1343            function: FunctionIdCached::new(stmt.function, ctx),
1344            inputs: stmt.inputs.iter().map(|var| VarUsageCached::new(*var, ctx)).collect(),
1345            with_coupon: stmt.with_coupon,
1346            outputs: stmt.outputs.iter().map(|var| var.index()).collect(),
1347            location: LocationIdCached::new(stmt.location, ctx),
1348        }
1349    }
1350    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementCall {
1351        StatementCall {
1352            function: self.function.embed(ctx),
1353            inputs: self.inputs.into_iter().map(|var_id| var_id.embed(ctx)).collect(),
1354            with_coupon: self.with_coupon,
1355            outputs: self
1356                .outputs
1357                .into_iter()
1358                .map(|var_id| ctx.flat_lowered_variables_id[var_id])
1359                .collect(),
1360            location: self.location.embed(ctx),
1361        }
1362    }
1363}
1364
1365#[derive(Serialize, Deserialize, Clone)]
1366enum FunctionCached {
1367    /// An original function from the user code.
1368    Semantic(SemanticFunctionIdCached),
1369    /// A function generated by the compiler.
1370    Generated(GeneratedFunctionCached),
1371}
1372impl FunctionCached {
1373    fn new(function: FunctionLongId, ctx: &mut CacheSavingContext<'_>) -> Self {
1374        match function {
1375            FunctionLongId::Semantic(id) => {
1376                FunctionCached::Semantic(SemanticFunctionIdCached::new(id, &mut ctx.semantic_ctx))
1377            }
1378            FunctionLongId::Generated(id) => {
1379                FunctionCached::Generated(GeneratedFunctionCached::new(id, ctx))
1380            }
1381        }
1382    }
1383    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> FunctionId {
1384        match self {
1385            FunctionCached::Semantic(id) => {
1386                FunctionLongId::Semantic(id.embed(&mut ctx.semantic_ctx))
1387            }
1388            FunctionCached::Generated(id) => FunctionLongId::Generated(id.embed(ctx)),
1389        }
1390        .intern(ctx.db)
1391    }
1392}
1393
1394#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
1395struct FunctionIdCached(usize);
1396impl FunctionIdCached {
1397    fn new(function_id: FunctionId, ctx: &mut CacheSavingContext<'_>) -> Self {
1398        if let Some(id) = ctx.function_ids.get(&function_id) {
1399            return *id;
1400        }
1401        let function = FunctionCached::new(function_id.lookup_intern(ctx.db), ctx);
1402        let id = FunctionIdCached(ctx.function_ids_lookup.len());
1403        ctx.function_ids_lookup.push(function);
1404        ctx.function_ids.insert(function_id, id);
1405        id
1406    }
1407    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> FunctionId {
1408        if let Some(function_id) = ctx.function_ids.get(&self) {
1409            return *function_id;
1410        }
1411
1412        let function = ctx.function_ids_lookup[self.0].clone();
1413        let function_id = function.embed(ctx);
1414        ctx.function_ids.insert(self, function_id);
1415        function_id
1416    }
1417}
1418
1419#[derive(Serialize, Deserialize, Clone)]
1420struct SemanticFunctionCached {
1421    generic_function: GenericFunctionCached,
1422
1423    generic_args: Vec<GenericArgumentCached>,
1424}
1425impl SemanticFunctionCached {
1426    fn new(
1427        function_id: semantic::FunctionLongId,
1428        ctx: &mut SemanticCacheSavingContext<'_>,
1429    ) -> Self {
1430        let function = function_id.function;
1431        Self {
1432            generic_function: GenericFunctionCached::new(function.generic_function, ctx),
1433            generic_args: function
1434                .generic_args
1435                .into_iter()
1436                .map(|arg| GenericArgumentCached::new(arg, ctx))
1437                .collect(),
1438        }
1439    }
1440    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::FunctionLongId {
1441        semantic::FunctionLongId {
1442            function: ConcreteFunction {
1443                generic_function: self.generic_function.embed(ctx),
1444                generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
1445            },
1446        }
1447    }
1448}
1449#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
1450struct SemanticFunctionIdCached(usize);
1451impl SemanticFunctionIdCached {
1452    fn new(function_id: semantic::FunctionId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1453        if let Some(id) = ctx.function_ids.get(&function_id) {
1454            return *id;
1455        }
1456        let function = SemanticFunctionCached::new(function_id.lookup_intern(ctx.db), ctx);
1457        let id = SemanticFunctionIdCached(ctx.function_ids_lookup.len());
1458        ctx.function_ids_lookup.push(function);
1459        ctx.function_ids.insert(function_id, id);
1460        id
1461    }
1462    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::FunctionId {
1463        if let Some(function_id) = ctx.function_ids.get(&self) {
1464            return *function_id;
1465        }
1466
1467        let function = ctx.function_ids_lookup[self.0].clone();
1468        let function_id = function.embed(ctx).intern(ctx.db);
1469        ctx.function_ids.insert(self, function_id);
1470        function_id
1471    }
1472}
1473
1474#[derive(Serialize, Deserialize, Clone)]
1475enum GenericFunctionCached {
1476    /// A generic free function.
1477    Free(LanguageElementCached),
1478    /// A generic extern function.
1479    Extern(LanguageElementCached),
1480    /// A generic function of an impl.
1481    Impl(ImplIdCached, LanguageElementCached),
1482}
1483impl GenericFunctionCached {
1484    fn new(generic_function: GenericFunctionId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1485        match generic_function {
1486            GenericFunctionId::Free(id) => {
1487                GenericFunctionCached::Free(LanguageElementCached::new(id, ctx))
1488            }
1489            GenericFunctionId::Extern(id) => {
1490                GenericFunctionCached::Extern(LanguageElementCached::new(id, ctx))
1491            }
1492            GenericFunctionId::Impl(id) => GenericFunctionCached::Impl(
1493                ImplIdCached::new(id.impl_id, ctx),
1494                LanguageElementCached::new(id.function, ctx),
1495            ),
1496        }
1497    }
1498    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GenericFunctionId {
1499        match self {
1500            GenericFunctionCached::Free(id) => {
1501                let (module_id, stable_ptr) = id.embed(ctx);
1502                let id =
1503                    FreeFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr)).intern(ctx.db);
1504                GenericFunctionId::Free(id)
1505            }
1506            GenericFunctionCached::Extern(id) => {
1507                let (module_id, stable_ptr) = id.embed(ctx);
1508                let id = ExternFunctionLongId(module_id, ItemExternFunctionPtr(stable_ptr))
1509                    .intern(ctx.db);
1510                GenericFunctionId::Extern(id)
1511            }
1512            GenericFunctionCached::Impl(id, name) => {
1513                let impl_id = id.embed(ctx);
1514                let (module_file_id, stable_ptr) = name.embed(ctx);
1515                let trait_function_id =
1516                    TraitFunctionLongId(module_file_id, TraitItemFunctionPtr(stable_ptr))
1517                        .intern(ctx.db);
1518
1519                GenericFunctionId::Impl(ImplGenericFunctionId {
1520                    impl_id,
1521                    function: trait_function_id,
1522                })
1523            }
1524        }
1525    }
1526}
1527
1528#[derive(Serialize, Deserialize, Clone)]
1529struct GeneratedFunctionCached {
1530    parent: SemanticConcreteFunctionWithBodyCached,
1531    key: GeneratedFunctionKeyCached,
1532}
1533impl GeneratedFunctionCached {
1534    fn new(function: GeneratedFunction, ctx: &mut CacheSavingContext<'_>) -> Self {
1535        Self {
1536            parent: SemanticConcreteFunctionWithBodyCached::new(
1537                function.parent,
1538                &mut ctx.semantic_ctx,
1539            ),
1540            key: GeneratedFunctionKeyCached::new(function.key, ctx),
1541        }
1542    }
1543    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> GeneratedFunction {
1544        GeneratedFunction {
1545            parent: self.parent.embed(&mut ctx.semantic_ctx),
1546            key: self.key.embed(ctx),
1547        }
1548    }
1549}
1550#[derive(Serialize, Deserialize, Clone)]
1551struct SemanticConcreteFunctionWithBodyCached {
1552    generic_function: GenericFunctionWithBodyCached,
1553    generic_args: Vec<GenericArgumentCached>,
1554}
1555impl SemanticConcreteFunctionWithBodyCached {
1556    fn new(
1557        function_id: semantic::ConcreteFunctionWithBodyId,
1558        ctx: &mut SemanticCacheSavingContext<'_>,
1559    ) -> Self {
1560        Self {
1561            generic_function: GenericFunctionWithBodyCached::new(
1562                function_id.generic_function(ctx.db),
1563                ctx,
1564            ),
1565            generic_args: function_id
1566                .lookup_intern(ctx.db)
1567                .generic_args
1568                .into_iter()
1569                .map(|arg| GenericArgumentCached::new(arg, ctx))
1570                .collect(),
1571        }
1572    }
1573    fn embed(
1574        self,
1575        ctx: &mut SemanticCacheLoadingContext<'_>,
1576    ) -> semantic::ConcreteFunctionWithBodyId {
1577        let generic_function = self.generic_function.embed(ctx);
1578        let generic_args = self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect();
1579        ConcreteFunctionWithBody { generic_function, generic_args }.intern(ctx.db)
1580    }
1581}
1582
1583#[derive(Serialize, Deserialize, Clone)]
1584enum GenericFunctionWithBodyCached {
1585    Free(LanguageElementCached),
1586    Impl(ConcreteImplCached, ImplFunctionBodyCached),
1587}
1588
1589impl GenericFunctionWithBodyCached {
1590    fn new(
1591        generic_function: GenericFunctionWithBodyId,
1592        ctx: &mut SemanticCacheSavingContext<'_>,
1593    ) -> Self {
1594        match generic_function {
1595            GenericFunctionWithBodyId::Free(id) => {
1596                GenericFunctionWithBodyCached::Free(LanguageElementCached::new(id, ctx))
1597            }
1598            GenericFunctionWithBodyId::Impl(id) => GenericFunctionWithBodyCached::Impl(
1599                ConcreteImplCached::new(id.concrete_impl_id, ctx),
1600                ImplFunctionBodyCached::new(id.function_body, ctx),
1601            ),
1602            GenericFunctionWithBodyId::Trait(_id) => {
1603                unreachable!("Trait functions are not supported in serialization")
1604            }
1605        }
1606    }
1607    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GenericFunctionWithBodyId {
1608        match self {
1609            GenericFunctionWithBodyCached::Free(id) => {
1610                let (module_id, stable_ptr) = id.embed(ctx);
1611                let id =
1612                    FreeFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr)).intern(ctx.db);
1613                GenericFunctionWithBodyId::Free(id)
1614            }
1615            GenericFunctionWithBodyCached::Impl(id, function_body) => {
1616                // todo handle trait functions
1617                GenericFunctionWithBodyId::Impl(ImplGenericFunctionWithBodyId {
1618                    concrete_impl_id: id.embed(ctx),
1619                    function_body: function_body.embed(ctx),
1620                })
1621            }
1622        }
1623    }
1624}
1625
1626#[derive(Serialize, Deserialize, Clone)]
1627enum ImplFunctionBodyCached {
1628    /// A function that was implemented in the impl.
1629    Impl(LanguageElementCached),
1630    /// The default implementation of a trait function in the trait.
1631    Trait(LanguageElementCached),
1632}
1633impl ImplFunctionBodyCached {
1634    fn new(function_body: ImplFunctionBodyId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1635        match function_body {
1636            ImplFunctionBodyId::Impl(id) => {
1637                ImplFunctionBodyCached::Impl(LanguageElementCached::new(id, ctx))
1638            }
1639            ImplFunctionBodyId::Trait(id) => {
1640                ImplFunctionBodyCached::Trait(LanguageElementCached::new(id, ctx))
1641            }
1642        }
1643    }
1644    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplFunctionBodyId {
1645        match self {
1646            ImplFunctionBodyCached::Impl(id) => {
1647                let (module_file_id, stable_ptr) = id.embed(ctx);
1648                ImplFunctionBodyId::Impl(
1649                    ImplFunctionLongId(module_file_id, FunctionWithBodyPtr(stable_ptr))
1650                        .intern(ctx.db),
1651                )
1652            }
1653            ImplFunctionBodyCached::Trait(id) => {
1654                let (module_file_id, stable_ptr) = id.embed(ctx);
1655                ImplFunctionBodyId::Trait(
1656                    TraitFunctionLongId(module_file_id, TraitItemFunctionPtr(stable_ptr))
1657                        .intern(ctx.db),
1658                )
1659            }
1660        }
1661    }
1662}
1663
1664#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
1665enum GeneratedFunctionKeyCached {
1666    Loop(SyntaxStablePtrIdCached),
1667    TraitFunc(LanguageElementCached, SyntaxStablePtrIdCached),
1668}
1669
1670impl GeneratedFunctionKeyCached {
1671    fn new(key: GeneratedFunctionKey, ctx: &mut CacheSavingContext<'_>) -> Self {
1672        match key {
1673            GeneratedFunctionKey::Loop(id) => GeneratedFunctionKeyCached::Loop(
1674                SyntaxStablePtrIdCached::new(id.untyped(), &mut ctx.semantic_ctx),
1675            ),
1676            GeneratedFunctionKey::TraitFunc(id, stable_location) => {
1677                GeneratedFunctionKeyCached::TraitFunc(
1678                    LanguageElementCached::new(id, &mut ctx.semantic_ctx),
1679                    SyntaxStablePtrIdCached::new(
1680                        stable_location.stable_ptr(),
1681                        &mut ctx.semantic_ctx,
1682                    ),
1683                )
1684            }
1685        }
1686    }
1687    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> GeneratedFunctionKey {
1688        match self {
1689            GeneratedFunctionKeyCached::Loop(id) => {
1690                GeneratedFunctionKey::Loop(ExprPtr(id.embed(&mut ctx.semantic_ctx)))
1691            }
1692            GeneratedFunctionKeyCached::TraitFunc(id, stable_location) => {
1693                let (module_file_id, stable_ptr) = id.embed(&mut ctx.semantic_ctx);
1694                GeneratedFunctionKey::TraitFunc(
1695                    TraitFunctionLongId(module_file_id, TraitItemFunctionPtr(stable_ptr))
1696                        .intern(ctx.db),
1697                    StableLocation::new(stable_location.embed(&mut ctx.semantic_ctx)),
1698                )
1699            }
1700        }
1701    }
1702}
1703
1704#[derive(Serialize, Deserialize)]
1705struct StatementStructConstructCached {
1706    inputs: Vec<VarUsageCached>,
1707    /// The variable to bind the value to.
1708    output: usize,
1709}
1710impl StatementStructConstructCached {
1711    fn new(stmt: StatementStructConstruct, _ctx: &mut CacheSavingContext<'_>) -> Self {
1712        Self {
1713            inputs: stmt.inputs.iter().map(|var| VarUsageCached::new(*var, _ctx)).collect(),
1714            output: stmt.output.index(),
1715        }
1716    }
1717    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementStructConstruct {
1718        StatementStructConstruct {
1719            inputs: self.inputs.into_iter().map(|var_id| var_id.embed(ctx)).collect(),
1720            output: ctx.flat_lowered_variables_id[self.output],
1721        }
1722    }
1723}
1724#[derive(Serialize, Deserialize)]
1725struct StatementStructDestructureCached {
1726    /// A living variable in current scope to destructure.
1727    input: VarUsageCached,
1728    /// The variables to bind values to.
1729    outputs: Vec<usize>,
1730}
1731impl StatementStructDestructureCached {
1732    fn new(stmt: StatementStructDestructure, _ctx: &mut CacheSavingContext<'_>) -> Self {
1733        Self {
1734            input: VarUsageCached::new(stmt.input, _ctx),
1735            outputs: stmt.outputs.iter().map(|var| var.index()).collect(),
1736        }
1737    }
1738    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementStructDestructure {
1739        StatementStructDestructure {
1740            input: self.input.embed(ctx),
1741            outputs: self
1742                .outputs
1743                .into_iter()
1744                .map(|var_id| ctx.flat_lowered_variables_id[var_id])
1745                .collect(),
1746        }
1747    }
1748}
1749
1750#[derive(Serialize, Deserialize)]
1751struct StatementEnumConstructCached {
1752    variant: ConcreteVariantCached,
1753    /// A living variable in current scope to wrap with the variant.
1754    input: VarUsageCached,
1755    /// The variable to bind the value to.
1756    output: usize,
1757}
1758impl StatementEnumConstructCached {
1759    fn new(stmt: StatementEnumConstruct, ctx: &mut CacheSavingContext<'_>) -> Self {
1760        Self {
1761            variant: ConcreteVariantCached::new(stmt.variant, &mut ctx.semantic_ctx),
1762            input: VarUsageCached::new(stmt.input, ctx),
1763            output: stmt.output.index(),
1764        }
1765    }
1766    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementEnumConstruct {
1767        StatementEnumConstruct {
1768            variant: self.variant.embed(&mut ctx.semantic_ctx),
1769            input: self.input.embed(ctx),
1770            output: ctx.flat_lowered_variables_id[self.output],
1771        }
1772    }
1773}
1774
1775#[derive(Serialize, Deserialize)]
1776struct StatementSnapshotCached {
1777    input: VarUsageCached,
1778    outputs: [usize; 2],
1779}
1780impl StatementSnapshotCached {
1781    fn new(stmt: StatementSnapshot, _ctx: &mut CacheSavingContext<'_>) -> Self {
1782        Self {
1783            input: VarUsageCached::new(stmt.input, _ctx),
1784            outputs: stmt.outputs.map(|var| var.index()),
1785        }
1786    }
1787    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementSnapshot {
1788        StatementSnapshot {
1789            input: self.input.embed(ctx),
1790            outputs: [
1791                ctx.flat_lowered_variables_id[self.outputs[0]],
1792                ctx.flat_lowered_variables_id[self.outputs[1]],
1793            ],
1794        }
1795    }
1796}
1797
1798#[derive(Serialize, Deserialize)]
1799struct StatementDesnapCached {
1800    input: VarUsageCached,
1801    /// The variable to bind the value to.
1802    output: usize,
1803}
1804impl StatementDesnapCached {
1805    fn new(stmt: StatementDesnap, ctx: &mut CacheSavingContext<'_>) -> Self {
1806        Self { input: VarUsageCached::new(stmt.input, ctx), output: stmt.output.index() }
1807    }
1808    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> StatementDesnap {
1809        StatementDesnap {
1810            input: self.input.embed(ctx),
1811            output: ctx.flat_lowered_variables_id[self.output],
1812        }
1813    }
1814}
1815
1816#[derive(Serialize, Deserialize, Clone)]
1817enum GenericArgumentCached {
1818    Type(TypeIdCached),
1819    Value(ConstValueCached),
1820    Impl(ImplIdCached),
1821    NegImpl,
1822}
1823
1824impl GenericArgumentCached {
1825    fn new(
1826        generic_argument_id: semantic::GenericArgumentId,
1827        ctx: &mut SemanticCacheSavingContext<'_>,
1828    ) -> Self {
1829        match generic_argument_id {
1830            semantic::GenericArgumentId::Type(type_id) => {
1831                GenericArgumentCached::Type(TypeIdCached::new(type_id, ctx))
1832            }
1833            semantic::GenericArgumentId::Constant(const_value_id) => {
1834                GenericArgumentCached::Value(ConstValueCached::new(
1835                    const_value_id.lookup_intern(ctx.db), // todo intern
1836                    ctx,
1837                ))
1838            }
1839            semantic::GenericArgumentId::Impl(impl_id) => {
1840                GenericArgumentCached::Impl(ImplIdCached::new(impl_id, ctx))
1841            }
1842            semantic::GenericArgumentId::NegImpl => GenericArgumentCached::NegImpl,
1843        }
1844    }
1845    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::GenericArgumentId {
1846        match self {
1847            GenericArgumentCached::Type(ty) => semantic::GenericArgumentId::Type(ty.embed(ctx)),
1848            GenericArgumentCached::Value(value) => {
1849                semantic::GenericArgumentId::Constant(value.embed(ctx).intern(ctx.db))
1850            }
1851            GenericArgumentCached::Impl(imp) => semantic::GenericArgumentId::Impl(imp.embed(ctx)),
1852            GenericArgumentCached::NegImpl => semantic::GenericArgumentId::NegImpl,
1853        }
1854    }
1855}
1856
1857#[derive(Serialize, Deserialize, Clone)]
1858enum TypeCached {
1859    Concrete(ConcreteTypeCached),
1860    /// Some expressions might have invalid types during processing, either due to errors or
1861    /// during inference.
1862    Tuple(Vec<TypeIdCached>),
1863    Snapshot(Box<TypeIdCached>),
1864    GenericParameter(GenericParamCached),
1865    ImplType(ImplTypeCached),
1866    FixedSizeArray(TypeIdCached, ConstValueCached),
1867}
1868
1869impl TypeCached {
1870    fn new(type_id: TypeLongId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1871        match type_id {
1872            semantic::TypeLongId::Concrete(concrete_type_id) => {
1873                TypeCached::Concrete(ConcreteTypeCached::new(concrete_type_id, ctx))
1874            }
1875            semantic::TypeLongId::Tuple(vec) => {
1876                TypeCached::Tuple(vec.into_iter().map(|ty| TypeIdCached::new(ty, ctx)).collect())
1877            }
1878            semantic::TypeLongId::Snapshot(type_id) => {
1879                TypeCached::Snapshot(Box::new(TypeIdCached::new(type_id, ctx)))
1880            }
1881            semantic::TypeLongId::GenericParameter(generic_param_id) => {
1882                TypeCached::GenericParameter(GenericParamCached::new(generic_param_id, ctx))
1883            }
1884            semantic::TypeLongId::ImplType(impl_type_id) => {
1885                TypeCached::ImplType(ImplTypeCached::new(impl_type_id, ctx))
1886            }
1887            semantic::TypeLongId::FixedSizeArray { type_id, size } => TypeCached::FixedSizeArray(
1888                TypeIdCached::new(type_id, ctx),
1889                ConstValueCached::new(size.lookup_intern(ctx.db), ctx),
1890            ),
1891            TypeLongId::Var(_)
1892            | TypeLongId::Closure(_)
1893            | TypeLongId::Missing(_)
1894            | TypeLongId::Coupon(_) => {
1895                unreachable!(
1896                    "type {:?} is not supported for caching",
1897                    type_id.debug(ctx.db.elongate())
1898                )
1899            }
1900        }
1901    }
1902    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> TypeLongId {
1903        match self {
1904            TypeCached::Concrete(concrete_type) => TypeLongId::Concrete(concrete_type.embed(ctx)),
1905            TypeCached::Tuple(vec) => {
1906                TypeLongId::Tuple(vec.into_iter().map(|ty| ty.embed(ctx)).collect())
1907            }
1908            TypeCached::Snapshot(type_id) => TypeLongId::Snapshot(type_id.embed(ctx)),
1909            TypeCached::GenericParameter(generic_param) => {
1910                TypeLongId::GenericParameter(generic_param.embed(ctx))
1911            }
1912            TypeCached::ImplType(impl_type) => TypeLongId::ImplType(impl_type.embed(ctx)),
1913            TypeCached::FixedSizeArray(type_id, size) => TypeLongId::FixedSizeArray {
1914                type_id: type_id.embed(ctx),
1915                size: size.embed(ctx).intern(ctx.db),
1916            },
1917        }
1918    }
1919}
1920
1921#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
1922struct TypeIdCached(usize);
1923
1924impl TypeIdCached {
1925    fn new(ty: TypeId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1926        if let Some(id) = ctx.type_ids.get(&ty) {
1927            return *id;
1928        }
1929        let ty_long = TypeCached::new(ty.lookup_intern(ctx.db), ctx);
1930        let id = TypeIdCached(ctx.type_ids_lookup.len());
1931        ctx.type_ids_lookup.push(ty_long);
1932        ctx.type_ids.insert(ty, id);
1933        id
1934    }
1935    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> TypeId {
1936        if let Some(type_id) = ctx.type_ids.get(&self) {
1937            return *type_id;
1938        }
1939
1940        let ty = ctx.type_ids_lookup[self.0].clone();
1941        let ty = ty.embed(ctx).intern(ctx.db);
1942        ctx.type_ids.insert(self, ty);
1943        ty
1944    }
1945}
1946
1947#[derive(Serialize, Deserialize, Clone)]
1948enum ConcreteTypeCached {
1949    Struct(ConcreteStructCached),
1950    Enum(ConcreteEnumCached),
1951    Extern(ConcreteExternTypeCached),
1952}
1953
1954impl ConcreteTypeCached {
1955    fn new(
1956        concrete_type_id: semantic::ConcreteTypeId,
1957        ctx: &mut SemanticCacheSavingContext<'_>,
1958    ) -> Self {
1959        match concrete_type_id {
1960            semantic::ConcreteTypeId::Struct(id) => {
1961                ConcreteTypeCached::Struct(ConcreteStructCached::new(id, ctx))
1962            }
1963            semantic::ConcreteTypeId::Enum(id) => {
1964                ConcreteTypeCached::Enum(ConcreteEnumCached::new(id, ctx))
1965            }
1966            semantic::ConcreteTypeId::Extern(id) => {
1967                ConcreteTypeCached::Extern(ConcreteExternTypeCached::new(id, ctx))
1968            }
1969        }
1970    }
1971    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteTypeId {
1972        match self {
1973            ConcreteTypeCached::Struct(s) => semantic::ConcreteTypeId::Struct(s.embed(ctx)),
1974            ConcreteTypeCached::Enum(e) => semantic::ConcreteTypeId::Enum(e.embed(ctx)),
1975            ConcreteTypeCached::Extern(e) => semantic::ConcreteTypeId::Extern(e.embed(ctx)),
1976        }
1977    }
1978}
1979
1980#[derive(Serialize, Deserialize, Clone)]
1981struct ImplTypeCached {
1982    impl_id: ImplIdCached,
1983    trait_type: TraitTypeCached,
1984}
1985impl ImplTypeCached {
1986    fn new(impl_type_id: ImplTypeId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
1987        Self {
1988            impl_id: ImplIdCached::new(impl_type_id.impl_id(), ctx),
1989            trait_type: TraitTypeCached::new(impl_type_id.ty(), ctx),
1990        }
1991    }
1992    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplTypeId {
1993        let impl_id = self.impl_id.embed(ctx);
1994        let ty = self.trait_type.embed(ctx);
1995        ImplTypeId::new(impl_id, ty, ctx.db)
1996    }
1997}
1998
1999#[derive(Serialize, Deserialize, Clone)]
2000struct TraitTypeCached {
2001    language_element: LanguageElementCached,
2002}
2003impl TraitTypeCached {
2004    fn new(trait_type_id: TraitTypeId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2005        Self { language_element: LanguageElementCached::new(trait_type_id, ctx) }
2006    }
2007    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> TraitTypeId {
2008        let (module_file_id, stable_ptr) = self.language_element.embed(ctx);
2009        TraitTypeLongId(module_file_id, TraitItemTypePtr(stable_ptr)).intern(ctx.db)
2010    }
2011}
2012
2013#[derive(Serialize, Deserialize, Clone)]
2014enum ImplCached {
2015    Concrete(ConcreteImplCached),
2016    GenericParameter(GenericParamCached),
2017}
2018impl ImplCached {
2019    fn new(impl_id: ImplLongId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2020        match impl_id {
2021            ImplLongId::Concrete(concrete_impl) => {
2022                ImplCached::Concrete(ConcreteImplCached::new(concrete_impl, ctx))
2023            }
2024            ImplLongId::GenericParameter(generic_param_id) => {
2025                ImplCached::GenericParameter(GenericParamCached::new(generic_param_id, ctx))
2026            }
2027            ImplLongId::ImplVar(_)
2028            | ImplLongId::ImplImpl(_)
2029            | ImplLongId::SelfImpl(_)
2030            | ImplLongId::GeneratedImpl(_) => {
2031                unreachable!(
2032                    "impl {:?} is not supported for caching",
2033                    impl_id.debug(ctx.db.elongate())
2034                )
2035            }
2036        }
2037    }
2038    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplLongId {
2039        match self {
2040            ImplCached::Concrete(concrete_impl) => ImplLongId::Concrete(concrete_impl.embed(ctx)),
2041            ImplCached::GenericParameter(generic_param) => {
2042                ImplLongId::GenericParameter(generic_param.embed(ctx))
2043            }
2044        }
2045    }
2046}
2047#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
2048struct ImplIdCached(usize);
2049
2050impl ImplIdCached {
2051    fn new(impl_id: ImplId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2052        if let Some(id) = ctx.impl_ids.get(&impl_id) {
2053            return *id;
2054        }
2055        let imp = ImplCached::new(impl_id.lookup_intern(ctx.db), ctx);
2056        let id = ImplIdCached(ctx.impl_ids_lookup.len());
2057        ctx.impl_ids_lookup.push(imp);
2058        ctx.impl_ids.insert(impl_id, id);
2059        id
2060    }
2061    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplId {
2062        if let Some(impl_id) = ctx.impl_ids.get(&self) {
2063            return *impl_id;
2064        }
2065
2066        let imp = ctx.impl_ids_lookup[self.0].clone();
2067        let imp = imp.embed(ctx).intern(ctx.db);
2068        ctx.impl_ids.insert(self, imp);
2069        imp
2070    }
2071}
2072
2073#[derive(Serialize, Deserialize, Clone)]
2074struct ConcreteImplCached {
2075    impl_def_id: ImplDefIdCached,
2076    generic_args: Vec<GenericArgumentCached>,
2077}
2078impl ConcreteImplCached {
2079    fn new(
2080        concrete_impl: semantic::ConcreteImplId,
2081        ctx: &mut SemanticCacheSavingContext<'_>,
2082    ) -> Self {
2083        let long_id = concrete_impl.lookup_intern(ctx.db);
2084        Self {
2085            impl_def_id: ImplDefIdCached::new(long_id.impl_def_id, ctx),
2086            generic_args: long_id
2087                .generic_args
2088                .into_iter()
2089                .map(|arg| GenericArgumentCached::new(arg, ctx))
2090                .collect(),
2091        }
2092    }
2093    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteImplId {
2094        let impl_def_id = self.impl_def_id.embed(ctx);
2095        let long_id = ConcreteImplLongId {
2096            impl_def_id,
2097            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
2098        };
2099        long_id.intern(ctx.db)
2100    }
2101}
2102
2103#[derive(Serialize, Deserialize, Clone)]
2104struct ImplDefIdCached {
2105    language_element: LanguageElementCached,
2106}
2107impl ImplDefIdCached {
2108    fn new(impl_def_id: ImplDefId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2109        Self { language_element: LanguageElementCached::new(impl_def_id, ctx) }
2110    }
2111    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ImplDefId {
2112        let (module_file_id, stable_ptr) = self.language_element.embed(ctx);
2113        ImplDefLongId(module_file_id, ItemImplPtr(stable_ptr)).intern(ctx.db)
2114    }
2115}
2116
2117#[derive(Serialize, Deserialize, Clone)]
2118struct GenericParamCached {
2119    language_element: LanguageElementCached,
2120}
2121impl GenericParamCached {
2122    fn new(generic_param_id: GenericParamId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2123        Self { language_element: LanguageElementCached::new(generic_param_id, ctx) }
2124    }
2125    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GenericParamId {
2126        let (module_file_id, stable_ptr) = self.language_element.embed(ctx);
2127        GenericParamLongId(module_file_id, GenericParamPtr(stable_ptr)).intern(ctx.db)
2128    }
2129}
2130
2131#[derive(Serialize, Deserialize, Clone)]
2132struct ConcreteVariantCached {
2133    concrete_enum_id: ConcreteEnumCached,
2134    id: LanguageElementCached,
2135    ty: TypeIdCached,
2136    /// The index of the variant from within the variant list.
2137    idx: usize,
2138}
2139impl ConcreteVariantCached {
2140    fn new(
2141        concrete_variant: semantic::ConcreteVariant,
2142        ctx: &mut SemanticCacheSavingContext<'_>,
2143    ) -> Self {
2144        Self {
2145            concrete_enum_id: ConcreteEnumCached::new(concrete_variant.concrete_enum_id, ctx),
2146            id: LanguageElementCached::new(concrete_variant.id, ctx),
2147            ty: TypeIdCached::new(concrete_variant.ty, ctx),
2148            idx: concrete_variant.idx,
2149        }
2150    }
2151    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteVariant {
2152        let concrete_enum_id = self.concrete_enum_id.embed(ctx);
2153        let ty = self.ty.embed(ctx);
2154        let (module_file_id, stable_ptr) = self.id.embed(ctx);
2155
2156        let id = VariantLongId(module_file_id, VariantPtr(stable_ptr)).intern(ctx.db);
2157        semantic::ConcreteVariant { concrete_enum_id, id, ty, idx: self.idx }
2158    }
2159}
2160
2161#[derive(Serialize, Deserialize, Clone)]
2162struct ConcreteEnumCached {
2163    enum_id: LanguageElementCached,
2164    generic_args: Vec<GenericArgumentCached>,
2165}
2166
2167impl ConcreteEnumCached {
2168    fn new(
2169        concrete_enum: semantic::ConcreteEnumId,
2170        ctx: &mut SemanticCacheSavingContext<'_>,
2171    ) -> Self {
2172        let long_id = concrete_enum.lookup_intern(ctx.db);
2173        Self {
2174            enum_id: LanguageElementCached::new(long_id.enum_id, ctx),
2175            generic_args: long_id
2176                .generic_args
2177                .into_iter()
2178                .map(|arg| GenericArgumentCached::new(arg, ctx))
2179                .collect(),
2180        }
2181    }
2182    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteEnumId {
2183        let (module_file_id, stable_ptr) = self.enum_id.embed(ctx);
2184
2185        let long_id = ConcreteEnumLongId {
2186            enum_id: EnumLongId(module_file_id, ItemEnumPtr(stable_ptr)).intern(ctx.db),
2187            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
2188        };
2189        long_id.intern(ctx.db)
2190    }
2191}
2192
2193#[derive(Serialize, Deserialize, Clone)]
2194struct ConcreteStructCached {
2195    struct_id: LanguageElementCached,
2196    generic_args: Vec<GenericArgumentCached>,
2197}
2198impl ConcreteStructCached {
2199    fn new(
2200        concrete_struct: semantic::ConcreteStructId,
2201        ctx: &mut SemanticCacheSavingContext<'_>,
2202    ) -> Self {
2203        let long_id = concrete_struct.lookup_intern(ctx.db);
2204        Self {
2205            struct_id: LanguageElementCached::new(long_id.struct_id, ctx),
2206            generic_args: long_id
2207                .generic_args
2208                .into_iter()
2209                .map(|arg| GenericArgumentCached::new(arg, ctx))
2210                .collect(),
2211        }
2212    }
2213    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteStructId {
2214        let (module_file_id, stable_ptr) = self.struct_id.embed(ctx);
2215
2216        let long_id = ConcreteStructLongId {
2217            struct_id: StructLongId(module_file_id, ItemStructPtr(stable_ptr)).intern(ctx.db),
2218            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
2219        };
2220        long_id.intern(ctx.db)
2221    }
2222}
2223
2224#[derive(Serialize, Deserialize, Clone)]
2225struct ConcreteExternTypeCached {
2226    language_element: LanguageElementCached,
2227    generic_args: Vec<GenericArgumentCached>,
2228}
2229impl ConcreteExternTypeCached {
2230    fn new(
2231        concrete_extern_type: semantic::ConcreteExternTypeId,
2232        ctx: &mut SemanticCacheSavingContext<'_>,
2233    ) -> Self {
2234        let long_id = concrete_extern_type.lookup_intern(ctx.db);
2235        Self {
2236            language_element: LanguageElementCached::new(long_id.extern_type_id, ctx),
2237            generic_args: long_id
2238                .generic_args
2239                .into_iter()
2240                .map(|arg| GenericArgumentCached::new(arg, ctx))
2241                .collect(),
2242        }
2243    }
2244    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> semantic::ConcreteExternTypeId {
2245        let (module_file_id, stable_ptr) = self.language_element.embed(ctx);
2246
2247        let long_id = ConcreteExternTypeLongId {
2248            extern_type_id: ExternTypeLongId(module_file_id, ItemExternTypePtr(stable_ptr))
2249                .intern(ctx.db),
2250            generic_args: self.generic_args.into_iter().map(|arg| arg.embed(ctx)).collect(),
2251        };
2252        long_id.intern(ctx.db)
2253    }
2254}
2255
2256#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
2257struct ModuleFileCached {
2258    module: ModuleIdCached,
2259    file_index: usize,
2260}
2261impl ModuleFileCached {
2262    fn new(module_file_id: ModuleFileId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2263        Self { module: ModuleIdCached::new(module_file_id.0, ctx), file_index: module_file_id.1.0 }
2264    }
2265    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ModuleFileId {
2266        ModuleFileId(self.module.embed(ctx), FileIndex(self.file_index))
2267    }
2268}
2269
2270#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
2271enum ModuleIdCached {
2272    CrateRoot(CrateIdCached),
2273    Submodule(SubmoduleIdCached),
2274}
2275impl ModuleIdCached {
2276    fn new(module_id: ModuleId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2277        match module_id {
2278            ModuleId::CrateRoot(crate_id) => {
2279                ModuleIdCached::CrateRoot(CrateIdCached::new(crate_id, ctx))
2280            }
2281            ModuleId::Submodule(submodule_id) => {
2282                ModuleIdCached::Submodule(SubmoduleIdCached::new(submodule_id, ctx))
2283            }
2284        }
2285    }
2286    fn embed(&self, ctx: &mut SemanticCacheLoadingContext<'_>) -> ModuleId {
2287        match self {
2288            ModuleIdCached::CrateRoot(crate_id) => ModuleId::CrateRoot(crate_id.embed(ctx)),
2289            ModuleIdCached::Submodule(submodule_id) => ModuleId::Submodule(submodule_id.embed(ctx)),
2290        }
2291    }
2292}
2293
2294#[derive(Serialize, Deserialize, Clone)]
2295enum CrateCached {
2296    Real { name: SmolStr, discriminator: Option<SmolStr> },
2297    Virtual { name: SmolStr, file_id: FileIdCached, settings: String },
2298}
2299impl CrateCached {
2300    fn new(crate_id: CrateLongId, _ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2301        match crate_id {
2302            CrateLongId::Real { name, discriminator } => CrateCached::Real { name, discriminator },
2303            CrateLongId::Virtual { name, file_id, settings, cache_file: _ } => {
2304                CrateCached::Virtual { name, file_id: FileIdCached::new(file_id, _ctx), settings }
2305            }
2306        }
2307    }
2308    fn embed(self, _ctx: &mut SemanticCacheLoadingContext<'_>) -> CrateLongId {
2309        match self {
2310            CrateCached::Real { name, discriminator } => CrateLongId::Real { name, discriminator },
2311            CrateCached::Virtual { name, file_id, settings } => {
2312                CrateLongId::Virtual {
2313                    name,
2314                    file_id: file_id.embed(_ctx),
2315                    settings,
2316                    cache_file: None, // todo  if two virtual crates are supported
2317                }
2318            }
2319        }
2320    }
2321}
2322#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
2323enum CrateIdCached {
2324    SelfCrate,
2325    Other(usize),
2326}
2327impl CrateIdCached {
2328    fn new(crate_id: CrateId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2329        if crate_id == ctx.self_crate_id {
2330            return CrateIdCached::SelfCrate;
2331        }
2332        if let Some(id) = ctx.crate_ids.get(&crate_id) {
2333            return *id;
2334        }
2335        let crate_long_id = CrateCached::new(crate_id.lookup_intern(ctx.db), ctx);
2336        let id = CrateIdCached::Other(ctx.crate_ids_lookup.len());
2337        ctx.crate_ids_lookup.push(crate_long_id);
2338        ctx.crate_ids.insert(crate_id, id);
2339        id
2340    }
2341    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> CrateId {
2342        let CrateIdCached::Other(id) = self else {
2343            return ctx.self_crate_id;
2344        };
2345
2346        if let Some(crate_id) = ctx.crate_ids.get(&self) {
2347            return *crate_id;
2348        }
2349        let crate_long_id = ctx.crate_ids_lookup[id].clone();
2350        let crate_id = crate_long_id.embed(ctx).intern(ctx.db);
2351        ctx.crate_ids.insert(self, crate_id);
2352        crate_id
2353    }
2354}
2355
2356#[derive(Serialize, Deserialize, Clone)]
2357struct SubmoduleCached {
2358    language_element: LanguageElementCached,
2359}
2360impl SubmoduleCached {
2361    fn new(submodule_id: SubmoduleLongId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2362        Self { language_element: LanguageElementCached::new(submodule_id.intern(ctx.db), ctx) }
2363    }
2364    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> SubmoduleLongId {
2365        let (module_file_id, stable_ptr) = self.language_element.embed(ctx);
2366
2367        SubmoduleLongId(module_file_id, ItemModulePtr(stable_ptr))
2368    }
2369}
2370
2371#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
2372struct SubmoduleIdCached(usize);
2373
2374impl SubmoduleIdCached {
2375    fn new(submodule_id: SubmoduleId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2376        if let Some(id) = ctx.submodule_ids.get(&submodule_id) {
2377            return *id;
2378        }
2379        let submodule = SubmoduleCached::new(submodule_id.lookup_intern(ctx.db), ctx);
2380        let id = SubmoduleIdCached(ctx.submodule_ids_lookup.len());
2381        ctx.submodule_ids_lookup.push(submodule);
2382        ctx.submodule_ids.insert(submodule_id, id);
2383        id
2384    }
2385    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> SubmoduleId {
2386        if let Some(submodule_id) = ctx.submodule_ids.get(&self) {
2387            return *submodule_id;
2388        }
2389        let submodule = ctx.submodule_ids_lookup[self.0].clone();
2390        let submodule = submodule.embed(ctx).intern(ctx.db);
2391        ctx.submodule_ids.insert(self, submodule);
2392        submodule
2393    }
2394}
2395
2396#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
2397struct LanguageElementCached {
2398    module_file_id: ModuleFileCached,
2399    stable_ptr: SyntaxStablePtrIdCached,
2400}
2401impl LanguageElementCached {
2402    fn new<T: LanguageElementId>(
2403        language_element: T,
2404        ctx: &mut SemanticCacheSavingContext<'_>,
2405    ) -> Self {
2406        Self {
2407            module_file_id: ModuleFileCached::new(
2408                language_element.module_file_id(ctx.db.upcast()),
2409                ctx,
2410            ),
2411            stable_ptr: SyntaxStablePtrIdCached::new(
2412                language_element.untyped_stable_ptr(ctx.db.upcast()),
2413                ctx,
2414            ),
2415        }
2416    }
2417    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> (ModuleFileId, SyntaxStablePtrId) {
2418        let module_file_id = self.module_file_id.embed(ctx);
2419        let stable_ptr = self.stable_ptr.embed(ctx);
2420        (module_file_id, stable_ptr)
2421    }
2422}
2423
2424#[derive(Serialize, Deserialize, Clone)]
2425struct LocationCached {
2426    /// The stable location of the object.
2427    stable_location: SyntaxStablePtrIdCached,
2428    /// Function call locations where this value was inlined from.
2429    inline_locations: Vec<SyntaxStablePtrIdCached>,
2430}
2431impl LocationCached {
2432    fn new(location: Location, ctx: &mut CacheSavingContext<'_>) -> Self {
2433        Self {
2434            stable_location: SyntaxStablePtrIdCached::new(
2435                location.stable_location.stable_ptr(),
2436                &mut ctx.semantic_ctx,
2437            ),
2438            inline_locations: location
2439                .inline_locations
2440                .iter()
2441                .map(|loc| SyntaxStablePtrIdCached::new(loc.stable_ptr(), &mut ctx.semantic_ctx))
2442                .collect(),
2443        }
2444    }
2445    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> Location {
2446        Location {
2447            stable_location: StableLocation::new(self.stable_location.embed(&mut ctx.semantic_ctx)),
2448            inline_locations: self
2449                .inline_locations
2450                .into_iter()
2451                .map(|loc| StableLocation::new(loc.embed(&mut ctx.semantic_ctx)))
2452                .collect(),
2453            notes: Default::default(),
2454        }
2455    }
2456}
2457
2458#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
2459struct LocationIdCached(usize);
2460
2461impl LocationIdCached {
2462    fn new(location_id: LocationId, ctx: &mut CacheSavingContext<'_>) -> Self {
2463        if let Some(id) = ctx.location_ids.get(&location_id) {
2464            return *id;
2465        }
2466        let location = LocationCached::new(location_id.lookup_intern(ctx.db), ctx);
2467        let id = LocationIdCached(ctx.location_ids_lookup.len());
2468        ctx.location_ids_lookup.push(location);
2469        ctx.location_ids.insert(location_id, id);
2470        id
2471    }
2472    fn embed(self, ctx: &mut CacheLoadingContext<'_>) -> LocationId {
2473        if let Some(location_id) = ctx.location_ids.get(&self) {
2474            return *location_id;
2475        }
2476        let location = ctx.location_ids_lookup[self.0].clone();
2477        let location = location.embed(ctx).intern(ctx.db);
2478        ctx.location_ids.insert(self, location);
2479        location
2480    }
2481}
2482
2483#[derive(Serialize, Deserialize, Clone)]
2484enum SyntaxStablePtrCached {
2485    /// The root node of the tree.
2486    Root(FileIdCached, GreenIdCached),
2487    /// A child node.
2488    Child {
2489        /// The parent of the node.
2490        parent: SyntaxStablePtrIdCached,
2491        /// The SyntaxKind of the node.
2492        kind: SyntaxKind,
2493        /// A list of field values for this node, to index by.
2494        /// Which fields are used is determined by each SyntaxKind.
2495        /// For example, a function item might use the name of the function.
2496        key_fields: Vec<GreenIdCached>,
2497        /// Chronological index among all nodes with the same (parent, kind, key_fields).
2498        index: usize,
2499    },
2500}
2501
2502impl SyntaxStablePtrCached {
2503    fn new(syntax_stable_ptr: SyntaxStablePtr, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2504        match syntax_stable_ptr {
2505            SyntaxStablePtr::Root(root, green_id) => SyntaxStablePtrCached::Root(
2506                FileIdCached::new(root, ctx),
2507                GreenIdCached::new(green_id, ctx),
2508            ),
2509            SyntaxStablePtr::Child { parent, kind, key_fields, index } => {
2510                SyntaxStablePtrCached::Child {
2511                    parent: SyntaxStablePtrIdCached::new(parent, ctx),
2512                    kind,
2513                    key_fields: key_fields
2514                        .into_iter()
2515                        .map(|field| GreenIdCached::new(field, ctx))
2516                        .collect(),
2517                    index,
2518                }
2519            }
2520        }
2521    }
2522    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> SyntaxStablePtr {
2523        match self {
2524            SyntaxStablePtrCached::Root(file, green_id) => {
2525                SyntaxStablePtr::Root(file.embed(ctx), green_id.embed(ctx))
2526            }
2527            SyntaxStablePtrCached::Child { parent, kind, key_fields, index } => {
2528                SyntaxStablePtr::Child {
2529                    parent: parent.embed(ctx),
2530                    kind,
2531                    key_fields: key_fields.into_iter().map(|field| field.embed(ctx)).collect(),
2532                    index,
2533                }
2534            }
2535        }
2536    }
2537}
2538
2539#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
2540struct SyntaxStablePtrIdCached(usize);
2541impl SyntaxStablePtrIdCached {
2542    fn new(
2543        syntax_stable_ptr_id: SyntaxStablePtrId,
2544        ctx: &mut SemanticCacheSavingContext<'_>,
2545    ) -> Self {
2546        if let Some(id) = ctx.syntax_stable_ptr_ids.get(&syntax_stable_ptr_id) {
2547            return *id;
2548        }
2549        let stable_ptr =
2550            SyntaxStablePtrCached::new(syntax_stable_ptr_id.lookup_intern(ctx.db), ctx);
2551        let id = SyntaxStablePtrIdCached(ctx.syntax_stable_ptr_ids_lookup.len());
2552        ctx.syntax_stable_ptr_ids_lookup.push(stable_ptr);
2553        ctx.syntax_stable_ptr_ids.insert(syntax_stable_ptr_id, id);
2554        id
2555    }
2556    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> SyntaxStablePtrId {
2557        if let Some(syntax_stable_ptr_id) = ctx.syntax_stable_ptr_ids.get(&self) {
2558            return *syntax_stable_ptr_id;
2559        }
2560        let stable_ptr = ctx.syntax_stable_ptr_ids_lookup[self.0].clone();
2561        let stable_ptr = stable_ptr.embed(ctx);
2562        let stable_ptr_id = stable_ptr.intern(ctx.db);
2563        ctx.syntax_stable_ptr_ids.insert(self, stable_ptr_id);
2564        stable_ptr_id
2565    }
2566}
2567
2568#[derive(Serialize, Deserialize, Clone)]
2569enum GreenNodeDetailsCached {
2570    Token(SmolStr),
2571    Node { children: Vec<GreenIdCached>, width: TextWidth },
2572}
2573
2574impl GreenNodeDetailsCached {
2575    fn new(
2576        green_node_details: &GreenNodeDetails,
2577        ctx: &mut SemanticCacheSavingContext<'_>,
2578    ) -> GreenNodeDetailsCached {
2579        match green_node_details {
2580            GreenNodeDetails::Token(token) => GreenNodeDetailsCached::Token(token.clone()),
2581            GreenNodeDetails::Node { children, width } => GreenNodeDetailsCached::Node {
2582                children: children.iter().map(|child| GreenIdCached::new(*child, ctx)).collect(),
2583                width: *width,
2584            },
2585        }
2586    }
2587    fn embed(&self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GreenNodeDetails {
2588        match self {
2589            GreenNodeDetailsCached::Token(token) => GreenNodeDetails::Token(token.clone()),
2590            GreenNodeDetailsCached::Node { children, width } => GreenNodeDetails::Node {
2591                children: children.iter().map(|child| child.embed(ctx)).collect(),
2592                width: *width,
2593            },
2594        }
2595    }
2596}
2597
2598#[derive(Serialize, Deserialize, Clone)]
2599struct GreenNodeCached {
2600    kind: SyntaxKind,
2601    details: GreenNodeDetailsCached,
2602}
2603impl GreenNodeCached {
2604    fn new(green_node: &GreenNode, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2605        Self {
2606            kind: green_node.kind,
2607            details: GreenNodeDetailsCached::new(&green_node.details, ctx),
2608        }
2609    }
2610    fn embed(&self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GreenNode {
2611        GreenNode { kind: self.kind, details: self.details.embed(ctx) }
2612    }
2613}
2614
2615#[derive(Serialize, Deserialize, Clone, Copy, Eq, Hash, PartialEq)]
2616struct GreenIdCached(usize);
2617
2618impl GreenIdCached {
2619    fn new(green_id: GreenId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2620        if let Some(id) = ctx.green_ids.get(&green_id) {
2621            return *id;
2622        }
2623        let green_node = GreenNodeCached::new(green_id.lookup_intern(ctx.db).as_ref(), ctx);
2624        let id = GreenIdCached(ctx.green_ids_lookup.len());
2625        ctx.green_ids_lookup.push(green_node);
2626        ctx.green_ids.insert(green_id, id);
2627        id
2628    }
2629    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> GreenId {
2630        if let Some(green_id) = ctx.green_ids.get(&self) {
2631            return *green_id;
2632        }
2633        let green_node = ctx.green_ids_lookup[self.0].clone();
2634        let green_node = Arc::new(green_node.embed(ctx));
2635        let green_id = green_node.intern(ctx.db);
2636        ctx.green_ids.insert(self, green_id);
2637        green_id
2638    }
2639}
2640#[derive(Serialize, Deserialize, Clone)]
2641enum FileCached {
2642    OnDisk(PathBuf),
2643    Virtual(VirtualFileCached),
2644    External(PluginGeneratedFileCached),
2645}
2646
2647impl FileCached {
2648    fn new(file: &FileLongId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2649        match file {
2650            FileLongId::OnDisk(path) => FileCached::OnDisk(path.clone()),
2651            FileLongId::Virtual(virtual_file) => {
2652                FileCached::Virtual(VirtualFileCached::new(virtual_file, ctx))
2653            }
2654            FileLongId::External(external_file) => {
2655                FileCached::External(PluginGeneratedFileCached::new(
2656                    PluginGeneratedFileId::from_intern_id(*external_file),
2657                    ctx,
2658                ))
2659            }
2660        }
2661    }
2662    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> FileLongId {
2663        match self {
2664            FileCached::OnDisk(path) => FileLongId::OnDisk(path.clone()),
2665            FileCached::Virtual(virtual_file) => FileLongId::Virtual(virtual_file.embed(ctx)),
2666            FileCached::External(external_file) => {
2667                FileLongId::External(external_file.embed(ctx).as_intern_id())
2668            }
2669        }
2670    }
2671}
2672
2673#[derive(Serialize, Deserialize, Clone, Copy, Eq, Hash, PartialEq)]
2674struct FileIdCached(usize);
2675impl FileIdCached {
2676    fn new(file_id: FileId, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2677        if let Some(id) = ctx.file_ids.get(&file_id) {
2678            return *id;
2679        }
2680        let file = FileCached::new(&file_id.lookup_intern(ctx.db), ctx);
2681        let id = FileIdCached(ctx.file_ids_lookup.len());
2682        ctx.file_ids_lookup.push(file);
2683        ctx.file_ids.insert(file_id, id);
2684        id
2685    }
2686    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> FileId {
2687        if let Some(file_id) = ctx.file_ids.get(&self) {
2688            return *file_id;
2689        }
2690        let file = ctx.file_ids_lookup[self.0].clone();
2691        let file = file.embed(ctx);
2692        let file_id = file.intern(ctx.db);
2693        ctx.file_ids.insert(self, file_id);
2694        file_id
2695    }
2696}
2697
2698#[derive(Serialize, Deserialize, Clone)]
2699struct VirtualFileCached {
2700    parent: Option<FileIdCached>,
2701    name: SmolStr,
2702    content: String,
2703    code_mappings: Vec<CodeMapping>,
2704    kind: FileKind,
2705}
2706
2707impl VirtualFileCached {
2708    fn new(virtual_file: &VirtualFile, ctx: &mut SemanticCacheSavingContext<'_>) -> Self {
2709        Self {
2710            parent: virtual_file.parent.map(|parent| FileIdCached::new(parent, ctx)),
2711            name: virtual_file.name.clone(),
2712            content: String::from(&*(virtual_file.content)),
2713            code_mappings: virtual_file.code_mappings.to_vec(),
2714            kind: virtual_file.kind.clone(),
2715        }
2716    }
2717    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> VirtualFile {
2718        VirtualFile {
2719            parent: self.parent.map(|parent| parent.embed(ctx)),
2720            name: self.name,
2721            content: self.content.into(),
2722            code_mappings: self.code_mappings.into(),
2723            kind: self.kind,
2724        }
2725    }
2726}
2727
2728#[derive(Serialize, Deserialize, Clone)]
2729struct PluginGeneratedFileCached {
2730    /// The module that the file was generated from.
2731    module_id: ModuleIdCached,
2732    /// The stable pointer the file was generated from being ran on.
2733    stable_ptr: SyntaxStablePtrIdCached,
2734    /// The name of the generated file to differentiate between different generated files.
2735    name: SmolStr,
2736}
2737
2738impl PluginGeneratedFileCached {
2739    fn new(
2740        plugin_generated_file: PluginGeneratedFileId,
2741        ctx: &mut SemanticCacheSavingContext<'_>,
2742    ) -> Self {
2743        let long_id = plugin_generated_file.lookup_intern(ctx.db);
2744        Self {
2745            module_id: ModuleIdCached::new(long_id.module_id, ctx),
2746            stable_ptr: SyntaxStablePtrIdCached::new(long_id.stable_ptr, ctx),
2747            name: long_id.name.clone(),
2748        }
2749    }
2750    fn embed(self, ctx: &mut SemanticCacheLoadingContext<'_>) -> PluginGeneratedFileId {
2751        let module_id = self.module_id.embed(ctx);
2752        let stable_ptr = self.stable_ptr.embed(ctx);
2753        let long_id = PluginGeneratedFileLongId { module_id, stable_ptr, name: self.name };
2754        long_id.intern(ctx.db)
2755    }
2756}