Skip to content

Commit c796a56

Browse files
authored
Report note about binary operation on the same location as error (#8936)
This way we also suppress the note when ignoring the error.
1 parent d49e245 commit c796a56

File tree

6 files changed

+36
-8
lines changed

6 files changed

+36
-8
lines changed

mypy/checkexpr.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,12 +2680,16 @@ def check_op(self, method: str, base_type: Type,
26802680

26812681
if msg.is_errors():
26822682
self.msg.add_errors(msg)
2683+
# Point any notes to the same location as an existing message.
2684+
recent_context = msg.most_recent_context()
26832685
if len(left_variants) >= 2 and len(right_variants) >= 2:
2684-
self.msg.warn_both_operands_are_from_unions(context)
2686+
self.msg.warn_both_operands_are_from_unions(recent_context)
26852687
elif len(left_variants) >= 2:
2686-
self.msg.warn_operand_was_from_union("Left", base_type, context=right_expr)
2688+
self.msg.warn_operand_was_from_union(
2689+
"Left", base_type, context=recent_context)
26872690
elif len(right_variants) >= 2:
2688-
self.msg.warn_operand_was_from_union("Right", right_type, context=right_expr)
2691+
self.msg.warn_operand_was_from_union(
2692+
"Right", right_type, context=recent_context)
26892693

26902694
# See the comment in 'check_overload_call' for more details on why
26912695
# we call 'combine_function_signature' instead of just unioning the inferred

mypy/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ def is_errors_for_file(self, file: str) -> bool:
405405
"""Are there any errors for the given file?"""
406406
return file in self.error_info_map
407407

408+
def most_recent_error_location(self) -> Tuple[int, int]:
409+
info = self.error_info_map[self.file][-1]
410+
return info.line, info.column
411+
408412
def raise_error(self, use_stdout: bool = True) -> None:
409413
"""Raise a CompileError with the generated messages.
410414

mypy/messages.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
FuncDef, reverse_builtin_aliases,
3232
ARG_POS, ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2,
3333
ReturnStmt, NameExpr, Var, CONTRAVARIANT, COVARIANT, SymbolNode,
34-
CallExpr, SymbolTable
34+
CallExpr, SymbolTable, TempNode
3535
)
3636
from mypy.subtypes import (
3737
is_subtype, find_member, get_member_flags,
@@ -145,6 +145,14 @@ def enable_errors(self) -> None:
145145
def is_errors(self) -> bool:
146146
return self.errors.is_errors()
147147

148+
def most_recent_context(self) -> Context:
149+
"""Return a dummy context matching the most recent generated error in current file."""
150+
line, column = self.errors.most_recent_error_location()
151+
node = TempNode(NoneType())
152+
node.line = line
153+
node.column = column
154+
return node
155+
148156
def report(self,
149157
msg: str,
150158
context: Optional[Context],

test-data/unit/check-errorcodes.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,15 @@ class C:
736736
def __rsub__(self, x): pass
737737

738738
x - C() # type: ignore[operator]
739+
740+
[case testErrorCodeMultiLineBinaryOperatorOperand]
741+
# flags: --strict-optional
742+
from typing import Optional
743+
744+
class C: pass
745+
746+
def f() -> Optional[C]:
747+
return None
748+
749+
f( # type: ignore[operator]
750+
) + C()

test-data/unit/check-isinstance.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,8 +974,8 @@ def foo() -> Union[int, str, A]: pass
974974
def bar() -> None:
975975
x = foo()
976976
x + 1 # E: Unsupported left operand type for + ("A") \
977-
# E: Unsupported operand types for + ("str" and "int") \
978-
# N: Left operand is of type "Union[int, str, A]"
977+
# N: Left operand is of type "Union[int, str, A]" \
978+
# E: Unsupported operand types for + ("str" and "int")
979979
if isinstance(x, A):
980980
x.a
981981
else:

test-data/unit/check-unions.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,9 @@ from typing import Union
303303
class A: pass
304304
def f(x: Union[int, str, A]):
305305
x + object() # E: Unsupported left operand type for + ("A") \
306+
# N: Left operand is of type "Union[int, str, A]" \
306307
# E: Unsupported operand types for + ("int" and "object") \
307-
# E: Unsupported operand types for + ("str" and "object") \
308-
# N: Left operand is of type "Union[int, str, A]"
308+
# E: Unsupported operand types for + ("str" and "object")
309309
[builtins fixtures/primitives.pyi]
310310

311311
[case testNarrowingDownNamedTupleUnion]

0 commit comments

Comments
 (0)