diff --git a/ast/src/canonicalization/module.rs b/ast/src/canonicalization/module.rs index 64c568af5f..634e7e881c 100644 --- a/ast/src/canonicalization/module.rs +++ b/ast/src/canonicalization/module.rs @@ -7,6 +7,7 @@ use roc_can::operator::desugar_def; use roc_collections::all::{default_hasher, ImMap, ImSet, MutMap, MutSet, SendMap}; use roc_module::ident::Ident; use roc_module::ident::Lowercase; +use roc_module::symbol::IdentIdsByModule; use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol}; use roc_parse::ast; use roc_parse::pattern::PatternType; @@ -48,7 +49,7 @@ pub fn canonicalize_module_defs<'a>( home: ModuleId, module_ids: &ModuleIds, exposed_ident_ids: IdentIds, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, aliases: MutMap, exposed_imports: MutMap, mut exposed_symbols: MutSet, diff --git a/ast/src/lang/env.rs b/ast/src/lang/env.rs index 0af9303543..d2ea5448bd 100644 --- a/ast/src/lang/env.rs +++ b/ast/src/lang/env.rs @@ -2,7 +2,7 @@ use crate::mem_pool::pool::{NodeId, Pool}; use bumpalo::{collections::Vec as BumpVec, Bump}; use roc_collections::all::{MutMap, MutSet}; use roc_module::ident::{Ident, Lowercase, ModuleName}; -use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol}; +use roc_module::symbol::{IdentIds, IdentIdsByModule, ModuleId, ModuleIds, Symbol}; use roc_problem::can::{Problem, RuntimeError}; use roc_region::all::{Loc, Region}; use roc_types::subs::VarStore; @@ -19,7 +19,7 @@ pub struct Env<'a> { pub problems: BumpVec<'a, Problem>, - pub dep_idents: MutMap, + pub dep_idents: IdentIdsByModule, pub module_ids: &'a ModuleIds, pub ident_ids: IdentIds, pub exposed_ident_ids: IdentIds, @@ -41,7 +41,7 @@ impl<'a> Env<'a> { arena: &'a Bump, pool: &'a mut Pool, var_store: &'a mut VarStore, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, module_ids: &'a ModuleIds, exposed_ident_ids: IdentIds, ) -> Env<'a> { diff --git a/ast/src/lang/scope.rs b/ast/src/lang/scope.rs index 1f57b4360b..ced87957e4 100644 --- a/ast/src/lang/scope.rs +++ b/ast/src/lang/scope.rs @@ -12,7 +12,8 @@ use crate::mem_pool::shallow_clone::ShallowClone; use roc_collections::all::{MutMap, MutSet}; use roc_module::ident::{Ident, Lowercase}; use roc_module::symbol::{ - get_module_ident_ids, get_module_ident_ids_mut, IdentIds, Interns, ModuleId, Symbol, + get_module_ident_ids, get_module_ident_ids_mut, IdentIds, IdentIdsByModule, Interns, ModuleId, + Symbol, }; use roc_problem::can::RuntimeError; use roc_region::all::{Loc, Region}; @@ -320,11 +321,7 @@ impl Scope { self.aliases.contains_key(&name) } - pub fn fill_scope( - &mut self, - env: &Env, - all_ident_ids: &mut MutMap, - ) -> ASTResult<()> { + pub fn fill_scope(&mut self, env: &Env, all_ident_ids: &mut IdentIdsByModule) -> ASTResult<()> { let ident_ids = get_module_ident_ids(all_ident_ids, &env.home)?.clone(); for (_, ident_ref) in ident_ids.ident_strs() { diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index a5413def46..bf7520dbcd 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -984,7 +984,7 @@ fn add_annotation_aliases( aliases: &mut VecMap, ) { for (name, alias) in type_annotation.aliases.iter() { - if !aliases.contains(name) { + if !aliases.contains_key(name) { aliases.insert(*name, alias.clone()); } } diff --git a/compiler/can/src/env.rs b/compiler/can/src/env.rs index 2c7a28ad69..e127c32bea 100644 --- a/compiler/can/src/env.rs +++ b/compiler/can/src/env.rs @@ -1,7 +1,7 @@ use crate::procedure::References; use roc_collections::{MutMap, VecSet}; use roc_module::ident::{Ident, Lowercase, ModuleName}; -use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol}; +use roc_module::symbol::{IdentIds, IdentIdsByModule, ModuleId, ModuleIds, Symbol}; use roc_problem::can::{Problem, RuntimeError}; use roc_region::all::{Loc, Region}; @@ -11,7 +11,7 @@ pub struct Env<'a> { /// are assumed to be relative to this path. pub home: ModuleId, - pub dep_idents: &'a MutMap, + pub dep_idents: &'a IdentIdsByModule, pub module_ids: &'a ModuleIds, @@ -42,7 +42,7 @@ pub struct Env<'a> { impl<'a> Env<'a> { pub fn new( home: ModuleId, - dep_idents: &'a MutMap, + dep_idents: &'a IdentIdsByModule, module_ids: &'a ModuleIds, exposed_ident_ids: IdentIds, ) -> Env<'a> { diff --git a/compiler/can/src/module.rs b/compiler/can/src/module.rs index db8cd17b1c..0db77094cc 100644 --- a/compiler/can/src/module.rs +++ b/compiler/can/src/module.rs @@ -10,7 +10,7 @@ use bumpalo::Bump; use roc_collections::{MutMap, SendMap, VecSet}; use roc_module::ident::Ident; use roc_module::ident::Lowercase; -use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol}; +use roc_module::symbol::{IdentIds, IdentIdsByModule, ModuleId, ModuleIds, Symbol}; use roc_parse::ast; use roc_parse::header::HeaderFor; use roc_parse::pattern::PatternType; @@ -170,7 +170,7 @@ pub fn canonicalize_module_defs<'a>( home: ModuleId, module_ids: &ModuleIds, exposed_ident_ids: IdentIds, - dep_idents: &'a MutMap, + dep_idents: &'a IdentIdsByModule, aliases: MutMap, exposed_imports: MutMap, exposed_symbols: &VecSet, diff --git a/compiler/collections/src/vec_map.rs b/compiler/collections/src/vec_map.rs index 60b1608737..68de20f849 100644 --- a/compiler/collections/src/vec_map.rs +++ b/compiler/collections/src/vec_map.rs @@ -54,7 +54,7 @@ impl VecMap { } } - pub fn contains(&self, key: &K) -> bool { + pub fn contains_key(&self, key: &K) -> bool { self.keys.contains(key) } @@ -69,6 +69,34 @@ impl VecMap { } } + pub fn get(&self, key: &K) -> Option<&V> { + match self.keys.iter().position(|x| x == key) { + None => None, + Some(index) => Some(&self.values[index]), + } + } + + pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { + match self.keys.iter().position(|x| x == key) { + None => None, + Some(index) => Some(&mut self.values[index]), + } + } + + pub fn get_or_insert(&mut self, key: K, default_value: impl Fn() -> V) -> &mut V { + match self.keys.iter().position(|x| x == &key) { + Some(index) => &mut self.values[index], + None => { + let value = default_value(); + + self.keys.push(key); + self.values.push(value); + + self.values.last_mut().unwrap() + } + } + } + pub fn iter(&self) -> impl Iterator { self.keys.iter().zip(self.values.iter()) } diff --git a/compiler/load_internal/src/file.rs b/compiler/load_internal/src/file.rs index 20584442b3..3b5acebcc6 100644 --- a/compiler/load_internal/src/file.rs +++ b/compiler/load_internal/src/file.rs @@ -18,8 +18,8 @@ use roc_constrain::module::{ use roc_error_macros::internal_error; use roc_module::ident::{Ident, ModuleName, QualifiedModuleName, TagName}; use roc_module::symbol::{ - IdentIds, Interns, ModuleId, ModuleIds, PQModuleName, PackageModuleIds, PackageQualified, - Symbol, + IdentIds, IdentIdsByModule, Interns, ModuleId, ModuleIds, PQModuleName, PackageModuleIds, + PackageQualified, Symbol, }; use roc_mono::ir::{ CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs, @@ -168,6 +168,8 @@ impl Default for ModuleCache<'_> { } } +type SharedIdentIdsByModule = Arc>; + fn start_phase<'a>( module_id: ModuleId, phase: Phase, @@ -228,8 +230,7 @@ fn start_phase<'a>( let deps_by_name = &parsed.deps_by_name; let num_deps = deps_by_name.len(); - let mut dep_idents: MutMap = - IdentIds::exposed_builtins(num_deps); + let mut dep_idents: IdentIdsByModule = IdentIds::exposed_builtins(num_deps); let State { ident_ids_by_module, @@ -419,7 +420,7 @@ pub struct LoadedModule { pub type_problems: MutMap>, pub declarations_by_id: MutMap>, pub exposed_to_host: MutMap, - pub dep_idents: MutMap, + pub dep_idents: IdentIdsByModule, pub exposed_aliases: MutMap, pub exposed_values: Vec, pub sources: MutMap)>, @@ -483,7 +484,7 @@ struct ConstrainedModule { constraint: ConstraintSoa, ident_ids: IdentIds, var_store: VarStore, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, module_timing: ModuleTiming, } @@ -587,7 +588,7 @@ enum Msg<'a> { solved_module: SolvedModule, solved_subs: Solved, decls: Vec, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, module_timing: ModuleTiming, abilities_store: AbilitiesStore, }, @@ -595,7 +596,7 @@ enum Msg<'a> { solved_subs: Solved, exposed_vars_by_symbol: Vec<(Symbol, Variable)>, exposed_aliases_by_symbol: MutMap, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, documentation: MutMap, abilities_store: AbilitiesStore, }, @@ -668,13 +669,13 @@ struct State<'a> { /// This is the "final" list of IdentIds, after canonicalization and constraint gen /// have completed for a given module. - pub constrained_ident_ids: MutMap, + pub constrained_ident_ids: IdentIdsByModule, /// From now on, these will be used by multiple threads; time to make an Arc>! pub arc_modules: Arc>>, pub arc_shorthands: Arc>>>, - pub ident_ids_by_module: Arc>>, + pub ident_ids_by_module: SharedIdentIdsByModule, pub declarations_by_id: MutMap>, @@ -705,7 +706,7 @@ impl<'a> State<'a> { goal_phase: Phase, exposed_types: ExposedByModule, arc_modules: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, cached_subs: MutMap)>, render: RenderTarget, ) -> Self { @@ -814,7 +815,7 @@ enum BuildTask<'a> { module_name: PQModuleName<'a>, module_ids: Arc>>, shorthands: Arc>>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, }, Parse { header: ModuleHeader<'a>, @@ -822,7 +823,7 @@ enum BuildTask<'a> { CanonicalizeAndConstrain { parsed: ParsedModule<'a>, module_ids: ModuleIds, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, exposed_symbols: VecSet, aliases: MutMap, skip_constraint_gen: bool, @@ -837,7 +838,7 @@ enum BuildTask<'a> { constraint: ConstraintSoa, var_store: VarStore, declarations: Vec, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, cached_subs: CachedSubs, }, BuildPendingSpecializations { @@ -951,7 +952,7 @@ pub enum PrintTarget { pub struct LoadStart<'a> { arc_modules: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, root_id: ModuleId, root_msg: Msg<'a>, } @@ -2403,7 +2404,7 @@ fn finish( solved: Solved, exposed_aliases_by_symbol: MutMap, exposed_vars_by_symbol: Vec<(Symbol, Variable)>, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, documentation: MutMap, abilities_store: AbilitiesStore, ) -> LoadedModule { @@ -2451,7 +2452,7 @@ fn load_pkg_config<'a>( shorthand: &'a str, app_module_id: ModuleId, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, ) -> Result, LoadingProblem<'a>> { let module_start_time = SystemTime::now(); @@ -2569,7 +2570,7 @@ fn load_builtin_module_help<'a>( fn load_builtin_module<'a>( arena: &'a Bump, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, module_timing: ModuleTiming, module_id: ModuleId, module_name: &str, @@ -2594,7 +2595,7 @@ fn load_module<'a>( module_name: PQModuleName<'a>, module_ids: Arc>>, arc_shorthands: Arc>>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, ) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { let module_start_time = SystemTime::now(); @@ -2781,7 +2782,7 @@ fn parse_header<'a>( is_root_module: bool, opt_shorthand: Option<&'a str>, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, src_bytes: &'a [u8], start_time: SystemTime, ) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { @@ -2969,7 +2970,7 @@ fn load_filename<'a>( is_root_module: bool, opt_shorthand: Option<&'a str>, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, module_start_time: SystemTime, ) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { let file_io_start = SystemTime::now(); @@ -3003,7 +3004,7 @@ fn load_from_str<'a>( filename: PathBuf, src: &'a str, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, module_start_time: SystemTime, ) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { let file_io_start = SystemTime::now(); @@ -3039,7 +3040,7 @@ fn send_header<'a>( info: HeaderInfo<'a>, parse_state: roc_parse::state::State<'a>, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { use ModuleNameEnum::*; @@ -3102,9 +3103,7 @@ fn send_header<'a>( home = module_ids.get_or_insert(&name); // Ensure this module has an entry in the exposed_ident_ids map. - ident_ids_by_module - .entry(home) - .or_insert_with(IdentIds::default); + ident_ids_by_module.get_or_insert(home); // For each of our imports, add an entry to deps_by_name // @@ -3131,9 +3130,7 @@ fn send_header<'a>( // Add the new exposed idents to the dep module's IdentIds, so // once that module later gets loaded, its lookups will resolve // to the same symbols as the ones we're using here. - let ident_ids = ident_ids_by_module - .entry(module_id) - .or_insert_with(IdentIds::default); + let ident_ids = ident_ids_by_module.get_or_insert(module_id); for ident in exposed_idents { let ident_id = ident_ids.get_or_insert(&ident); @@ -3255,7 +3252,7 @@ fn send_header_two<'a>( info: PlatformHeaderInfo<'a>, parse_state: roc_parse::state::State<'a>, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { let PlatformHeaderInfo { @@ -3314,9 +3311,7 @@ fn send_header_two<'a>( home = module_ids.get_or_insert(&name); // Ensure this module has an entry in the exposed_ident_ids map. - ident_ids_by_module - .entry(home) - .or_insert_with(IdentIds::default); + ident_ids_by_module.get_or_insert(home); // For each of our imports, add an entry to deps_by_name // @@ -3338,9 +3333,7 @@ fn send_header_two<'a>( // Add the new exposed idents to the dep module's IdentIds, so // once that module later gets loaded, its lookups will resolve // to the same symbols as the ones we're using here. - let ident_ids = ident_ids_by_module - .entry(module_id) - .or_insert_with(IdentIds::default); + let ident_ids = ident_ids_by_module.get_or_insert(module_id); for ident in exposed_idents { let ident_id = ident_ids.get_or_insert(&ident); @@ -3354,9 +3347,7 @@ fn send_header_two<'a>( } { - let ident_ids = ident_ids_by_module - .entry(app_module_id) - .or_insert_with(IdentIds::default); + let ident_ids = ident_ids_by_module.get_or_insert(app_module_id); for entry in requires { let entry = entry.value; @@ -3486,7 +3477,7 @@ impl<'a> BuildTask<'a> { var_store: VarStore, imported_modules: MutMap, exposed_types: &mut ExposedByModule, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, declarations: Vec, cached_subs: CachedSubs, ) -> Self { @@ -3668,7 +3659,7 @@ fn run_solve<'a>( constraint: ConstraintSoa, var_store: VarStore, decls: Vec, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, cached_subs: CachedSubs, ) -> Msg<'a> { let solve_start = SystemTime::now(); @@ -3758,7 +3749,7 @@ fn fabricate_pkg_config_module<'a>( filename: PathBuf, parse_state: roc_parse::state::State<'a>, module_ids: Arc>>, - ident_ids_by_module: Arc>>, + ident_ids_by_module: SharedIdentIdsByModule, header: &PlatformHeader<'a>, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { @@ -3791,7 +3782,7 @@ fn fabricate_pkg_config_module<'a>( fn canonicalize_and_constrain<'a>( arena: &'a Bump, module_ids: &ModuleIds, - dep_idents: MutMap, + dep_idents: IdentIdsByModule, exposed_symbols: VecSet, aliases: MutMap, parsed: ParsedModule<'a>, @@ -4576,7 +4567,7 @@ fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String { fn to_parse_problem_report<'a>( problem: FileError<'a, SyntaxError<'a>>, mut module_ids: ModuleIds, - all_ident_ids: MutMap, + all_ident_ids: IdentIdsByModule, render: RenderTarget, ) -> String { use roc_reporting::report::{parse_problem, RocDocAllocator, DEFAULT_PALETTE}; diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 6f30cd0f6f..7043223a93 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -1,6 +1,6 @@ use crate::ident::{Ident, ModuleName}; use crate::module_err::{IdentIdNotFound, ModuleIdNotFound, ModuleResult}; -use roc_collections::all::{default_hasher, MutMap, SendMap}; +use roc_collections::{default_hasher, MutMap, SendMap, VecMap}; use roc_ident::IdentStr; use roc_region::all::Region; use snafu::OptionExt; @@ -207,7 +207,7 @@ lazy_static! { #[derive(Debug, Default)] pub struct Interns { pub module_ids: ModuleIds, - pub all_ident_ids: MutMap, + pub all_ident_ids: IdentIdsByModule, } impl Interns { @@ -249,7 +249,7 @@ impl Interns { } pub fn get_module_ident_ids<'a>( - all_ident_ids: &'a MutMap, + all_ident_ids: &'a IdentIdsByModule, module_id: &ModuleId, ) -> ModuleResult<&'a IdentIds> { all_ident_ids @@ -261,7 +261,7 @@ pub fn get_module_ident_ids<'a>( } pub fn get_module_ident_ids_mut<'a>( - all_ident_ids: &'a mut MutMap, + all_ident_ids: &'a mut IdentIdsByModule, module_id: &ModuleId, ) -> ModuleResult<&'a mut IdentIds> { all_ident_ids @@ -697,6 +697,35 @@ impl IdentIds { } } +#[derive(Debug, Default)] +pub struct IdentIdsByModule(VecMap); + +impl IdentIdsByModule { + pub fn get_or_insert(&mut self, module_id: ModuleId) -> &mut IdentIds { + self.0.get_or_insert(module_id, IdentIds::default) + } + + pub fn get_mut(&mut self, key: &ModuleId) -> Option<&mut IdentIds> { + self.0.get_mut(key) + } + + pub fn get(&self, key: &ModuleId) -> Option<&IdentIds> { + self.0.get(key) + } + + pub fn insert(&mut self, key: ModuleId, value: IdentIds) -> Option { + self.0.insert(key, value) + } + + pub fn keys(&self) -> impl Iterator { + self.0.keys() + } + + pub fn len(&self) -> usize { + self.0.len() + } +} + // BUILTINS const fn offset_helper(mut array: [u32; N]) -> [u32; N] { @@ -778,8 +807,8 @@ macro_rules! define_builtins { num_modules: $total:literal } => { impl IdentIds { - pub fn exposed_builtins(extra_capacity: usize) -> MutMap { - let mut exposed_idents_by_module = HashMap::with_capacity_and_hasher(extra_capacity + $total, default_hasher()); + pub fn exposed_builtins(extra_capacity: usize) -> IdentIdsByModule { + let mut exposed_idents_by_module = VecMap::with_capacity(extra_capacity + $total); $( debug_assert!(!exposed_idents_by_module.contains_key(&ModuleId($module_id)), r"Error setting up Builtins: when setting up module {} {:?} - the module ID {} is already present in the map. Check the map for duplicate module IDs!", $module_id, $module_name, $module_id); @@ -838,7 +867,7 @@ macro_rules! define_builtins { debug_assert!(exposed_idents_by_module.len() == $total, "Error setting up Builtins: `total:` is set to the wrong amount. It was set to {} but {} modules were set up.", $total, exposed_idents_by_module.len()); - exposed_idents_by_module + IdentIdsByModule(exposed_idents_by_module) } } diff --git a/docs/src/lib.rs b/docs/src/lib.rs index a2c01973c7..965fc7480f 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -6,13 +6,12 @@ use html::mark_node_to_html; use roc_can::scope::Scope; use roc_code_markup::markup::nodes::MarkupNode; use roc_code_markup::slow_pool::SlowPool; -use roc_collections::all::MutMap; use roc_highlight::highlight_parser::{highlight_defs, highlight_expr}; use roc_load::docs::DocEntry::DocDef; use roc_load::docs::{DocEntry, TypeAnnotation}; use roc_load::docs::{ModuleDocumentation, RecordField}; use roc_load::{LoadedModule, LoadingProblem}; -use roc_module::symbol::{IdentIds, Interns, ModuleId}; +use roc_module::symbol::{IdentIdsByModule, Interns, ModuleId}; use roc_parse::ident::{parse_ident, Ident}; use roc_parse::state::State; use roc_region::all::Region; @@ -711,7 +710,7 @@ struct DocUrl { fn doc_url<'a>( home: ModuleId, exposed_values: &[&str], - dep_idents: &MutMap, + dep_idents: &IdentIdsByModule, scope: &Scope, interns: &'a Interns, mut module_name: &'a str,