Skip to main content

cairo_lang_lowering/cache/
mod.rs

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