Skip to content

Commit bd953b4

Browse files
committed
Support in assignments too
1 parent 320effb commit bd953b4

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

mypy/checker.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,7 +2241,11 @@ def check_method_override_for_base_with_name(
22412241

22422242
if name == "__hash__" and isinstance(original_type, NoneType):
22432243
# Allow defining `__hash__` even if parent class was explicitly made unhashable
2244-
return False
2244+
if base.fullname == "builtins.object":
2245+
# This is only for test stubs to avoid adding object.__hash__
2246+
# to all of them.
2247+
return True
2248+
return self.check_method_override_for_base_with_name(defn, name, base.mro[-1])
22452249

22462250
if (
22472251
is_property(defn)
@@ -3493,7 +3497,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
34933497
lvalue, lvalue_type, base_type, base
34943498
)
34953499
return
3496-
if base is last_immediate_base:
3500+
if base is last_immediate_base and base_node.name != "__hash__":
34973501
# At this point, the attribute was found to be compatible with all
34983502
# immediate parents.
34993503
break
@@ -3507,6 +3511,9 @@ def check_compatibility_super(
35073511
base_node: Node,
35083512
always_allow_covariant: bool,
35093513
) -> bool:
3514+
if base_node.name == "__hash__" and isinstance(base_type, NoneType):
3515+
# Allow defining `__hash__` even if parent class was explicitly made unhashable
3516+
return True
35103517
# TODO: check __set__() type override for custom descriptors.
35113518
# TODO: for descriptors check also class object access override.
35123519
ok = self.check_subtype(

test-data/unit/check-classes.test

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,30 @@ class A:
155155
__hash__ = None
156156

157157
class B(A):
158-
def __hash__(self) -> int: return 0
158+
def __hash__(self) -> int:
159+
return 0
160+
161+
class C(A):
162+
__hash__ = object.__hash__
163+
164+
class D(A):
165+
def __hash__(self, x: int) -> str: # E: Signature of "__hash__" incompatible with supertype "object" \
166+
# N: Superclass: \
167+
# N: def __hash__(self) -> int \
168+
# N: Subclass: \
169+
# N: def __hash__(self, x: int) -> str \
170+
# N: Superclass: \
171+
# N: def __hash__(self) -> int \
172+
# N: Subclass: \
173+
# N: def __hash__(self, x: int) -> str
174+
return ''
175+
176+
def bad_hash(x: E, y: str) -> str:
177+
return y
178+
179+
class E(A):
180+
__hash__ = bad_hash # E: Incompatible types in assignment (expression has type "Callable[[str], str]", base class "object" defined the type as "Callable[[], int]")
181+
159182
[builtins fixtures/primitives.pyi]
160183

161184
[case testHashNoneBadOverride]

0 commit comments

Comments
 (0)