False errors when using issubclass on argument of type type[T] where T is generic
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
The below code gives the following type error (strict mode): `test.py:63:16 - error: Type "bool | bool* | int | None" is not assignable to return type "T@Test"
Type "bool | bool* | int | None" is not assignable to type "T@Test" (reportReturnType)`.
The issue seems to be related to the `issubclass` call possibly confusing the type narrowing. If I remove it, the error goes away. It's not clear to me why it thinks `result` can be `bool*` (which, from what I've read, is an internal type for something possibly falsy), but presumably that's why it can't be assigned to the generic.
mypy does not throw an error here, and it works fine at runtime.
**Code or Screenshots**
If possible, provide a minimal, self-contained code sample (surrounded by triple back ticks) to demonstrate the issue. The code should define or import all referenced symbols.
```python
import sys
from typing import Any, Generic, Self, TypeVar
class Base:
@classmethod
def bar(cls, _: Any) -> Self:
return cls()
class Derived(Base):
def print(self):
print("called print")
def foo() -> bool | int | None:
return None if len(sys.argv) > 1 else 4
MyTypes = bool | int | None
T = TypeVar("T", bound=Base | MyTypes)
class Test(Generic[T]):
def __init__(self, return_type: type[T]):
self._return_type = return_type
def __call__(self) -> T:
result = foo()
if issubclass(self._return_type, Base):
return self._return_type.bar(result)
if not isinstance(result, self._return_type):
raise TypeError
return result
if len(sys.argv) > 1:
MyTest = Test[Derived](Derived)
a = MyTest()
a.print() # outputs "called print"
else:
MyTest2 = Test[int](int)
b = MyTest2() # no type error
MyTest3 = Test[bool](bool)
c = MyTest3() # raises TypeError
```
**VS Code extension or command-line**
pyright 1.1.406 command line
Contributor guide
Research direction
Start by running the provided sample with pyright 1.1.406 in strict mode and inspect the narrowing around issubclass(self._return_type, Base), the generic type[T], and the subsequent isinstance check. Done means the valid Base, int, and bool cases no longer produce the reported false return-type error while the runtime behavior remains covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100