2Tests TypeVars with upper bounds.
5# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#type-variables-with-an-upper-bound
7from typing import Collection, Generic, Sized, TypeVar, assert_type
9# > A type variable may specify an upper bound using bound=<type>
11T_Good1 = TypeVar("T_Good1", bound=int) # OK
12T_Good2 = TypeVar("T_Good2", bound="ForwardRef | str") # OK
18# > <type> itself cannot be parameterized by type variables.
23class Test(Generic[T]):
24 T_Bad1 = TypeVar("T_Bad1", bound=list[T]) # E
[invalid-type-variable-bound] TypeVar upper bound cannot be generic
27ST = TypeVar("ST", bound=Sized)
30def longer(x: ST, y: ST) -> ST:
37assert_type(longer([1], [1, 2]), list[int])
Unexpected error
[type-assertion-failure] Type `list[int]` does not match asserted type `list[Unknown | int]`
38assert_type(longer({1}, {1, 2}), set[int])
Unexpected error
[type-assertion-failure] Type `set[int]` does not match asserted type `set[Unknown | int]`
40# Type checkers that use a join rather than a union (like mypy)
41# will produce Collection[int] here instead of list[int] | set[int].
42# Both answers are conformant with the spec.
43assert_type(longer([1], {1, 2}), list[int] | set[int]) # E?
[type-assertion-failure] Type `list[int] | set[int]` does not match asserted type `list[Unknown | int] | set[Unknown | int]`
46def requires_collection(c: Collection[int]) -> None: ...
49requires_collection(longer([1], [1, 2])) # OK
[invalid-argument-type] Argument to function `longer` is incorrect: Argument type `Literal[3]` does not satisfy upper bound `Sized` of type variable `ST`
[invalid-argument-type] Argument to function `longer` is incorrect: Argument type `Literal[3]` does not satisfy upper bound `Sized` of type variable `ST`
54# > An upper bound cannot be combined with type constraints
56T_Bad2 = TypeVar("T_Bad2", str, int, bound="int") # E
[invalid-legacy-type-variable] A `TypeVar` cannot have both a bound and constraints