2Tests recursive (self-referential) type aliases.
5# The typing specification doesn't mandate support for recursive
6# (self-referential) type aliases prior to PEP 695, but it also
7# doesn't indicates that they shouldn't work.
8# Most type checkers now support them, and many libraries and code
9# bases have started to rely on them.
10# PEP 695 formally mandates that recursive type aliases work.
12from typing import Mapping, TypeAlias, TypeVar, Union
14Json = Union[None, int, str, float, list["Json"], dict[str, "Json"]]
16j1: Json = [1, {"a": 1}] # OK
18j3: Json = [1.2, None, [1.2, [""]]] # OK
19j4: Json = {"a": 1, "b": 3j} # E: incompatible type
Expected a ty diagnostic for this line
20j5: Json = [2, 3j] # E: incompatible type
Expected a ty diagnostic for this line
23# This type alias should be equivalent to Json.
24Json2 = Union[None, int, str, float, list["Json2"], dict[str, "Json2"]]
26def func1(j1: Json) -> Json2:
30RecursiveTuple = str | int | tuple["RecursiveTuple", ...]
33t1: RecursiveTuple = (1, 1) # OK
34t2: RecursiveTuple = (1, "1") # OK
35t3: RecursiveTuple = (1, "1", 1, "2") # OK
36t4: RecursiveTuple = (1, ("1", 1), "2") # OK
37t5: RecursiveTuple = (1, ("1", 1), (1, (1, 2))) # OK
38t6: RecursiveTuple = (1, ("1", 1), (1, (1, [2]))) # E
Expected a ty diagnostic for this line
39t6: RecursiveTuple = (1, [1]) # E
Expected a ty diagnostic for this line
42RecursiveMapping = str | int | Mapping[str, "RecursiveMapping"]
44m1: RecursiveMapping = 1 # OK
45m2: RecursiveMapping = "1" # OK
46m3: RecursiveMapping = {"1": "1"} # OK
47m4: RecursiveMapping = {"1": "1", "2": 1} # OK
48m5: RecursiveMapping = {"1": "1", "2": 1, "3": {}} # OK
49m6: RecursiveMapping = {"1": "1", "2": 1, "3": {"0": "0", "1": "2", "2": {}}} # OK
50m7: RecursiveMapping = {"1": [1]} # E
Expected a ty diagnostic for this line
51m8: RecursiveMapping = {"1": "1", "2": 1, "3": [1, 2]} # E
Expected a ty diagnostic for this line
52m9: RecursiveMapping = {"1": "1", "2": 1, "3": {"0": "0", "1": 1, "2": [1, 2, 3]}} # E
Expected a ty diagnostic for this line
55T1 = TypeVar("T1", str, int)
58GenericTypeAlias1 = list["GenericTypeAlias1[T1]" | T1]
59SpecializedTypeAlias1 = GenericTypeAlias1[str]
61g1: SpecializedTypeAlias1 = ["hi", ["hi", "hi"]] # OK
62g2: GenericTypeAlias1[str] = ["hi", "bye", [""], [["hi"]]] # OK
63g3: GenericTypeAlias1[str] = ["hi", [2.4]] # E
Expected a ty diagnostic for this line
65GenericTypeAlias2 = list["GenericTypeAlias2[T1, T2]" | T1 | T2]
67g4: GenericTypeAlias2[str, int] = [[3, ["hi"]], "hi"] # OK
68g5: GenericTypeAlias2[str, float] = [[3, ["hi", 3.4, [3.4]]], "hi"] # OK
69g6: GenericTypeAlias2[str, int] = [[3, ["hi", 3, [3.4]]], "hi"] # E
Expected a ty diagnostic for this line
72RecursiveUnion: TypeAlias = Union["RecursiveUnion", int] # E: cyclical reference
Expected a ty diagnostic for this line
74# On one line because different type checkers report the error on different lines
75MutualReference1: TypeAlias = Union["MutualReference2", int]; MutualReference2: TypeAlias = Union["MutualReference1", str] # E: cyclical reference
Expected a ty diagnostic for this line