Skip to content

Commit 7927a49

Browse files
committed
Extend tests for dataclass hashability
1 parent 6b1a64c commit 7927a49

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

conformance/tests/dataclasses_hash.py

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
"""
44

55
from dataclasses import dataclass
6-
from typing import Hashable
6+
from typing import Hashable, assert_type
77

88

99
@dataclass
1010
class DC1:
1111
a: int
1212

1313

14-
# This should generate an error because DC1 isn't hashable.
14+
assert_type(DC1.__hash__, None)
15+
16+
# These should generate errors because DC1 isn't hashable.
17+
DC1(0).__hash__() # E
18+
hash(DC1(0)) # E
1519
v1: Hashable = DC1(0) # E
1620

1721

@@ -20,15 +24,26 @@ class DC2:
2024
a: int
2125

2226

23-
v2: Hashable = DC2(0)
27+
# Because `DC2` is frozen, type checkers should synthesize
28+
# a callable `__hash__` method for it, and therefore should
29+
# emit a diagnostic here:
30+
assert_type(DC2.__hash__, None) # E
31+
32+
DC2(0).__hash__() # OK
33+
hash(DC2(0)) # OK
34+
v2: Hashable = DC2(0) # OK
2435

2536

2637
@dataclass(eq=True)
2738
class DC3:
2839
a: int
2940

3041

31-
# This should generate an error because DC3 isn't hashable.
42+
assert_type(DC3.__hash__, None)
43+
44+
# These should generate errors because DC3 isn't hashable.
45+
DC3(0).__hash__() # E
46+
hash(DC3(0)) # E
3247
v3: Hashable = DC3(0) # E
3348

3449

@@ -37,15 +52,29 @@ class DC4:
3752
a: int
3853

3954

40-
v4: Hashable = DC4(0)
55+
# Because `DC4` is frozen, type checkers should synthesize
56+
# a callable `__hash__` method for it, and therefore should
57+
# emit a diagnostic here:
58+
assert_type(DC4.__hash__, None) # E
59+
60+
DC4(0).__hash__() # OK
61+
hash(DC4(0)) # OK
62+
v4: Hashable = DC4(0) # OK
4163

4264

4365
@dataclass(eq=True, unsafe_hash=True)
4466
class DC5:
4567
a: int
4668

4769

48-
v5: Hashable = DC5(0)
70+
# Type checkers should synthesize a callable `__hash__`
71+
# method for `DC5` due to `unsafe_hash=True`, and therefore
72+
# should emit a diagnostic here:
73+
assert_type(DC5.__hash__, None) # E
74+
75+
DC5(0).__hash__() # OK
76+
hash(DC5(0)) # OK
77+
v5: Hashable = DC5(0) # OK
4978

5079

5180
@dataclass(eq=True)
@@ -56,7 +85,13 @@ def __hash__(self) -> int:
5685
return 0
5786

5887

59-
v6: Hashable = DC6(0)
88+
# Type checkers should respect the manually defined `__hash__`
89+
# method for `DC6`, and therefore should emit a diagnostic here:
90+
assert_type(DC6.__hash__, None) # E
91+
92+
DC6(0).__hash__() # OK
93+
hash(DC6(0)) # OK
94+
v6: Hashable = DC6(0) # OK
6095

6196

6297
@dataclass(frozen=True)
@@ -67,4 +102,11 @@ def __eq__(self, other) -> bool:
67102
return self.a == other.a
68103

69104

70-
v7: Hashable = DC7(0)
105+
# Because `DC7` is frozen, type checkers should synthesize
106+
# a callable `__hash__` method for it, and therefore should
107+
# emit a diagnostic here:
108+
assert_type(DC7.__hash__, None) # E
109+
110+
DC7(0).__hash__() # OK
111+
hash(DC7(0)) # OK
112+
v7: Hashable = DC7(0) # OK

0 commit comments

Comments
 (0)