diff --git a/mypy/checker.py b/mypy/checker.py index 33ed5387554d..3e0ec4f2de95 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1979,14 +1979,19 @@ def check_reverse_op_method( assert defn.info # First check for a valid signature - method_type = CallableType( - [AnyType(TypeOfAny.special_form), AnyType(TypeOfAny.special_form)], - [nodes.ARG_POS, nodes.ARG_POS], - [None, None], - AnyType(TypeOfAny.special_form), - self.named_type("builtins.function"), - ) - if not is_subtype(reverse_type, method_type): + method_types = [ + CallableType( + [AnyType(TypeOfAny.special_form)] * num_args, + [nodes.ARG_POS] * num_args, + [None] * num_args, + AnyType(TypeOfAny.special_form), + self.named_type("builtins.function"), + ) + # The data model allows __rpow__ to take an optional third "modulo" + # argument, mirroring the ternary form of __pow__. + for num_args in ([2, 3] if reverse_name == "__rpow__" else [2]) + ] + if not any(is_subtype(reverse_type, method_type) for method_type in method_types): self.msg.invalid_signature(reverse_type, context) return diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 2cd43c74ebb5..75619803459a 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2509,6 +2509,25 @@ class C: tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]" tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]" +[case testReverseOperatorMethodTernaryPow] +from foo import * +[file foo.pyi] +from typing import overload +class A: + def __rpow__(self, other: A, modulo: A) -> A: ... +class B: + @overload + def __rpow__(self, other: B) -> B: ... + @overload + def __rpow__(self, other: B, modulo: B) -> B: ... +class C: + def __rpow__(self, other: C, modulo: C, oops: C) -> C: ... +class D: + def __radd__(self, other: D, modulo: D) -> D: ... +[out] +tmp/foo.pyi:10: error: Invalid signature "Callable[[C, C, C, C], C]" +tmp/foo.pyi:12: error: Invalid signature "Callable[[D, D, D], D]" + [case testReverseOperatorOrderingCase1] class A: def __radd__(self, other: 'A') -> int: ...