diff --git a/crates/cairo-lang-compiler/src/db.rs b/crates/cairo-lang-compiler/src/db.rs index 91949c6714d..04e8b4339cf 100644 --- a/crates/cairo-lang-compiler/src/db.rs +++ b/crates/cairo-lang-compiler/src/db.rs @@ -3,8 +3,9 @@ use cairo_lang_defs::db::{init_defs_group, init_external_files}; use cairo_lang_diagnostics::Maybe; use cairo_lang_filesystem::cfg::CfgSet; use cairo_lang_filesystem::db::{ - CORELIB_VERSION, FileContentStorage, FileContentView, FilesGroup, init_dev_corelib, - init_files_group, register_files_group_view, + CORELIB_VERSION, CrateConfigStorage, CrateConfigView, FileContentStorage, FileContentView, + FilesGroup, init_dev_corelib, init_files_group, register_crate_config_view, + register_files_group_view, }; use cairo_lang_filesystem::detect::detect_corelib; use cairo_lang_filesystem::flag::{Flag, FlagsGroup}; @@ -73,6 +74,7 @@ fn estimate_code_size( pub struct RootDatabase { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl salsa::Database for RootDatabase {} @@ -81,6 +83,11 @@ impl FileContentView for RootDatabase { Some(&self.file_contents) } } +impl CrateConfigView for RootDatabase { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl CloneableDatabase for RootDatabase { fn dyn_clone(&self) -> Box { Box::new(self.clone()) @@ -89,8 +96,14 @@ impl CloneableDatabase for RootDatabase { impl RootDatabase { fn new(default_plugin_suite: PluginSuite, optimizations: Optimizations) -> Self { - let mut res = Self { storage: Default::default(), file_contents: Default::default() }; + let mut res = Self { + storage: Default::default(), + file_contents: Default::default(), + crate_configs: Default::default(), + }; + register_files_group_view(&res); + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_lowering_group(&mut res, optimizations, Some(estimate_code_size)); @@ -113,7 +126,11 @@ impl RootDatabase { /// Snapshots the db for read only. pub fn snapshot(&self) -> RootDatabase { - RootDatabase { storage: self.storage.clone(), file_contents: self.file_contents.clone() } + RootDatabase { + storage: self.storage.clone(), + file_contents: self.file_contents.clone(), + crate_configs: self.crate_configs.clone(), + } } } diff --git a/crates/cairo-lang-compiler/src/project.rs b/crates/cairo-lang-compiler/src/project.rs index 32df7adc702..58601c0c2c8 100644 --- a/crates/cairo-lang-compiler/src/project.rs +++ b/crates/cairo-lang-compiler/src/project.rs @@ -5,10 +5,9 @@ use cairo_lang_defs::db::DefsGroup; use cairo_lang_defs::ids::ModuleId; use cairo_lang_filesystem::db::{ CORELIB_CRATE_NAME, CrateConfiguration, CrateIdentifier, CrateSettings, FilesGroup, - set_generated_file_content_for_input, + set_crate_config_for_input, set_generated_file_content_for_input, }; use cairo_lang_filesystem::ids::{CrateId, CrateInput, CrateLongId, Directory, SmolStrId}; -use cairo_lang_filesystem::set_crate_config; pub use cairo_lang_project::*; use cairo_lang_utils::Intern; use salsa::Database; @@ -45,24 +44,25 @@ pub fn setup_single_file_project( let file_dir = canonical.parent().ok_or_else(bad_path_err)?; let file_stem = path.file_stem().and_then(OsStr::to_str).ok_or_else(bad_path_err)?; if file_stem == "lib" { - let crate_name = file_dir.to_str().ok_or_else(bad_path_err)?; - let crate_id = CrateId::plain(db, SmolStrId::from(db, crate_name)); - set_crate_config!( - db, - crate_id, - Some(CrateConfiguration::default_for_root(Directory::Real(file_dir.to_path_buf()))) - ); + let crate_name = file_dir.to_str().ok_or_else(bad_path_err)?.to_string(); + let crate_input = + CrateInput::Real { name: crate_name.clone(), discriminator: Some(crate_name.clone()) }; + let config = CrateConfiguration::default_for_root(Directory::Real(file_dir.to_path_buf())) + .into_crate_configuration_input(db); + set_crate_config_for_input(db, crate_input, Some(config)); let crate_id = CrateId::plain(db, SmolStrId::from(db, crate_name)); Ok(crate_id.long(db).clone().into_crate_input(db)) } else { // If file_stem is not lib, create a fake lib file. { - let crate_id = CrateId::plain(db, SmolStrId::from(db, file_stem)); - set_crate_config!( - db, - crate_id, - Some(CrateConfiguration::default_for_root(Directory::Real(file_dir.to_path_buf()))) - ); + let crate_input = CrateInput::Real { + name: file_stem.to_string(), + discriminator: Some(file_stem.to_string()), + }; + let config = + CrateConfiguration::default_for_root(Directory::Real(file_dir.to_path_buf())) + .into_crate_configuration_input(db); + set_crate_config_for_input(db, crate_input, Some(config)); } let file_input = { let crate_id = CrateId::plain(db, SmolStrId::from(db, file_stem)); @@ -98,11 +98,10 @@ pub fn update_crate_root( root: Directory<'_>, ) { let (crate_id, crate_settings) = get_crate_id_and_settings(db, crate_identifier, config); - set_crate_config!( - db, - crate_id, - Some(CrateConfiguration { root, settings: crate_settings.clone(), cache_file: None }) - ); + let crate_input = db.crate_input(crate_id).clone(); + let config = CrateConfiguration { root, settings: crate_settings.clone(), cache_file: None } + .into_crate_configuration_input(db); + set_crate_config_for_input(db, crate_input, Some(config)); } /// Sets up the DB to compile the project at the given path. diff --git a/crates/cairo-lang-defs/src/test.rs b/crates/cairo-lang-defs/src/test.rs index 4810ec70d7c..499dced8ecd 100644 --- a/crates/cairo-lang-defs/src/test.rs +++ b/crates/cairo-lang-defs/src/test.rs @@ -3,8 +3,9 @@ use std::sync::Arc; use cairo_lang_debug::debug::DebugWithDb; use cairo_lang_filesystem::db::{ - CrateConfiguration, FileContentStorage, FileContentView, FilesGroup, init_files_group, - override_file_content_for_input, register_files_group_view, + CrateConfigStorage, CrateConfigView, CrateConfiguration, FileContentStorage, FileContentView, + FilesGroup, init_files_group, override_file_content_for_input, register_crate_config_view, + register_files_group_view, }; use cairo_lang_filesystem::ids::{CrateId, Directory, FileLongId, SmolStrId}; use cairo_lang_filesystem::set_crate_config; @@ -32,6 +33,7 @@ use crate::plugin::{ pub struct DatabaseForTesting { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl salsa::Database for DatabaseForTesting {} @@ -40,11 +42,22 @@ impl FileContentView for DatabaseForTesting { Some(&self.file_contents) } } +impl CrateConfigView for DatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl Default for DatabaseForTesting { fn default() -> Self { - let mut res = Self { storage: Default::default(), file_contents: Default::default() }; + let mut res = Self { + storage: Default::default(), + file_contents: Default::default(), + crate_configs: Default::default(), + }; + register_files_group_view(&res); + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_defs_group(&mut res); diff --git a/crates/cairo-lang-doc/src/tests/test_utils.rs b/crates/cairo-lang-doc/src/tests/test_utils.rs index 228591f0955..836009c3a60 100644 --- a/crates/cairo-lang-doc/src/tests/test_utils.rs +++ b/crates/cairo-lang-doc/src/tests/test_utils.rs @@ -2,8 +2,9 @@ use anyhow::{Result, anyhow}; use cairo_lang_defs::db::{DefsGroup, init_defs_group}; use cairo_lang_defs::ids::ModuleId; use cairo_lang_filesystem::db::{ - CrateConfiguration, FileContentStorage, FileContentView, FilesGroup, init_dev_corelib, - init_files_group, override_file_content_for_input, register_files_group_view, + CrateConfigStorage, CrateConfigView, CrateConfiguration, FileContentStorage, FileContentView, + FilesGroup, init_dev_corelib, init_files_group, override_file_content_for_input, + register_crate_config_view, register_files_group_view, }; use cairo_lang_filesystem::detect::detect_corelib; use cairo_lang_filesystem::ids::{CrateId, Directory, FileLongId, SmolStrId}; @@ -19,6 +20,7 @@ use salsa::Database; pub struct TestDatabase { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl salsa::Database for TestDatabase {} @@ -27,11 +29,22 @@ impl FileContentView for TestDatabase { Some(&self.file_contents) } } +impl CrateConfigView for TestDatabase { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl Default for TestDatabase { fn default() -> Self { - let mut res = Self { storage: Default::default(), file_contents: Default::default() }; + let mut res = Self { + storage: Default::default(), + file_contents: Default::default(), + crate_configs: Default::default(), + }; + register_files_group_view(&res); + register_crate_config_view(&res); init_files_group(&mut res); init_defs_group(&mut res); init_semantic_group(&mut res); diff --git a/crates/cairo-lang-filesystem/src/db.rs b/crates/cairo-lang-filesystem/src/db.rs index e4c889f15f7..3e93c0b9319 100644 --- a/crates/cairo-lang-filesystem/src/db.rs +++ b/crates/cairo-lang-filesystem/src/db.rs @@ -231,9 +231,9 @@ pub type ExtAsVirtual = // TODO(eytan-starkware): Change this mechanism to hold input handles on the db struct outside // salsa mechanism, and invalidate manually. pub struct FilesGroupInput { - /// Main input of the project. Lists all the crates configurations. - #[returns(ref)] - pub crate_configs: Option>, + /// Structural revision bumped each time a new [`CrateConfig`] handle is first created for a + /// previously-unregistered crate. + pub crate_configs_revision: u64, /// Structural revision bumped each time a new [`FileContentOverride`] handle is first created /// for a previously-unregistered file. /// @@ -257,7 +257,7 @@ pub struct FilesGroupInput { #[salsa::tracked] pub fn files_group_input(db: &dyn Database) -> FilesGroupInput { - FilesGroupInput::new(db, None, 0, None, None, None) + FilesGroupInput::new(db, 0, 0, None, None, None) } /// Input used for overriding the content of a single file. @@ -280,6 +280,24 @@ pub struct FileContentOverride { /// via [`FileContentView`]. pub type FileContentStorage = Arc>>; +/// Input used for overriding the configuration of a single crate. +/// +/// Notice that this structure holds a configuration override for a single crate only — not the +/// whole map of configurations for all crates. This is done to ensure granular invalidation — +/// so that we don't invalidate everything when a single crate's configuration changes. +#[salsa::input] +pub struct CrateConfig { + #[returns(ref)] + pub config: Option, +} + +/// Side-table mapping each crate to its [`CrateConfig`] Salsa input. +/// +/// Lives on the concrete database struct (outside Salsa storage) so that new handles can be +/// created with `&mut dyn Database` while existing ones are read from within tracked functions +/// via [`CrateConfigView`]. +pub type CrateConfigStorage = Arc>>; + /// View trait for accessing the [`FileContentStorage`] side-table from within tracked functions. /// Implement this on the concrete DB struct and register it with [`register_files_group_view`]. pub trait FileContentView: Database { @@ -334,6 +352,68 @@ where }); } +/// View trait for accessing the [`CrateConfigStorage`] side-table from within tracked functions. +/// Implement this on the concrete DB struct and register it with [`register_crate_config_view`]. +pub trait CrateConfigView: Database { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + None + } + + /// Returns a granular config handle for the given crate input, if one exists. + fn crate_config_for_input(&self, crate_input: &CrateInput) -> Option { + self.crate_config_storage()?.read().unwrap().get(crate_input).copied() + } + + /// Returns crate configuration input for the given crate id. + fn crate_config_input_for<'db>( + &'db self, + crate_id: CrateId<'db>, + ) -> Option<&'db CrateConfigurationInput> { + let crate_input = self.crate_input(crate_id).clone(); + self.crate_config_input_for_input(&crate_input) + } + + /// Returns crate configuration input for the given crate input. + fn crate_config_input_for_input<'db>( + &'db self, + crate_input: &CrateInput, + ) -> Option<&'db CrateConfigurationInput> { + self.crate_config_for_input(crate_input).and_then(|config| config.config(self).as_ref()) + } +} + +fn cast_crate_config_view( + db: NonNull, +) -> NonNull { + let db_ref = unsafe { db.as_ref() }; + NonNull::from(db_ref as &dyn CrateConfigView) +} + +fn crate_config_view(db: &dyn Database) -> &dyn CrateConfigView { + let caster = + catch_unwind(AssertUnwindSafe(|| *views(db).downcaster_for::())).ok(); + + let caster = caster.expect("granular crate config view is not registered"); + unsafe { caster.downcast_unchecked(db.into()) } +} + +fn crate_config_storage(db: &dyn Database) -> &CrateConfigStorage { + crate_config_view(db) + .crate_config_storage() + .expect("granular crate config storage is not registered") +} + +/// Registers the concrete database type `Db` as a [`CrateConfigView`]. +/// +/// Must be called once during database initialization for any database struct that holds a +/// [`CrateConfigStorage`]. +pub fn register_crate_config_view(db: &Db) +where + Db: Database + CrateConfigView + 'static, +{ + views(db).add::(cast_crate_config_view::); +} + /// Queries over the files group. pub trait FilesGroup: Database { /// Interned version of `crate_configs_input`. @@ -397,7 +477,7 @@ impl FilesGroup for T {} pub fn init_files_group<'db>(db: &mut (dyn Database + 'db)) { // Initialize inputs. let inp = files_group_input(db); - inp.set_crate_configs(db).to(Some(Default::default())); + inp.set_crate_configs_revision(db).to(0); inp.set_file_contents_revision(db).to(0); inp.set_flags(db).to(Some(Default::default())); inp.set_cfg_set(db).to(Some(Default::default())); @@ -410,23 +490,62 @@ fn bump_file_contents_revision(db: &mut dyn Database) { files_group_input(db).set_file_contents_revision(db).to(next); } -pub fn set_crate_configs_input( +fn bump_crate_configs_revision(db: &mut dyn Database) { + let next = files_group_input(db).crate_configs_revision(db).saturating_add(1); + files_group_input(db).set_crate_configs_revision(db).to(next); +} + +fn ensure_crate_config_handle_for_input( + db: &mut dyn Database, + crate_input: CrateInput, +) -> CrateConfig { + if let Some(handle) = crate_config_view(db).crate_config_for_input(&crate_input) { + return handle; + } + + let storage = crate_config_storage(db); + let handle = CrateConfig::new(db, None); + storage.write().unwrap().insert(crate_input, handle); + bump_crate_configs_revision(db); + handle +} + +/// Sets the configuration for a crate. +/// Used by build tools to configure crates in the compilation unit. +pub fn set_crate_config_for_input( db: &mut dyn Database, - crate_configs: Option>, + crate_input: CrateInput, + config: Option, ) { - files_group_input(db).set_crate_configs(db).to(crate_configs); + let handle = ensure_crate_config_handle_for_input(db, crate_input); + // HIGH durability: crate configurations change rarely. + handle.set_config(db).with_durability(Durability::HIGH).to(config); } +/// Returns the map of all crate configurations. +/// +/// # Invalidation +/// +/// Reads [`FilesGroupInput::crate_configs_revision`] so the query re-executes when a +/// [`CrateConfig`] handle is first created for a previously-unregistered crate. #[salsa::tracked(returns(ref))] pub fn crate_configs<'db>( db: &'db dyn Database, ) -> OrderedHashMap, CrateConfiguration<'db>> { - let inp = files_group_input(db).crate_configs(db).as_ref().expect("crate_configs is not set"); - inp.iter() + let _ = files_group_input(db).crate_configs_revision(db); + crate_config_storage(db) + .read() + .unwrap() + .iter() .map(|(crate_input, config)| { ( crate_input.clone().into_crate_long_id(db).intern(db), - config.clone().into_crate_configuration(db), + config + .config(db) + .as_ref() + .expect("granular crate config handle should always contain a config") + .clone() + .into_crate_configuration(db), ) }) .collect() @@ -459,7 +578,6 @@ fn crate_configuration_input<'db>( } pub fn init_dev_corelib(db: &mut dyn salsa::Database, core_lib_dir: PathBuf) { - let core = CrateLongId::core(db).intern(db); let root = CrateConfiguration { root: Directory::Real(core_lib_dir), settings: CrateSettings { @@ -478,33 +596,39 @@ pub fn init_dev_corelib(db: &mut dyn salsa::Database, core_lib_dir: PathBuf) { }, cache_file: None, }; - let crate_configs = update_crate_configuration_input_helper(db, core, Some(root)); - set_crate_configs_input(db, Some(crate_configs)); + let core_input = { + let core = CrateLongId::core(db).intern(db); + db.crate_input(core).clone() + }; + let config = db.crate_configuration_input(root).clone(); + set_crate_config_for_input(db, core_input, Some(config)); } -/// Updates crate configuration input for standalone use. -pub fn update_crate_configuration_input_helper( - db: &dyn Database, +/// Sets the root directory of the crate. None value removes the crate. +pub fn set_crate_config( + db: &mut dyn Database, crt: CrateId<'_>, root: Option>, -) -> OrderedHashMap { - let crt = db.crate_input(crt); - let db_ref: &dyn Database = db; - let mut crate_configs = files_group_input(db_ref).crate_configs(db_ref).clone().unwrap(); - match root { - Some(root) => crate_configs.insert(crt.clone(), db.crate_configuration_input(root).clone()), - None => crate_configs.swap_remove(crt), - }; - crate_configs +) { + let crate_input = db.crate_input(crt).clone(); + let config = root.map(|root| db.crate_configuration_input(root).clone()); + set_crate_config_for_input(db, crate_input, config); } /// Sets the root directory of the crate. None value removes the crate. #[macro_export] macro_rules! set_crate_config { - ($self:expr, $crt:expr, $root:expr) => { - let crate_configs = $crate::db::update_crate_configuration_input_helper($self, $crt, $root); - $crate::db::set_crate_configs_input($self, Some(crate_configs)); - }; + ($self:expr, $crt:expr, $root:expr) => {{ + let crate_input = { + let db_ref: &dyn salsa::Database = &*$self; + $crate::db::FilesGroup::crate_input(db_ref, $crt).clone() + }; + let config = { + let db_ref: &dyn salsa::Database = &*$self; + ($root).map(|root| root.into_crate_configuration_input(db_ref)) + }; + $crate::db::set_crate_config_for_input($self, crate_input, config); + }}; } fn ensure_file_contents_handle_for_input( @@ -574,6 +698,22 @@ pub fn snapshot_file_contents(db: &dyn Database) -> FileContentSnapshot { .collect() } +/// Returns a snapshot of all per-crate configurations registered in this database. +/// Useful for copying configurations from one database to another. +pub fn snapshot_crate_configs( + db: &dyn Database, +) -> OrderedHashMap { + crate_config_storage(db) + .read() + .unwrap() + .iter() + .filter_map(|(crate_input, handle)| { + let config = handle.config(db).as_ref()?.clone(); + Some((crate_input.clone(), config)) + }) + .collect() +} + fn cfg_set_helper(db: &dyn Database) -> &CfgSet { files_group_input(db).cfg_set(db).as_ref().expect("cfg_set is not set") } @@ -585,13 +725,22 @@ fn crates<'db>(db: &'db dyn Database) -> Vec> { } /// Tracked function to return the configuration of a crate. +/// +/// # Invalidation +/// +/// Reads [`FilesGroupInput::crate_configs_revision`] so the query re-executes when a +/// [`CrateConfig`] handle is first created for a previously-unregistered crate. #[salsa::tracked(returns(ref))] fn crate_config_helper<'db>( db: &'db dyn Database, crt: CrateId<'db>, ) -> Option> { + let _ = files_group_input(db).crate_configs_revision(db); match crt.long(db) { - CrateLongId::Real { .. } => db.crate_configs().get(&crt).cloned(), + CrateLongId::Real { .. } => crate_config_view(db) + .crate_config_input_for(crt) + .cloned() + .map(|config| config.into_crate_configuration(db)), CrateLongId::Virtual { name: _, file_id, settings, cache_file } => { Some(CrateConfiguration { root: Directory::Virtual { diff --git a/crates/cairo-lang-filesystem/src/test_utils.rs b/crates/cairo-lang-filesystem/src/test_utils.rs index d8c44558b1f..94bd2e1d4ed 100644 --- a/crates/cairo-lang-filesystem/src/test_utils.rs +++ b/crates/cairo-lang-filesystem/src/test_utils.rs @@ -1,4 +1,7 @@ -use crate::db::{FileContentStorage, FileContentView, init_files_group, register_files_group_view}; +use crate::db::{ + CrateConfigStorage, CrateConfigView, FileContentStorage, FileContentView, init_files_group, + register_crate_config_view, register_files_group_view, +}; // Test salsa database. #[salsa::db] @@ -6,6 +9,7 @@ use crate::db::{FileContentStorage, FileContentView, init_files_group, register_ pub struct FilesDatabaseForTesting { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] @@ -15,11 +19,22 @@ impl FileContentView for FilesDatabaseForTesting { Some(&self.file_contents) } } +impl CrateConfigView for FilesDatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl Default for FilesDatabaseForTesting { fn default() -> Self { - let mut res = Self { storage: Default::default(), file_contents: Default::default() }; + let mut res = Self { + storage: Default::default(), + file_contents: Default::default(), + crate_configs: Default::default(), + }; + register_files_group_view(&res); + register_crate_config_view(&res); init_files_group(&mut res); res } diff --git a/crates/cairo-lang-lowering/src/cache/test.rs b/crates/cairo-lang-lowering/src/cache/test.rs index 3137d7bfaf3..248ca5af704 100644 --- a/crates/cairo-lang-lowering/src/cache/test.rs +++ b/crates/cairo-lang-lowering/src/cache/test.rs @@ -1,4 +1,4 @@ -use cairo_lang_filesystem::db::{FilesGroup, files_group_input, set_crate_configs_input}; +use cairo_lang_filesystem::db::{FilesGroup, set_crate_config_for_input}; use cairo_lang_filesystem::ids::BlobLongId; use cairo_lang_semantic::corelib::CorelibSemantic; use cairo_lang_semantic::test_utils::setup_test_function_ex; @@ -37,11 +37,14 @@ fn test_cache_check( let artifact = generate_crate_cache(db, test_function.module_id.owning_crate(db)).unwrap(); let core_artifact = generate_crate_cache(db, db.core_crate()).unwrap(); let mut new_db = LoweringDatabaseForTesting::new(); - let crt = new_db.crate_input(new_db.core_crate()); - let mut crate_configs = files_group_input(&new_db).crate_configs(&new_db).clone().unwrap(); - let config = crate_configs.get_mut(crt).unwrap(); + let crt = new_db.crate_input(new_db.core_crate()).clone(); + let mut config = new_db + .crate_config(new_db.core_crate()) + .unwrap() + .clone() + .into_crate_configuration_input(&new_db); config.cache_file = Some(BlobLongId::Virtual(core_artifact)); - set_crate_configs_input(&mut new_db, Some(crate_configs)); + set_crate_config_for_input(&mut new_db, crt, Some(config)); let cached_file = BlobLongId::Virtual(artifact).intern(&new_db); let (test_function, semantic_diagnostics) = setup_test_function_ex( diff --git a/crates/cairo-lang-lowering/src/test_utils.rs b/crates/cairo-lang-lowering/src/test_utils.rs index b0f589bed03..53cbedc9e2a 100644 --- a/crates/cairo-lang-lowering/src/test_utils.rs +++ b/crates/cairo-lang-lowering/src/test_utils.rs @@ -2,7 +2,10 @@ use std::sync::{LazyLock, Mutex}; use cairo_lang_debug::DebugWithDb; use cairo_lang_defs::db::{init_defs_group, init_external_files}; -use cairo_lang_filesystem::db::{FileContentView, init_dev_corelib, init_files_group}; +use cairo_lang_filesystem::db::{ + CrateConfigStorage, CrateConfigView, FileContentView, init_dev_corelib, init_files_group, + register_crate_config_view, +}; use cairo_lang_filesystem::detect::detect_corelib; use cairo_lang_filesystem::flag::{Flag, FlagsGroup}; use cairo_lang_filesystem::ids::FlagLongId; @@ -20,14 +23,24 @@ use crate::utils::InliningStrategy; #[derive(Clone)] pub struct LoweringDatabaseForTesting { storage: salsa::Storage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl salsa::Database for LoweringDatabaseForTesting {} impl FileContentView for LoweringDatabaseForTesting {} +impl CrateConfigView for LoweringDatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl LoweringDatabaseForTesting { pub fn new() -> Self { - let mut res = LoweringDatabaseForTesting { storage: Default::default() }; + let mut res = LoweringDatabaseForTesting { + storage: Default::default(), + crate_configs: Default::default(), + }; + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_defs_group(&mut res); diff --git a/crates/cairo-lang-plugins/src/test.rs b/crates/cairo-lang-plugins/src/test.rs index 2c9da43b495..46ad85a899b 100644 --- a/crates/cairo-lang-plugins/src/test.rs +++ b/crates/cairo-lang-plugins/src/test.rs @@ -8,8 +8,9 @@ use cairo_lang_defs::plugin::{ }; use cairo_lang_filesystem::cfg::CfgSet; use cairo_lang_filesystem::db::{ - CrateConfiguration, FileContentStorage, FileContentView, FilesGroup, files_group_input, - init_files_group, override_file_content_for_input, register_files_group_view, + CrateConfigStorage, CrateConfigView, CrateConfiguration, FileContentStorage, FileContentView, + FilesGroup, files_group_input, init_files_group, override_file_content_for_input, + register_crate_config_view, register_files_group_view, }; use cairo_lang_filesystem::ids::{ CodeMapping, CodeOrigin, CrateId, Directory, FileLongId, SmolStrId, @@ -57,6 +58,7 @@ cairo_lang_test_utils::test_file_test!( pub struct DatabaseForTesting { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl salsa::Database for DatabaseForTesting {} @@ -65,11 +67,22 @@ impl FileContentView for DatabaseForTesting { Some(&self.file_contents) } } +impl CrateConfigView for DatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl Default for DatabaseForTesting { fn default() -> Self { - let mut res = Self { storage: Default::default(), file_contents: Default::default() }; + let mut res = Self { + storage: Default::default(), + file_contents: Default::default(), + crate_configs: Default::default(), + }; + register_files_group_view(&res); + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_defs_group(&mut res); diff --git a/crates/cairo-lang-semantic/src/test_utils.rs b/crates/cairo-lang-semantic/src/test_utils.rs index d93c481ef23..1a0daee7c3d 100644 --- a/crates/cairo-lang-semantic/src/test_utils.rs +++ b/crates/cairo-lang-semantic/src/test_utils.rs @@ -4,8 +4,9 @@ use cairo_lang_defs::db::{DefsGroup, init_defs_group, init_external_files}; use cairo_lang_defs::ids::{FunctionWithBodyId, ModuleId}; use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder}; use cairo_lang_filesystem::db::{ - CrateSettings, Edition, ExperimentalFeaturesConfig, FileContentStorage, FileContentView, - init_dev_corelib, init_files_group, register_files_group_view, + CrateConfigStorage, CrateConfigView, CrateSettings, Edition, ExperimentalFeaturesConfig, + FileContentStorage, FileContentView, init_dev_corelib, init_files_group, + register_crate_config_view, register_files_group_view, }; use cairo_lang_filesystem::detect::detect_corelib; use cairo_lang_filesystem::ids::{ @@ -31,6 +32,7 @@ use crate::{ConcreteFunctionWithBodyId, SemanticDiagnostic, semantic}; pub struct SemanticDatabaseForTesting { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] @@ -40,6 +42,11 @@ impl FileContentView for SemanticDatabaseForTesting { Some(&self.file_contents) } } +impl CrateConfigView for SemanticDatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl SemanticDatabaseForTesting { pub fn new_empty() -> Self { @@ -51,8 +58,10 @@ impl SemanticDatabaseForTesting { let mut res = SemanticDatabaseForTesting { storage: Default::default(), file_contents: Default::default(), + crate_configs: Default::default(), }; register_files_group_view(&res); + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_defs_group(&mut res); diff --git a/crates/cairo-lang-sierra-generator/src/test_utils.rs b/crates/cairo-lang-sierra-generator/src/test_utils.rs index 84b71c3c2b0..493108aed83 100644 --- a/crates/cairo-lang-sierra-generator/src/test_utils.rs +++ b/crates/cairo-lang-sierra-generator/src/test_utils.rs @@ -4,8 +4,8 @@ use cairo_lang_defs as defs; use cairo_lang_defs::db::{DefsGroup, init_defs_group, init_external_files}; use cairo_lang_defs::ids::ModuleId; use cairo_lang_filesystem::db::{ - FileContentStorage, FileContentView, init_dev_corelib, init_files_group, - register_files_group_view, + CrateConfigStorage, CrateConfigView, FileContentStorage, FileContentView, init_dev_corelib, + init_files_group, register_crate_config_view, register_files_group_view, }; use cairo_lang_filesystem::detect::detect_corelib; use cairo_lang_filesystem::flag::{Flag, FlagsGroup}; @@ -36,6 +36,7 @@ use crate::utils::{jump_statement, return_statement, simple_statement}; pub struct SierraGenDatabaseForTesting { storage: salsa::Storage, file_contents: FileContentStorage, + crate_configs: CrateConfigStorage, } #[salsa::db] impl Database for SierraGenDatabaseForTesting {} @@ -45,6 +46,11 @@ impl FileContentView for SierraGenDatabaseForTesting { Some(&self.file_contents) } } +impl CrateConfigView for SierraGenDatabaseForTesting { + fn crate_config_storage(&self) -> Option<&CrateConfigStorage> { + Some(&self.crate_configs) + } +} impl CloneableDatabase for SierraGenDatabaseForTesting { fn dyn_clone(&self) -> Box { @@ -74,8 +80,10 @@ impl SierraGenDatabaseForTesting { let mut res = SierraGenDatabaseForTesting { storage: Default::default(), file_contents: Default::default(), + crate_configs: Default::default(), }; register_files_group_view(&res); + register_crate_config_view(&res); init_external_files(&mut res); init_files_group(&mut res); init_defs_group(&mut res); @@ -103,6 +111,7 @@ impl SierraGenDatabaseForTesting { SierraGenDatabaseForTesting { storage: self.storage.clone(), file_contents: self.file_contents.clone(), + crate_configs: self.crate_configs.clone(), } } }