Description
Bug Report
Variance inference works out whether a type variable should be co-, contra- or in-variant, based on the way it is used as an argument type, a result type, or both.
But it seems it cannot see through a Union type used in a result. In this example, it correctly determines that T
in class Example
is used as both argument and result, therefore is invariant, and does not complain becuase the TypeVar is (by default) invariant. But in class Example2
, T
is still used as both argument and result, albeit through a Union. It seems that mypy cannot see through the union, and reports errors just as though the method had no variables in its return type. For comparison, in Example3
, the type variables are not used at all in the return type, so it correctly infers that T should be contravariant; mypy gives the same error messages as Example2
, suggesting that it doesn't see S|T
as containing any type variables at all.
To Reproduce
from typing import Generic, Protocol, TypeVar
S = TypeVar("S")
T = TypeVar("T")
class Example(Protocol, Generic[T]):
def method(self, arg: T) -> T:
return arg
class Example2(Protocol, Generic[S, T]):
def method(self, arg: T) -> S|T: # <-- bug here
return arg
class Example3(Protocol, Generic[S, T]):
def method(self, arg: T) -> int:
return 7
Expected Behavior
In the class Example2, I expect mypy to recognize that T
is used positively in method arguments and result types, and therefore to infer that T
should be an invariant variable. (The inference for S
is not important for this report; but the bug does not repro if the other type is a concrete type like int
.)
Actual Behavior
$ mypy example.py
example.py:10: error: Invariant type variable "S" used in protocol where covariant one is expected [misc]
example.py:10: error: Invariant type variable "T" used in protocol where contravariant one is expected [misc]
example.py:14: error: Invariant type variable "S" used in protocol where covariant one is expected [misc]
example.py:14: error: Invariant type variable "T" used in protocol where contravariant one is expected [misc]
Your Environment
- Mypy version used: 1.11.2 (compiled: yes)
- Mypy command-line flags: none, just the python file name
- Mypy configuration options from
mypy.ini
(and other config files): none - Python version used: 3.10.14