Bug Report
issubclass() fails to narrow type[A] to type[M] when A and M are unrelated NamedTuples. A plain if guard block treats the branch as unreachable instead. A comprehension filter keeps the unnarrowed type instead.
Note: This is NOT a duplicate of #21635 or #21677. Although each of these three issues has the same surface bug behavior -- mypy gets confused during type narrowing and bails out by setting the type to Never, causing the reported symptoms -- each has a completely different root cause for the confusion.
To Reproduce
from typing import NamedTuple, reveal_type
class A(NamedTuple):
a: int
class M(NamedTuple):
m: int
cls: type[A] = A
if issubclass(cls, M):
reveal_type(cls)
Expected Behavior
reveal_type(cls) reports type[<subclass of "A" and "M">].
Actual Behavior
Success: no issues found in 1 source file
No reveal_type note at all -- the branch is silently treated as unreachable.
Second repro (comprehension)
from typing import NamedTuple, reveal_type
class A(NamedTuple):
a: int
class M(NamedTuple):
m: int
alist: list[type[A]] = [A]
mlist: list[type[M]] = [cls for cls in alist if issubclass(cls, M)]
reveal_type(mlist)
Expected Behavior
No error, mlist is list[type[M]].
Actual Behavior
error: List comprehension has incompatible type List[type[A]]; expected List[type[M]] [misc]
Environment
- Mypy version used: mypy 2.2.0+dev (main branch)
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini (and other config files): nothing special
- Python version used: 3.12
Bug Report
issubclass()fails to narrowtype[A]totype[M]whenAandMare unrelatedNamedTuples. A plainifguard block treats the branch as unreachable instead. A comprehension filter keeps the unnarrowed type instead.Note: This is NOT a duplicate of #21635 or #21677. Although each of these three issues has the same surface bug behavior -- mypy gets confused during type narrowing and bails out by setting the type to
Never, causing the reported symptoms -- each has a completely different root cause for the confusion.To Reproduce
Expected Behavior
reveal_type(cls)reportstype[<subclass of "A" and "M">].Actual Behavior
No
reveal_typenote at all -- the branch is silently treated as unreachable.Second repro (comprehension)
Expected Behavior
No error,
mlistislist[type[M]].Actual Behavior
Environment
mypy.ini(and other config files): nothing special