From 65d8f9e8fe5d3a410c9b02e9f2107c8c1b406f56 Mon Sep 17 00:00:00 2001 From: Cam McHenry Date: Tue, 24 Sep 2024 07:29:08 -0400 Subject: [PATCH] perf(linter, ast-tools, coverage): Use `FxHashSet` instead of `std::collections::HashSet` (#6001) --- .clippy.toml | 1 + Cargo.lock | 1 + .../src/rules/eslint/no_this_before_super.rs | 10 +++--- .../src/rules/react/jsx_boolean_value.rs | 5 ++- .../explicit_function_return_type.rs | 5 ++- .../src/rules/vitest/prefer_each.rs | 31 +++++++++---------- .../oxc_linter/src/snapshots/prefer_each.snap | 8 ++--- tasks/ast_tools/src/derives/mod.rs | 5 ++- tasks/ast_tools/src/schema/mod.rs | 3 +- tasks/coverage/src/driver.rs | 5 +-- tasks/coverage/src/runtime/mod.rs | 6 ++-- tasks/prettier_conformance/Cargo.toml | 1 + tasks/prettier_conformance/src/lib.rs | 4 +-- 13 files changed, 42 insertions(+), 43 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 18a0450382296..9da0cf0e84dcc 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -11,4 +11,5 @@ disallowed-methods = [ disallowed-types = [ { path = "std::collections::HashMap", reason = "Use `rustc_hash::FxHashMap` instead, which is typically faster." }, + { path = "std::collections::HashSet", reason = "Use `rustc_hash::FxHashSet` instead, which is typically faster." }, ] diff --git a/Cargo.lock b/Cargo.lock index 022199e1f84a0..fd42d2857f3e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1815,6 +1815,7 @@ dependencies = [ "oxc_span", "oxc_tasks_common", "pico-args", + "rustc-hash", "walkdir", ] diff --git a/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs b/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs index 519826ebb5a78..db4fb50439d5e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs +++ b/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use oxc_ast::{ ast::{Argument, Expression, MethodDefinitionKind}, AstKind, @@ -12,7 +10,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; use oxc_span::{GetSpan, Span}; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -62,7 +60,7 @@ impl Rule for NoThisBeforeSuper { // first pass -> find super calls and local violations let mut wanted_nodes = Vec::new(); - let mut basic_blocks_with_super_called = HashSet::::new(); + let mut basic_blocks_with_super_called = FxHashSet::::default(); let mut basic_blocks_with_local_violations = FxHashMap::>::default(); for node in semantic.nodes() { @@ -154,7 +152,7 @@ impl NoThisBeforeSuper { fn analyze( cfg: &ControlFlowGraph, id: BasicBlockId, - basic_blocks_with_super_called: &HashSet, + basic_blocks_with_super_called: &FxHashSet, basic_blocks_with_local_violations: &FxHashMap>, follow_join: bool, ) -> Vec { @@ -213,7 +211,7 @@ impl NoThisBeforeSuper { fn check_for_violation( cfg: &ControlFlowGraph, output: Vec, - basic_blocks_with_super_called: &HashSet, + basic_blocks_with_super_called: &FxHashSet, basic_blocks_with_local_violations: &FxHashMap>, ) -> bool { // Deciding whether we definitely call this before super in all diff --git a/crates/oxc_linter/src/rules/react/jsx_boolean_value.rs b/crates/oxc_linter/src/rules/react/jsx_boolean_value.rs index 3a949bdff6152..e0c970ba5c974 100644 --- a/crates/oxc_linter/src/rules/react/jsx_boolean_value.rs +++ b/crates/oxc_linter/src/rules/react/jsx_boolean_value.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use oxc_ast::{ ast::{Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue}, AstKind, @@ -7,6 +5,7 @@ use oxc_ast::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; +use rustc_hash::FxHashSet; use crate::{ context::{ContextHost, LintContext}, @@ -43,7 +42,7 @@ pub enum EnforceBooleanAttribute { #[derive(Debug, Default, Clone)] pub struct JsxBooleanValueConfig { pub enforce_boolean_attribute: EnforceBooleanAttribute, - pub exceptions: HashSet, + pub exceptions: FxHashSet, pub assume_undefined_is_false: bool, } diff --git a/crates/oxc_linter/src/rules/typescript/explicit_function_return_type.rs b/crates/oxc_linter/src/rules/typescript/explicit_function_return_type.rs index 4e9d4a62b7140..ac06754280d3b 100644 --- a/crates/oxc_linter/src/rules/typescript/explicit_function_return_type.rs +++ b/crates/oxc_linter/src/rules/typescript/explicit_function_return_type.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use oxc_ast::{ ast::{ ArrowFunctionExpression, BindingPatternKind, Expression, FunctionType, JSXAttributeItem, @@ -11,6 +9,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; use oxc_syntax::operator::UnaryOperator; +use rustc_hash::FxHashSet; use crate::{ ast_util::outermost_paren_parent, @@ -32,7 +31,7 @@ pub struct ExplicitFunctionReturnTypeConfig { allow_direct_const_assertion_in_arrow_functions: bool, allow_concise_arrow_function_expressions_starting_with_void: bool, allow_functions_without_type_parameters: bool, - allowed_names: HashSet, + allowed_names: FxHashSet, allow_higher_order_functions: bool, allow_iifes: bool, } diff --git a/crates/oxc_linter/src/rules/vitest/prefer_each.rs b/crates/oxc_linter/src/rules/vitest/prefer_each.rs index 70499876c74c2..5f1427b11a919 100644 --- a/crates/oxc_linter/src/rules/vitest/prefer_each.rs +++ b/crates/oxc_linter/src/rules/vitest/prefer_each.rs @@ -1,10 +1,9 @@ -use std::collections::HashSet; - use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::{AstNode, NodeId}; use oxc_span::{GetSpan, Span}; +use rustc_hash::FxHashSet; use crate::{ context::LintContext, @@ -70,7 +69,7 @@ declare_oxc_lint!( impl Rule for PreferEach { fn run_once(&self, ctx: &LintContext<'_>) { - let mut skip = HashSet::::new(); + let mut skip = FxHashSet::::default(); ctx.nodes().iter().for_each(|node| { Self::run(node, ctx, &mut skip); }); @@ -78,7 +77,7 @@ impl Rule for PreferEach { } impl PreferEach { - fn run<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>, skip: &mut HashSet) { + fn run<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>, skip: &mut FxHashSet) { let kind = node.kind(); let AstKind::CallExpression(call_expr) = kind else { return }; @@ -164,7 +163,7 @@ fn test() { });"#, r#"it("only returns numbers that are greater than seven", function () { const numbers = getNumbers(); - + for (let i = 0; i < numbers.length; i++) { expect(numbers[i]).toBeGreaterThan(7); } @@ -191,7 +190,7 @@ fn test() { }); }); } - + for (const [input, expected] of data) { it.skip(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) @@ -205,7 +204,7 @@ fn test() { "it('is true', () => { expect(true).toBe(false); }); - + for (const [input, expected] of data) { it.skip(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) @@ -216,20 +215,20 @@ fn test() { expect(fn(input)).toBe(expected) }); } - + it('is true', () => { expect(true).toBe(false); });", " it('is true', () => { expect(true).toBe(false); }); - + for (const [input, expected] of data) { it.skip(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) }); } - + it('is true', () => { expect(true).toBe(false); });", @@ -237,7 +236,7 @@ fn test() { it(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) }); - + it(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) }); @@ -247,7 +246,7 @@ fn test() { expect(fn(input)).toBe(expected) }); } - + for (const [input, expected] of data) { it(`results in ${expected}`, () => { expect(fn(input)).toBe(expected) @@ -255,7 +254,7 @@ fn test() { }", "for (const [input, expected] of data) { beforeEach(() => setupSomething(input)); - + test(`results in ${expected}`, () => { expect(doSomething()).toBe(expected) }); @@ -264,7 +263,7 @@ fn test() { for (const [input, expected] of data) { it("only returns numbers that are greater than seven", function () { const numbers = getNumbers(input); - + for (let i = 0; i < numbers.length; i++) { expect(numbers[i]).toBeGreaterThan(7); } @@ -274,10 +273,10 @@ fn test() { r#" for (const [input, expected] of data) { beforeEach(() => setupSomething(input)); - + it("only returns numbers that are greater than seven", function () { const numbers = getNumbers(); - + for (let i = 0; i < numbers.length; i++) { expect(numbers[i]).toBeGreaterThan(7); } diff --git a/crates/oxc_linter/src/snapshots/prefer_each.snap b/crates/oxc_linter/src/snapshots/prefer_each.snap index 930894635a5ec..2ef1724a4472d 100644 --- a/crates/oxc_linter/src/snapshots/prefer_each.snap +++ b/crates/oxc_linter/src/snapshots/prefer_each.snap @@ -27,7 +27,7 @@ source: crates/oxc_linter/src/tester.rs ⚠ eslint-plugin-vitest(prefer-each): Enforce using `each` rather than manual loops ╭─[prefer_each.tsx:9:11] - 8 │ + 8 │ 9 │ for (const [input, expected] of data) { · ────────────────────────────────────── 10 │ it.skip(`results in ${expected}`, () => { @@ -44,7 +44,7 @@ source: crates/oxc_linter/src/tester.rs ⚠ eslint-plugin-vitest(prefer-each): Enforce using `each` rather than manual loops ╭─[prefer_each.tsx:5:11] - 4 │ + 4 │ 5 │ for (const [input, expected] of data) { · ────────────────────────────────────── 6 │ it.skip(`results in ${expected}`, () => { @@ -61,7 +61,7 @@ source: crates/oxc_linter/src/tester.rs ⚠ eslint-plugin-vitest(prefer-each): Enforce using `each` rather than manual loops ╭─[prefer_each.tsx:5:11] - 4 │ + 4 │ 5 │ for (const [input, expected] of data) { · ────────────────────────────────────── 6 │ it.skip(`results in ${expected}`, () => { @@ -86,7 +86,7 @@ source: crates/oxc_linter/src/tester.rs ⚠ eslint-plugin-vitest(prefer-each): Enforce using `each` rather than manual loops ╭─[prefer_each.tsx:7:11] - 6 │ + 6 │ 7 │ for (const [input, expected] of data) { · ────────────────────────────────────── 8 │ it(`results in ${expected}`, () => { diff --git a/tasks/ast_tools/src/derives/mod.rs b/tasks/ast_tools/src/derives/mod.rs index af4f330251bc4..f6617b34cc399 100644 --- a/tasks/ast_tools/src/derives/mod.rs +++ b/tasks/ast_tools/src/derives/mod.rs @@ -77,11 +77,10 @@ macro_rules! define_derive { } fn run(&mut self, ctx: &$crate::codegen::LateCtx) -> $crate::Result { - use std::collections::{HashSet}; use std::vec::Vec; use convert_case::{Case, Casing}; use itertools::Itertools; - use rustc_hash::FxHashMap; + use rustc_hash::{FxHashMap, FxHashSet}; use $crate::derives::DeriveTemplate; @@ -91,7 +90,7 @@ macro_rules! define_derive { .into_iter() .filter(|def| def.generates_derive(trait_name)) .map(|def| (def, self.derive(def, ctx))) - .fold(FxHashMap::<&str, (HashSet<&str>, Vec)>::default(), |mut acc, (def, stream)| { + .fold(FxHashMap::<&str, (FxHashSet<&str>, Vec)>::default(), |mut acc, (def, stream)| { let module_path = def.module_path(); let krate = module_path.split("::").next().unwrap(); if !acc.contains_key(krate) { diff --git a/tasks/ast_tools/src/schema/mod.rs b/tasks/ast_tools/src/schema/mod.rs index 5121a6a2100be..67e005326f318 100644 --- a/tasks/ast_tools/src/schema/mod.rs +++ b/tasks/ast_tools/src/schema/mod.rs @@ -1,4 +1,5 @@ use quote::ToTokens; +use rustc_hash::FxHashSet; use serde::Serialize; use crate::{ @@ -294,7 +295,7 @@ fn get_docs(attrs: &[syn::Attribute]) -> Vec { } fn parse_generate_derive(attrs: &[syn::Attribute]) -> Vec { - let mut derives = std::collections::HashSet::new(); + let mut derives = FxHashSet::default(); for attr in attrs { if !attr.path().is_ident("generate_derive") { continue; diff --git a/tasks/coverage/src/driver.rs b/tasks/coverage/src/driver.rs index acde33772b179..d22fb31aee873 100644 --- a/tasks/coverage/src/driver.rs +++ b/tasks/coverage/src/driver.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, ops::ControlFlow, path::PathBuf}; +use std::{ops::ControlFlow, path::PathBuf}; use oxc::{ allocator::Allocator, @@ -19,6 +19,7 @@ use oxc::{ transformer::{TransformOptions, TransformerReturn}, CompilerInterface, }; +use rustc_hash::FxHashSet; use crate::suite::TestResult; @@ -146,7 +147,7 @@ impl Driver { } fn check_comments(&mut self, trivias: &Trivias) -> bool { - let mut uniq: HashSet = HashSet::new(); + let mut uniq: FxHashSet = FxHashSet::default(); for comment in trivias.comments() { if !uniq.insert(comment.span) { self.errors diff --git a/tasks/coverage/src/runtime/mod.rs b/tasks/coverage/src/runtime/mod.rs index 572f8a622d6c9..0b534fdce00ca 100644 --- a/tasks/coverage/src/runtime/mod.rs +++ b/tasks/coverage/src/runtime/mod.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, fs, path::{Path, PathBuf}, time::Duration, @@ -8,6 +7,7 @@ use std::{ use oxc::{allocator::Allocator, codegen::CodeGenerator, parser::Parser, span::SourceType}; use oxc_tasks_common::agent; use phf::{phf_set, Set}; +use rustc_hash::FxHashSet; use serde_json::json; use crate::{ @@ -19,8 +19,8 @@ use crate::{ pub const V8_TEST_262_FAILED_TESTS_PATH: &str = "src/runtime/v8_test262.status"; lazy_static::lazy_static! { - static ref V8_TEST_262_FAILED_TESTS: HashSet = { - let mut set = HashSet::default(); + static ref V8_TEST_262_FAILED_TESTS: FxHashSet = { + let mut set = FxHashSet::default(); fs::read_to_string(workspace_root().join(V8_TEST_262_FAILED_TESTS_PATH)) .expect("Failed to read v8_test262.status") .lines() diff --git a/tasks/prettier_conformance/Cargo.toml b/tasks/prettier_conformance/Cargo.toml index 7562d591adce9..e4909c66383ac 100644 --- a/tasks/prettier_conformance/Cargo.toml +++ b/tasks/prettier_conformance/Cargo.toml @@ -31,4 +31,5 @@ oxc_span = { workspace = true } oxc_tasks_common = { workspace = true } pico-args = { workspace = true } +rustc-hash = { workspace = true } walkdir = { workspace = true } diff --git a/tasks/prettier_conformance/src/lib.rs b/tasks/prettier_conformance/src/lib.rs index bc8fd2189aa44..c04dce386e3e3 100644 --- a/tasks/prettier_conformance/src/lib.rs +++ b/tasks/prettier_conformance/src/lib.rs @@ -3,7 +3,6 @@ mod ignore_list; mod spec; use std::{ - collections::HashSet, fs, path::{Path, PathBuf}, }; @@ -13,6 +12,7 @@ use oxc_parser::{ParseOptions, Parser}; use oxc_prettier::{Prettier, PrettierOptions}; use oxc_span::SourceType; use oxc_tasks_common::project_root; +use rustc_hash::FxHashSet; use walkdir::WalkDir; use crate::{ @@ -113,7 +113,7 @@ impl TestRunner { .filter(|path| path.join("__snapshots__").exists()) .collect::>(); - let dir_set: HashSet<_> = dirs.iter().cloned().collect(); + let dir_set: FxHashSet<_> = dirs.iter().cloned().collect(); dirs = dir_set.into_iter().collect(); dirs.sort_unstable();