python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.39k stars 2.82k forks source link

Incompatible types when calling generinc `__init__` from generic `@classmethod` #17937

Open bjoernpollex opened 1 week ago

bjoernpollex commented 1 week ago

Bug Report

When calling a generic __init__ from a generic @classmethod on a class that is itself not generic, mypy reports incompatible types.

To Reproduce

from typing import TypeVar

T = TypeVar("T")

class Foo:
    @classmethod
    def make_foo(cls, arg: T) -> None:
        cls(arg)

    def __init__(self, arg: T) -> None:
        pass

Expected Behavior

mypy reports no errors.

Actual Behavior

error: Argument 1 to "Foo" has incompatible type "T@make_foo"; expected "T@__init__"

Your Environment

aatle commented 1 week ago

From more investigation, the specific problem is that a when a variable of type type[C] is called, it's constructor type variables reject all types except Any. (classmethod gives cls the type type[C].)

# --strict
from typing import TypeVar
from collections.abc import Callable

T = TypeVar("T")

class C:
    def __init__(self, arg1: T, arg2: T):
        pass

C(1, 1)  # okay

bar: Callable[[object, object], C] = C
bar(1, 1)  # okay

foo: type[C]
foo(1, 1)  # error
# main.py:17: error: Argument 1 to "C" has incompatible type "int"; expected "T"  [arg-type]