1# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#scoping-rules-for-type-variables
3from typing import TypeVar, Generic, Iterable, TypeAlias, assert_type, Literal
5# > A type variable used in a generic function could be inferred to represent
6# > different types in the same code block.
9def fun_1(x: T) -> T: # T here
11def fun_2(x: T) -> T: # and here could be different
14# One of these two should pass; either is acceptable:
15assert_type(fun_1(1), int) # E[fun1]
Tag 'fun1'
[type-assertion-failure] Type `Literal[1]` does not match asserted type `int`
16assert_type(fun_1(1), Literal[1]) # E[fun1]
18# One of these two should pass; either is acceptable:
19assert_type(fun_2("a"), str) # E[fun2]
Tag 'fun2'
[type-assertion-failure] Type `Literal["a"]` does not match asserted type `str`
20assert_type(fun_2("a"), Literal["a"]) # E[fun2]
22# > A type variable used in a method of a generic class that coincides
23# > with one of the variables that parameterize this class is always bound
26class MyClass(Generic[T]):
27 def meth_1(self, x: T) -> T: # T here
29 def meth_2(self, x: T) -> T: # and here are always the same
32a: MyClass[int] = MyClass()
[invalid-argument-type] Argument to bound method `meth_2` is incorrect: Expected `int`, found `Literal["a"]`
36# > A type variable used in a method that does not match any of the variables
37# > that parameterize the class makes this method a generic function in that
43 def method(self, x: T, y: S) -> S:
48# Either of these is acceptable; one of the two should pass:
49assert_type(x.method(0, "abc"), str) # E[method-str]
Tag 'method-str'
[type-assertion-failure] Type `Literal["abc"]` does not match asserted type `str`
50assert_type(x.method(0, "abc"), Literal["abc"]) # E[method-str]
52# Either of these is acceptable; one of the two should pass:
53assert_type(x.method(0, b"abc"), bytes) # E[method-bytes]
Tag 'method-bytes'
[type-assertion-failure] Type `Literal[b"abc"]` does not match asserted type `bytes`
54assert_type(x.method(0, b"abc"), Literal[b"abc"]) # E[method-bytes]
56# > Unbound type variables should not appear in the bodies of generic functions,
57# > or in the class bodies apart from method definitions.
59def fun_3(x: T) -> list[T]:
[unbound-type-variable] Type variable `S` is not bound to any outer generic context
65 an_attr: list[S] = [] # E
[unbound-type-variable] Type variable `S` is not bound to any outer generic context
67 def do_something(self, x: S) -> S: # OK
70# A generic class definition that appears inside a generic function
71# should not use type variables that parameterize the generic function.
73def fun_4(x: T) -> list[T]:
74 a_list: list[T] = [] # OK
76 class MyGeneric(Generic[T]): # E
[shadowed-type-variable] Generic class `MyGeneric` uses type variable `T` already bound by an enclosing scope
[shadowed-type-variable] Generic class `MyGeneric` uses type variable `T` already bound by an enclosing scope
81# > A generic class nested in another generic class cannot use the same type
82# > variables. The scope of the type variables of the outer class
83# > doesn't cover the inner one
85class Outer(Generic[T]):
86 class Bad(Iterable[T]): # E
[shadowed-type-variable] Generic class `Bad` uses type variable `T` already bound by an enclosing scope
[unbound-type-variable] Type variable `T` is not bound to any outer generic context
91 def __init__(self, x: list[T]) -> None: # E?
94 class Inner(Iterable[S]): # OK
98 alias: TypeAlias = list[T] # E
Expected a ty diagnostic for this line
100 def __init__(self, attr: Inner[T]) -> None:
104# Test unbound type variables at global scope
[unbound-type-variable] Type variable `T` is not bound to any outer generic context
106global_var2: list[T] = [] # E
[unbound-type-variable] Type variable `T` is not bound to any outer generic context
Expected a ty diagnostic for this line