Repository navigation
Fix overload override matching order - #11704
Bill Schnurr (bschnurr) wants to merge 1 commit into
Conversation
|
Diff from mypy_primer, showing the effect of this PR on open source code: sympy (https://github.com/sympy/sympy)
- .../projects/sympy/sympy/solvers/bivariate.py:135:15 - error: Operator "-" not supported for "None" (reportOptionalOperand)
- .../projects/sympy/sympy/solvers/bivariate.py:139:17 - error: Operator "-" not supported for type "Basic | Unknown" (reportOperatorIssue)
- .../projects/sympy/sympy/solvers/bivariate.py:144:23 - error: Operator "-" not supported for "None" (reportOptionalOperand)
- .../projects/sympy/sympy/solvers/deutils.py:234:14 - error: Operator "not in" not supported for types "str" and "Unknown | int"
- Operator "not in" not supported for types "str" and "int" (reportOperatorIssue)
- .../projects/sympy/sympy/solvers/diophantine/diophantine.py:423:38 - error: Argument of type "Unknown | Expr | Literal[0]" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:423:38 - error: Argument of type "int | Expr" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
- Type "Unknown | Expr | Literal[0]" is not assignable to type "Expr"
+ Type "int | Expr" is not assignable to type "Expr"
- "Literal[0]" is not assignable to "Expr" (reportArgumentType)
+ "int" is not assignable to "Expr" (reportArgumentType)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:504:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:505:19 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:506:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:569:42 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+ Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:569:50 - error: Operator "*" not supported for types "Expr" and "Unknown | Basic"
+ Operator "*" not supported for types "Expr" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:725:42 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:735:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:736:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:737:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:814:47 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:841:26 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:842:22 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:36 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+ Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:42 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:51 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+ Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:57 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:66 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:845:53 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:854:18 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:856:22 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:865:22 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:865:36 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:867:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:868:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:869:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:870:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:871:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:872:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:876:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:877:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:878:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+ Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:879:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:880:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:881:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+ Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:888:37 - error: Operator "*" not supported for types "int" and "Unknown | None"
+ Operator "*" not supported for types "int" and "None" (reportOperatorIssue)
+ .../projects/sympy/sympy/solvers/diophantine/diophantine.py:888:45 - error: Operator "*" not supported for types "int" and "Unknown | None"
+ Operator "*" not supported for types "int" and "None" (reportOperatorIssue)
... (truncated 643 lines) ...
pyodide (https://github.com/pyodide/pyodide)
+ .../projects/pyodide/src/py/_pyodide/_core_docs.py:1120:9 - error: Method "get" overrides class "Mapping" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- .../projects/pyodide/src/py/_pyodide/_core_docs.py:1131:7 - error: Base classes for class "JsMutableMap" define method "get" in incompatible way
+ .../projects/pyodide/src/py/_pyodide/_core_docs.py:1158:9 - error: Method "pop" overrides class "MutableMapping" in an incompatible manner
- 848 errors, 24 warnings, 0 informations
+ 849 errors, 24 warnings, 0 informations
prefect (https://github.com/PrefectHQ/prefect)
+ .../projects/prefect/src/prefect/flows.py:2467:9 - error: Method "__call__" overrides class "Flow" in an incompatible manner
+ Overloads for override method must be in the same order as the base method (reportIncompatibleMethodOverride)
- 6025 errors, 201 warnings, 0 informations
+ 6026 errors, 201 warnings, 0 informations
werkzeug (https://github.com/pallets/werkzeug)
- .../projects/werkzeug/src/werkzeug/datastructures/accept.py:85:9 - error: Method "__getitem__" overrides class "list" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 354 errors, 18 warnings, 0 informations
+ 353 errors, 18 warnings, 0 informations
Tanjun (https://github.com/FasterSpeeding/Tanjun)
- .../projects/Tanjun/tanjun/clients.py:2250:9 - warning: Method "iter_menu_commands" overrides class "Client" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 36 errors, 112 warnings, 0 informations
+ 36 errors, 111 warnings, 0 informations
mypy (https://github.com/python/mypy)
- .../projects/mypy/mypy/typeshed/stdlib/configparser.pyi:383:9 - error: Method "get" overrides class "Mapping" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- .../projects/mypy/mypy/typeshed/stdlib/ssl.pyi:411:9 - error: Method "get_ca_certs" overrides class "_SSLContext" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- .../projects/mypy/mypy/typeshed/stdlib/tempfile.pyi:257:9 - error: Method "write" overrides class "IO" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 1074 errors, 78 warnings, 0 informations
+ 1071 errors, 78 warnings, 0 informations
xarray (https://github.com/pydata/xarray)
- .../projects/xarray/xarray/core/datatree.py:320:9 - error: Method "__getitem__" overrides class "Dataset" in an incompatible manner
+ .../projects/xarray/xarray/core/utils.py:557:9 - error: Method "get" overrides class "Mapping" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
+ .../projects/xarray/xarray/tests/test_namedarray.py:425:17 - error: Method "_new" overrides class "NamedArray" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
+ .../projects/xarray/xarray/tests/test_namedarray.py:486:17 - error: Method "_new" overrides class "NamedArray" in an incompatible manner
- 2320 errors, 201 warnings, 0 informations
+ 2322 errors, 201 warnings, 0 informations
pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ .../projects/pandas-stubs/pandas-stubs/_libs/tslibs/timedeltas.pyi
+ .../projects/pandas-stubs/pandas-stubs/_libs/tslibs/timedeltas.pyi:260:9 - error: Method "__truediv__" overrides class "timedelta" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
+ .../projects/pandas-stubs/pandas-stubs/core/window/ewm.pyi
+ .../projects/pandas-stubs/pandas-stubs/core/window/ewm.pyi:59:39 - error: Unnecessary "# pyright: ignore" rule: "reportIncompatibleMethodOverride" (reportUnnecessaryTypeIgnoreComment)
- 470 errors, 3 warnings, 0 informations
+ 472 errors, 3 warnings, 0 informations
pip (https://github.com/pypa/pip)
+ .../projects/pip/src/pip/_vendor/requests/structures.py
+ .../projects/pip/src/pip/_vendor/requests/structures.py:129:9 - error: Method "get" overrides class "dict" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 562 errors, 38 warnings, 0 informations
+ 563 errors, 38 warnings, 0 informations
spack (https://github.com/spack/spack)
+ .../projects/spack/lib/spack/spack/build_environment.py:248:9 - error: Method "__call__" overrides class "Executable" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 1851 errors, 21 warnings, 0 informations
+ 1852 errors, 21 warnings, 0 informations
steam.py (https://github.com/Gobot1234/steam.py)
+ .../projects/steam.py/steam/utils.py:565:9 - error: Method "pop" overrides class "ChainMap" in an incompatible manner
+ Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 8304 errors, 87 warnings, 0 informations
+ 8305 errors, 87 warnings, 0 informations
scipy-stubs (https://github.com/scipy/scipy-stubs)
+ .../projects/scipy-stubs/scipy-stubs/sparse/_dok.pyi:93:72 - error: Unnecessary "# pyright: ignore" rule: "reportIncompatibleMethodOverride" (reportUnnecessaryTypeIgnoreComment)
+ .../projects/scipy-stubs/scipy-stubs/stats/_distribution_infrastructure.pyi:483:35 - error: Unnecessary "# pyright: ignore" rule: "reportIncompatibleMethodOverride" (reportUnnecessaryTypeIgnoreComment)
- 1495 errors, 0 warnings, 0 informations
+ 1497 errors, 0 warnings, 0 informations
bidict (https://github.com/jab/bidict)
- .../projects/bidict/bidict/_bidict.py
- .../projects/bidict/bidict/_bidict.py:159:9 - error: Method "pop" overrides class "MutableMapping" in an incompatible manner
- Override does not handle all overloads of base method (reportIncompatibleMethodOverride)
- 9 errors, 1 warning, 0 informations
+ 8 errors, 1 warning, 0 informations
|
🔴 Pyright CLI QA —
|
|
/benchmark |
|
Compared candidate View the full release history charts with the base and PR results. Execution time historyPeak memory historyType checker benchmark🟢 No performance regressions detected. Regression threshold:
Pyright stats
|
|
I found an incompatible override that this change newly accepts. The baseline ( The signatures below have different optional keyword parameters, but both accept from typing import overload
class Base:
@overload
def f(self, x: int, *, a: int = 0) -> int: ...
@overload
def f(self, x: str, *, a: int = 0) -> str: ...
def f(self, x: int | str, *, a: int = 0) -> int | str:
return x
class Child(Base):
@overload
def f(self, x: int, *, b: int = 0) -> str: ...
@overload
def f(self, x: int, *, a: int = 0) -> int: ...
@overload
def f(self, x: str, *, a: int = 0) -> str: ...
def f(self, x: int | str, **kwargs: int) -> int | str:
if isinstance(x, int) and "a" not in kwargs:
return "not an int"
return x
def use_base(value: Base) -> int:
return value.f(1) + 1
use_base(Child()) # TypeError in CPython 3.12.10The new overlap check treats the extra child signature as disjoint, then accepts the later signatures as covering the base overloads. However, the shared call Could the overlap check account for shared calls when parameter names/defaults differ, and add a regression test? I also reproduced this with |
Description
Accept overloaded overrides that add disjoint extra overloads or cover multiple base domains without spurious ordering failures, while continuing to reject incompatible overlaps and genuinely reordered matches.
How you figured out what to do
I traced overloaded override comparison in
typeEvaluator.tsand added a focused matrix of positive and negative subclass cases. The prior implementation selected one best match, which made compatibility depend on the placement of otherwise valid additional overloads.Implementation
Compare override overloads against base call domains rather than selecting a single match. The new logic tracks newly covered base overload indices, preserves monotonic base ordering, and rejects incompatible overlapping extras unless an earlier compatible match already shadows the overlap.
Screenshots or GIFs are not applicable because this change affects analyzer or language-service behavior and has no visual UI.
Testing
Added
overloadOverride2.pyand its evaluator test with positive cases for extras before and after base overloads and broad compatible coverage, plus negative cases for reordered matches and incompatible broad overlaps. The evaluator regression suite passed.Addresses
Fixes #11549