Skip to content
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

Pylance assumes type hints will be enforced at runtime #6849

Closed
landoskape opened this issue Jan 14, 2025 · 4 comments
Closed

Pylance assumes type hints will be enforced at runtime #6849

landoskape opened this issue Jan 14, 2025 · 4 comments
Assignees
Labels
needs repro Issue has not been reproduced yet

Comments

@landoskape
Copy link

Environment data

  • Pylance version: 2024.8.1
  • OS and version: Microsoft Windows [Version 10.0.19045.5247]
  • Python version (& distribution if applicable, e.g. Anaconda): 3.11.11

Code Snippet

    def check_integer(self, value: int) -> int:
        if not isinstance(value, int):
            # Pylance doesn't know that this is a valid check
            # It grays it out and says it's unreachable...
            raise TypeError(f"Expected int, got {type(value)}")
        return value

Note the comment in the code block. Pylance grays out the raise TypeError line indicating that it's unreachable. I believe this is because it assumes the typehint will be enforced at runtime, but it's just a hint so if you want to properly check, you still need the if - raise statements.

@github-actions github-actions bot added the needs repro Issue has not been reproduced yet label Jan 14, 2025
@erictraut
Copy link
Contributor

Pyright (the static type analysis tool upon which pylance is built) does not assume that type hints are enforced at runtime. After all, they are not. However, it assumes that type annotations accurately reflect the assumptions made by the code. In your code sample, you have declared that value will contain only an int instance or a subtype thereof.

If you want to reflect the fact that your function accepts a value of potentially any type, you can change the annotation for value to indicate int | Any.

@landoskape
Copy link
Author

This is fair - but isn't it misleading for it to say "code is unreachable" when the code is very much reachable?

def has_unreachable_code():
     return "hello world"
     print("oops I'm unreachable") # actually unreachable

In the above example, the print line is unreachable. (It's unreachable no matter what the caller of the function does, there's no way ever, ever that the print line will be used.

    def check_integer(self, value: int) -> int:
        if not isinstance(value, int):
            # Pylance doesn't know that this is a valid check
            # It grays it out and says it's unreachable...
            raise TypeError(f"Expected int, got {type(value)}") # very much reachable
        return value

In my initial example, the raise TypeError line is very much reachable (even though it won't be reached if caller functions obey the type hints). Should we omit type checks when we have type hints? Of course not, because as you say, type hints aren't enforced at runtime. So to enforce them at runtime, we need type checks like the one above... therefore it seems inappropriate for pylance to indicate that the code is unreachable. Don't you think so?

@erictraut
Copy link
Contributor

Pyright is a static analyzer. Based on the type declarations you've made, this code is unreachable via static analysis. Static analysis results will be only as good as the annotations you provide, so if you declare that value will accept only an int, then the static analyzer will use that information in its analysis.

Unreachable code detection and reporting is a useful way to find bugs, which is why pyright (and therefore pylance) display it as "grayed out". If you know that this code is reachable because your type annotations are not accurately declaring the types of objects that the function accepts, then you can simply ignore the fact that the code is grayed out. Pyright intentionally doesn't emit an error or a warning in this case. It simply tells VS Code to display the code in a grayed-out manner so you can decide whether it's an actual problem or something that'e expected in your code.

@landoskape
Copy link
Author

Okay, I understand your perspective. In software dev, it's pretty fair to assume that a type hint will be followed, which makes the statement "unreachable" true by the static analysis based on the type hints.

I'm coming from the academic science world where there's a lot of novice programmers (me included a while back) who learn good coding practice from things like pylance. People might be confused by the statement "code is unreachable" when the code is reachable (just hopefully won't be because the type hint should be followed). This is just my two cents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs repro Issue has not been reproduced yet
Projects
None yet
Development

No branches or pull requests

3 participants