basedmypy icon indicating copy to clipboard operation
basedmypy copied to clipboard

Don't allow `<nothing>` to suppress unreachable errors

Open KotlinIsland opened this issue 3 years ago • 1 comments

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.

KotlinIsland avatar Mar 21 '22 07:03 KotlinIsland

def foo() -> int:
    return 1
    raise Exception  # no error

dumb

KotlinIsland avatar Aug 12 '22 06:08 KotlinIsland