Skip to content

Commit 4fc7400

Browse files
authored
Fix error code of binary operation involving overload (#8124)
Previously the error code for the error message was 'call-overload', which was inconsistent. In addition, the related note had the 'operator' error code, which made things worse. Now both the error message and the note have the 'operator' error code.
1 parent 7e65f1e commit 4fc7400

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

mypy/checkexpr.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1495,8 +1495,12 @@ def check_overload_call(self,
14951495
target = AnyType(TypeOfAny.from_error)
14961496

14971497
if not self.chk.should_suppress_optional_error(arg_types):
1498+
if not is_operator_method(callable_name):
1499+
code = None
1500+
else:
1501+
code = codes.OPERATOR
14981502
arg_messages.no_variant_matches_arguments(
1499-
plausible_targets, callee, arg_types, context)
1503+
plausible_targets, callee, arg_types, context, code=code)
15001504

15011505
result = self.check_call(target, args, arg_kinds, context, arg_names,
15021506
arg_messages=arg_messages,
@@ -4277,3 +4281,13 @@ def type_info_from_type(typ: Type) -> Optional[TypeInfo]:
42774281
# A complicated type. Too tricky, give up.
42784282
# TODO: Do something more clever here.
42794283
return None
4284+
4285+
4286+
def is_operator_method(fullname: Optional[str]) -> bool:
4287+
if fullname is None:
4288+
return False
4289+
short_name = fullname.split('.')[-1]
4290+
return (
4291+
short_name in nodes.op_methods.values() or
4292+
short_name in nodes.reverse_op_methods.values() or
4293+
short_name in nodes.unary_op_methods.values())

mypy/messages.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,10 @@ def no_variant_matches_arguments(self,
659659
plausible_targets: List[CallableType],
660660
overload: Overloaded,
661661
arg_types: List[Type],
662-
context: Context) -> None:
662+
context: Context,
663+
*,
664+
code: Optional[ErrorCode] = None) -> None:
665+
code = code or codes.CALL_OVERLOAD
663666
name = callable_name(overload)
664667
if name:
665668
name_str = ' of {}'.format(name)
@@ -669,16 +672,16 @@ def no_variant_matches_arguments(self,
669672
num_args = len(arg_types)
670673
if num_args == 0:
671674
self.fail('All overload variants{} require at least one argument'.format(name_str),
672-
context, code=codes.CALL_OVERLOAD)
675+
context, code=code)
673676
elif num_args == 1:
674677
self.fail('No overload variant{} matches argument type {}'
675-
.format(name_str, arg_types_str), context, code=codes.CALL_OVERLOAD)
678+
.format(name_str, arg_types_str), context, code=code)
676679
else:
677680
self.fail('No overload variant{} matches argument types {}'
678-
.format(name_str, arg_types_str), context, code=codes.CALL_OVERLOAD)
681+
.format(name_str, arg_types_str), context, code=code)
679682

680683
self.pretty_overload_matches(plausible_targets, overload, context, offset=2, max_items=2,
681-
code=codes.CALL_OVERLOAD)
684+
code=code)
682685

683686
def wrong_number_values_to_unpack(self, provided: int, expected: int,
684687
context: Context) -> None:

test-data/unit/check-errorcodes.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,29 @@ class InvalidReturn:
703703
# N: If return type of "__exit__" implies that it may return True, the context manager may swallow exceptions
704704
return False
705705
[builtins fixtures/bool.pyi]
706+
707+
[case testErrorCodeOverloadedOperatorMethod]
708+
# flags: --strict-optional
709+
from typing import Optional, overload
710+
711+
class A:
712+
@overload
713+
def __add__(self, x: int) -> A: ...
714+
@overload
715+
def __add__(self, x: str) -> str: ...
716+
def __add__(self, x): pass
717+
718+
class B:
719+
pass
720+
721+
x: Optional[B]
722+
A() + x # type: ignore[operator]
723+
724+
class C:
725+
@overload
726+
def __rsub__(self, x: int) -> A: ...
727+
@overload
728+
def __rsub__(self, x: str) -> str: ...
729+
def __rsub__(self, x): pass
730+
731+
x - C() # type: ignore[operator]

0 commit comments

Comments
 (0)