Open
Description
Bug Report
I wanted to define two type hierarchies: model types, and handlers that are contravariant over models, where models can specify their handlers as class keyword arguments. I've included a simplified example in the To Reproduce section below.
The problem seems to be that, when __init_subclass__
runs for Foo
, it's treating Self
as if it were Model
rather than Foo
, which fails because T
is contravariant and FooHandler
is not a subtype of Handler[Model]
.
To Reproduce
from __future__ import annotations
from typing import Any, ClassVar, Self, TypeVar, Generic
T = TypeVar("T", bound="Model", contravariant=True)
class Handler(Generic[T]):
pass
class Model:
handler: ClassVar[type[Handler[Self]]]
def __init_subclass__(cls, *, handler: type[Handler[Self]]) -> None:
super().__init_subclass__()
cls.handler = handler
class FooHandler(Handler[Foo]):
pass
class Foo(Model, handler=FooHandler):
pass
Expected Behavior
I expected mypy to treat Self
as Foo
when running Model.__init_subclass__(Foo, ...)
.
Actual Behavior
main.py:15: error: Incompatible types in assignment (expression has type "type[Handler[Self]]", variable has type "type[Handler[Model]]") [assignment]
main.py:21: error: Argument "handler" to "__init_subclass__" of "Model" has incompatible type "type[FooHandler]"; expected "type[Handler[Model]]" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 1.4.1 and master branch (both from playground)
- Python version used: 3.11