diff --git a/Cargo.lock b/Cargo.lock index 4e66fa7..05faa8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -695,6 +695,7 @@ dependencies = [ "insta", "mabo-parser", "miette", + "rustc-hash", "schemars", "serde", "serde_json", @@ -756,6 +757,7 @@ dependencies = [ "ouroboros", "parking_lot", "ropey", + "rustc-hash", "serde", "serde_json", "time", @@ -1083,6 +1085,12 @@ dependencies = [ "str_indices", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.38.30" diff --git a/Cargo.toml b/Cargo.toml index 62ec6ce..37ec4db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ miette = "5.10.0" mimalloc = "0.1.39" proc-macro2 = { version = "1.0.76", default-features = false } quote = { version = "1.0.35", default-features = false } +rustc-hash = "1.1.0" serde = { version = "1.0.195", features = ["derive"] } serde_json = "1.0.111" syn = "2.0.48" diff --git a/crates/mabo-compiler/Cargo.toml b/crates/mabo-compiler/Cargo.toml index b0404c8..b49d7b1 100644 --- a/crates/mabo-compiler/Cargo.toml +++ b/crates/mabo-compiler/Cargo.toml @@ -14,6 +14,7 @@ anstream.workspace = true anstyle.workspace = true mabo-parser = { path = "../mabo-parser" } miette.workspace = true +rustc-hash.workspace = true schemars = { version = "0.8.16", optional = true } serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } diff --git a/crates/mabo-compiler/src/resolve/mod.rs b/crates/mabo-compiler/src/resolve/mod.rs index 7725e29..bbcc2e5 100644 --- a/crates/mabo-compiler/src/resolve/mod.rs +++ b/crates/mabo-compiler/src/resolve/mod.rs @@ -1,12 +1,11 @@ //! Ensure all referenced types within a schema itself, aswell as between schemas exist and are //! correct. -use std::collections::HashMap; - use mabo_parser::{ DataType, Definition, ExternalType, Fields, Generics, Import, Name, Schema, Spanned, Type, }; use miette::NamedSource; +use rustc_hash::FxHashMap; pub use self::error::{ Error, GenericsCount, InvalidKind, MissingDefinition, MissingImport, MissingModule, @@ -83,7 +82,7 @@ pub(crate) struct Module<'a> { /// List of types that are declared in this module. types: Vec>, /// Direct submodules located in this module. - modules: HashMap<&'a str, Module<'a>>, + modules: FxHashMap<&'a str, Module<'a>>, /// List of original definitions. definitions: &'a [Definition<'a>], } @@ -411,7 +410,7 @@ fn visit_module_tree<'a>( path, imports: Vec::new(), types: Vec::new(), - modules: HashMap::new(), + modules: FxHashMap::default(), definitions: defs, }; diff --git a/crates/mabo-compiler/src/validate/generics.rs b/crates/mabo-compiler/src/validate/generics.rs index efa3f4e..d08b522 100644 --- a/crates/mabo-compiler/src/validate/generics.rs +++ b/crates/mabo-compiler/src/validate/generics.rs @@ -1,7 +1,8 @@ -use std::{collections::HashMap, ops::Range}; +use std::{hash::BuildHasherDefault, ops::Range}; use mabo_parser::{DataType, Enum, ExternalType, Fields, Generics, Span, Spanned, Struct, Type}; use miette::Diagnostic; +use rustc_hash::FxHashMap; use thiserror::Error; /// Generic type parameters are considered invalid. @@ -53,7 +54,7 @@ pub fn validate_struct_generics(value: &Struct<'_>) -> Result<(), InvalidGeneric .0 .iter() .map(|gen| (gen.get(), gen.span())) - .collect::>(); + .collect::>(); validate_field_generics(&value.fields, &mut unvisited); @@ -75,7 +76,7 @@ pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType .0 .iter() .map(|gen| (gen.get(), gen.span())) - .collect::>(); + .collect::>(); for variant in &value.variants { validate_field_generics(&variant.fields, &mut unvisited); @@ -92,7 +93,8 @@ pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType /// Ensure all generic type arguments are unique within a struct or enum. fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGenericName> { - let mut visited = HashMap::with_capacity(value.0.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(value.0.len(), BuildHasherDefault::default()); value .0 .iter() @@ -110,7 +112,7 @@ fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGene /// Iterate over all the fields and mark any generic types as used when disvored as type for a /// field. -fn validate_field_generics(value: &Fields<'_>, unvisited: &mut HashMap<&str, Span>) { +fn validate_field_generics(value: &Fields<'_>, unvisited: &mut FxHashMap<&str, Span>) { match &value { Fields::Named(named) => { for field in named { diff --git a/crates/mabo-compiler/src/validate/ids.rs b/crates/mabo-compiler/src/validate/ids.rs index 5e26a4f..afd6d28 100644 --- a/crates/mabo-compiler/src/validate/ids.rs +++ b/crates/mabo-compiler/src/validate/ids.rs @@ -1,7 +1,8 @@ -use std::{collections::HashMap, ops::Range}; +use std::{hash::BuildHasherDefault, ops::Range}; use mabo_parser::{Enum, Fields, Id, Spanned, Struct}; use miette::Diagnostic; +use rustc_hash::FxHashMap; use thiserror::Error; use crate::IdGenerator; @@ -97,7 +98,8 @@ pub(crate) fn validate_struct_ids(value: &Struct<'_>) -> Result<(), DuplicateFie /// Ensure all IDs inside an enum are unique, which means all variants have a unique ID, plus all /// potential fields in a variant are unique (within that variant). pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> { - let mut visited = HashMap::with_capacity(value.variants.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(value.variants.len(), BuildHasherDefault::default()); let mut id_gen = IdGenerator::new(); value @@ -131,7 +133,8 @@ pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> { fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { match value { Fields::Named(named) => { - let mut visited = HashMap::with_capacity(named.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(named.len(), BuildHasherDefault::default()); let mut id_gen = IdGenerator::new(); named @@ -152,7 +155,8 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { .map_or(Ok(()), Err)?; } Fields::Unnamed(unnamed) => { - let mut visited = HashMap::with_capacity(unnamed.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(unnamed.len(), BuildHasherDefault::default()); let mut id_gen = IdGenerator::new(); unnamed diff --git a/crates/mabo-compiler/src/validate/names.rs b/crates/mabo-compiler/src/validate/names.rs index b97a039..e03a460 100644 --- a/crates/mabo-compiler/src/validate/names.rs +++ b/crates/mabo-compiler/src/validate/names.rs @@ -1,7 +1,8 @@ -use std::{collections::HashMap, ops::Range}; +use std::{hash::BuildHasherDefault, ops::Range}; use mabo_parser::{Definition, Enum, Fields, Import, Spanned, Struct}; use miette::Diagnostic; +use rustc_hash::FxHashMap; use thiserror::Error; /// Duplicate name was encountered for two elements in the same scope. @@ -76,7 +77,8 @@ pub(crate) fn validate_struct_names(value: &Struct<'_>) -> Result<(), DuplicateF /// Ensure all names inside an enum are unique, which means all variants have a unique name, plus /// all potential fields in a variant are unique (within that variant). pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> { - let mut visited = HashMap::with_capacity(value.variants.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(value.variants.len(), BuildHasherDefault::default()); value .variants .iter() @@ -104,7 +106,8 @@ pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> { match value { Fields::Named(named) => { - let mut visited = HashMap::with_capacity(named.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(named.len(), BuildHasherDefault::default()); named .iter() .find_map(|field| { @@ -125,7 +128,8 @@ fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> { } pub(crate) fn validate_names_in_module(value: &[Definition<'_>]) -> Result<(), DuplicateName> { - let mut visited = HashMap::with_capacity(value.len()); + let mut visited = + FxHashMap::with_capacity_and_hasher(value.len(), BuildHasherDefault::default()); value .iter() .find_map(|definition| { diff --git a/crates/mabo-lsp/Cargo.toml b/crates/mabo-lsp/Cargo.toml index 8419ad6..57024cf 100644 --- a/crates/mabo-lsp/Cargo.toml +++ b/crates/mabo-lsp/Cargo.toml @@ -24,6 +24,7 @@ mabo-project = { path = "../mabo-project" } ouroboros = "0.18.2" parking_lot = "0.12.1" ropey = "1.6.1" +rustc-hash.workspace = true serde_json.workspace = true serde.workspace = true time = { version = "0.3.31", features = ["formatting", "local-offset", "macros"] } diff --git a/crates/mabo-lsp/src/main.rs b/crates/mabo-lsp/src/main.rs index 4f2489c..f05cdf2 100644 --- a/crates/mabo-lsp/src/main.rs +++ b/crates/mabo-lsp/src/main.rs @@ -2,7 +2,7 @@ #![warn(clippy::expect_used, clippy::unwrap_used)] -use std::{collections::HashMap, net::Ipv4Addr, time::Instant}; +use std::{net::Ipv4Addr, time::Instant}; use anyhow::{bail, Result}; use log::{as_debug, debug, error, info, warn}; @@ -18,6 +18,7 @@ use lsp_types::{ }, DocumentSymbol, InitializeParams, SemanticTokens, }; +use rustc_hash::FxHashMap; use self::{cli::Cli, client::Client}; use crate::state::GlobalState; @@ -45,7 +46,7 @@ fn main() -> Result<()> { let mut state = GlobalState { client: Client::new(&connection), - files: HashMap::default(), + files: FxHashMap::default(), settings: config::Global::default(), }; diff --git a/crates/mabo-lsp/src/state.rs b/crates/mabo-lsp/src/state.rs index 27b6246..702b654 100644 --- a/crates/mabo-lsp/src/state.rs +++ b/crates/mabo-lsp/src/state.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use anyhow::{ensure, Context, Result}; use line_index::LineIndex; use log::{as_debug, debug}; @@ -7,13 +5,14 @@ use lsp_types::{ConfigurationItem, Diagnostic, Url}; use mabo_parser::Schema; use ouroboros::self_referencing; use ropey::Rope; +use rustc_hash::FxHashMap; use crate::{client::Client, config}; #[allow(clippy::module_name_repetitions)] pub struct GlobalState<'a> { pub client: Client<'a>, - pub files: HashMap, + pub files: FxHashMap, pub settings: config::Global, }