2Tests the handling and enforcement of TypeVar variance.
5# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#variance
7from typing import Sequence, TypeVar, Generic
8from collections.abc import Iterable, Iterator
10# > To facilitate the declaration of container types where covariant or
11# > contravariant type checking is acceptable, type variables accept
12# > keyword arguments covariant=True or contravariant=True. At most one of
13# > these may be passed.
14X1 = TypeVar("X1", covariant=True, contravariant=True) # E
[invalid-legacy-type-variable] A `TypeVar` cannot be both covariant and contravariant
18T_co = TypeVar("T_co", covariant=True)
19T_contra = TypeVar("T_contra", contravariant=True)
22class ImmutableList(Generic[T_co]):
23 def __init__(self, items: Iterable[T_co]) -> None:
26 def __iter__(self) -> Iterator[T_co]:
27 raise NotImplementedError
34class Manager(Employee):
38managers: ImmutableList[Manager] = ImmutableList([Manager()])
39employees: ImmutableList[Employee] = managers # OK
42E = TypeVar("E", bound=Employee)
45def dump_employee(e: E) -> E:
49dump_employee(Manager()) # OK
52B_co = TypeVar("B_co", covariant=True)
55# > Variance has no meaning, and should therefore be ignored by type checkers,
56# > if a type variable is bound to a generic function or type alias.
57def func(x: list[B_co]) -> B_co: # OK
58 raise NotImplementedError
61class Co(Generic[T_co]):
65class Contra(Generic[T_contra]):
73class CoContra(Generic[T_co, T_contra]):
77class Class1(Inv[T_co]): # E: Inv requires invariant TypeVar
Expected a ty diagnostic for this line
81class Class2(Inv[T_contra]): # E: Inv requires invariant TypeVar
Expected a ty diagnostic for this line
85class Co_Child1(Co[T_co]): # OK
89class Co_Child2(Co[T]): # OK
93class Co_Child3(Co[T_contra]): # E: Co requires covariant
Expected a ty diagnostic for this line
97class Contra_Child1(Contra[T_contra]): # OK
101class Contra_Child2(Contra[T]): # OK
105class Contra_Child3(Contra[T_co]): # E: Contra requires contravariant
Expected a ty diagnostic for this line
109class Contra_Child4(Contra[Co[T_contra]]): # OK
113class Contra_Child5(Contra[Co[T_co]]): # E: Contra requires contravariant
Expected a ty diagnostic for this line
117class Contra_Child6(Contra[Co[T]]): # OK
121class CoContra_Child1(CoContra[T_co, T_contra]): # OK
125class CoContra_Child2( # E[CoContra_Child2]: Second type arg must be contravariant
Expected a ty diagnostic for this line (tag 'CoContra_Child2')
126 CoContra[T_co, T_co] # E[CoContra_Child2]: Second type arg must be contravariant
Expected a ty diagnostic for this line (tag 'CoContra_Child2')
131class CoContra_Child3( # E[CoContra_Child3]: First type arg must be covariant
Expected a ty diagnostic for this line (tag 'CoContra_Child3')
132 CoContra[T_contra, T_contra] # E[CoContra_Child3]: First type arg must be covariant
Expected a ty diagnostic for this line (tag 'CoContra_Child3')
137class CoContra_Child4(CoContra[T, T]): # OK
141class CoContra_Child5( # E[CoContra_Child5]: Second type arg must be contravariant
Expected a ty diagnostic for this line (tag 'CoContra_Child5')
142 CoContra[Co[T_co], Co[T_co]] # E[CoContra_Child5]: Second type arg must be contravariant
Expected a ty diagnostic for this line (tag 'CoContra_Child5')
147class CoToContra(Contra[Co[T_contra]]): # OK
151class ContraToContra(Contra[Contra[T_co]]): # OK
155class CoToCo(Co[Co[T_co]]): # OK
159class ContraToCo(Co[Contra[T_contra]]): # OK
163class CoToContraToContra(Contra[Co[Contra[T_contra]]]): # E
Expected a ty diagnostic for this line
167class ContraToContraToContra(Contra[Contra[Contra[T_co]]]): # E
Expected a ty diagnostic for this line
172Contra_TA = Contra[T_contra]
175class CoToContra_WithTA(Contra_TA[Co_TA[T_contra]]): # OK
179class ContraToContra_WithTA(Contra_TA[Contra_TA[T_co]]): # OK
183class CoToCo_WithTA(Co_TA[Co_TA[T_co]]): # OK
187class ContraToCo_WithTA(Co_TA[Contra_TA[T_contra]]): # OK
191class CoToContraToContra_WithTA(Contra_TA[Co_TA[Contra_TA[T_contra]]]): # E
Expected a ty diagnostic for this line
195class ContraToContraToContra_WithTA( # E[ContraToContraToContra_WithTA]
Expected a ty diagnostic for this line (tag 'ContraToContraToContra_WithTA')
196 Contra_TA[Contra_TA[Contra_TA[T_co]]] # E[ContraToContraToContra_WithTA]
Expected a ty diagnostic for this line (tag 'ContraToContraToContra_WithTA')