-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix partially defined in the case of missing type maps #15995
Conversation
Thanks @AlexWaygood for sending me on this adventure. This took me a while to debug! It turns out when we don't need to warn about unreachable code, we don't end up calling `self.is_noop_for_reachability(s)` (which is meant to tell us whether the code should be warned about or is `raise AssertionError` or `typing.assert_never(never)` or something. https://github.com/python/mypy/blob/6f650cff9ab21f81069e0ae30c92eae94219ea63/mypy/checker.py#L2748 This innocuous check has a side effect that turns out to be important for the partially undefined checks. These checks work by reaching into the type map populated by the checker. But if we never actually ended up analysing the code, we never populate the type map. This therefore changes things to assume that if we couldn't find the expression in the type map, it's probably because it was unreachable.
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Thanks so much for digging into this! :D |
[case testUnreachableCausingMissingTypeMap] | ||
# flags: --enable-error-code possibly-undefined --enable-error-code used-before-def --no-warn-unreachable | ||
# Regression test for https://github.com/python/mypy/issues/15958 | ||
from typing import Union, NoReturn | ||
|
||
def assert_never(__x: NoReturn) -> NoReturn: ... | ||
|
||
def foo(x: Union[int, str]) -> None: | ||
if isinstance(x, str): | ||
f = "foo" | ||
elif isinstance(x, int): | ||
f = "bar" | ||
else: | ||
assert_never(x) | ||
f # OK | ||
[builtins fixtures/tuple.pyi] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be worth adding a match/case
test as well, or would that just be unnecessarily duplicative?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good q, I think just duplicative. (fwiw I'd changed to if
since that runs on all Python versions)
Thanks @AlexWaygood for sending me on this adventure. This took me a while for me to debug!
When we don't need to warn about unreachable code, we don't end up calling
self.is_noop_for_reachability(s)
(which is meant to tell us whether the code should be warned about or israise AssertionError
ortyping.assert_never(never)
or something).mypy/mypy/checker.py
Line 2748 in 6f650cf
This innocuous check has a side effect that turns out to be important for the partially undefined checks. These checks work by reaching into the type map populated by the checker. But if we never actually ended up analysing the code, we never populate the type map.
This therefore changes things to assume that if we couldn't find the expression in the type map, it's probably because it was unreachable.