-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[red-knot] How should we handle unreachable code? #15797
Comments
Per @AlexWaygood: #15676 (comment)
|
I think there is also a valid use case (c) where the user intends the code to be unreachable, but only in certain scenarios. This would be the case for if sys.version_info >= (3, 11):
# [code that makes use of symbols only available in 3.11+]
I think this could lead to many false-positives for the scenario (c) above, because we would emit unresolved-reference diagnostics for all 3.11+ symbols, if we check that code with a target version <3.11. As @AlexWaygood pointed out recently: we shouldn't even treat that use case (c) in the same way that we treat (a) and (b). Of course we would/could still gray-out the code inside that conditional if the target version is <3.11, but emitting a unreachable-code diagnostic for this code section would be rather annoying, I believe.
There is also a distinct third option, where we call a function that does not return (has return type See also: this section in the Pyright documentation. |
Personal feedback: my expectation as a user is that the type inference is unchanged because of the presence of a known return. The reason is that for debugging purposes it's very common to introduce a temporary early return that is unconditional. Now there are subtleties but I think that the right thing to do is to type check it as if it was reachable. |
I think in general, if some code is provably unreachable, this warrants a warning, but should not by itself change types of anything. If the code is unreachable because, for example, you eliminated all alternatives in a union, that should be a warning, plus the union type should decay to Never. |
We can statically determine that code is unreachable, due to terminal statements or statically known branches:
We should consider how we want to handle this. I think the uncontroversial part is that we should produce a (possibly optional?) diagnostic about the code being unreachable. But after that, there are several options:
We could mark all bindings as not visible once we reach a terminal statement. That would produce an
unresolved-reference
errors. This seems least helpful, since it seems likely that the user either (a) didn't intend for the code to become unreachable or (b) is inserting e.g. early returns as part of a debugging process. In both cases the user expects the supposedly unreachable code to be well-typed, and would want diagnostics about ways that it's not.We could consider the bindings visible, but update their inferred type to be
Never
to signify that those symbols wouldn't have any values in the unreachable code. This is arguably the most accurate interpretation, but doesn't provide much value over the "this code is unreachable" diagnostic.We could type-check the unreachable code as if it were reachable. Note that this would only apply to truly unreachable code, but not in something like:
Here, the
return
statement isn't always executed, and so thereveal_type
is not unreachable, and the obviously correct result isLiteral[1]
.We should also look into what mypy and pyright do here, to see if there's an obvious community consensus we should follow.
The text was updated successfully, but these errors were encountered: