Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions conformance/results/mypy/dataclasses_hash.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
conformant = "Partial"
conformant = "Unsupported"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that mypy has implemented support for any of the functionality tested in dataclasses_hash.py, so I downgraded its score from "Partial" to "Unsupported". I'm very happy to revert this change if anybody feels this is unfair or if I've missed something!

notes = """
Does not synthesize `__hash__ = None` as a class attribute for unhashable dataclasses.
Does not report when an unhashable dataclass has `__hash__` called directly on an instance.
Does not report when dataclass is not compatible with Hashable protocol.
"""
output = """
dataclasses_hash.py:14: error: Expression is of type "Callable[[object], int]", not "None" [assert-type]
dataclasses_hash.py:36: error: Expression is of type "Callable[[object], int]", not "None" [assert-type]
"""
conformance_automated = "Fail"
errors_diff = """
Line 15: Expected 1 errors
Line 32: Expected 1 errors
Line 17: Expected 1 errors
Line 18: Expected 1 errors
Line 39: Expected 1 errors
Line 40: Expected 1 errors
Line 14: Unexpected errors ['dataclasses_hash.py:14: error: Expression is of type "Callable[[object], int]", not "None" [assert-type]']
Line 36: Unexpected errors ['dataclasses_hash.py:36: error: Expression is of type "Callable[[object], int]", not "None" [assert-type]']
"""
6 changes: 4 additions & 2 deletions conformance/results/pyrefly/dataclasses_hash.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
ERROR dataclasses_hash.py:15:16-22: `DC1` is not assignable to `Hashable` [bad-assignment]
ERROR dataclasses_hash.py:32:16-22: `DC3` is not assignable to `Hashable` [bad-assignment]
ERROR dataclasses_hash.py:17:1-16: Expected a callable, got `None` [not-callable]
ERROR dataclasses_hash.py:18:16-22: `DC1` is not assignable to `Hashable` [bad-assignment]
ERROR dataclasses_hash.py:39:1-16: Expected a callable, got `None` [not-callable]
ERROR dataclasses_hash.py:40:16-22: `DC3` is not assignable to `Hashable` [bad-assignment]
"""
6 changes: 4 additions & 2 deletions conformance/results/pyright/dataclasses_hash.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
conformant = "Pass"
output = """
dataclasses_hash.py:15:16 - error: Type "DC1" is not assignable to declared type "Hashable"
dataclasses_hash.py:17:1 - error: Object of type "None" cannot be called (reportOptionalCall)
dataclasses_hash.py:18:16 - error: Type "DC1" is not assignable to declared type "Hashable"
  "DC1" is incompatible with protocol "Hashable"
    "__hash__" is an incompatible type
      Type "None" is not assignable to type "() -> int" (reportAssignmentType)
dataclasses_hash.py:32:16 - error: Type "DC3" is not assignable to declared type "Hashable"
dataclasses_hash.py:39:1 - error: Object of type "None" cannot be called (reportOptionalCall)
dataclasses_hash.py:40:16 - error: Type "DC3" is not assignable to declared type "Hashable"
  "DC3" is incompatible with protocol "Hashable"
    "__hash__" is an incompatible type
      Type "None" is not assignable to type "() -> int" (reportAssignmentType)
Expand Down
4 changes: 2 additions & 2 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -737,9 +737,9 @@ <h3>Python Type System Conformance Test Results</h3>
<th class="column col2 conformant">Pass</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_hash</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not report when dataclass is not compatible with Hashable protocol.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 not-conformant"><div class="hover-text">Unsupported<span class="tooltip-text" id="bottom"><p>Does not synthesize `__hash__ = None` as a class attribute for unhashable dataclasses.</p><p>Does not report when an unhashable dataclass has `__hash__` called directly on an instance.</p><p>Does not report when dataclass is not compatible with Hashable protocol.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not synthesize a `__hash__ = None` class attribute for unhashable dataclasses.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_inheritance</th>
Expand Down
16 changes: 13 additions & 3 deletions conformance/results/zuban/dataclasses_hash.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
conformance_automated = "Pass"
conformance_automated = "Fail"
conformant = "Partial"
notes = """
Does not synthesize a `__hash__ = None` class attribute for unhashable dataclasses.
"""
errors_diff = """
Line 14: Unexpected errors ['dataclasses_hash.py:14: error: Expression is of type "Callable[[object], int]", not "None" [misc]']
Line 36: Unexpected errors ['dataclasses_hash.py:36: error: Expression is of type "Callable[[object], int]", not "None" [misc]']
"""
output = """
dataclasses_hash.py:15: error: Incompatible types in assignment (expression has type "DC1", variable has type "Hashable") [assignment]
dataclasses_hash.py:32: error: Incompatible types in assignment (expression has type "DC3", variable has type "Hashable") [assignment]
dataclasses_hash.py:14: error: Expression is of type "Callable[[object], int]", not "None" [misc]
dataclasses_hash.py:17: error: "DC1" has no attribute "__hash__" [attr-defined]
dataclasses_hash.py:18: error: Incompatible types in assignment (expression has type "DC1", variable has type "Hashable") [assignment]
dataclasses_hash.py:36: error: Expression is of type "Callable[[object], int]", not "None" [misc]
dataclasses_hash.py:39: error: "DC3" has no attribute "__hash__" [attr-defined]
dataclasses_hash.py:40: error: Incompatible types in assignment (expression has type "DC3", variable has type "Hashable") [assignment]
"""
32 changes: 24 additions & 8 deletions conformance/tests/dataclasses_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
"""

from dataclasses import dataclass
from typing import Hashable
from typing import Callable, Hashable, assert_type


@dataclass
class DC1:
a: int


# This should generate an error because DC1 isn't hashable.
assert_type(DC1.__hash__, None)

# These should generate errors because DC1 isn't hashable.
DC1(0).__hash__() # E
v1: Hashable = DC1(0) # E


Expand All @@ -20,15 +23,20 @@ class DC2:
a: int


v2: Hashable = DC2(0)
dc2_hash: Callable[..., int] = DC2.__hash__ # OK
DC2(0).__hash__() # OK
v2: Hashable = DC2(0) # OK


@dataclass(eq=True)
class DC3:
a: int


# This should generate an error because DC3 isn't hashable.
assert_type(DC3.__hash__, None)

# These should generate errors because DC3 isn't hashable.
DC3(0).__hash__() # E
v3: Hashable = DC3(0) # E


Expand All @@ -37,15 +45,19 @@ class DC4:
a: int


v4: Hashable = DC4(0)
dc4_hash: Callable[..., int] = DC4.__hash__ # OK
DC4(0).__hash__() # OK
v4: Hashable = DC4(0) # OK


@dataclass(eq=True, unsafe_hash=True)
class DC5:
a: int


v5: Hashable = DC5(0)
dc5_hash: Callable[..., int] = DC5.__hash__ # OK
DC5(0).__hash__() # OK
v5: Hashable = DC5(0) # OK


@dataclass(eq=True)
Expand All @@ -56,7 +68,9 @@ def __hash__(self) -> int:
return 0


v6: Hashable = DC6(0)
dc6_hash: Callable[..., int] = DC6.__hash__ # OK
DC6(0).__hash__() # OK
v6: Hashable = DC6(0) # OK


@dataclass(frozen=True)
Expand All @@ -67,4 +81,6 @@ def __eq__(self, other) -> bool:
return self.a == other.a


v7: Hashable = DC7(0)
dc7_hash: Callable[..., int] = DC7.__hash__ # OK
DC7(0).__hash__() # OK
v7: Hashable = DC7(0) # OK