mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Incorrect "Type application has too few types"

Open Dr-Irv opened this issue 3 years ago • 1 comments

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

Dr-Irv avatar Aug 17 '22 00:08 Dr-Irv

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.

finite-state-machine avatar Feb 15 '24 23:02 finite-state-machine

I am getting a similar error as well, although I did not define my own __new__ method.

man2machine avatar Jul 18 '24 04:07 man2machine