basedmypy
basedmypy copied to clipboard
Don't allow `<nothing>` to suppress unreachable errors
def foo(data: list[str]):
if data is None:
print("hi") # error, unreachable
if data is None:
raise Exception # no error
Due to the unsoundness of Pythons runtime, mypy allows raise and other <nothing> forms to suppress "unreachable" errors to allow for a smooth way to validate types and data dynamically.
I don't like this as you could:
- run into situations where you unintentionally create a
<nothing>on an unreachable line - have dead code lying around that is no longer needed.
I don't know what the best way to handle this is though, as there would be no way to detect if the code in question is dead or intentional.
Additional ramblings
Ideally there should be a special error type for this exact purpose, with hard and soft checks depending of if it's syntactically or type-based unreachable:
class UnreachableAssertion(AssertionError):
"""Used to indicate when a branch should be unreachable."""
pass
assert False
message = "among"
assert_unreachable(message) # type-based unreachable, no error
raise UnreachableAssertion(message) # syntax based unreachable, no error
raise UnreachableAssertion(message) # error, absolutely unreachable
assert True
raise UnreachableAssertion(message) # error, statement is reachable
Or maybe that is over-engineering a problem that doesn't exist, maybe just only special casing assert_never is enough.
def foo() -> int:
return 1
raise Exception # no error
dumb