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