Incorrect "Type application has too few types"
Bug Report
A Generic class that is a subclass of a class with a __new__() declared where there is a TypeVar as a parameter of __new__() reports that "Type application has too few types"
To Reproduce
from __future__ import annotations
from typing import Generic, Sequence, TypeVar, Union
T1 = TypeVar("T1", Sequence, list)
T2 = TypeVar("T2")
class Base:
def __new__(cls, data: T1 | str) -> Base:
...
def meth(self, data: T1 | str) -> int:
...
class GenBase(Base, Generic[T2]):
...
def fun() -> GenBase[int]:
return GenBase[int]("ac")
Actual Behavior mypy 0.971 reports:
gentypevar.py:21: error: Returning Any from function declared to return "GenBase[int]"
gentypevar.py:21: error: Type application has too few types (2 expected)
Your Environment
- Mypy version used: 0.971
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini(and other config files): None - Python version used: 3.8
- Operating system and version: Windows 10
Note that if T1 is changed to a Union, then no error is reported:
from __future__ import annotations
from typing import Generic, Sequence, TypeVar, Union
U1 = Union[Sequence, list, str]
T2 = TypeVar("T2")
class Base2:
def __new__(cls, data: U1 | str) -> Base2:
...
def meth(self, data: U1 | str) -> int:
...
class GenBase2(Base2, Generic[T2]):
...
def fun2() -> GenBase2[int]:
return GenBase2[int]("ac")
This came up with the pandas-stubs project. https://github.com/pandas-dev/pandas-stubs/issues/197
I believe this (or a similar issue) affects some built-in types as well , such as zip():
from __future__ import annotations
from typing_extensions import (
Iterator,
Tuple,
TypeAlias,
)
i1: Iterator[int]
i2: Iterator[str]
i3: Iterator[bool]
z1 = zip(i1, i2, i3)
reveal_type(z1) # zip[Tuple[int, str, bool]] # line 'A'
z_type: TypeAlias = zip[Tuple[int, str, bool]] # line 'B'
# actual mypy error [misc]:
# "type application has too few types (2 expected)"
# expected behavior: [no error]
# note: the expression on the right of the '=' equal sign is
# identical to the output of 'reveal_type(z1)' on
# line 'A'
# FURTHER ANALYSIS:
# fortunately, everything seems to go well if the mypy error on
# line 'B' (declaration of 'z_type', previous statement) is ignored:
z2: z_type
reveal_type(z2) # revealed type is [exactly the same as for 'z1']
# there are no issues with assignment either way:
if bool():
z2 = z1
else:
z1 = z2
control: int # show that neither 'z1'/'z2' are behaving as 'Any':
control = z1 # type: ignore[assignment]
control = z2 # type: ignore[assignment]
The typeshed representation ofzip (actually a class) does have __new__() with generics.
I am getting a similar error as well, although I did not define my own __new__ method.