Skip to main content

cairo_lang_defs/cache/
mod.rs

1use std::hash::{Hash, Hasher};
2use std::ops::{Deref, DerefMut};
3use std::path::PathBuf;
4use std::sync::Arc;
5
6use cairo_lang_diagnostics::{DiagnosticNote, Severity};
7use cairo_lang_filesystem::db::FilesGroup;
8use cairo_lang_filesystem::flag::{Flag, FlagsGroup};
9use cairo_lang_filesystem::ids::{
10    CodeMapping, CrateId, CrateLongId, FileId, FileKind, FileLongId, SmolStrId, SpanInFile,
11    VirtualFile,
12};
13use cairo_lang_filesystem::span::{TextSpan, TextWidth};
14use cairo_lang_syntax::node::ast::{
15    FunctionWithBodyPtr, GenericParamPtr, ItemConstantPtr, ItemEnumPtr, ItemExternFunctionPtr,
16    ItemExternTypePtr, ItemImplAliasPtr, ItemImplPtr, ItemInlineMacroPtr, ItemMacroDeclarationPtr,
17    ItemModulePtr, ItemStructPtr, ItemTraitPtr, ItemTypeAliasPtr, UsePathLeafPtr, UsePathStarPtr,
18};
19use cairo_lang_syntax::node::green::{GreenNode, GreenNodeDetails};
20use cairo_lang_syntax::node::ids::{GreenId, SyntaxStablePtrId};
21use cairo_lang_syntax::node::kind::SyntaxKind;
22use cairo_lang_syntax::node::{SyntaxNode, SyntaxNodeId, TypedSyntaxNode, ast};
23use cairo_lang_utils::Intern;
24use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
25use salsa::Database;
26use serde::{Deserialize, Serialize};
27
28use crate::db::{
29    ModuleData, ModuleDataCacheAndLoadingData, ModuleFilesData, ModuleNamedItemsData,
30    ModuleTypesData, ModuleUnnamedItemsData,
31};
32use crate::ids::{
33    ConstantId, ConstantLongId, EnumId, EnumLongId, ExternFunctionId, ExternFunctionLongId,
34    ExternTypeId, ExternTypeLongId, FreeFunctionId, FreeFunctionLongId, GenericParamId,
35    GenericParamLongId, GlobalUseId, GlobalUseLongId, ImplAliasId, ImplAliasLongId, ImplDefId,
36    ImplDefLongId, LanguageElementId, MacroCallId, MacroCallLongId, MacroDeclarationId,
37    MacroDeclarationLongId, ModuleId, ModuleItemId, ModuleTypeAliasId, ModuleTypeAliasLongId,
38    PluginGeneratedFileId, PluginGeneratedFileLongId, StructId, StructLongId, SubmoduleId,
39    SubmoduleLongId, TraitId, TraitLongId, UseId, UseLongId,
40};
41use crate::plugin::{DynGeneratedFileAuxData, PluginDiagnostic};
42
43/// Metadata for a cached crate.
44#[derive(Serialize, Deserialize)]
45pub struct CachedCrateMetadata {
46    /// Hash of the settings the crate was compiled with.
47    pub settings: Option<u64>,
48    /// The version of the compiler that compiled the crate.
49    pub compiler_version: String,
50    /// The global flags the crate was compiled with.
51    pub global_flags: OrderedHashMap<String, Flag>,
52}
53
54impl CachedCrateMetadata {
55    /// Creates a new [CachedCrateMetadata] from the input crate with the current settings.
56    pub fn new(crate_id: CrateId<'_>, db: &dyn Database) -> Self {
57        let settings = db.crate_config(crate_id).map(|config| &config.settings).map(|v| {
58            let mut hasher = xxhash_rust::xxh3::Xxh3::default();
59            v.hash(&mut hasher);
60            hasher.finish()
61        });
62        let compiler_version = env!("CARGO_PKG_VERSION").to_string();
63        let global_flags =
64            db.flags().iter().map(|(flag_id, flag)| (flag_id.long(db).0.clone(), *flag)).collect();
65        Self { settings, compiler_version, global_flags }
66    }
67}
68
69/// Validates that the metadata of the cached crate is valid.
70fn validate_metadata(crate_id: CrateId<'_>, metadata: &CachedCrateMetadata, db: &dyn Database) {
71    let current_metadata = CachedCrateMetadata::new(crate_id, db);
72
73    if current_metadata.compiler_version != metadata.compiler_version {
74        panic!("Cached crate was compiled with a different compiler version.");
75    }
76    if current_metadata.settings != metadata.settings {
77        panic!("Cached crate was compiled with different settings.");
78    }
79
80    if !current_metadata.global_flags.eq_unordered(&metadata.global_flags) {
81        panic!("Cached crate was compiled with different global flags.");
82    }
83}
84
85type DefCache<'db> = (CachedCrateMetadata, CrateDefCache<'db>, DefCacheLookups);
86
87/// Load the cached lowering of a crate if it has a cache file configuration.
88pub fn load_cached_crate_modules<'db>(
89    db: &'db dyn Database,
90    crate_id: CrateId<'db>,
91) -> Option<ModuleDataCacheAndLoadingData<'db>> {
92    let blob_id = db.crate_config(crate_id)?.cache_file?;
93    let Some(content) = db.blob_content(blob_id) else {
94        return Default::default();
95    };
96
97    let size = usize::from_be_bytes(content[..8].try_into().unwrap());
98
99    let content = &content[8..size + 8];
100
101    let (metadata, module_data, defs_lookups): DefCache<'_> = postcard::from_bytes(content)
102        .unwrap_or_else(|e| {
103            panic!(
104                "failed to deserialize modules cache for crate `{}`: {e}",
105                crate_id.long(db).name().long(db),
106            )
107        });
108
109    validate_metadata(crate_id, &metadata, db);
110
111    let mut ctx = DefCacheLoadingContext::new(db, defs_lookups, crate_id);
112    Some((
113        module_data
114            .0
115            .into_iter()
116            .map(|(module_id, module_data)| {
117                let module_id = module_id.embed(&mut ctx);
118
119                let module_data = module_data.embed(&mut ctx);
120                (module_id, module_data)
121            })
122            .collect::<OrderedHashMap<_, _>>()
123            .into(),
124        ctx.data.into(),
125    ))
126}
127
128#[derive(Serialize, Deserialize)]
129pub struct CrateDefCache<'db>(Vec<(ModuleIdCached, ModuleDataCached<'db>)>);
130
131impl<'db> CrateDefCache<'db> {
132    pub fn new(modules: Vec<(ModuleIdCached, ModuleDataCached<'db>)>) -> Self {
133        Self(modules)
134    }
135}
136
137/// Context for loading cache into the database.
138struct DefCacheLoadingContext<'db> {
139    /// The variable ids of the flat lowered that is currently being loaded.
140    db: &'db dyn Database,
141
142    /// data for loading the entire cache into the database.
143    data: DefCacheLoadingData<'db>,
144}
145
146impl<'db> DefCacheLoadingContext<'db> {
147    pub fn new(
148        db: &'db dyn Database,
149        lookups: DefCacheLookups,
150        self_crate_id: CrateId<'db>,
151    ) -> Self {
152        let mut res = Self { db, data: DefCacheLoadingData::new(lookups, self_crate_id) };
153        res.embed_lookups();
154        res
155    }
156    fn embed_lookups(&mut self) {
157        for id in 0..self.lookups.green_ids_lookup.len() {
158            let id = GreenIdCached(id);
159            let embed = id.embed(self);
160            self.reverse_green_ids.insert(embed, id);
161        }
162        for id in 0..self.lookups.crate_ids_lookup.len() {
163            CrateIdCached::Other(id).embed(self);
164        }
165        for id in 0..self.lookups.file_ids_lookup.len() {
166            FileIdCached(id).embed(self);
167        }
168
169        for id in 0..self.lookups.syntax_node_lookup.len() {
170            SyntaxNodeCached(id).embed(self);
171        }
172
173        for id in 0..self.lookups.submodule_ids_lookup.len() {
174            SubmoduleIdCached(id).embed(self);
175        }
176        for id in 0..self.lookups.constant_ids_lookup.len() {
177            ConstantIdCached(id).embed(self);
178        }
179        for id in 0..self.lookups.use_ids_lookup.len() {
180            UseIdCached(id).embed(self);
181        }
182        for id in 0..self.lookups.free_function_ids_lookup.len() {
183            FreeFunctionIdCached(id).embed(self);
184        }
185        for id in 0..self.lookups.struct_ids_lookup.len() {
186            StructIdCached(id).embed(self);
187        }
188        for id in 0..self.lookups.enum_ids_lookup.len() {
189            EnumIdCached(id).embed(self);
190        }
191        for id in 0..self.lookups.type_alias_ids_lookup.len() {
192            ModuleTypeAliasIdCached(id).embed(self);
193        }
194        for id in 0..self.lookups.impl_alias_ids_lookup.len() {
195            ImplAliasIdCached(id).embed(self);
196        }
197        for id in 0..self.lookups.trait_ids_lookup.len() {
198            TraitIdCached(id).embed(self);
199        }
200        for id in 0..self.lookups.impl_def_ids_lookup.len() {
201            ImplDefIdCached(id).embed(self);
202        }
203        for id in 0..self.lookups.extern_type_ids_lookup.len() {
204            ExternTypeIdCached(id).embed(self);
205        }
206        for id in 0..self.lookups.extern_function_ids_lookup.len() {
207            ExternFunctionIdCached(id).embed(self);
208        }
209        for id in 0..self.lookups.global_use_ids_lookup.len() {
210            GlobalUseIdCached(id).embed(self);
211        }
212    }
213}
214
215impl<'db> Deref for DefCacheLoadingContext<'db> {
216    type Target = DefCacheLoadingData<'db>;
217
218    fn deref(&self) -> &Self::Target {
219        &self.data
220    }
221}
222impl DerefMut for DefCacheLoadingContext<'_> {
223    fn deref_mut(&mut self) -> &mut Self::Target {
224        &mut self.data
225    }
226}
227
228/// Data for loading cache into the database.
229#[derive(PartialEq, Eq, salsa::Update)]
230pub struct DefCacheLoadingData<'db> {
231    green_ids: OrderedHashMap<GreenIdCached, GreenId<'db>>,
232    reverse_green_ids: OrderedHashMap<GreenId<'db>, GreenIdCached>,
233    crate_ids: OrderedHashMap<CrateIdCached, CrateId<'db>>,
234    reverse_syntax_node_lookup: OrderedHashMap<SyntaxNodeIdCached, SyntaxNodeCached>,
235    syntax_nodes: OrderedHashMap<SyntaxNodeCached, SyntaxNode<'db>>,
236    submodule_ids: OrderedHashMap<SubmoduleIdCached, SubmoduleId<'db>>,
237    constant_ids: OrderedHashMap<ConstantIdCached, ConstantId<'db>>,
238    use_ids: OrderedHashMap<UseIdCached, UseId<'db>>,
239    free_function_ids: OrderedHashMap<FreeFunctionIdCached, FreeFunctionId<'db>>,
240    struct_ids: OrderedHashMap<StructIdCached, StructId<'db>>,
241    enum_ids: OrderedHashMap<EnumIdCached, EnumId<'db>>,
242    type_alias_ids: OrderedHashMap<ModuleTypeAliasIdCached, ModuleTypeAliasId<'db>>,
243    impl_alias_ids: OrderedHashMap<ImplAliasIdCached, ImplAliasId<'db>>,
244    trait_ids: OrderedHashMap<TraitIdCached, TraitId<'db>>,
245    impl_def_ids: OrderedHashMap<ImplDefIdCached, ImplDefId<'db>>,
246    extern_type_ids: OrderedHashMap<ExternTypeIdCached, ExternTypeId<'db>>,
247    extern_function_ids: OrderedHashMap<ExternFunctionIdCached, ExternFunctionId<'db>>,
248    macro_declaration_ids: OrderedHashMap<MacroDeclarationIdCached, MacroDeclarationId<'db>>,
249    macro_call_ids: OrderedHashMap<MacroCallIdCached, MacroCallId<'db>>,
250    global_use_ids: OrderedHashMap<GlobalUseIdCached, GlobalUseId<'db>>,
251
252    file_ids: OrderedHashMap<FileIdCached, FileId<'db>>,
253    self_crate_id: CrateId<'db>,
254    lookups: DefCacheLookups,
255}
256
257impl<'db> DefCacheLoadingData<'db> {
258    fn new(lookups: DefCacheLookups, self_crate_id: CrateId<'db>) -> Self {
259        Self {
260            green_ids: OrderedHashMap::default(),
261            reverse_green_ids: OrderedHashMap::default(),
262            reverse_syntax_node_lookup: lookups
263                .syntax_node_lookup
264                .iter()
265                .enumerate()
266                .map(|(index, syntax_node)| (syntax_node.clone(), SyntaxNodeCached(index)))
267                .collect(),
268            syntax_nodes: OrderedHashMap::default(),
269            crate_ids: OrderedHashMap::default(),
270            submodule_ids: OrderedHashMap::default(),
271            constant_ids: OrderedHashMap::default(),
272            use_ids: OrderedHashMap::default(),
273            free_function_ids: OrderedHashMap::default(),
274            struct_ids: OrderedHashMap::default(),
275            enum_ids: OrderedHashMap::default(),
276            type_alias_ids: OrderedHashMap::default(),
277            impl_alias_ids: OrderedHashMap::default(),
278            trait_ids: OrderedHashMap::default(),
279            impl_def_ids: OrderedHashMap::default(),
280            extern_type_ids: OrderedHashMap::default(),
281            extern_function_ids: OrderedHashMap::default(),
282            macro_declaration_ids: OrderedHashMap::default(),
283            macro_call_ids: OrderedHashMap::default(),
284            global_use_ids: OrderedHashMap::default(),
285
286            file_ids: OrderedHashMap::default(),
287            self_crate_id,
288            lookups,
289        }
290    }
291}
292
293impl<'db> std::fmt::Debug for DefCacheLoadingData<'db> {
294    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295        f.debug_struct("DefCacheLoadingData").finish()
296    }
297}
298
299impl<'db> Deref for DefCacheLoadingData<'db> {
300    type Target = DefCacheLookups;
301
302    fn deref(&self) -> &Self::Target {
303        &self.lookups
304    }
305}
306impl<'db> DerefMut for DefCacheLoadingData<'db> {
307    fn deref_mut(&mut self) -> &mut Self::Target {
308        &mut self.lookups
309    }
310}
311
312/// Context for saving cache from the database.
313pub struct DefCacheSavingContext<'db> {
314    db: &'db dyn Database,
315    data: DefCacheSavingData<'db>,
316    self_crate_id: CrateId<'db>,
317}
318impl<'db> Deref for DefCacheSavingContext<'db> {
319    type Target = DefCacheSavingData<'db>;
320
321    fn deref(&self) -> &Self::Target {
322        &self.data
323    }
324}
325impl DerefMut for DefCacheSavingContext<'_> {
326    fn deref_mut(&mut self) -> &mut Self::Target {
327        &mut self.data
328    }
329}
330impl<'db> DefCacheSavingContext<'db> {
331    pub fn new(db: &'db dyn Database, self_crate_id: CrateId<'db>) -> Self {
332        Self { db, data: DefCacheSavingData::default(), self_crate_id }
333    }
334}
335
336/// Data for saving cache from the database.
337#[derive(Default)]
338pub struct DefCacheSavingData<'db> {
339    green_ids: OrderedHashMap<GreenId<'db>, GreenIdCached>,
340    crate_ids: OrderedHashMap<CrateId<'db>, CrateIdCached>,
341    submodule_ids: OrderedHashMap<SubmoduleId<'db>, SubmoduleIdCached>,
342    constant_ids: OrderedHashMap<ConstantId<'db>, ConstantIdCached>,
343    use_ids: OrderedHashMap<UseId<'db>, UseIdCached>,
344    free_function_ids: OrderedHashMap<FreeFunctionId<'db>, FreeFunctionIdCached>,
345    struct_ids: OrderedHashMap<StructId<'db>, StructIdCached>,
346    enum_ids: OrderedHashMap<EnumId<'db>, EnumIdCached>,
347    type_alias_ids: OrderedHashMap<ModuleTypeAliasId<'db>, ModuleTypeAliasIdCached>,
348    impl_alias_ids: OrderedHashMap<ImplAliasId<'db>, ImplAliasIdCached>,
349    trait_ids: OrderedHashMap<TraitId<'db>, TraitIdCached>,
350    impl_def_ids: OrderedHashMap<ImplDefId<'db>, ImplDefIdCached>,
351    extern_type_ids: OrderedHashMap<ExternTypeId<'db>, ExternTypeIdCached>,
352    extern_function_ids: OrderedHashMap<ExternFunctionId<'db>, ExternFunctionIdCached>,
353    global_use_ids: OrderedHashMap<GlobalUseId<'db>, GlobalUseIdCached>,
354    macro_declaration_ids: OrderedHashMap<MacroDeclarationId<'db>, MacroDeclarationIdCached>,
355    macro_call_ids: OrderedHashMap<MacroCallId<'db>, MacroCallIdCached>,
356
357    syntax_nodes: OrderedHashMap<SyntaxNode<'db>, SyntaxNodeCached>,
358    file_ids: OrderedHashMap<FileId<'db>, FileIdCached>,
359
360    pub lookups: DefCacheLookups,
361}
362
363impl<'db> Deref for DefCacheSavingData<'db> {
364    type Target = DefCacheLookups;
365
366    fn deref(&self) -> &Self::Target {
367        &self.lookups
368    }
369}
370impl<'db> DerefMut for DefCacheSavingData<'db> {
371    fn deref_mut(&mut self) -> &mut Self::Target {
372        &mut self.lookups
373    }
374}
375
376#[derive(Serialize, Deserialize)]
377pub struct ModuleDataCached<'db> {
378    items: Vec<ModuleItemIdCached>,
379
380    constants: OrderedHashMap<ConstantIdCached, TypeSyntaxNodeCached<'db, ast::ItemConstant<'db>>>,
381    submodules: OrderedHashMap<SubmoduleIdCached, TypeSyntaxNodeCached<'db, ast::ItemModule<'db>>>,
382    uses: OrderedHashMap<UseIdCached, TypeSyntaxNodeCached<'db, ast::UsePathLeaf<'db>>>,
383    free_functions:
384        OrderedHashMap<FreeFunctionIdCached, TypeSyntaxNodeCached<'db, ast::FunctionWithBody<'db>>>,
385    structs: OrderedHashMap<StructIdCached, TypeSyntaxNodeCached<'db, ast::ItemStruct<'db>>>,
386    enums: OrderedHashMap<EnumIdCached, TypeSyntaxNodeCached<'db, ast::ItemEnum<'db>>>,
387    type_aliases:
388        OrderedHashMap<ModuleTypeAliasIdCached, TypeSyntaxNodeCached<'db, ast::ItemTypeAlias<'db>>>,
389    impl_aliases:
390        OrderedHashMap<ImplAliasIdCached, TypeSyntaxNodeCached<'db, ast::ItemImplAlias<'db>>>,
391    traits: OrderedHashMap<TraitIdCached, TypeSyntaxNodeCached<'db, ast::ItemTrait<'db>>>,
392    impls: OrderedHashMap<ImplDefIdCached, TypeSyntaxNodeCached<'db, ast::ItemImpl<'db>>>,
393    extern_types:
394        OrderedHashMap<ExternTypeIdCached, TypeSyntaxNodeCached<'db, ast::ItemExternType<'db>>>,
395    extern_functions: OrderedHashMap<
396        ExternFunctionIdCached,
397        TypeSyntaxNodeCached<'db, ast::ItemExternFunction<'db>>,
398    >,
399    macro_declarations: OrderedHashMap<
400        MacroDeclarationIdCached,
401        TypeSyntaxNodeCached<'db, ast::ItemMacroDeclaration<'db>>,
402    >,
403    global_uses:
404        OrderedHashMap<GlobalUseIdCached, TypeSyntaxNodeCached<'db, ast::UsePathStar<'db>>>,
405    macro_calls:
406        OrderedHashMap<MacroCallIdCached, TypeSyntaxNodeCached<'db, ast::ItemInlineMacro<'db>>>,
407
408    files: Vec<FileIdCached>,
409
410    generated_file_aux_data: OrderedHashMap<FileIdCached, Option<DynGeneratedFileAuxData>>,
411    plugin_diagnostics: Vec<(ModuleIdCached, PluginDiagnosticCached)>,
412    diagnostics_notes: PluginFileDiagnosticNotesCached,
413}
414impl<'db> ModuleDataCached<'db> {
415    pub fn new(
416        db: &'db dyn Database,
417        module_data: ModuleData<'db>,
418        ctx: &mut DefCacheSavingContext<'db>,
419    ) -> Self {
420        Self {
421            items: module_data
422                .items(db)
423                .iter()
424                .map(|id| ModuleItemIdCached::new(*id, ctx))
425                .collect(),
426            constants: module_data
427                .constants(db)
428                .iter()
429                .map(|(id, node)| {
430                    (ConstantIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
431                })
432                .collect(),
433
434            submodules: module_data
435                .submodules(db)
436                .iter()
437                .map(|(id, node)| {
438                    (SubmoduleIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
439                })
440                .collect(),
441
442            uses: module_data
443                .uses(db)
444                .iter()
445                .map(|(id, node)| {
446                    (UseIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
447                })
448                .collect(),
449            free_functions: module_data
450                .free_functions(db)
451                .iter()
452                .map(|(id, node)| {
453                    (
454                        FreeFunctionIdCached::new(*id, ctx),
455                        TypeSyntaxNodeCached::new(node.clone(), ctx),
456                    )
457                })
458                .collect(),
459            structs: module_data
460                .structs(db)
461                .iter()
462                .map(|(id, node)| {
463                    (StructIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
464                })
465                .collect(),
466            enums: module_data
467                .enums(db)
468                .iter()
469                .map(|(id, node)| {
470                    (EnumIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
471                })
472                .collect(),
473            type_aliases: module_data
474                .type_aliases(db)
475                .iter()
476                .map(|(id, node)| {
477                    (
478                        ModuleTypeAliasIdCached::new(*id, ctx),
479                        TypeSyntaxNodeCached::new(node.clone(), ctx),
480                    )
481                })
482                .collect(),
483            impl_aliases: module_data
484                .impl_aliases(db)
485                .iter()
486                .map(|(id, node)| {
487                    (ImplAliasIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
488                })
489                .collect(),
490            traits: module_data
491                .traits(db)
492                .iter()
493                .map(|(id, node)| {
494                    (TraitIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
495                })
496                .collect(),
497            impls: module_data
498                .impls(db)
499                .iter()
500                .map(|(id, node)| {
501                    (ImplDefIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
502                })
503                .collect(),
504            extern_types: module_data
505                .extern_types(db)
506                .iter()
507                .map(|(id, node)| {
508                    (
509                        ExternTypeIdCached::new(*id, ctx),
510                        TypeSyntaxNodeCached::new(node.clone(), ctx),
511                    )
512                })
513                .collect(),
514            extern_functions: module_data
515                .extern_functions(db)
516                .iter()
517                .map(|(id, node)| {
518                    (
519                        ExternFunctionIdCached::new(*id, ctx),
520                        TypeSyntaxNodeCached::new(node.clone(), ctx),
521                    )
522                })
523                .collect(),
524
525            macro_declarations: module_data
526                .macro_declarations(db)
527                .iter()
528                .map(|(id, node)| {
529                    (
530                        MacroDeclarationIdCached::new(*id, ctx),
531                        TypeSyntaxNodeCached::new(node.clone(), ctx),
532                    )
533                })
534                .collect(),
535            global_uses: module_data
536                .global_uses(db)
537                .iter()
538                .map(|(id, node)| {
539                    (GlobalUseIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
540                })
541                .collect(),
542            macro_calls: module_data
543                .macro_calls(db)
544                .iter()
545                .map(|(id, node)| {
546                    (MacroCallIdCached::new(*id, ctx), TypeSyntaxNodeCached::new(node.clone(), ctx))
547                })
548                .collect(),
549            files: module_data.files(db).iter().map(|id| FileIdCached::new(*id, ctx)).collect(),
550            generated_file_aux_data: module_data
551                .generated_file_aux_data(db)
552                .iter()
553                .map(|(file, aux_data)| (FileIdCached::new(*file, ctx), aux_data.clone()))
554                .collect(),
555
556            plugin_diagnostics: module_data
557                .plugin_diagnostics(db)
558                .iter()
559                .map(|(file_id, diagnostic)| {
560                    (
561                        ModuleIdCached::new(*file_id, ctx),
562                        PluginDiagnosticCached::new(diagnostic, ctx),
563                    )
564                })
565                .collect(),
566            diagnostics_notes: module_data
567                .diagnostics_notes(db)
568                .iter()
569                .map(|(file_id, note)| {
570                    (FileIdCached::new(*file_id, ctx), DiagnosticNoteCached::new(note.clone(), ctx))
571                })
572                .collect(),
573        }
574    }
575    fn embed(self, ctx: &mut DefCacheLoadingContext<'db>) -> ModuleData<'db> {
576        ModuleData::new(
577            ctx.db,
578            self.items.iter().map(|id| id.embed(ctx)).collect(),
579            ModuleTypesData::new(
580                ctx.db,
581                self.structs.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
582                self.enums.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
583                self.type_aliases
584                    .iter()
585                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
586                    .collect(),
587                self.extern_types
588                    .iter()
589                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
590                    .collect(),
591            ),
592            ModuleNamedItemsData::new(
593                ctx.db,
594                self.constants.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
595                self.submodules.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
596                self.uses.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
597                self.free_functions
598                    .iter()
599                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
600                    .collect(),
601                self.impl_aliases
602                    .iter()
603                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
604                    .collect(),
605                self.traits.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
606                self.impls.iter().map(|(id, node)| (id.embed(ctx), node.embed(ctx))).collect(),
607                self.extern_functions
608                    .iter()
609                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
610                    .collect(),
611                self.macro_declarations
612                    .iter()
613                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
614                    .collect(),
615            ),
616            ModuleUnnamedItemsData::new(
617                ctx.db,
618                self.global_uses
619                    .iter()
620                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
621                    .collect(),
622                self.macro_calls
623                    .iter()
624                    .map(|(id, node)| (id.embed(ctx), node.embed(ctx)))
625                    .collect(),
626            ),
627            ModuleFilesData::new(
628                ctx.db,
629                self.files.iter().map(|id| id.embed(ctx)).collect(),
630                self.generated_file_aux_data
631                    .into_iter()
632                    .map(|(file, aux_data)| (file.embed(ctx), aux_data))
633                    .collect(),
634                self.plugin_diagnostics
635                    .into_iter()
636                    .map(|(file_id, diagnostic)| (file_id.embed(ctx), diagnostic.embed(ctx)))
637                    .collect(),
638                self.diagnostics_notes
639                    .into_iter()
640                    .map(|(file_id, note)| (file_id.embed(ctx), note.embed(ctx)))
641                    .collect(),
642            ),
643        )
644    }
645}
646
647/// Saved interned items for the cache.
648#[derive(Serialize, Deserialize, Default, PartialEq, Eq, salsa::Update)]
649pub struct DefCacheLookups {
650    green_ids_lookup: Vec<GreenNodeCached>,
651    crate_ids_lookup: Vec<CrateCached>,
652    submodule_ids_lookup: Vec<SubmoduleCached>,
653    constant_ids_lookup: Vec<ConstantCached>,
654    use_ids_lookup: Vec<UseCached>,
655    free_function_ids_lookup: Vec<FreeFunctionCached>,
656    struct_ids_lookup: Vec<StructCached>,
657    enum_ids_lookup: Vec<EnumCached>,
658    type_alias_ids_lookup: Vec<ModuleTypeAliasCached>,
659    impl_alias_ids_lookup: Vec<ImplAliasCached>,
660    trait_ids_lookup: Vec<TraitCached>,
661    impl_def_ids_lookup: Vec<ImplDefCached>,
662    extern_type_ids_lookup: Vec<ExternTypeCached>,
663    extern_function_ids_lookup: Vec<ExternFunctionCached>,
664    global_use_ids_lookup: Vec<GlobalUseCached>,
665    macro_declaration_ids_lookup: Vec<MacroDeclarationCached>,
666    macro_call_ids_lookup: Vec<MacroCallCached>,
667
668    syntax_node_lookup: Vec<SyntaxNodeIdCached>,
669    file_ids_lookup: Vec<FileCached>,
670}
671
672#[derive(Serialize, Deserialize, Clone)]
673struct TypeSyntaxNodeCached<'db, T: TypedSyntaxNode<'db>> {
674    syntax_node: SyntaxNodeCached,
675    _marker: std::marker::PhantomData<&'db T>,
676}
677impl<'db, T: TypedSyntaxNode<'db>> TypeSyntaxNodeCached<'db, T> {
678    fn new(syntax_node: T, ctx: &mut DefCacheSavingContext<'db>) -> Self {
679        Self {
680            syntax_node: SyntaxNodeCached::new(syntax_node.as_syntax_node(), ctx),
681            _marker: std::marker::PhantomData,
682        }
683    }
684    fn embed(&self, ctx: &mut DefCacheLoadingContext<'db>) -> T {
685        T::from_syntax_node(ctx.db, self.syntax_node.embed(ctx))
686    }
687}
688
689#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
690pub struct GenericParamCached {
691    language_element: LanguageElementCached,
692}
693impl GenericParamCached {
694    pub fn new<'db>(
695        generic_param_id: GenericParamId<'db>,
696        ctx: &mut DefCacheSavingContext<'db>,
697    ) -> Self {
698        Self { language_element: LanguageElementCached::new(generic_param_id, ctx) }
699    }
700
701    pub fn get_embedded<'db>(
702        self,
703        data: &Arc<DefCacheLoadingData<'db>>,
704        db: &'db dyn Database,
705    ) -> GenericParamId<'db> {
706        let (module_id, stable_ptr) = self.language_element.get_embedded(data);
707        GenericParamLongId(module_id, GenericParamPtr(stable_ptr)).intern(db)
708    }
709}
710
711#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
712pub enum ModuleIdCached {
713    CrateRoot(CrateIdCached),
714    Submodule(SubmoduleIdCached),
715    MacroCall { id: MacroCallIdCached, generated_file_id: FileIdCached, is_expose: bool },
716}
717impl ModuleIdCached {
718    pub fn new<'db>(module_id: ModuleId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
719        match module_id {
720            ModuleId::CrateRoot(crate_id) => {
721                ModuleIdCached::CrateRoot(CrateIdCached::new(crate_id, ctx))
722            }
723            ModuleId::Submodule(submodule_id) => {
724                ModuleIdCached::Submodule(SubmoduleIdCached::new(submodule_id, ctx))
725            }
726            ModuleId::MacroCall { id, generated_file_id, is_expose } => ModuleIdCached::MacroCall {
727                id: MacroCallIdCached::new(id, ctx),
728                generated_file_id: FileIdCached::new(generated_file_id, ctx),
729                is_expose,
730            },
731        }
732    }
733    fn embed<'db>(&self, ctx: &mut DefCacheLoadingContext<'db>) -> ModuleId<'db> {
734        match self {
735            ModuleIdCached::CrateRoot(crate_id) => ModuleId::CrateRoot(crate_id.embed(ctx)),
736            ModuleIdCached::Submodule(submodule_id) => ModuleId::Submodule(submodule_id.embed(ctx)),
737            ModuleIdCached::MacroCall { id, generated_file_id, is_expose } => ModuleId::MacroCall {
738                id: id.embed(ctx),
739                generated_file_id: generated_file_id.embed(ctx),
740                is_expose: *is_expose,
741            },
742        }
743    }
744    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ModuleId<'db> {
745        match self {
746            ModuleIdCached::CrateRoot(crate_id) => ModuleId::CrateRoot(crate_id.get_embedded(data)),
747            ModuleIdCached::Submodule(submodule_id) => {
748                ModuleId::Submodule(submodule_id.get_embedded(data))
749            }
750            ModuleIdCached::MacroCall { id, generated_file_id, is_expose } => ModuleId::MacroCall {
751                id: id.get_embedded(data),
752                generated_file_id: generated_file_id.get_embedded(data),
753                is_expose,
754            },
755        }
756    }
757}
758
759#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
760enum CrateCached {
761    Real { name: String, discriminator: Option<String> },
762    Virtual { name: String, file_id: FileIdCached, settings: String },
763}
764impl CrateCached {
765    fn new<'db>(crate_id: CrateLongId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
766        match crate_id {
767            CrateLongId::Real { name, discriminator } => {
768                CrateCached::Real { name: name.to_string(ctx.db), discriminator }
769            }
770            CrateLongId::Virtual { name, file_id, settings, cache_file: _ } => {
771                CrateCached::Virtual {
772                    name: name.to_string(ctx.db),
773                    file_id: FileIdCached::new(file_id, ctx),
774                    settings,
775                }
776            }
777        }
778    }
779    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> CrateLongId<'db> {
780        match self {
781            CrateCached::Real { name, discriminator } => {
782                CrateLongId::Real { name: SmolStrId::from(ctx.db, name), discriminator }
783            }
784            CrateCached::Virtual { name, file_id, settings } => {
785                CrateLongId::Virtual {
786                    name: SmolStrId::from(ctx.db, name),
787                    file_id: file_id.embed(ctx),
788                    settings,
789                    cache_file: None, // todo: if two virtual crates are supported
790                }
791            }
792        }
793    }
794}
795#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
796pub enum CrateIdCached {
797    SelfCrate,
798    Other(usize),
799}
800impl CrateIdCached {
801    fn new<'db>(crate_id: CrateId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
802        if crate_id == ctx.self_crate_id {
803            return CrateIdCached::SelfCrate;
804        }
805        if let Some(id) = ctx.crate_ids.get(&crate_id) {
806            return *id;
807        }
808        let crate_long_id = CrateCached::new(crate_id.long(ctx.db).clone(), ctx);
809        let id = CrateIdCached::Other(ctx.crate_ids_lookup.len());
810        ctx.crate_ids_lookup.push(crate_long_id);
811        ctx.crate_ids.insert(crate_id, id);
812        id
813    }
814    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> CrateId<'db> {
815        let CrateIdCached::Other(id) = self else {
816            return ctx.self_crate_id;
817        };
818
819        if let Some(crate_id) = ctx.crate_ids.get(&self) {
820            return *crate_id;
821        }
822        let crate_long_id = ctx.crate_ids_lookup[id].clone();
823        let crate_id = crate_long_id.embed(ctx).intern(ctx.db);
824        ctx.data.crate_ids.insert(self, crate_id);
825        crate_id
826    }
827    fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> CrateId<'db> {
828        let CrateIdCached::Other(_) = self else {
829            return data.self_crate_id;
830        };
831        data.crate_ids[&self]
832    }
833}
834
835#[derive(Serialize, Deserialize, Copy, Clone)]
836pub enum ModuleItemIdCached {
837    Constant(ConstantIdCached),
838    Submodule(SubmoduleIdCached),
839    Use(UseIdCached),
840    FreeFunction(FreeFunctionIdCached),
841    Struct(StructIdCached),
842    Enum(EnumIdCached),
843    TypeAlias(ModuleTypeAliasIdCached),
844    ImplAlias(ImplAliasIdCached),
845    Trait(TraitIdCached),
846    Impl(ImplDefIdCached),
847    ExternType(ExternTypeIdCached),
848    ExternFunction(ExternFunctionIdCached),
849    MacroDeclaration(MacroDeclarationIdCached),
850}
851
852impl ModuleItemIdCached {
853    pub fn new<'db>(
854        module_item_id: ModuleItemId<'db>,
855        ctx: &mut DefCacheSavingContext<'db>,
856    ) -> Self {
857        match module_item_id {
858            ModuleItemId::Constant(constant_id) => {
859                ModuleItemIdCached::Constant(ConstantIdCached::new(constant_id, ctx))
860            }
861            ModuleItemId::Submodule(submodule_id) => {
862                ModuleItemIdCached::Submodule(SubmoduleIdCached::new(submodule_id, ctx))
863            }
864            ModuleItemId::Use(use_id) => ModuleItemIdCached::Use(UseIdCached::new(use_id, ctx)),
865            ModuleItemId::FreeFunction(free_function_id) => {
866                ModuleItemIdCached::FreeFunction(FreeFunctionIdCached::new(free_function_id, ctx))
867            }
868            ModuleItemId::Struct(struct_id) => {
869                ModuleItemIdCached::Struct(StructIdCached::new(struct_id, ctx))
870            }
871            ModuleItemId::Enum(enum_id) => {
872                ModuleItemIdCached::Enum(EnumIdCached::new(enum_id, ctx))
873            }
874            ModuleItemId::TypeAlias(type_alias_id) => {
875                ModuleItemIdCached::TypeAlias(ModuleTypeAliasIdCached::new(type_alias_id, ctx))
876            }
877            ModuleItemId::ImplAlias(impl_alias_id) => {
878                ModuleItemIdCached::ImplAlias(ImplAliasIdCached::new(impl_alias_id, ctx))
879            }
880            ModuleItemId::Trait(trait_id) => {
881                ModuleItemIdCached::Trait(TraitIdCached::new(trait_id, ctx))
882            }
883            ModuleItemId::Impl(impl_def_id) => {
884                ModuleItemIdCached::Impl(ImplDefIdCached::new(impl_def_id, ctx))
885            }
886            ModuleItemId::ExternType(extern_type_id) => {
887                ModuleItemIdCached::ExternType(ExternTypeIdCached::new(extern_type_id, ctx))
888            }
889            ModuleItemId::ExternFunction(extern_function_id) => ModuleItemIdCached::ExternFunction(
890                ExternFunctionIdCached::new(extern_function_id, ctx),
891            ),
892            ModuleItemId::MacroDeclaration(macro_declaration_id) => {
893                ModuleItemIdCached::MacroDeclaration(MacroDeclarationIdCached::new(
894                    macro_declaration_id,
895                    ctx,
896                ))
897            }
898        }
899    }
900    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ModuleItemId<'db> {
901        match self {
902            ModuleItemIdCached::Constant(constant_id) => {
903                ModuleItemId::Constant(constant_id.embed(ctx))
904            }
905            ModuleItemIdCached::Submodule(submodule_id) => {
906                ModuleItemId::Submodule(submodule_id.embed(ctx))
907            }
908            ModuleItemIdCached::Use(use_id) => ModuleItemId::Use(use_id.embed(ctx)),
909            ModuleItemIdCached::FreeFunction(free_function_id) => {
910                ModuleItemId::FreeFunction(free_function_id.embed(ctx))
911            }
912            ModuleItemIdCached::Struct(struct_id) => ModuleItemId::Struct(struct_id.embed(ctx)),
913            ModuleItemIdCached::Enum(enum_id) => ModuleItemId::Enum(enum_id.embed(ctx)),
914            ModuleItemIdCached::TypeAlias(type_alias_id) => {
915                ModuleItemId::TypeAlias(type_alias_id.embed(ctx))
916            }
917            ModuleItemIdCached::ImplAlias(impl_alias_id) => {
918                ModuleItemId::ImplAlias(impl_alias_id.embed(ctx))
919            }
920            ModuleItemIdCached::Trait(trait_id) => ModuleItemId::Trait(trait_id.embed(ctx)),
921            ModuleItemIdCached::Impl(impl_def_id) => ModuleItemId::Impl(impl_def_id.embed(ctx)),
922            ModuleItemIdCached::ExternType(extern_type_id) => {
923                ModuleItemId::ExternType(extern_type_id.embed(ctx))
924            }
925            ModuleItemIdCached::ExternFunction(extern_function_id) => {
926                ModuleItemId::ExternFunction(extern_function_id.embed(ctx))
927            }
928            ModuleItemIdCached::MacroDeclaration(macro_declaration_id) => {
929                ModuleItemId::MacroDeclaration(macro_declaration_id.embed(ctx))
930            }
931        }
932    }
933    pub fn get_embedded<'db>(&self, data: &Arc<DefCacheLoadingData<'db>>) -> ModuleItemId<'db> {
934        match self {
935            ModuleItemIdCached::Constant(id) => ModuleItemId::Constant(id.get_embedded(data)),
936            ModuleItemIdCached::Submodule(id) => ModuleItemId::Submodule(id.get_embedded(data)),
937            ModuleItemIdCached::Use(id) => ModuleItemId::Use(id.get_embedded(data)),
938            ModuleItemIdCached::FreeFunction(id) => {
939                ModuleItemId::FreeFunction(id.get_embedded(data))
940            }
941            ModuleItemIdCached::Struct(id) => ModuleItemId::Struct(id.get_embedded(data)),
942            ModuleItemIdCached::Enum(id) => ModuleItemId::Enum(id.get_embedded(data)),
943            ModuleItemIdCached::TypeAlias(id) => ModuleItemId::TypeAlias(id.get_embedded(data)),
944            ModuleItemIdCached::ImplAlias(id) => ModuleItemId::ImplAlias(id.get_embedded(data)),
945            ModuleItemIdCached::Trait(id) => ModuleItemId::Trait(id.get_embedded(data)),
946            ModuleItemIdCached::Impl(id) => ModuleItemId::Impl(id.get_embedded(data)),
947            ModuleItemIdCached::ExternType(id) => ModuleItemId::ExternType(id.get_embedded(data)),
948            ModuleItemIdCached::ExternFunction(id) => {
949                ModuleItemId::ExternFunction(id.get_embedded(data))
950            }
951            ModuleItemIdCached::MacroDeclaration(id) => {
952                ModuleItemId::MacroDeclaration(id.get_embedded(data))
953            }
954        }
955    }
956}
957
958#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
959struct ConstantCached {
960    language_element: LanguageElementCached,
961}
962impl ConstantCached {
963    fn new<'db>(constant_id: ConstantId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
964        Self { language_element: LanguageElementCached::new(constant_id, ctx) }
965    }
966    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ConstantLongId<'db> {
967        let (module_id, stable_ptr) = self.language_element.embed(ctx);
968
969        ConstantLongId(module_id, ItemConstantPtr(stable_ptr))
970    }
971}
972
973#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
974pub struct ConstantIdCached(usize);
975
976impl ConstantIdCached {
977    fn new<'db>(id: ConstantId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
978        if let Some(cached_id) = ctx.constant_ids.get(&id) {
979            return *cached_id;
980        }
981        let cached = ConstantCached::new(id, ctx);
982        let cached_id = ConstantIdCached(ctx.constant_ids_lookup.len());
983        ctx.constant_ids_lookup.push(cached);
984        ctx.constant_ids.insert(id, cached_id);
985        cached_id
986    }
987    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ConstantId<'db> {
988        if let Some(id) = ctx.constant_ids.get(&self) {
989            return *id;
990        }
991        let cached = ctx.constant_ids_lookup[self.0].clone();
992        let id = cached.embed(ctx).intern(ctx.db);
993        ctx.constant_ids.insert(self, id);
994        id
995    }
996    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ConstantId<'db> {
997        data.constant_ids[&self]
998    }
999}
1000
1001#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1002struct SubmoduleCached {
1003    language_element: LanguageElementCached,
1004}
1005impl SubmoduleCached {
1006    fn new<'db>(submodule_id: SubmoduleId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1007        Self { language_element: LanguageElementCached::new(submodule_id, ctx) }
1008    }
1009    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> SubmoduleLongId<'db> {
1010        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1011
1012        SubmoduleLongId(module_id, ItemModulePtr(stable_ptr))
1013    }
1014}
1015
1016#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1017pub struct SubmoduleIdCached(usize);
1018
1019impl SubmoduleIdCached {
1020    fn new<'db>(id: SubmoduleId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1021        if let Some(cached_id) = ctx.submodule_ids.get(&id) {
1022            return *cached_id;
1023        }
1024        let cached = SubmoduleCached::new(id, ctx);
1025        let cached_id = SubmoduleIdCached(ctx.submodule_ids_lookup.len());
1026        ctx.submodule_ids_lookup.push(cached);
1027        ctx.submodule_ids.insert(id, cached_id);
1028        cached_id
1029    }
1030    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> SubmoduleId<'db> {
1031        if let Some(id) = ctx.submodule_ids.get(&self) {
1032            return *id;
1033        }
1034        let cached = ctx.submodule_ids_lookup[self.0].clone();
1035        let id = cached.embed(ctx).intern(ctx.db);
1036        ctx.submodule_ids.insert(self, id);
1037        id
1038    }
1039    fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> SubmoduleId<'db> {
1040        data.submodule_ids[&self]
1041    }
1042}
1043
1044#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1045struct UseCached {
1046    language_element: LanguageElementCached,
1047}
1048impl UseCached {
1049    fn new<'db>(use_id: UseId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1050        Self { language_element: LanguageElementCached::new(use_id, ctx) }
1051    }
1052    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> UseLongId<'db> {
1053        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1054
1055        UseLongId(module_id, UsePathLeafPtr(stable_ptr))
1056    }
1057}
1058
1059#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1060pub struct UseIdCached(usize);
1061
1062impl UseIdCached {
1063    fn new<'db>(id: UseId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1064        if let Some(cached_id) = ctx.use_ids.get(&id) {
1065            return *cached_id;
1066        }
1067        let cached = UseCached::new(id, ctx);
1068        let cached_id = UseIdCached(ctx.use_ids_lookup.len());
1069        ctx.use_ids_lookup.push(cached);
1070        ctx.use_ids.insert(id, cached_id);
1071        cached_id
1072    }
1073    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> UseId<'db> {
1074        if let Some(id) = ctx.use_ids.get(&self) {
1075            return *id;
1076        }
1077        let cached = ctx.use_ids_lookup[self.0].clone();
1078        let id = cached.embed(ctx).intern(ctx.db);
1079        ctx.use_ids.insert(self, id);
1080        id
1081    }
1082    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> UseId<'db> {
1083        data.use_ids[&self]
1084    }
1085}
1086
1087#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1088struct FreeFunctionCached {
1089    language_element: LanguageElementCached,
1090}
1091impl FreeFunctionCached {
1092    fn new<'db>(
1093        free_function_id: FreeFunctionId<'db>,
1094        ctx: &mut DefCacheSavingContext<'db>,
1095    ) -> Self {
1096        Self { language_element: LanguageElementCached::new(free_function_id, ctx) }
1097    }
1098    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> FreeFunctionLongId<'db> {
1099        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1100
1101        FreeFunctionLongId(module_id, FunctionWithBodyPtr(stable_ptr))
1102    }
1103}
1104
1105#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1106pub struct FreeFunctionIdCached(usize);
1107
1108impl FreeFunctionIdCached {
1109    fn new<'db>(id: FreeFunctionId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1110        if let Some(cached_id) = ctx.free_function_ids.get(&id) {
1111            return *cached_id;
1112        }
1113        let cached = FreeFunctionCached::new(id, ctx);
1114        let cached_id = FreeFunctionIdCached(ctx.free_function_ids_lookup.len());
1115        ctx.free_function_ids_lookup.push(cached);
1116        ctx.free_function_ids.insert(id, cached_id);
1117        cached_id
1118    }
1119    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> FreeFunctionId<'db> {
1120        if let Some(id) = ctx.free_function_ids.get(&self) {
1121            return *id;
1122        }
1123        let cached = ctx.free_function_ids_lookup[self.0].clone();
1124        let id = cached.embed(ctx).intern(ctx.db);
1125        ctx.free_function_ids.insert(self, id);
1126        id
1127    }
1128    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> FreeFunctionId<'db> {
1129        data.free_function_ids[&self]
1130    }
1131}
1132
1133#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1134struct StructCached {
1135    language_element: LanguageElementCached,
1136}
1137impl StructCached {
1138    fn new<'db>(struct_id: StructId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1139        Self { language_element: LanguageElementCached::new(struct_id, ctx) }
1140    }
1141    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> StructLongId<'db> {
1142        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1143
1144        StructLongId(module_id, ItemStructPtr(stable_ptr))
1145    }
1146}
1147
1148#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1149pub struct StructIdCached(usize);
1150
1151impl StructIdCached {
1152    fn new<'db>(id: StructId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1153        if let Some(cached_id) = ctx.struct_ids.get(&id) {
1154            return *cached_id;
1155        }
1156        let cached = StructCached::new(id, ctx);
1157        let cached_id = StructIdCached(ctx.struct_ids_lookup.len());
1158        ctx.struct_ids_lookup.push(cached);
1159        ctx.struct_ids.insert(id, cached_id);
1160        cached_id
1161    }
1162    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> StructId<'db> {
1163        if let Some(id) = ctx.struct_ids.get(&self) {
1164            return *id;
1165        }
1166        let cached = ctx.struct_ids_lookup[self.0].clone();
1167        let id = cached.embed(ctx).intern(ctx.db);
1168        ctx.struct_ids.insert(self, id);
1169        id
1170    }
1171    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> StructId<'db> {
1172        data.struct_ids[&self]
1173    }
1174}
1175
1176#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1177struct EnumCached {
1178    language_element: LanguageElementCached,
1179}
1180impl EnumCached {
1181    fn new<'db>(enum_id: EnumId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1182        Self { language_element: LanguageElementCached::new(enum_id, ctx) }
1183    }
1184    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> EnumLongId<'db> {
1185        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1186
1187        EnumLongId(module_id, ItemEnumPtr(stable_ptr))
1188    }
1189}
1190
1191#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1192pub struct EnumIdCached(usize);
1193
1194impl EnumIdCached {
1195    fn new<'db>(id: EnumId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1196        if let Some(cached_id) = ctx.enum_ids.get(&id) {
1197            return *cached_id;
1198        }
1199        let cached = EnumCached::new(id, ctx);
1200        let cached_id = EnumIdCached(ctx.enum_ids_lookup.len());
1201        ctx.enum_ids_lookup.push(cached);
1202        ctx.enum_ids.insert(id, cached_id);
1203        cached_id
1204    }
1205    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> EnumId<'db> {
1206        if let Some(id) = ctx.enum_ids.get(&self) {
1207            return *id;
1208        }
1209        let cached = ctx.enum_ids_lookup[self.0].clone();
1210        let id = cached.embed(ctx).intern(ctx.db);
1211        ctx.enum_ids.insert(self, id);
1212        id
1213    }
1214    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> EnumId<'db> {
1215        data.enum_ids[&self]
1216    }
1217}
1218
1219#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1220struct ModuleTypeAliasCached {
1221    language_element: LanguageElementCached,
1222}
1223impl ModuleTypeAliasCached {
1224    fn new<'db>(
1225        type_alias_id: ModuleTypeAliasId<'db>,
1226        ctx: &mut DefCacheSavingContext<'db>,
1227    ) -> Self {
1228        Self { language_element: LanguageElementCached::new(type_alias_id, ctx) }
1229    }
1230    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ModuleTypeAliasLongId<'db> {
1231        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1232
1233        ModuleTypeAliasLongId(module_id, ItemTypeAliasPtr(stable_ptr))
1234    }
1235}
1236
1237#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1238pub struct ModuleTypeAliasIdCached(usize);
1239
1240impl ModuleTypeAliasIdCached {
1241    fn new<'db>(id: ModuleTypeAliasId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1242        if let Some(cached_id) = ctx.type_alias_ids.get(&id) {
1243            return *cached_id;
1244        }
1245        let cached = ModuleTypeAliasCached::new(id, ctx);
1246        let cached_id = ModuleTypeAliasIdCached(ctx.type_alias_ids_lookup.len());
1247        ctx.type_alias_ids_lookup.push(cached);
1248        ctx.type_alias_ids.insert(id, cached_id);
1249        cached_id
1250    }
1251    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ModuleTypeAliasId<'db> {
1252        if let Some(id) = ctx.type_alias_ids.get(&self) {
1253            return *id;
1254        }
1255        let cached = ctx.type_alias_ids_lookup[self.0].clone();
1256        let id = cached.embed(ctx).intern(ctx.db);
1257        ctx.type_alias_ids.insert(self, id);
1258        id
1259    }
1260    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ModuleTypeAliasId<'db> {
1261        data.type_alias_ids[&self]
1262    }
1263}
1264
1265#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1266struct ImplAliasCached {
1267    language_element: LanguageElementCached,
1268}
1269impl ImplAliasCached {
1270    fn new<'db>(impl_alias_id: ImplAliasId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1271        Self { language_element: LanguageElementCached::new(impl_alias_id, ctx) }
1272    }
1273    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ImplAliasLongId<'db> {
1274        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1275
1276        ImplAliasLongId(module_id, ItemImplAliasPtr(stable_ptr))
1277    }
1278}
1279
1280#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1281pub struct ImplAliasIdCached(usize);
1282
1283impl ImplAliasIdCached {
1284    pub fn new<'db>(id: ImplAliasId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1285        if let Some(cached_id) = ctx.impl_alias_ids.get(&id) {
1286            return *cached_id;
1287        }
1288        let cached = ImplAliasCached::new(id, ctx);
1289        let cached_id = ImplAliasIdCached(ctx.impl_alias_ids_lookup.len());
1290        ctx.impl_alias_ids_lookup.push(cached);
1291        ctx.impl_alias_ids.insert(id, cached_id);
1292        cached_id
1293    }
1294    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ImplAliasId<'db> {
1295        if let Some(id) = ctx.impl_alias_ids.get(&self) {
1296            return *id;
1297        }
1298        let cached = ctx.impl_alias_ids_lookup[self.0].clone();
1299        let id = cached.embed(ctx).intern(ctx.db);
1300        ctx.impl_alias_ids.insert(self, id);
1301        id
1302    }
1303    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ImplAliasId<'db> {
1304        data.impl_alias_ids[&self]
1305    }
1306}
1307
1308#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1309struct TraitCached {
1310    language_element: LanguageElementCached,
1311}
1312impl TraitCached {
1313    fn new<'db>(trait_id: TraitId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1314        Self { language_element: LanguageElementCached::new(trait_id, ctx) }
1315    }
1316    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> TraitLongId<'db> {
1317        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1318
1319        TraitLongId(module_id, ItemTraitPtr(stable_ptr))
1320    }
1321}
1322
1323#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1324pub struct TraitIdCached(usize);
1325
1326impl TraitIdCached {
1327    fn new<'db>(id: TraitId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1328        if let Some(cached_id) = ctx.trait_ids.get(&id) {
1329            return *cached_id;
1330        }
1331        let cached = TraitCached::new(id, ctx);
1332        let cached_id = TraitIdCached(ctx.trait_ids_lookup.len());
1333        ctx.trait_ids_lookup.push(cached);
1334        ctx.trait_ids.insert(id, cached_id);
1335        cached_id
1336    }
1337    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> TraitId<'db> {
1338        if let Some(id) = ctx.trait_ids.get(&self) {
1339            return *id;
1340        }
1341        let cached = ctx.trait_ids_lookup[self.0].clone();
1342        let id = cached.embed(ctx).intern(ctx.db);
1343        ctx.trait_ids.insert(self, id);
1344        id
1345    }
1346    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> TraitId<'db> {
1347        data.trait_ids[&self]
1348    }
1349}
1350
1351#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1352struct ImplDefCached {
1353    language_element: LanguageElementCached,
1354}
1355impl ImplDefCached {
1356    fn new<'db>(impl_def_id: ImplDefId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1357        Self { language_element: LanguageElementCached::new(impl_def_id, ctx) }
1358    }
1359    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ImplDefLongId<'db> {
1360        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1361
1362        ImplDefLongId(module_id, ItemImplPtr(stable_ptr))
1363    }
1364}
1365
1366#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1367pub struct ImplDefIdCached(usize);
1368
1369impl ImplDefIdCached {
1370    pub fn new<'db>(id: ImplDefId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1371        if let Some(cached_id) = ctx.impl_def_ids.get(&id) {
1372            return *cached_id;
1373        }
1374        let cached = ImplDefCached::new(id, ctx);
1375        let cached_id = ImplDefIdCached(ctx.impl_def_ids_lookup.len());
1376        ctx.impl_def_ids_lookup.push(cached);
1377        ctx.impl_def_ids.insert(id, cached_id);
1378        cached_id
1379    }
1380
1381    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ImplDefId<'db> {
1382        if let Some(id) = ctx.impl_def_ids.get(&self) {
1383            return *id;
1384        }
1385        let cached = ctx.impl_def_ids_lookup[self.0].clone();
1386        let id = cached.embed(ctx).intern(ctx.db);
1387        ctx.impl_def_ids.insert(self, id);
1388        id
1389    }
1390
1391    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ImplDefId<'db> {
1392        data.impl_def_ids[&self]
1393    }
1394}
1395
1396#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1397struct ExternTypeCached {
1398    language_element: LanguageElementCached,
1399}
1400impl ExternTypeCached {
1401    fn new<'db>(extern_type_id: ExternTypeId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1402        Self { language_element: LanguageElementCached::new(extern_type_id, ctx) }
1403    }
1404    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ExternTypeLongId<'db> {
1405        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1406
1407        ExternTypeLongId(module_id, ItemExternTypePtr(stable_ptr))
1408    }
1409}
1410
1411#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1412pub struct ExternTypeIdCached(usize);
1413
1414impl ExternTypeIdCached {
1415    fn new<'db>(id: ExternTypeId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1416        if let Some(cached_id) = ctx.extern_type_ids.get(&id) {
1417            return *cached_id;
1418        }
1419        let cached = ExternTypeCached::new(id, ctx);
1420        let cached_id = ExternTypeIdCached(ctx.extern_type_ids_lookup.len());
1421        ctx.extern_type_ids_lookup.push(cached);
1422        ctx.extern_type_ids.insert(id, cached_id);
1423        cached_id
1424    }
1425    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ExternTypeId<'db> {
1426        if let Some(id) = ctx.extern_type_ids.get(&self) {
1427            return *id;
1428        }
1429        let cached = ctx.extern_type_ids_lookup[self.0].clone();
1430        let id = cached.embed(ctx).intern(ctx.db);
1431        ctx.extern_type_ids.insert(self, id);
1432        id
1433    }
1434    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ExternTypeId<'db> {
1435        data.extern_type_ids[&self]
1436    }
1437}
1438
1439#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1440struct ExternFunctionCached {
1441    language_element: LanguageElementCached,
1442}
1443impl ExternFunctionCached {
1444    fn new<'db>(
1445        extern_function_id: ExternFunctionId<'db>,
1446        ctx: &mut DefCacheSavingContext<'db>,
1447    ) -> Self {
1448        Self { language_element: LanguageElementCached::new(extern_function_id, ctx) }
1449    }
1450    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ExternFunctionLongId<'db> {
1451        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1452
1453        ExternFunctionLongId(module_id, ItemExternFunctionPtr(stable_ptr))
1454    }
1455}
1456
1457#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1458pub struct ExternFunctionIdCached(usize);
1459
1460impl ExternFunctionIdCached {
1461    fn new<'db>(id: ExternFunctionId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1462        if let Some(cached_id) = ctx.extern_function_ids.get(&id) {
1463            return *cached_id;
1464        }
1465        let cached = ExternFunctionCached::new(id, ctx);
1466        let cached_id = ExternFunctionIdCached(ctx.extern_function_ids_lookup.len());
1467        ctx.extern_function_ids_lookup.push(cached);
1468        ctx.extern_function_ids.insert(id, cached_id);
1469        cached_id
1470    }
1471    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> ExternFunctionId<'db> {
1472        if let Some(id) = ctx.extern_function_ids.get(&self) {
1473            return *id;
1474        }
1475        let cached = ctx.extern_function_ids_lookup[self.0].clone();
1476        let id = cached.embed(ctx).intern(ctx.db);
1477        ctx.extern_function_ids.insert(self, id);
1478        id
1479    }
1480    pub fn get_embedded<'db>(self, data: &Arc<DefCacheLoadingData<'db>>) -> ExternFunctionId<'db> {
1481        data.extern_function_ids[&self]
1482    }
1483}
1484#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1485struct MacroDeclarationCached {
1486    language_element: LanguageElementCached,
1487}
1488
1489impl MacroDeclarationCached {
1490    fn new<'db>(
1491        macro_declaration_id: MacroDeclarationId<'db>,
1492        ctx: &mut DefCacheSavingContext<'db>,
1493    ) -> Self {
1494        Self { language_element: LanguageElementCached::new(macro_declaration_id, ctx) }
1495    }
1496    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> MacroDeclarationLongId<'db> {
1497        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1498
1499        MacroDeclarationLongId(module_id, ItemMacroDeclarationPtr(stable_ptr))
1500    }
1501}
1502
1503#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1504pub struct MacroDeclarationIdCached(usize);
1505
1506impl MacroDeclarationIdCached {
1507    fn new<'db>(id: MacroDeclarationId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1508        if let Some(cached_id) = ctx.macro_declaration_ids.get(&id) {
1509            return *cached_id;
1510        }
1511        let cached = MacroDeclarationCached::new(id, ctx);
1512        let cached_id = MacroDeclarationIdCached(ctx.macro_declaration_ids_lookup.len());
1513        ctx.macro_declaration_ids_lookup.push(cached);
1514        ctx.macro_declaration_ids.insert(id, cached_id);
1515        cached_id
1516    }
1517    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> MacroDeclarationId<'db> {
1518        if let Some(id) = ctx.macro_declaration_ids.get(&self) {
1519            return *id;
1520        }
1521        let cached = ctx.macro_declaration_ids_lookup[self.0].clone();
1522        let id = cached.embed(ctx).intern(ctx.db);
1523        ctx.macro_declaration_ids.insert(self, id);
1524        id
1525    }
1526    pub fn get_embedded<'db>(
1527        self,
1528        data: &Arc<DefCacheLoadingData<'db>>,
1529    ) -> MacroDeclarationId<'db> {
1530        data.macro_declaration_ids[&self]
1531    }
1532}
1533
1534#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1535struct MacroCallCached {
1536    language_element: LanguageElementCached,
1537}
1538impl MacroCallCached {
1539    fn new<'db>(macro_call: MacroCallId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1540        Self { language_element: LanguageElementCached::new(macro_call, ctx) }
1541    }
1542
1543    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> MacroCallLongId<'db> {
1544        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1545        MacroCallLongId(module_id, ItemInlineMacroPtr(stable_ptr))
1546    }
1547}
1548
1549#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1550pub struct MacroCallIdCached(usize);
1551impl MacroCallIdCached {
1552    fn new<'db>(id: MacroCallId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1553        if let Some(cached_id) = ctx.macro_call_ids.get(&id) {
1554            return *cached_id;
1555        }
1556        let cached = MacroCallCached::new(id, ctx);
1557        let id_cached = MacroCallIdCached(ctx.macro_call_ids_lookup.len());
1558        ctx.macro_call_ids_lookup.push(cached);
1559        ctx.macro_call_ids.insert(id, id_cached);
1560        id_cached
1561    }
1562    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> MacroCallId<'db> {
1563        if let Some(id) = ctx.macro_call_ids.get(&self) {
1564            return *id;
1565        }
1566        let cached = ctx.macro_call_ids_lookup[self.0].clone();
1567        let id = cached.embed(ctx).intern(ctx.db);
1568        ctx.macro_call_ids.insert(self, id);
1569        id
1570    }
1571    fn get_embedded<'db>(&self, data: &Arc<DefCacheLoadingData<'db>>) -> MacroCallId<'db> {
1572        data.macro_call_ids[self]
1573    }
1574}
1575
1576#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1577struct GlobalUseCached {
1578    language_element: LanguageElementCached,
1579}
1580impl GlobalUseCached {
1581    fn new<'db>(global_use_id: GlobalUseId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1582        Self { language_element: LanguageElementCached::new(global_use_id, ctx) }
1583    }
1584    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> GlobalUseLongId<'db> {
1585        let (module_id, stable_ptr) = self.language_element.embed(ctx);
1586
1587        GlobalUseLongId(module_id, UsePathStarPtr(stable_ptr))
1588    }
1589}
1590
1591#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, salsa::Update)]
1592pub struct GlobalUseIdCached(usize);
1593
1594impl GlobalUseIdCached {
1595    pub fn new<'db>(id: GlobalUseId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1596        if let Some(cached_id) = ctx.global_use_ids.get(&id) {
1597            return *cached_id;
1598        }
1599        let cached = GlobalUseCached::new(id, ctx);
1600        let cached_id = GlobalUseIdCached(ctx.global_use_ids_lookup.len());
1601        ctx.global_use_ids_lookup.push(cached);
1602        ctx.global_use_ids.insert(id, cached_id);
1603        cached_id
1604    }
1605    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> GlobalUseId<'db> {
1606        if let Some(id) = ctx.global_use_ids.get(&self) {
1607            return *id;
1608        }
1609        let cached = ctx.global_use_ids_lookup[self.0].clone();
1610        let id = cached.embed(ctx).intern(ctx.db);
1611        ctx.global_use_ids.insert(self, id);
1612        id
1613    }
1614    pub fn get_embedded<'db>(&self, data: &Arc<DefCacheLoadingData<'db>>) -> GlobalUseId<'db> {
1615        data.global_use_ids[self]
1616    }
1617}
1618
1619#[derive(Serialize, Deserialize, Clone, Copy, Hash, Eq, PartialEq, salsa::Update, Debug)]
1620struct SyntaxNodeCached(usize);
1621
1622#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1623enum SyntaxNodeIdCached {
1624    Root(FileIdCached, GreenIdCached),
1625    Child {
1626        parent: SyntaxNodeCached,
1627        kind: SyntaxKind,
1628        key_fields: Vec<GreenIdCached>,
1629        index: usize,
1630    },
1631}
1632
1633impl SyntaxNodeIdCached {
1634    fn new<'db>(
1635        ctx: &mut DefCacheSavingContext<'db>,
1636        id: &SyntaxNodeId<'db>,
1637        syntax_node: SyntaxNode<'db>,
1638    ) -> Self {
1639        match id {
1640            SyntaxNodeId::Root(file_id) => {
1641                let green = syntax_node.green_node(ctx.db).clone().intern(ctx.db);
1642                Self::Root(FileIdCached::new(*file_id, ctx), GreenIdCached::new(green, ctx))
1643            }
1644            SyntaxNodeId::Child { parent, key_fields, index } => Self::Child {
1645                parent: SyntaxNodeCached::new(*parent, ctx),
1646                kind: syntax_node.kind(ctx.db),
1647                key_fields: key_fields.into_iter().map(|id| GreenIdCached::new(*id, ctx)).collect(),
1648                index: *index,
1649            },
1650        }
1651    }
1652
1653    fn from_raw(
1654        ctx: &mut DefCacheLoadingContext<'_>,
1655        parent: SyntaxNodeCached,
1656        kind: SyntaxKind,
1657        index: usize,
1658        key_fields: &[GreenId<'_>],
1659    ) -> Option<Self> {
1660        let mut cached_key_fields = Vec::with_capacity(key_fields.len());
1661        for id in key_fields {
1662            let Some(cached_id) = ctx.reverse_green_ids.get(id) else {
1663                // Green ID not found in cache, this child can't be reconstructed
1664                return None;
1665            };
1666            cached_key_fields.push(*cached_id);
1667        }
1668        Some(Self::Child { parent, kind, key_fields: cached_key_fields, index })
1669    }
1670}
1671
1672impl SyntaxNodeCached {
1673    fn new<'db>(syntax_node: SyntaxNode<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1674        if let Some(res) = ctx.syntax_nodes.get(&syntax_node) {
1675            return *res;
1676        }
1677        let db = ctx.db;
1678        // Cache the green node and all its children to ensure they're available during load
1679        let green = syntax_node.green_node(db);
1680        GreenIdCached::new(green.clone().intern(db), ctx);
1681
1682        let id = SyntaxNodeIdCached::new(ctx, syntax_node.raw_id(db), syntax_node);
1683        let cached_node = SyntaxNodeCached(ctx.syntax_node_lookup.len());
1684        ctx.syntax_node_lookup.push(id);
1685        ctx.syntax_nodes.insert(syntax_node, cached_node);
1686        cached_node
1687    }
1688    fn embed<'db>(&self, ctx: &mut DefCacheLoadingContext<'db>) -> SyntaxNode<'db> {
1689        if let Some(node) = ctx.syntax_nodes.get(self) {
1690            return *node;
1691        }
1692        let id_cached = ctx.syntax_node_lookup[self.0].clone();
1693        match &id_cached {
1694            SyntaxNodeIdCached::Root(file_id, green_id) => {
1695                let fid = file_id.embed(ctx);
1696                let green = green_id.embed(ctx);
1697                let syntax = cairo_lang_syntax::node::SyntaxNode::new_root(ctx.db, fid, green);
1698                ctx.syntax_nodes.insert(*self, syntax);
1699            }
1700            SyntaxNodeIdCached::Child { parent, .. } => {
1701                let parent_node = parent.embed(ctx);
1702                let children = parent_node.get_children(ctx.db);
1703                // For each child, create the cached syntax node ID and insert into syntax_nodes map
1704                for child in children {
1705                    let SyntaxNodeId::Child { index, key_fields, .. } = child.raw_id(ctx.db) else {
1706                        panic!("Unexpected SyntaxNodeId type root when creating child");
1707                    };
1708                    let kind = child.kind(ctx.db);
1709                    let Some(child_id) =
1710                        SyntaxNodeIdCached::from_raw(ctx, *parent, kind, *index, key_fields)
1711                    else {
1712                        continue;
1713                    };
1714                    // Check if this child was cached during save
1715                    let Some(&child_cached) = ctx.reverse_syntax_node_lookup.get(&child_id) else {
1716                        continue;
1717                    };
1718                    ctx.syntax_nodes.insert(child_cached, *child);
1719                }
1720            }
1721        };
1722        *ctx.syntax_nodes
1723            .get(self)
1724            .unwrap_or_else(|| panic!("Failed to find syntax node {:?} after embedding", self.0))
1725    }
1726    fn get_embedded<'db>(&self, data: &Arc<DefCacheLoadingData<'db>>) -> SyntaxNode<'db> {
1727        data.syntax_nodes[self]
1728    }
1729}
1730
1731#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
1732pub struct LanguageElementCached {
1733    module_id: ModuleIdCached,
1734    stable_ptr: SyntaxStablePtrIdCached,
1735}
1736impl LanguageElementCached {
1737    pub fn new<'db, T: LanguageElementId<'db> + 'db>(
1738        language_element: T,
1739        ctx: &mut DefCacheSavingContext<'db>,
1740    ) -> Self {
1741        Self {
1742            module_id: ModuleIdCached::new(language_element.parent_module(ctx.db), ctx),
1743            stable_ptr: SyntaxStablePtrIdCached::new(
1744                language_element.untyped_stable_ptr(ctx.db),
1745                ctx,
1746            ),
1747        }
1748    }
1749    fn embed<'db>(
1750        self,
1751        ctx: &mut DefCacheLoadingContext<'db>,
1752    ) -> (ModuleId<'db>, SyntaxStablePtrId<'db>) {
1753        let module_id = self.module_id.embed(ctx);
1754        let stable_ptr = self.stable_ptr.embed(ctx);
1755        (module_id, stable_ptr)
1756    }
1757    pub fn get_embedded<'db>(
1758        self,
1759        data: &Arc<DefCacheLoadingData<'db>>,
1760    ) -> (ModuleId<'db>, SyntaxStablePtrId<'db>) {
1761        let module_id = self.module_id.get_embedded(data);
1762        let stable_ptr = self.stable_ptr.get_embedded(data);
1763        (module_id, stable_ptr)
1764    }
1765}
1766
1767#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1768enum GreenNodeDetailsCached {
1769    Token(String),
1770    Node { children: Vec<GreenIdCached>, width: TextWidth },
1771}
1772
1773impl GreenNodeDetailsCached {
1774    fn new<'db>(
1775        green_node_details: &GreenNodeDetails<'db>,
1776        ctx: &mut DefCacheSavingContext<'db>,
1777    ) -> GreenNodeDetailsCached {
1778        match green_node_details {
1779            GreenNodeDetails::Token(token) => {
1780                GreenNodeDetailsCached::Token(token.long(ctx.db).to_string())
1781            }
1782            GreenNodeDetails::Node { children, width } => GreenNodeDetailsCached::Node {
1783                children: children.iter().map(|child| GreenIdCached::new(*child, ctx)).collect(),
1784                width: *width,
1785            },
1786        }
1787    }
1788    fn embed<'db>(&self, ctx: &mut DefCacheLoadingContext<'db>) -> GreenNodeDetails<'db> {
1789        match self {
1790            GreenNodeDetailsCached::Token(token) => {
1791                GreenNodeDetails::Token(SmolStrId::from(ctx.db, token))
1792            }
1793            GreenNodeDetailsCached::Node { children, width } => GreenNodeDetails::Node {
1794                children: children.iter().map(|child| child.embed(ctx)).collect(),
1795                width: *width,
1796            },
1797        }
1798    }
1799}
1800
1801#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1802struct GreenNodeCached {
1803    kind: SyntaxKind,
1804    details: GreenNodeDetailsCached,
1805}
1806impl GreenNodeCached {
1807    fn new<'db>(green_node: &GreenNode<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1808        Self {
1809            kind: green_node.kind,
1810            details: GreenNodeDetailsCached::new(&green_node.details, ctx),
1811        }
1812    }
1813    fn embed<'db>(&self, ctx: &mut DefCacheLoadingContext<'db>) -> GreenNode<'db> {
1814        GreenNode { kind: self.kind, details: self.details.embed(ctx) }
1815    }
1816}
1817
1818#[derive(Serialize, Deserialize, Clone, Copy, Eq, Hash, PartialEq, salsa::Update, Debug)]
1819struct GreenIdCached(usize);
1820
1821impl GreenIdCached {
1822    fn new<'db>(id: GreenId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1823        if let Some(cached_id) = ctx.green_ids.get(&id) {
1824            return *cached_id;
1825        }
1826        let cached = GreenNodeCached::new(id.long(ctx.db), ctx);
1827        let cached_id = GreenIdCached(ctx.green_ids_lookup.len());
1828        ctx.green_ids_lookup.push(cached);
1829        ctx.green_ids.insert(id, cached_id);
1830        cached_id
1831    }
1832    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> GreenId<'db> {
1833        if let Some(id) = ctx.green_ids.get(&self) {
1834            return *id;
1835        }
1836        let cached = ctx.green_ids_lookup[self.0].clone();
1837        let id = cached.embed(ctx).intern(ctx.db);
1838        ctx.green_ids.insert(self, id);
1839        id
1840    }
1841}
1842#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1843enum FileCached {
1844    OnDisk(PathBuf),
1845    Virtual(VirtualFileCached),
1846    External(PluginGeneratedFileCached),
1847}
1848
1849impl FileCached {
1850    fn new<'db>(file: &FileLongId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1851        match file {
1852            FileLongId::OnDisk(path) => FileCached::OnDisk(path.clone()),
1853            FileLongId::Virtual(virtual_file) => {
1854                FileCached::Virtual(VirtualFileCached::new(virtual_file, ctx))
1855            }
1856            FileLongId::External(external_file) => {
1857                FileCached::External(PluginGeneratedFileCached::new(
1858                    PluginGeneratedFileId::from_intern_id(*external_file),
1859                    ctx,
1860                ))
1861            }
1862        }
1863    }
1864    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> FileLongId<'db> {
1865        match self {
1866            FileCached::OnDisk(path) => FileLongId::OnDisk(path),
1867            FileCached::Virtual(virtual_file) => FileLongId::Virtual(virtual_file.embed(ctx)),
1868            FileCached::External(external_file) => {
1869                FileLongId::External(external_file.embed(ctx).as_intern_id())
1870            }
1871        }
1872    }
1873}
1874
1875#[derive(Serialize, Deserialize, Clone, Copy, Eq, Hash, PartialEq, salsa::Update, Debug)]
1876pub struct FileIdCached(usize);
1877impl FileIdCached {
1878    fn new<'db>(id: FileId<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1879        if let Some(cached_id) = ctx.file_ids.get(&id) {
1880            return *cached_id;
1881        }
1882        let cached = FileCached::new(id.long(ctx.db), ctx);
1883        let cached_id = FileIdCached(ctx.file_ids_lookup.len());
1884        ctx.file_ids_lookup.push(cached);
1885        ctx.file_ids.insert(id, cached_id);
1886        cached_id
1887    }
1888    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> FileId<'db> {
1889        if let Some(id) = ctx.file_ids.get(&self) {
1890            return *id;
1891        }
1892        let cached = ctx.file_ids_lookup[self.0].clone();
1893        let id = cached.embed(ctx).intern(ctx.db);
1894        ctx.file_ids.insert(self, id);
1895        id
1896    }
1897    fn get_embedded<'db>(&self, data: &Arc<DefCacheLoadingData<'db>>) -> FileId<'db> {
1898        data.file_ids[self]
1899    }
1900}
1901
1902#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1903struct VirtualFileCached {
1904    parent: Option<SpanInFileCached>,
1905    name: String,
1906    content: String,
1907    code_mappings: Vec<CodeMapping>,
1908    kind: FileKind,
1909    original_item_removed: bool,
1910}
1911
1912impl VirtualFileCached {
1913    fn new<'db>(virtual_file: &VirtualFile<'db>, ctx: &mut DefCacheSavingContext<'db>) -> Self {
1914        Self {
1915            parent: virtual_file.parent.map(|parent| SpanInFileCached::new(&parent, ctx)),
1916            name: virtual_file.name.to_string(ctx.db),
1917            content: virtual_file.content.to_string(ctx.db),
1918            code_mappings: virtual_file.code_mappings.to_vec(),
1919            kind: virtual_file.kind,
1920            original_item_removed: virtual_file.original_item_removed,
1921        }
1922    }
1923    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> VirtualFile<'db> {
1924        VirtualFile {
1925            parent: self.parent.map(|parent| parent.embed(ctx)),
1926            name: SmolStrId::from(ctx.db, self.name),
1927            content: SmolStrId::from(ctx.db, self.content),
1928            code_mappings: self.code_mappings.into(),
1929            kind: self.kind,
1930            original_item_removed: self.original_item_removed,
1931        }
1932    }
1933}
1934
1935#[derive(Serialize, Deserialize, Clone, Copy, Eq, Hash, PartialEq, salsa::Update)]
1936pub struct SyntaxStablePtrIdCached(SyntaxNodeCached);
1937
1938impl SyntaxStablePtrIdCached {
1939    pub fn new<'db>(
1940        stable_ptr: SyntaxStablePtrId<'db>,
1941        ctx: &mut DefCacheSavingContext<'db>,
1942    ) -> Self {
1943        Self(SyntaxNodeCached::new(stable_ptr.0, ctx))
1944    }
1945
1946    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> SyntaxStablePtrId<'db> {
1947        SyntaxStablePtrId(self.0.embed(ctx))
1948    }
1949
1950    pub fn get_embedded<'db>(
1951        &self,
1952        data: &Arc<DefCacheLoadingData<'db>>,
1953    ) -> SyntaxStablePtrId<'db> {
1954        SyntaxStablePtrId(self.0.get_embedded(data))
1955    }
1956}
1957
1958#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1959struct PluginGeneratedFileCached {
1960    module_id: ModuleIdCached,
1961    stable_ptr: SyntaxStablePtrIdCached,
1962    name: String,
1963}
1964
1965impl PluginGeneratedFileCached {
1966    fn new<'db>(
1967        plugin_generated_file: PluginGeneratedFileId<'db>,
1968        ctx: &mut DefCacheSavingContext<'db>,
1969    ) -> Self {
1970        let long_id = plugin_generated_file.long(ctx.db);
1971        Self {
1972            module_id: ModuleIdCached::new(long_id.module_id, ctx),
1973            stable_ptr: SyntaxStablePtrIdCached::new(long_id.stable_ptr, ctx),
1974            name: long_id.name.clone(),
1975        }
1976    }
1977    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> PluginGeneratedFileId<'db> {
1978        let module_id = self.module_id.embed(ctx);
1979        let stable_ptr = self.stable_ptr.embed(ctx);
1980        let long_id = PluginGeneratedFileLongId { module_id, stable_ptr, name: self.name };
1981        long_id.intern(ctx.db)
1982    }
1983}
1984
1985#[derive(Serialize, Deserialize, Clone)]
1986enum SeverityCached {
1987    Error,
1988    Warning,
1989}
1990
1991#[derive(Serialize, Deserialize, Clone)]
1992struct PluginDiagnosticCached {
1993    stable_ptr: SyntaxStablePtrIdCached,
1994    message: String,
1995    severity: SeverityCached,
1996    inner_span: Option<(TextWidth, TextWidth)>,
1997}
1998
1999impl PluginDiagnosticCached {
2000    fn new<'db>(
2001        diagnostic: &PluginDiagnostic<'db>,
2002        ctx: &mut DefCacheSavingContext<'db>,
2003    ) -> PluginDiagnosticCached {
2004        PluginDiagnosticCached {
2005            stable_ptr: SyntaxStablePtrIdCached::new(diagnostic.stable_ptr, ctx),
2006            message: diagnostic.message.clone(),
2007            severity: match diagnostic.severity {
2008                Severity::Error => SeverityCached::Error,
2009                Severity::Warning => SeverityCached::Warning,
2010            },
2011            inner_span: diagnostic.inner_span,
2012        }
2013    }
2014    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> PluginDiagnostic<'db> {
2015        PluginDiagnostic {
2016            stable_ptr: self.stable_ptr.embed(ctx),
2017            message: self.message,
2018            severity: match self.severity {
2019                SeverityCached::Error => Severity::Error,
2020                SeverityCached::Warning => Severity::Warning,
2021            },
2022            inner_span: self.inner_span,
2023            error_code: None,
2024        }
2025    }
2026}
2027
2028type PluginFileDiagnosticNotesCached = OrderedHashMap<FileIdCached, DiagnosticNoteCached>;
2029
2030#[derive(Serialize, Deserialize, Clone)]
2031struct DiagnosticNoteCached {
2032    text: String,
2033    location: Option<SpanInFileCached>,
2034}
2035
2036impl DiagnosticNoteCached {
2037    fn new<'db>(
2038        note: DiagnosticNote<'db>,
2039        ctx: &mut DefCacheSavingContext<'db>,
2040    ) -> DiagnosticNoteCached {
2041        DiagnosticNoteCached {
2042            text: note.text.clone(),
2043            location: note.location.map(|location| SpanInFileCached::new(&location, ctx)),
2044        }
2045    }
2046    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> DiagnosticNote<'db> {
2047        DiagnosticNote {
2048            text: self.text,
2049            location: self.location.map(|location| location.embed(ctx)),
2050        }
2051    }
2052}
2053
2054#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2055struct SpanInFileCached {
2056    file_id: FileIdCached,
2057    span: TextSpan,
2058}
2059
2060impl SpanInFileCached {
2061    fn new<'db>(
2062        location: &SpanInFile<'db>,
2063        ctx: &mut DefCacheSavingContext<'db>,
2064    ) -> SpanInFileCached {
2065        SpanInFileCached { file_id: FileIdCached::new(location.file_id, ctx), span: location.span }
2066    }
2067    fn embed<'db>(self, ctx: &mut DefCacheLoadingContext<'db>) -> SpanInFile<'db> {
2068        SpanInFile { file_id: self.file_id.embed(ctx), span: self.span }
2069    }
2070}