microsoft / microsoft/pyright

False errors when using issubclass on argument of type type[T] where T is generic

Open
#11,042 1 comment 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.