From 9dd1086e76c4d62011c2ff1479abae30565c6db2 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 3 Sep 2013 16:57:39 +0100 Subject: [PATCH] Reject unsafe operator method overrides --- mypy/checker.py | 10 ++++++++ mypy/test/data/check-classes.test | 42 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/mypy/checker.py b/mypy/checker.py index 7b64b903c986..f8321144b9a9 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -378,7 +378,17 @@ def check_override(self, override: FunctionLike, original: FunctionLike, len(cast(Callable, original).arg_types) or cast(Callable, override).min_args != cast(Callable, original).min_args): + # Use boolean variable to clarify code. + fail = False if not is_subtype(override, original): + fail = True + elif (not isinstance(original, Overloaded) and + isinstance(override, Overloaded) and + name in nodes.reverse_op_methods.keys()): + # Operator method overrides cannot introduce overloading, as + # this could be unsafe with reverse operator methods. + fail = True + if fail: self.msg.signature_incompatible_with_supertype( name, supertype, node) return diff --git a/mypy/test/data/check-classes.test b/mypy/test/data/check-classes.test index 925ac6771c9b..3457b03bd452 100644 --- a/mypy/test/data/check-classes.test +++ b/mypy/test/data/check-classes.test @@ -828,6 +828,48 @@ main: In class "D": main, line 6: disjointclass constraint of class B disallows A as a base class +-- Operator methods +-- ---------------- + + +[case testOperatorMethodOverrideIntroducingOverloading] +from typing import overload +class A: + def __add__(self, x: int) -> int: pass +class B(A): + @overload # E: Signature of "__add__" incompatible with supertype "A" + def __add__(self, x: int) -> int: pass + @overload + def __add__(self, x: str) -> str: pass +[out] +main: In class "B": + +[case testOperatorMethodOverrideWideningArgumentType] +from typing import overload +class A: + def __add__(self, x: int) -> int: pass +class B(A): + def __add__(self, x: object) -> int: pass # E: Argument 1 of "__add__" incompatible with supertype "A" +[out] +main: In class "B": + +[case testOperatorMethodOverrideNarrowingReturnType] +from typing import overload +class A: + def __add__(self, x: int) -> 'A': pass +class B(A): + def __add__(self, x: int) -> 'B': pass +[out] + +[case testOperatorMethodOverrideWithDynamicallyTyped] +from typing import overload +class A: + def __add__(self, x: int) -> 'A': pass +class B(A): + def __add__(self, x): pass +[out] + + -- Special cases -- -------------