Skip to content

Commit 402a066

Browse files
authored
Fix leaking error messages during overload selection (#5211)
Fixes #5210 When mypy tries selecting an appropriate overload alternative, it swaps out the current 'msg' object with a placeholder. If this placeholder does not accumulate any error messages, we know that alternative is a successful match. Previously, we replaced only checkexpr.ExpressionChecker's msg object with the placeholder. However, since checkexpr can sometimes call checker.TypeChecker, we need to replace its msg object as well to prevent error messages that would normally be silenced from leaking. More broadly, the current overload implementation broke the invariant that both msg fields refer to the same underlying MessageBuilder object. This pull request fixes that oversight.
1 parent 6a956d7 commit 402a066

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

mypy/checkexpr.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,9 @@ def infer_overload_return_type(self,
12381238
for typ in plausible_targets:
12391239
overload_messages = self.msg.clean_copy()
12401240
prev_messages = self.msg
1241+
assert self.msg is self.chk.msg
12411242
self.msg = overload_messages
1243+
self.chk.msg = overload_messages
12421244
try:
12431245
# Passing `overload_messages` as the `arg_messages` parameter doesn't
12441246
# seem to reliably catch all possible errors.
@@ -1253,6 +1255,7 @@ def infer_overload_return_type(self,
12531255
callable_name=callable_name,
12541256
object_type=object_type)
12551257
finally:
1258+
self.chk.msg = prev_messages
12561259
self.msg = prev_messages
12571260

12581261
is_match = not overload_messages.is_errors()

test-data/unit/check-overloading.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,3 +2620,32 @@ class FakeAttribute(Generic[T]):
26202620
@overload
26212621
def dummy(self, instance: T, owner: Type[T]) -> int: ...
26222622
def dummy(self, instance: Optional[T], owner: Type[T]) -> Union['FakeAttribute[T]', int]: ...
2623+
2624+
[case testOverloadLambdaUnpackingInference]
2625+
# flags: --py2
2626+
from typing import Callable, TypeVar, overload
2627+
2628+
T = TypeVar('T')
2629+
S = TypeVar('S')
2630+
2631+
@overload
2632+
def foo(func, item):
2633+
# type: (Callable[[T], S], T) -> S
2634+
pass
2635+
2636+
@overload
2637+
def foo():
2638+
# type: () -> None
2639+
pass
2640+
2641+
def foo(*args):
2642+
pass
2643+
2644+
def add_proxy(x, y):
2645+
# type: (int, str) -> str
2646+
pass
2647+
2648+
# The lambda definition is a syntax error in Python 3
2649+
tup = (1, '2')
2650+
reveal_type(foo(lambda (x, y): add_proxy(x, y), tup)) # E: Revealed type is 'builtins.str*'
2651+
[builtins fixtures/primitives.pyi]

0 commit comments

Comments
 (0)