Description
Bug Report
When a generic type defined via TypeVar
is used with constrained types, a base class for those types is computed and errors are reported against that base class.
To Reproduce
In this example, get()
uses some internal logic to select a constructor, which is either D1
or D2
, and add()
constructs the specified instance, performs some work with it and returns it to the caller.
from typing import TypeVar
from random import random
class B: ...
class D1(B):
def __repr__(self)->str: return "D1 class"
class D2(B):
def __repr__(self)->str: return "D2 class"
Q = TypeVar("Q", D1, D2) # triggers error 1, 2
#Q = TypeVar("Q", bound=B) # triggers error 2
#Q = TypeVar("Q") # triggers error 2
def add(c: type[Q])->Q:
return c()
def get() -> type[D1]|type[D2]:
return D1 if random() > 0.5 else D2
# [1] error: Value of type variable "Q" of "add" cannot be "B" [type-var]
# [2] error: Incompatible types in assignment (expression has type "B", variable has type "D1 | D2")
w: D1|D2 = add(get())
print(w)
Expected Behavior
No errors should be reported because all referenced types align against one another and the base class B
plays no role in this code. Moreover, if B
is removed as a base class of D1
and D2
, the errors are still reported, but against object
instead of B
.
I expect TypeVar
with this constraint to behave as if add()
is defined as below, which reports no errors.
def add(c: type[D1]|type[D2])->D1|D2:
return c()
Actual Behavior
main.py:24: error: Value of type variable "Q" of "add" cannot be "B" [type-var]
main.py:24: error: Incompatible types in assignment (expression has type "B", variable has type "D1 | D2") [assignment]
Your Environment
- Mypy version used: 1.5.1
- Mypy command-line flags: --strict --check-untyped-defs --strict-equality --warn-redundant-casts --warn-incomplete-stub --warn-unreachable --install-types --non-interactive
- Mypy configuration options from
mypy.ini
(and other config files): N/A (none) - Python version used: 3.10