False positive unreachable with unrelated types in match-case statement
Describe the bug
When type in a class pattern of a case branch is unrelated to the type of the scrutinee, pyright reports the branch as unreachable. That’s incorrect, because a common subclass of both types can exist.
Code or Screenshots
This code prints reached in runtime, but pyright reports the branch as unreachable and infers the type of t as Never instead of correct “subclass of Foo and Bar” as mypy does.
class Foo:
pass
class Bar:
pass
class Baz(Foo, Bar):
pass
def check(x: Foo) -> None:
match x:
case Bar() as t:
print('reached', t)
check(Baz())
VS Code extension or command-line I’m running pyright in Neovim, but this also reproduces on playground.
This is the same as this issue.
Pyright doesn't emit errors for unreachable code, so I'm not sure I'd consider this a "false positive" — at least not a false positive error. Pyright does emit a tagged hint to tell the client to display the code in a grayed-out manner, this is something that can be easily ignored.
I'll think about this a bit more, but my inclination is to leave the logic as is for now. As I mentioned in the other issue, I might be convinced to change this logic if there's sufficient signal from pyright users, but you're only the second person who has requested this change so far.
this is something that can be easily ignored
Note that this also creates an inference issue: t is inferred as Never, so it doesn’t get method autocompletion, proper type checking etc. (It’s also unsound, but I guess that doesn’t matter that much for Python)
I tried setting enableReachabilityAnalysis = false in our pyproject.toml to remove this hint, but it does not seem to work as expected. Was it wrong for me to assume this setting would stop this check from happening?
Is there another setting we can change for pyright to stop sending this hint to the editor? We are using Django and DRF and even their code is firing this hint before we even get started with our own code.
Thank you for your work on Pyright @erictraut
I tried setting enableReachabilityAnalysis = false in our pyproject.toml to remove this hint, but it does not seem to work as expected. Was it wrong for me to assume this setting would stop this check from happening?
I confirmed that when I add this line to pyproject.toml, the tagged hint is no longer reported. You may need to reset your language server after making the change depending on whether your client supports file change notifications.
Is there another setting we can change for pyright to stop sending this hint to the editor?
You can also set pyright.disableTaggedHints to "false" in your LSP settings, and pyright won't send any tagged hints to your editor even it claims to support them.
Interesting, how can I debug this to see what the debugger is passing to my client (Neovim btw 😆 ) ?
Our project code is no longer greying out, but the DRF Django library is still showing the type hint. Is there anything in Pyright that treats external libraries differently? Does it get cached as the code is assumed not to change? I am running this all inside a devcontainer and have done a complete rebuild so I don't think that has happened but makes me realise I am not aware of the moving parts at play.
/opt/venv/lib/python3.12/site-packages/rest_framework/generics.py:79
FYI I have set this in my project toml file and in my neovim config, this is what I get with LSPInfo command:
djangorestframework==3.16.0
The pyright settings in your pyrightconfig.json or pyproject.toml apply to files in your project. If you open a file that's outside of your project (such as a library file or a file in a directory that's elsewhere on your machine), pyright will still run on it, but it will use its default settings in that case.
If you want the LSP to disable tagged hints for all files, you can set the pyright.disableTaggedHints LSP setting to true.
Perfect, that makes sense as it ties in with what I have seen.
Thanks for the reply @erictraut and thank you for maintaining pyright