-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
assert False
makes rest of function not checked by mypy
#7467
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
Comments
Quick observation before I pick on this specific issue: the "prune everything after an An even simpler repro case: def expecting_check_error() -> str:
assert False
return 123 Pretty sure what's happening here is that Proof: the issue is "fixed" by a hacky little change like this: diff --git a/mypy/checker.py b/mypy/checker.py
index 1de0876e..07ae749b 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -3028,7 +3028,7 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
true_map, else_map = self.find_isinstance_check(s.expr)
if s.msg is not None:
self.expr_checker.analyze_cond_branch(else_map, s.msg, None)
- self.push_type_map(true_map)
+ self.push_type_map(true_map or {})
def visit_raise_stmt(self, s: RaiseStmt) -> None:
"""Type check a raise statement.""" If you look at IMO this is a bug (or at best surprising/"unsafe" behavior), but I think one of the core folks will need to weigh in on the actual expected semantics. |
From my perspective the options seem to be one of the following:
Defer to the experts but I'd personally prefer we default to (2) and maybe hook up (3) later to let folks opt-out of the stricter semantics. Just seems a bit safer. |
Thank you for digging into this @thomaslee! I view mypy as doing the correct thing here. Is there a real-world example where the current behavior causes issues? |
This behavior is by design, mypy doesn't type check code it can prove unreachable. There is also a new flag to issue a warning in this case |
@ethanhs (cc @ilevkivskyi) in an earlier draft I mentioned this but I guess it got lost somewhere along the way: the obvious one is Example: # my_package/__init__.py
def do_stuff():
assert False
print('I did stuff!')
# driver.py
from my_package import do_stuff
do_stuff() Then, without
But the same code, unmodified, with
Hopefully that makes the issue clear. EDIT: The above was using Python 3.7.4, but same results with a recent-ish 3.8 build. |
Thanks for the quick replies, everyone! And thanks @ilevkivskyi for clarifying that this is by design. Still, I think this is an incorrect design choice to make these errors/warnings silent by default and I would encourage we reopen this issue to improve the usability of this functionality. (For example, by doing things like making the warning default, or revisiting this design choice entirely due to the optimize case as above.) As a slightly less minimal example which mimics some code I was editing at work: from typing import Any
class Foo(object):
def __init__(self): # type: () -> None
self.data = None
def set_data(self, data): # type: (Any) -> None
self.data = data
def to_str(self): # type: () -> str
assert self.data
return self.data # should be a type error -- this is missing str()
foo = Foo()
foo.set_data(5)
mystr = '' # type: str
mystr = foo.to_str() # missing type error here
Clearly, one small solution is to add an annotation like |
Hm this would be a different issue to the one you originally raised I think. Suspect it works because mypy is inferring I personally think the "assume dead code for the |
@thomaslee @Hnasar Your problem is not forgetting annotation but using |
No worries @ilevkivskyi. I guess it just seems like forcing folks to modify their code to use something that ensures the code is truly unreachable under all circumstances (such as Anyway -- I won't argue the point further, feel free to ignore me if I'm being annoying. 😉 Thanks for the clarification! |
It seems when you have
assert False
, the rest of the function isn't checked.What are the versions of mypy and Python you are using?
I tried with mypy 0.501, all the way up to 0.720, and also from git master.
python 3.7.4 from Fedora 30.
What are the mypy flags you are using? (For example --strict-optional)
none
The text was updated successfully, but these errors were encountered: