Skip to content

Commit 9dd1086

Browse files
committed
Reject unsafe operator method overrides
1 parent aeb8426 commit 9dd1086

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

mypy/checker.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,17 @@ def check_override(self, override: FunctionLike, original: FunctionLike,
378378
len(cast(Callable, original).arg_types) or
379379
cast(Callable, override).min_args !=
380380
cast(Callable, original).min_args):
381+
# Use boolean variable to clarify code.
382+
fail = False
381383
if not is_subtype(override, original):
384+
fail = True
385+
elif (not isinstance(original, Overloaded) and
386+
isinstance(override, Overloaded) and
387+
name in nodes.reverse_op_methods.keys()):
388+
# Operator method overrides cannot introduce overloading, as
389+
# this could be unsafe with reverse operator methods.
390+
fail = True
391+
if fail:
382392
self.msg.signature_incompatible_with_supertype(
383393
name, supertype, node)
384394
return

mypy/test/data/check-classes.test

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,48 @@ main: In class "D":
828828
main, line 6: disjointclass constraint of class B disallows A as a base class
829829

830830

831+
-- Operator methods
832+
-- ----------------
833+
834+
835+
[case testOperatorMethodOverrideIntroducingOverloading]
836+
from typing import overload
837+
class A:
838+
def __add__(self, x: int) -> int: pass
839+
class B(A):
840+
@overload # E: Signature of "__add__" incompatible with supertype "A"
841+
def __add__(self, x: int) -> int: pass
842+
@overload
843+
def __add__(self, x: str) -> str: pass
844+
[out]
845+
main: In class "B":
846+
847+
[case testOperatorMethodOverrideWideningArgumentType]
848+
from typing import overload
849+
class A:
850+
def __add__(self, x: int) -> int: pass
851+
class B(A):
852+
def __add__(self, x: object) -> int: pass # E: Argument 1 of "__add__" incompatible with supertype "A"
853+
[out]
854+
main: In class "B":
855+
856+
[case testOperatorMethodOverrideNarrowingReturnType]
857+
from typing import overload
858+
class A:
859+
def __add__(self, x: int) -> 'A': pass
860+
class B(A):
861+
def __add__(self, x: int) -> 'B': pass
862+
[out]
863+
864+
[case testOperatorMethodOverrideWithDynamicallyTyped]
865+
from typing import overload
866+
class A:
867+
def __add__(self, x: int) -> 'A': pass
868+
class B(A):
869+
def __add__(self, x): pass
870+
[out]
871+
872+
831873
-- Special cases
832874
-- -------------
833875

0 commit comments

Comments
 (0)