diff --git a/Cargo.lock b/Cargo.lock index 486e7b6b89..3079057b9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2253,6 +2253,7 @@ dependencies = [ "dirs 4.0.0", "fern", "filetime", + "fnv", "getrandom 0.2.8", "glob", "insta", diff --git a/Cargo.toml b/Cargo.toml index 0cdee0c2b5..041871c280 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ common-path = { version = "1.0.0" } dirs = { version = "4.0.0" } fern = { version = "0.6.1" } filetime = { version = "0.2.17" } +fnv = { version = "1.0.7" } glob = { version = "0.3.0" } itertools = { version = "0.10.5" } libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "a13ec97dd4eb925bde4d426c6e422582793b260c" } diff --git a/src/ast/helpers.rs b/src/ast/helpers.rs index 593a9e3879..8051f08881 100644 --- a/src/ast/helpers.rs +++ b/src/ast/helpers.rs @@ -1,5 +1,4 @@ -use std::collections::BTreeSet; - +use fnv::FnvHashSet; use once_cell::sync::Lazy; use regex::Regex; use rustpython_ast::{Excepthandler, ExcepthandlerKind, Expr, ExprKind, Location, StmtKind}; @@ -47,7 +46,7 @@ pub fn match_name_or_attr_from_module( expr: &Expr, target: &str, module: &str, - imports: Option<&BTreeSet<&str>>, + imports: Option<&FnvHashSet<&str>>, ) -> bool { match &expr.node { ExprKind::Attribute { value, attr, .. } => match &value.node { diff --git a/src/check_ast.rs b/src/check_ast.rs index 71a5da8b16..bb8ade8131 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -1,9 +1,10 @@ //! Lint rules based on AST traversal. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::ops::Deref; use std::path::Path; +use fnv::{FnvHashMap, FnvHashSet}; use log::error; use rustpython_parser::ast::{ Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, @@ -64,9 +65,9 @@ pub struct Checker<'a> { definitions: Vec<(Definition<'a>, Visibility)>, // Edit tracking. // TODO(charlie): Instead of exposing deletions, wrap in a public API. - pub(crate) deletions: BTreeSet, + pub(crate) deletions: FnvHashSet, // Import tracking. - pub(crate) from_imports: BTreeMap<&'a str, BTreeSet<&'a str>>, + pub(crate) from_imports: FnvHashMap<&'a str, FnvHashSet<&'a str>>, // Retain all scopes and parent nodes, along with a stack of indexes to track which are active // at various points in time. pub(crate) parents: Vec<&'a Stmt>, @@ -409,14 +410,14 @@ where StmtKind::Return { .. } => { if self.settings.enabled.contains(&CheckCode::F706) { if let Some(index) = self.scope_stack.last().cloned() { - match self.scopes[index].kind { - ScopeKind::Class(_) | ScopeKind::Module => { - self.add_check(Check::new( - CheckKind::ReturnOutsideFunction, - Range::from_located(stmt), - )); - } - _ => {} + if matches!( + self.scopes[index].kind, + ScopeKind::Class(_) | ScopeKind::Module + ) { + self.add_check(Check::new( + CheckKind::ReturnOutsideFunction, + Range::from_located(stmt), + )); } } } @@ -592,7 +593,7 @@ where if TRACK_FROM_IMPORTS.contains(&module.as_str()) { self.from_imports .entry(module) - .or_insert_with(BTreeSet::new) + .or_insert_with(FnvHashSet::default) .extend( names .iter() diff --git a/src/flake8_bugbear/plugins/function_call_argument_default.rs b/src/flake8_bugbear/plugins/function_call_argument_default.rs index e1303cc280..27d6f2ded7 100644 --- a/src/flake8_bugbear/plugins/function_call_argument_default.rs +++ b/src/flake8_bugbear/plugins/function_call_argument_default.rs @@ -43,7 +43,7 @@ where match &expr.node { ExprKind::Call { func, args, .. } => { if !is_mutable_func(func) - && !is_immutable_func(func, &self.extend_immutable_calls) + && !is_immutable_func(func, self.extend_immutable_calls) && !is_nan_or_infinity(func, args) { self.checks.push(( diff --git a/src/flake8_bugbear/plugins/unused_loop_control_variable.rs b/src/flake8_bugbear/plugins/unused_loop_control_variable.rs index 9eb0cd84dd..684af5ddfb 100644 --- a/src/flake8_bugbear/plugins/unused_loop_control_variable.rs +++ b/src/flake8_bugbear/plugins/unused_loop_control_variable.rs @@ -1,5 +1,4 @@ -use std::collections::BTreeMap; - +use fnv::FnvHashMap; use rustpython_ast::{Expr, ExprKind, Stmt}; use crate::ast::types::Range; @@ -12,7 +11,7 @@ use crate::checks::{Check, CheckKind}; /// Identify all `ExprKind::Name` nodes in an AST. struct NameFinder<'a> { /// A map from identifier to defining expression. - names: BTreeMap<&'a str, &'a Expr>, + names: FnvHashMap<&'a str, &'a Expr>, } impl NameFinder<'_> { diff --git a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__extend_immutable_calls.snap b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__extend_immutable_calls.snap index 02b1147703..3ab3a34a83 100644 --- a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__extend_immutable_calls.snap +++ b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__extend_immutable_calls.snap @@ -4,10 +4,10 @@ expression: checks --- - kind: FunctionCallArgumentDefault location: - row: 15 + row: 16 column: 66 end_location: - row: 15 + row: 16 column: 77 fix: ~ diff --git a/src/python/typing.rs b/src/python/typing.rs index 566063d746..771038f669 100644 --- a/src/python/typing.rs +++ b/src/python/typing.rs @@ -1,11 +1,10 @@ -use std::collections::{BTreeMap, BTreeSet}; - +use fnv::{FnvHashMap, FnvHashSet}; use once_cell::sync::Lazy; use rustpython_ast::{Expr, ExprKind}; // See: https://pypi.org/project/typing-extensions/ -static TYPING_EXTENSIONS: Lazy> = Lazy::new(|| { - BTreeSet::from([ +static TYPING_EXTENSIONS: Lazy> = Lazy::new(|| { + FnvHashSet::from_iter([ "Annotated", "Any", "AsyncContextManager", @@ -64,9 +63,9 @@ pub fn in_extensions(name: &str) -> bool { } // See: https://docs.python.org/3/library/typing.html -static IMPORTED_SUBSCRIPTS: Lazy>> = +static IMPORTED_SUBSCRIPTS: Lazy>> = Lazy::new(|| { - let mut import_map = BTreeMap::new(); + let mut import_map = FnvHashMap::default(); for (name, module) in [ // `collections` ("ChainMap", "collections"), @@ -183,7 +182,7 @@ static IMPORTED_SUBSCRIPTS: Lazy>> ] { import_map .entry(name) - .or_insert_with(BTreeSet::new) + .or_insert_with(FnvHashSet::default) .insert(module); } import_map @@ -191,13 +190,13 @@ static IMPORTED_SUBSCRIPTS: Lazy>> // These are all assumed to come from the `typing` module. // See: https://peps.python.org/pep-0585/ -static PEP_585_BUILTINS_ELIGIBLE: Lazy> = - Lazy::new(|| BTreeSet::from(["Dict", "FrozenSet", "List", "Set", "Tuple", "Type"])); +static PEP_585_BUILTINS_ELIGIBLE: Lazy> = + Lazy::new(|| FnvHashSet::from_iter(["Dict", "FrozenSet", "List", "Set", "Tuple", "Type"])); // These are all assumed to come from the `typing` module. // See: https://peps.python.org/pep-0585/ -static PEP_585_BUILTINS: Lazy> = - Lazy::new(|| BTreeSet::from(["dict", "frozenset", "list", "set", "tuple", "type"])); +static PEP_585_BUILTINS: Lazy> = + Lazy::new(|| FnvHashSet::from_iter(["dict", "frozenset", "list", "set", "tuple", "type"])); fn is_pep593_annotated_subscript(name: &str) -> bool { name == "Annotated" @@ -210,7 +209,7 @@ pub enum SubscriptKind { pub fn match_annotated_subscript( expr: &Expr, - imports: &BTreeMap<&str, BTreeSet<&str>>, + imports: &FnvHashMap<&str, FnvHashSet<&str>>, ) -> Option { match &expr.node { ExprKind::Attribute { attr, value, .. } => { @@ -261,7 +260,7 @@ pub fn match_annotated_subscript( /// Returns `true` if `Expr` represents a reference to a typing object with a /// PEP 585 built-in. Note that none of the PEP 585 built-ins are in /// `typing_extensions`. -pub fn is_pep585_builtin(expr: &Expr, typing_imports: Option<&BTreeSet<&str>>) -> bool { +pub fn is_pep585_builtin(expr: &Expr, typing_imports: Option<&FnvHashSet<&str>>) -> bool { match &expr.node { ExprKind::Attribute { attr, value, .. } => { if let ExprKind::Name { id, .. } = &value.node { diff --git a/src/pyupgrade/checks.rs b/src/pyupgrade/checks.rs index 34cfccce9f..1294aad0b1 100644 --- a/src/pyupgrade/checks.rs +++ b/src/pyupgrade/checks.rs @@ -1,5 +1,4 @@ -use std::collections::BTreeSet; - +use fnv::FnvHashSet; use rustpython_ast::{Constant, KeywordData}; use rustpython_parser::ast::{ArgData, Expr, ExprKind, Stmt, StmtKind}; @@ -164,7 +163,7 @@ pub fn type_of_primitive(func: &Expr, args: &[Expr], location: Range) -> Option< pub fn unnecessary_lru_cache_params( decorator_list: &[Expr], target_version: PythonVersion, - imports: Option<&BTreeSet<&str>>, + imports: Option<&FnvHashSet<&str>>, ) -> Option { for expr in decorator_list.iter() { if let ExprKind::Call { diff --git a/src/pyupgrade/plugins/deprecated_unittest_alias.rs b/src/pyupgrade/plugins/deprecated_unittest_alias.rs index b66a85b6ad..7c4fe3a684 100644 --- a/src/pyupgrade/plugins/deprecated_unittest_alias.rs +++ b/src/pyupgrade/plugins/deprecated_unittest_alias.rs @@ -1,5 +1,4 @@ -use std::collections::BTreeMap; - +use fnv::FnvHashMap; use once_cell::sync::Lazy; use rustpython_ast::{Expr, ExprKind}; @@ -8,8 +7,8 @@ use crate::autofix::Fix; use crate::check_ast::Checker; use crate::checks::{Check, CheckKind}; -static DEPRECATED_ALIASES: Lazy> = Lazy::new(|| { - BTreeMap::from([ +static DEPRECATED_ALIASES: Lazy> = Lazy::new(|| { + FnvHashMap::from_iter([ ("failUnlessEqual", "assertEqual"), ("assertEquals", "assertEqual"), ("failIfEqual", "assertNotEqual"), diff --git a/src/rules/checks.rs b/src/rules/checks.rs index 5d3f6acdfc..47ae55932e 100644 --- a/src/rules/checks.rs +++ b/src/rules/checks.rs @@ -1,5 +1,4 @@ -use std::collections::BTreeMap; - +use fnv::FnvHashMap; use once_cell::sync::Lazy; use rustpython_ast::Location; @@ -10,8 +9,8 @@ use crate::source_code_locator::SourceCodeLocator; use crate::Check; /// See: https://github.com/microsoft/vscode/blob/095ddabc52b82498ee7f718a34f9dd11d59099a8/src/vs/base/common/strings.ts#L1094 -static CONFUSABLES: Lazy> = Lazy::new(|| { - BTreeMap::from([ +static CONFUSABLES: Lazy> = Lazy::new(|| { + FnvHashMap::from_iter([ (8232, 32), (8233, 32), (5760, 32),