1# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#arbitrary-generic-types-as-base-classes
3from typing import Generic, TypeVar, assert_type
7# > Generic[T] is only valid as a base class – it’s not a proper type. However,
8# > user-defined generic types [...] and built-in generic types and ABCs such as
9# > list[T] and Iterable[T] are valid both as types and as base classes.
15class SymbolTable(dict[str, list[Node]]): ...
18def takes_dict(x: dict): ...
19def takes_dict_typed(x: dict[str, list[Node]]): ...
20def takes_dict_incorrect(x: dict[str, list[object]]): ...
23def test_symbol_table(s: SymbolTable):
25 takes_dict_typed(s) # OK
26 takes_dict_incorrect(s) # E
[invalid-argument-type] Argument to function `takes_dict_incorrect` is incorrect: Expected `dict[str, list[object]]`, found `SymbolTable`
29def func1(y: Generic[T]): # E
[invalid-type-form] `typing.Generic` is not allowed in type expressions
[invalid-type-form] `typing.Generic` is not allowed in type expressions
33# > If a generic base class has a type variable as a type argument, this makes
34# > the defined class generic.
36# Note that there is overlap in the spec and tests in generics_basic.py
38from collections.abc import Iterable, Container, Iterator
41class LinkedList(Iterable[T], Container[T]): ...
44def test_linked_list(l: LinkedList[int]):
45 assert_type(iter(l), Iterator[int])
46 assert_type(l.__contains__(1), bool)
49linked_list_invalid: LinkedList[int, int] # E
[invalid-type-arguments] Too many type arguments to class `LinkedList`: expected 1, got 2
51from collections.abc import Mapping
54class MyDict(Mapping[str, T]): ...
57def test_my_dict(d: MyDict[int]):
58 assert_type(d["a"], int)
61my_dict_invalid: MyDict[int, int] # E
[invalid-type-arguments] Too many type arguments to class `MyDict`: expected 1, got 2
63# > Note that we can use T multiple times in the base class list,
64# > as long as we don’t use the same type variable T multiple times
65# > within Generic[...].
68class BadClass1(Generic[T, T]): # E
[invalid-generic-class] Type parameter `T` cannot appear multiple times in `Generic` subscription
72class GoodClass1(dict[T, T]): # OK
75# > Type variables are applied to the defined class in the order in which
76# > they first appear in any generic base classes.
82class Parent1(Generic[T1, T2]): ...
83class Parent2(Generic[T1, T2]): ...
84class Child(Parent1[T1, T3], Parent2[T2, T3]): ...
86def takes_parent1(x: Parent1[int, bytes]): ...
87def takes_parent2(x: Parent2[str, bytes]): ...
89child: Child[int, bytes, str] = Child()
90takes_parent1(child) # OK
91takes_parent2(child) # OK
93# > A type checker should report an error when the type variable order is
96class Grandparent(Generic[T1, T2]): ...
97class Parent(Grandparent[T1, T2]): ...
98class BadChild(Parent[T1, T2], Grandparent[T2, T1]): ... # E
Expected a ty diagnostic for this line