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