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

First draft of an update to the Overloads chapter (DRAFT: DO NOT MERGE) #1839

Draft
wants to merge 38 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 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
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
10 changes: 4 additions & 6 deletions conformance/results/mypy/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
conformant = "Pass"
output = """
overloads_basic.py:37: error: No overload variant of "__getitem__" of "Bytes" matches argument type "str" [call-overload]
overloads_basic.py:37: note: Possible overload variants:
overloads_basic.py:37: note: def __getitem__(self, int, /) -> int
overloads_basic.py:37: note: def __getitem__(self, slice[Any, Any, Any], /) -> bytes
overloads_basic.py:62: error: Single overload definition, multiple required [misc]
overloads_basic.py:74: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_basic.py:39: error: No overload variant of "__getitem__" of "Bytes" matches argument type "str" [call-overload]
overloads_basic.py:39: note: Possible overload variants:
overloads_basic.py:39: note: def __getitem__(self, int, /) -> int
overloads_basic.py:39: note: def __getitem__(self, slice[Any, Any, Any], /) -> bytes
"""
conformance_automated = "Pass"
errors_diff = """
Expand Down
8 changes: 8 additions & 0 deletions conformance/results/mypy/overloads_consistency.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
conformant = "Pass"
conformance_automated = "Pass"
errors_diff = """
"""
output = """
overloads_consistency.py:27: error: Overloaded function implementation cannot produce return type of signature 2 [misc]
overloads_consistency.py:43: error: Overloaded function implementation does not accept all possible arguments of signature 2 [misc]
"""
24 changes: 24 additions & 0 deletions conformance/results/mypy/overloads_definitions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
conformant = "Partial"
conformance_automated = "Fail"
notes = """
Does not allow an overload with no implementation in an abstract base class.
Allows @override to be on all overloads and implementation, instead of just implementation.
"""
errors_diff = """
Line 245: Expected 1 errors
Line 49: Unexpected errors ['overloads_definitions.py:49: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]']
"""
output = """
overloads_definitions.py:14: error: Single overload definition, multiple required [misc]
overloads_definitions.py:26: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_definitions.py:49: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_definitions.py:63: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
overloads_definitions.py:78: error: Overload does not consistently use the "@staticmethod" decorator on all function signatures. [misc]
overloads_definitions.py:88: error: Overloaded function implementation does not accept all possible arguments of signature 1 [misc]
overloads_definitions.py:88: error: Overloaded function implementation does not accept all possible arguments of signature 2 [misc]
overloads_definitions.py:91: error: Overload does not consistently use the "@classmethod" decorator on all function signatures. [misc]
overloads_definitions.py:133: error: @final should be applied only to overload implementation [misc]
overloads_definitions.py:148: error: @final should be applied only to overload implementation [misc]
overloads_definitions.py:196: error: Cannot override final attribute "final_method" (previously declared in base class "Base") [misc]
overloads_definitions.py:211: error: Method "bad_override" is marked as an override, but no base method was found with this name [misc]
"""
18 changes: 18 additions & 0 deletions conformance/results/mypy/overloads_definitions_stub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
conformant = "Partial"
notes = """
Allows @override to appear in a stub file not on the first overload.
"""
conformance_automated = "Fail"
errors_diff = """
Line 168: Expected 1 errors
"""
output = """
overloads_definitions_stub.pyi:13: error: Single overload definition, multiple required [misc]
overloads_definitions_stub.pyi:37: error: Overload does not consistently use the "@staticmethod" decorator on all function signatures. [misc]
overloads_definitions_stub.pyi:38: error: Self argument missing for a non-static method (or an invalid type for self) [misc]
overloads_definitions_stub.pyi:46: error: Overload does not consistently use the "@classmethod" decorator on all function signatures. [misc]
overloads_definitions_stub.pyi:85: error: In a stub file @final must be applied only to the first overload [misc]
overloads_definitions_stub.pyi:101: error: In a stub file @final must be applied only to the first overload [misc]
overloads_definitions_stub.pyi:128: error: Cannot override final attribute "final_method" (previously declared in base class "Base") [misc]
overloads_definitions_stub.pyi:140: error: Method "bad_override" is marked as an override, but no base method was found with this name [misc]
"""
43 changes: 43 additions & 0 deletions conformance/results/mypy/overloads_evaluation.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
conformant = "Partial"
notes = """
Does not expand boolean arguments to Literal[True] and Literal[False].
Does not expand enum arguments to literal variants.
Does not expand tuple arguments to possible combinations.
"""
conformance_automated = "Fail"
errors_diff = """
Line 106: Unexpected errors ['overloads_evaluation.py:106: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload]']
Line 107: Unexpected errors ['overloads_evaluation.py:107: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]']
Line 129: Unexpected errors ['overloads_evaluation.py:129: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload]']
Line 130: Unexpected errors ['overloads_evaluation.py:130: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]']
Line 169: Unexpected errors ['overloads_evaluation.py:169: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]']
Line 170: Unexpected errors ['overloads_evaluation.py:170: error: Expression is of type "int", not "int | str" [assert-type]']
"""
output = """
overloads_evaluation.py:32: error: All overload variants of "example1" require at least one argument [call-overload]
overloads_evaluation.py:32: note: Possible overload variants:
overloads_evaluation.py:32: note: def example1(x: int, y: str) -> int
overloads_evaluation.py:32: note: def example1(x: str) -> str
overloads_evaluation.py:40: error: No overload variant of "example1" matches argument types "int", "int" [call-overload]
overloads_evaluation.py:40: note: Possible overload variants:
overloads_evaluation.py:40: note: def example1(x: int, y: str) -> int
overloads_evaluation.py:40: note: def example1(x: str) -> str
overloads_evaluation.py:45: error: No overload variant of "example1" matches argument type "int" [call-overload]
overloads_evaluation.py:45: note: Possible overload variants:
overloads_evaluation.py:45: note: def example1(x: int, y: str) -> int
overloads_evaluation.py:45: note: def example1(x: str) -> str
overloads_evaluation.py:89: error: Argument 1 to "example2" has incompatible type "int | str"; expected "int" [arg-type]
overloads_evaluation.py:89: error: Argument 2 to "example2" has incompatible type "int | str"; expected "str" [arg-type]
overloads_evaluation.py:106: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload]
overloads_evaluation.py:106: note: Possible overload variants:
overloads_evaluation.py:106: note: def expand_bool(x: Literal[False]) -> Literal[0]
overloads_evaluation.py:106: note: def expand_bool(x: Literal[True]) -> Literal[1]
overloads_evaluation.py:107: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]
overloads_evaluation.py:129: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload]
overloads_evaluation.py:129: note: Possible overload variants:
overloads_evaluation.py:129: note: def expand_enum(x: Literal[Color.RED]) -> Literal[0]
overloads_evaluation.py:129: note: def expand_enum(x: Literal[Color.BLUE]) -> Literal[1]
overloads_evaluation.py:130: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]
overloads_evaluation.py:169: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]
overloads_evaluation.py:170: error: Expression is of type "int", not "int | str" [assert-type]
"""
8 changes: 8 additions & 0 deletions conformance/results/mypy/overloads_overlap.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
conformant = "Pass"
conformance_automated = "Pass"
errors_diff = """
"""
output = """
overloads_overlap.py:14: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [overload-overlap]
overloads_overlap.py:36: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match]
"""
4 changes: 2 additions & 2 deletions conformance/results/mypy/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "mypy 1.14.0"
test_duration = 1.6
version = "mypy 1.14.1"
test_duration = 1.7
6 changes: 1 addition & 5 deletions conformance/results/pyre/overloads_basic.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
conformant = "Pass"
notes = """
"""
output = """
overloads_basic.py:37:2 Incompatible parameter type [6]: In call `Bytes.__getitem__`, for 1st positional argument, expected `int` but got `str`.
overloads_basic.py:63:0 Incompatible overload [43]: At least two overload signatures must be present.
overloads_basic.py:75:0 Missing overload implementation [42]: Overloaded function `func2` must have an implementation.
overloads_basic.py:39:2 Incompatible parameter type [6]: In call `Bytes.__getitem__`, for 1st positional argument, expected `int` but got `str`.
"""
conformance_automated = "Pass"
errors_diff = """
Expand Down
18 changes: 18 additions & 0 deletions conformance/results/pyre/overloads_consistency.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
conformant = "Partial"
notes = """
Does not apply decorator transforms before checking overload consistency.
"""
conformance_automated = "Fail"
errors_diff = """
Line 107: Unexpected errors ['overloads_consistency.py:107:0 Incompatible overload [43]: The return type of overloaded function `decorated` (`None`) is incompatible with the return type of the implementation (`bytes`).', 'overloads_consistency.py:107:0 Incompatible overload [43]: The implementation of `decorated` does not accept all possible arguments of overload defined on line `107`.']
Line 111: Unexpected errors ['overloads_consistency.py:111:0 Incompatible overload [43]: The return type of overloaded function `decorated` (`str`) is incompatible with the return type of the implementation (`bytes`).', 'overloads_consistency.py:111:0 Incompatible overload [43]: The implementation of `decorated` does not accept all possible arguments of overload defined on line `111`.', 'overloads_consistency.py:111:0 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
"""
output = """
overloads_consistency.py:24:0 Incompatible overload [43]: The return type of overloaded function `return_type` (`str`) is incompatible with the return type of the implementation (`int`).
overloads_consistency.py:40:0 Incompatible overload [43]: The implementation of `parameter_type` does not accept all possible arguments of overload defined on line `40`.
overloads_consistency.py:107:0 Incompatible overload [43]: The return type of overloaded function `decorated` (`None`) is incompatible with the return type of the implementation (`bytes`).
overloads_consistency.py:107:0 Incompatible overload [43]: The implementation of `decorated` does not accept all possible arguments of overload defined on line `107`.
overloads_consistency.py:111:0 Incompatible overload [43]: The return type of overloaded function `decorated` (`str`) is incompatible with the return type of the implementation (`bytes`).
overloads_consistency.py:111:0 Incompatible overload [43]: The implementation of `decorated` does not accept all possible arguments of overload defined on line `111`.
overloads_consistency.py:111:0 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
"""
32 changes: 32 additions & 0 deletions conformance/results/pyre/overloads_definitions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
conformant = "Partial"
conformance_automated = "Fail"
notes = """
Does not allow an overload with no implementation in a Protocol or an abstract base class.
Expects @final/@override on all overloads and implementation, instead of implementation only.
"""
errors_diff = """
Line 245: Expected 1 errors
Lines 148, 150: Expected error (tag 'invalid_final_2')
Line 40: Unexpected errors ['overloads_definitions.py:40:4 Missing overload implementation [42]: Overloaded function `MyProto.func3` must have an implementation.']
Line 51: Unexpected errors ['overloads_definitions.py:51:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.']
Line 128: Unexpected errors ['overloads_definitions.py:128:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 239: Unexpected errors ['overloads_definitions.py:239:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
"""
output = """
overloads_definitions.py:15:0 Incompatible overload [43]: At least two overload signatures must be present.
overloads_definitions.py:27:0 Missing overload implementation [42]: Overloaded function `func2` must have an implementation.
overloads_definitions.py:40:4 Missing overload implementation [42]: Overloaded function `MyProto.func3` must have an implementation.
overloads_definitions.py:51:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.
overloads_definitions.py:64:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.not_abstract` must have an implementation.
overloads_definitions.py:80:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `80`.
overloads_definitions.py:85:4 Incompatible overload [43]: The implementation of `C.func5` does not accept all possible arguments of overload defined on line `85`.
overloads_definitions.py:88:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions.py:97:4 Incompatible overload [43]: The implementation of `C.func6` does not accept all possible arguments of overload defined on line `97`.
overloads_definitions.py:97:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions.py:128:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions.py:139:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions.py:204:4 Invalid override [40]: `overloads_definitions.Child.final_method` cannot override final method defined in `Base`.
overloads_definitions.py:220:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions.py:220:4 Invalid override [40]: `overloads_definitions.Child.bad_override` is decorated with @override, but no method of the same name exists in superclasses of `Child`.
overloads_definitions.py:239:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
"""
27 changes: 27 additions & 0 deletions conformance/results/pyre/overloads_definitions_stub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
conformant = "Partial"
notes = """
Expects @final and @override to be present on all overloads, not just first.
"""
conformance_automated = "Fail"
errors_diff = """
Line 168: Expected 1 errors
Lines 80, 82, 85, 87: Expected error (tag 'invalid_final')
Lines 96, 98, 101: Expected error (tag 'invalid_final_2')
Lines 122, 128, 129, 133: Expected error (tag 'override-final')
Line 75: Unexpected errors ['overloads_definitions_stub.pyi:75:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 91: Unexpected errors ['overloads_definitions_stub.pyi:91:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 146: Unexpected errors ['overloads_definitions_stub.pyi:146:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 162: Unexpected errors ['overloads_definitions_stub.pyi:162:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 174: Unexpected errors ['overloads_definitions_stub.pyi:174:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
"""
output = """
overloads_definitions_stub.pyi:14:0 Incompatible overload [43]: At least two overload signatures must be present.
overloads_definitions_stub.pyi:43:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:52:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:75:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:91:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:142:4 Invalid override [40]: `overloads_definitions_stub.Child.bad_override` is decorated with @override, but no method of the same name exists in superclasses of `Child`.
overloads_definitions_stub.pyi:146:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:162:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_definitions_stub.pyi:174:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
"""
Loading
Loading