Skip to content

Commit f7aab5a

Browse files
[pylint] Fixed false-positive on the rule PLW1641 (eq-without-hash) (#10566)
## Summary Fixed false-positive on the rule `PLW1641`, where the explicit assignment on the `__hash__` method is not counted as an definition of `__hash__`. (Discussed in #10557). Also, added one new testcase. ## Test Plan Checked on `cargo test` in `eq_without_hash.py`. Before the change, for the assignment into `__hash__`, only `__hash__ = None` was counted as an explicit definition of `__hash__` method. Probably any assignment into `__hash__` property could be counted as an explicit definition of hash, so I removed `value.is_none_literal_expr()` check.
1 parent 59ac3f4 commit f7aab5a

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

crates/ruff_linter/resources/test/fixtures/pylint/eq_without_hash.py

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def __init__(self):
55
def __eq__(self, other):
66
return isinstance(other, Person) and other.name == self.name
77

8+
89
# OK
910
class Language:
1011
def __init__(self):
@@ -16,8 +17,24 @@ def __eq__(self, other):
1617
def __hash__(self):
1718
return hash(self.name)
1819

20+
1921
class MyClass:
2022
def __eq__(self, other):
2123
return True
2224

2325
__hash__ = None
26+
27+
28+
class SingleClass:
29+
def __eq__(self, other):
30+
return True
31+
32+
def __hash__(self):
33+
return 7
34+
35+
36+
class ChildClass(SingleClass):
37+
def __eq__(self, other):
38+
return True
39+
40+
__hash__ = SingleClass.__hash__

crates/ruff_linter/src/rules/pylint/rules/eq_without_hash.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,21 @@ fn has_eq_without_hash(body: &[Stmt]) -> bool {
6767
let mut has_eq = false;
6868
for statement in body {
6969
match statement {
70-
Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
70+
Stmt::Assign(ast::StmtAssign { targets, .. }) => {
7171
let [Expr::Name(ast::ExprName { id, .. })] = targets.as_slice() else {
7272
continue;
7373
};
7474

75-
// Check if `__hash__` was explicitly set to `None`, as in:
75+
// Check if `__hash__` was explicitly set, as in:
7676
// ```python
77-
// class Class:
77+
// class Class(SuperClass):
7878
// def __eq__(self, other):
7979
// return True
8080
//
81-
// __hash__ = None
81+
// __hash__ = SuperClass.__hash__
8282
// ```
83-
if id == "__hash__" && value.is_none_literal_expr() {
83+
84+
if id == "__hash__" {
8485
has_hash = true;
8586
}
8687
}

0 commit comments

Comments
 (0)