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