No narrowing after `isinstance(obj, tuple)` if `tuple` contains a term.
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
The type narrowing of `isinstance(obj, class_or_tuple, /)` doesn't happen if one of the classes in `class_or_tuple` is not just a type, but a term.
I understand that we can't have dependent types, but in this example, I expect `C` to have been removed from the inferred type of `x` afer the `isinstance` has returned False. `C | T ∧ ¬C` or if the term cannot be statically inferred ` C | Unknown ^ ¬C`
**Code or Screenshots**
Code sample in [pyright playground](https://pyright-play.net/?pythonVersion=3.12&code=GYJw9gtgBALgngBwJYDsDmUkQWEMpRoCmMA%2BrkmqgDRQCGAzg0XqSkQG4sBQ3AxgBtGDKAGEAXNwIEEw3gBMiwKMADaAFQC6ACmYDgtAB7ixUAD5R1tGCfgIiGzQEpJ02Cwi3ERKAF5CJOQglKja6k5QuLBS0kjKSAyoDDB0KHxE2oa02qLWHk4uMW4EICQAriAoUABidALMRZjxiSjJqemZtKKFxdLCLGTsXCDaTtxAA)
```python
from typing import get_origin, assert_never
class C:
pass
def f[T](self, x: C | T, t: type[T]):
term: type = get_origin(T) or t
if isinstance(x, (C, term)):
return False
if isinstance(x, C):
assert_never()
```
note that the second `isinstance` is only to show the problem, not an actual use case.
Contributor guide
Research direction
Reproduce the example in the linked pyright playground with Python 3.12 and inspect the narrowing after the first isinstance check. Trace the type-analysis entry point for isinstance expressions and determine whether the false branch removes C when the tuple contains the term. Done means the second isinstance branch is recognized as unreachable in this example, with appropriate regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100