Incorrect reachability analysis involving NewType
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
With this program ([playground](https://pyright-play.net/?pythonVersion=3.13&strict=true&locale=en&enableExperimentalFeatures=true&code=GYJw9gtgBALgngBwJYDsDmUkQWEMoByApgO4AqiRAsAFC0FlQC8hpFCRAFAEQPcA0UAM4wQASlq0AxgBsAhkKFQAGpxHiAXLSg6oCBUMk0AJkWBRgnAB4bCZMVpq7M5pENQi5KKVyuDlDtrOuiBEAG5EcjIA%2BvAc1hJOukQyQkSOwSHhkTFxvom0lgycqtxW3GKVtEA)):
```python
from typing import NewType
NT = NewType("NT", str)
class X(str):
pass
def f(x: NT):
if isinstance(x, X):
reveal_type(x)
else:
reveal_type(x)
f(NT(X("x")))
```
Pyright reports `Unnecessary isinstance call; "NT" is never an instance of "X"`. This is incorrect, as the underlying value of the NewType may be an instance of a subclass of str.
Mypy correctly creates an ad-hoc intersection here and reports `Revealed type is "__main__."`.
Contributor guide
Research direction
Start with the linked playground reproducer and inspect the reachability analysis for isinstance narrowing of a NewType, comparing the result with the shown mypy behavior. Done means Pyright no longer reports the isinstance call as unreachable and preserves the possible subclass in both reveal_type results.
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
- 45/100