Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to the Overloads chapter #1839

Merged
merged 45 commits into from
Mar 28, 2025
Merged
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
bab532e
First draft of an update to the Overloads chapter.
erictraut Aug 13, 2024
de81026
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2024
5ca254e
Updated draft based on initial round of feedback.
erictraut Aug 16, 2024
33c819f
Merge branch 'overloads' of https://github.com/erictraut/typing into …
erictraut Aug 16, 2024
f993b28
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 16, 2024
660295c
Fixed reference.
erictraut Aug 16, 2024
06c86f1
Merge branch 'overloads' of https://github.com/erictraut/typing into …
erictraut Aug 16, 2024
831945b
Fixed reference.
erictraut Aug 16, 2024
3906a12
Another reference fix.
erictraut Aug 16, 2024
bb8fe09
Incorporated PR feedback.
erictraut Aug 23, 2024
cce3879
Made changes to proposed overload chapter based on reviewer feedback.
erictraut Aug 28, 2024
7591a4d
Incorporated additional feedback from reviewers.
erictraut Aug 28, 2024
91d4adc
Incorporated more feedback.
erictraut Aug 29, 2024
69d6d4a
Fixed typo in code sample.
erictraut Dec 13, 2024
e13dbbe
Update docs/spec/overload.rst
erictraut Dec 16, 2024
eed0815
Merge branch 'main' into overloads
carljm Jan 8, 2025
57495db
(very) initial steps on conformance tests
carljm Jan 9, 2025
27f1c79
fix abstractmethod without implementation check
carljm Jan 10, 2025
535075f
split overloads_invalid.py from overloads_basic.py
carljm Jan 10, 2025
8875a4a
add test for final with overload
carljm Jan 10, 2025
cb04dd6
add tests for correct usage of override with an overload
carljm Jan 10, 2025
5eabe53
add test for wrong use of override with overload
carljm Jan 10, 2025
484b03c
rename overloads_invalid to overloads_definitions
carljm Jan 10, 2025
ac3b70e
add support for stub test files, add overloads_definitions_stub.pyi
carljm Jan 10, 2025
87377ed
add initial overloads_consistency tests
carljm Jan 10, 2025
f7bf384
add tests for mixed async-def
carljm Jan 11, 2025
4936ac1
add tests for signature-transforming decorators
carljm Jan 11, 2025
e0e0b8a
add test for partially overlapping overloads
carljm Jan 11, 2025
cc748d3
add test for fully overlapping overloads
carljm Jan 11, 2025
17d3e15
add tests for step-1 of overload evaluation
carljm Jan 11, 2025
02f0652
add tests for steps 2 and 3 of overload evaluation
carljm Jan 11, 2025
f5bee93
add tests for bool expansion (no checker does this)
carljm Jan 11, 2025
169fa58
add tests for enum and tuple expansion
carljm Jan 11, 2025
c041484
add test for type[A | B] expansion
carljm Jan 11, 2025
c10a72d
add test for step 4 in overload matching
carljm Jan 11, 2025
8a98eae
add test for steps 5/6 in overload matching
carljm Jan 11, 2025
5d22e8d
no expectation of return type if there are call errors
carljm Jan 13, 2025
98f36e8
improve variadic test to not use overlapping overloads
carljm Jan 13, 2025
67c1675
Merge branch 'main' into overloads
erictraut Jan 25, 2025
d414386
Apply suggestions from code review
JelleZijlstra Feb 14, 2025
f4293e8
Update conformance/tests/overloads_consistency.py
AlexWaygood Feb 14, 2025
e835221
Removed section on overlapping overloads. We're struggling to get agr…
erictraut Feb 14, 2025
67768f4
Updated Step 5 of overload algorithm based on PR feedback.
erictraut Mar 24, 2025
f292575
Merge branch 'main' into overloads
erictraut Mar 28, 2025
babbc6d
Fixed bug in conformance test.
erictraut Mar 28, 2025
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
Prev Previous commit
Next Next commit
fix abstractmethod without implementation check
carljm committed Jan 10, 2025

Verified

This commit was signed with the committer’s verified signature.
carljm Carl Meyer
commit 27f1c796fac9f39186213f16779c83d9504520a3
9 changes: 5 additions & 4 deletions conformance/results/mypy/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -10,10 +10,11 @@ overloads_basic.py:41: note: def __getitem__(self, slice[Any, Any, Any], /)
overloads_basic.py:66: error: Single overload definition, multiple required [misc]
overloads_basic.py:78: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_basic.py:101: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_basic.py:116: error: Overload does not consistently use the "@staticmethod" decorator on all function signatures. [misc]
overloads_basic.py:126: error: Overloaded function implementation does not accept all possible arguments of signature 1 [misc]
overloads_basic.py:126: error: Overloaded function implementation does not accept all possible arguments of signature 2 [misc]
overloads_basic.py:129: error: Overload does not consistently use the "@classmethod" decorator on all function signatures. [misc]
overloads_basic.py:115: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_basic.py:130: error: Overload does not consistently use the "@staticmethod" decorator on all function signatures. [misc]
overloads_basic.py:140: error: Overloaded function implementation does not accept all possible arguments of signature 1 [misc]
overloads_basic.py:140: error: Overloaded function implementation does not accept all possible arguments of signature 2 [misc]
overloads_basic.py:143: error: Overload does not consistently use the "@classmethod" decorator on all function signatures. [misc]
"""
conformance_automated = "Fail"
errors_diff = """
17 changes: 9 additions & 8 deletions conformance/results/pyre/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -7,16 +7,17 @@ overloads_basic.py:41:2 Incompatible parameter type [6]: In call `Bytes.__getite
overloads_basic.py:67:0 Incompatible overload [43]: At least two overload signatures must be present.
overloads_basic.py:79:0 Missing overload implementation [42]: Overloaded function `func2` must have an implementation.
overloads_basic.py:92:4 Missing overload implementation [42]: Overloaded function `MyProto.func3` must have an implementation.
overloads_basic.py:102:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.
overloads_basic.py:118:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `118`.
overloads_basic.py:123:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `123`.
overloads_basic.py:126:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_basic.py:131:4 Incompatible overload [43]: The implementation of `C.func6` does not accept all possible arguments of overload defined on line `131`.
overloads_basic.py:136:4 Incompatible overload [43]: The implementation of `C.func6` does not accept all possible arguments of overload defined on line `136`.
overloads_basic.py:139:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_basic.py:103:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.
overloads_basic.py:116:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.not_abstract` must have an implementation.
overloads_basic.py:132:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `132`.
overloads_basic.py:137:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `137`.
overloads_basic.py:140:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_basic.py:145:4 Incompatible overload [43]: The implementation of `C.func6` does not accept all possible arguments of overload defined on line `145`.
overloads_basic.py:150:4 Incompatible overload [43]: The implementation of `C.func6` does not accept all possible arguments of overload defined on line `150`.
overloads_basic.py:153:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
"""
conformance_automated = "Fail"
errors_diff = """
Line 92: Unexpected errors ['overloads_basic.py:92:4 Missing overload implementation [42]: Overloaded function `MyProto.func3` must have an implementation.']
Line 102: Unexpected errors ['overloads_basic.py:102:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.']
Line 103: Unexpected errors ['overloads_basic.py:103:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.']
"""
2 changes: 1 addition & 1 deletion conformance/results/pyre/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyre 0.9.23"
test_duration = 5.9
test_duration = 6.2
18 changes: 8 additions & 10 deletions conformance/results/pyright/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
conformant = "Partial"
conformant = "Pass"
notes = """
Does not allow an overload with no implementation in an abstract base class.
"""
output = """
overloads_basic.py:41:1 - error: No overloads for "__getitem__" match the provided arguments (reportCallIssue)
overloads_basic.py:41:1 - error: Argument of type "Literal['']" cannot be assigned to parameter "__s" of type "slice[Any, Any, Any]" in function "__getitem__"
  "Literal['']" is not assignable to "slice[Any, Any, Any]" (reportArgumentType)
overloads_basic.py:67:5 - error: "func1" is marked as overload, but additional overloads are missing (reportInconsistentOverload)
overloads_basic.py:79:5 - error: "func2" is marked as overload, but no implementation is provided (reportNoOverloadImplementation)
overloads_basic.py:102:9 - error: "func4" is marked as overload, but no implementation is provided (reportNoOverloadImplementation)
overloads_basic.py:118:9 - error: Overloads for "func5" use @staticmethod inconsistently (reportInconsistentOverload)
overloads_basic.py:126:9 - error: Overloaded implementation is not consistent with signature of overload 1
overloads_basic.py:116:9 - error: "not_abstract" is marked as overload, but no implementation is provided (reportNoOverloadImplementation)
overloads_basic.py:132:9 - error: Overloads for "func5" use @staticmethod inconsistently (reportInconsistentOverload)
overloads_basic.py:140:9 - error: Overloaded implementation is not consistent with signature of overload 1
  Type "(self: Self@C, x: int | str) -> (int | str)" is not assignable to type "(x: int) -> int"
    Parameter name mismatch: "x" versus "self"
    Parameter 1: type "int" is incompatible with type "Self@C"
      Type "int" is not assignable to type "Self@C"
    Extra parameter "x" (reportInconsistentOverload)
overloads_basic.py:126:9 - error: Overloaded implementation is not consistent with signature of overload 2
overloads_basic.py:140:9 - error: Overloaded implementation is not consistent with signature of overload 2
  Type "(self: Self@C, x: int | str) -> (int | str)" is not assignable to type "(x: str) -> str"
    Parameter name mismatch: "x" versus "self"
    Parameter 1: type "str" is incompatible with type "Self@C"
      Type "str" is not assignable to type "Self@C"
    Extra parameter "x" (reportInconsistentOverload)
overloads_basic.py:131:9 - error: Overloads for "func6" use @classmethod inconsistently (reportInconsistentOverload)
overloads_basic.py:139:15 - warning: Instance methods should take a "self" parameter (reportSelfClsParameterName)
overloads_basic.py:145:9 - error: Overloads for "func6" use @classmethod inconsistently (reportInconsistentOverload)
overloads_basic.py:153:15 - warning: Instance methods should take a "self" parameter (reportSelfClsParameterName)
"""
conformance_automated = "Fail"
conformance_automated = "Pass"
errors_diff = """
Line 102: Unexpected errors ['overloads_basic.py:102:9 - error: "func4" is marked as overload, but no implementation is provided (reportNoOverloadImplementation)']
"""
23 changes: 15 additions & 8 deletions conformance/results/pytype/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -27,17 +27,22 @@ overloads_basic.py:98:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func3:
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m

overloads_basic.py:108:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func4: @typing.overload-decorated 'MyAbstractBase.func4' object is not callable [not-callable]
overloads_basic.py:110:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func4: @typing.overload-decorated 'MyAbstractBase.func4' object is not callable [not-callable]

...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m

overloads_basic.py:119:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func5: bad return type [bad-return-type]
overloads_basic.py:122:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in not_abstract: @typing.overload-decorated 'MyAbstractBase.not_abstract' object is not callable [not-callable]

...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m

overloads_basic.py:124:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func5: bad return type [bad-return-type]
overloads_basic.py:133:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func5: bad return type [bad-return-type]

...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m

overloads_basic.py:138:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in func5: bad return type [bad-return-type]

...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
@@ -47,12 +52,14 @@ conformance_automated = "Fail"
errors_diff = """
Lines 66, 67: Expected error (tag 'func1')
Lines 78, 79: Expected error (tag 'func2')
Lines 116, 118, 123, 126: Expected error (tag 'func5')
Lines 129, 131, 136, 139: Expected error (tag 'func6')
Lines 115, 116: Expected error (tag 'not_abstract')
Lines 130, 132, 137, 140: Expected error (tag 'func5')
Lines 143, 145, 150, 153: Expected error (tag 'func6')
Line 35: Unexpected errors ['overloads_basic.py:35:20: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in __getitem__: bad return type [bad-return-type]']
Line 62: Unexpected errors ['overloads_basic.py:62:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in map: bad return type [bad-return-type]']
Line 98: Unexpected errors ["overloads_basic.py:98:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func3: @typing.overload-decorated 'MyProto.func3' object is not callable [not-callable]"]
Line 108: Unexpected errors ["overloads_basic.py:108:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func4: @typing.overload-decorated 'MyAbstractBase.func4' object is not callable [not-callable]"]
Line 119: Unexpected errors ['overloads_basic.py:119:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func5: bad return type [bad-return-type]']
Line 124: Unexpected errors ['overloads_basic.py:124:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func5: bad return type [bad-return-type]']
Line 110: Unexpected errors ["overloads_basic.py:110:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func4: @typing.overload-decorated 'MyAbstractBase.func4' object is not callable [not-callable]"]
Line 122: Unexpected errors ["overloads_basic.py:122:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in not_abstract: @typing.overload-decorated 'MyAbstractBase.not_abstract' object is not callable [not-callable]"]
Line 133: Unexpected errors ['overloads_basic.py:133:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func5: bad return type [bad-return-type]']
Line 138: Unexpected errors ['overloads_basic.py:138:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in func5: bad return type [bad-return-type]']
"""
2 changes: 1 addition & 1 deletion conformance/results/pytype/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pytype 2024.10.11"
test_duration = 30.3
test_duration = 30.5
6 changes: 3 additions & 3 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
@@ -165,10 +165,10 @@ <h3>Python Type System Conformance Test Results</h3>
<div class='tc-time'>1.5sec</div>
</th>
<th class='tc-header'><div class='tc-name'>pyre 0.9.23</div>
<div class='tc-time'>5.9sec</div>
<div class='tc-time'>6.2sec</div>
</th>
<th class='tc-header'><div class='tc-name'>pytype 2024.10.11</div>
<div class='tc-time'>30.3sec</div>
<div class='tc-time'>30.5sec</div>
</th>
</tr>
<tr><th class="column" colspan="5">
@@ -670,7 +670,7 @@ <h3>Python Type System Conformance Test Results</h3>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not allow an overload with no implementation in an abstract base class.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not allow an overload with no implementation in an abstract base class.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not allow an overload with no implementation in a Protocol or an abstract base class.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject a function with a single @overload signature.</p><p>Does not reject a function with @overload signature but no implementation.</p><p>Does not allow an overload with no implementation in a Protocol or an abstract base class.</p><p>Does not exempt overloads from checking of return type in body, when also decorated with `@staticmethod`.</p><p>Does not error on overloads inconsistently decorated with `@staticmethod`.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject a function with a single @overload signature.</p><p>Does not reject a function with @overload signature but no implementation.</p><p>Does not allow an overload with no implementation in a Protocol or an abstract base class.</p><p>Does not exempt overloads from checking of return type in body, when also decorated with `@staticmethod`.</p><p>Does not error on overloads inconsistently decorated with `@staticmethod` or `@classmethod`.</p></span></div></th>
</tr>
<tr><th class="column" colspan="5">
<a class="test_group" href="https://typing.readthedocs.io/en/latest/spec/exceptions.html">Exceptions</a>
20 changes: 17 additions & 3 deletions conformance/tests/overloads_basic.py
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

# Specification: https://typing.readthedocs.io/en/latest/spec/overload.html#overload

from abc import ABC
from abc import ABC, abstractmethod
from typing import (
Any,
Callable,
@@ -85,8 +85,8 @@ def func2(x: str) -> str:
...


# > Overload definitions within stub files, protocols, and abstract base classes
# > are exempt from this check.
# > Overload definitions within stub files, protocols, and on abstract methods
# > within abstract base classes are exempt from this check.
class MyProto(Protocol):
@overload
def func3(self, x: int) -> int:
@@ -99,14 +99,28 @@ def func3(self, x: str) -> str:

class MyAbstractBase(ABC):
@overload
@abstractmethod
def func4(self, x: int) -> int:
...


@overload
@abstractmethod
def func4(self, x: str) -> str:
...

# A non-abstract method in an abstract base class still requires an
# implementation:

@overload # E[not_abstract]
def not_abstract(self, x: int) -> int: # E[not_abstract] no implementation
...


@overload
def not_abstract(self, x: str) -> str:
...


# > If one overload signature is decorated with ``@staticmethod`` or
# > ``@classmethod``, all overload signatures must be similarly decorated. The
4 changes: 2 additions & 2 deletions docs/spec/overload.rst
Original file line number Diff line number Diff line change
@@ -127,8 +127,8 @@ one is present, an error should be reported.
The ``@overload``-decorated definitions must be followed by an overload
implementation, which does not include an ``@overload`` decorator. Type
checkers should report an error or warning if an implementation is missing.
Overload definitions within stub files, protocols, and abstract base classes
are exempt from this check.
Overload definitions within stub files, protocols, and on abstract methods
within abstract base classes are exempt from this check.

If one overload signature is decorated with ``@staticmethod`` or
``@classmethod``, all overload signatures must be similarly decorated. The