Updated logic for PEP 696 (TypeVarLike "defaults") to change the syntax for ParamSpec default expressions. The draft PEP is being changed, and list expressions will now be used instead of tuples.

This commit is contained in:
Eric Traut 2023-03-11 12:08:37 -07:00
parent 128e169415
commit 7c23b1afb8
10 changed files with 145 additions and 55 deletions

View File

@ -11839,8 +11839,8 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
return functionType;
}
if (node.nodeType === ParseNodeType.Tuple) {
node.expressions.forEach((paramExpr, index) => {
if (node.nodeType === ParseNodeType.List) {
node.entries.forEach((paramExpr, index) => {
const typeResult = getTypeOfExpressionExpectingType(paramExpr);
FunctionType.addParameter(functionType, {

View File

@ -61,23 +61,23 @@ Ts6 = TypeVarTuple("Ts6", default=Unpack[tuple[int, ...]])
Ts7 = TypeVarTuple("Ts7", default=Unpack[tuple[S1, S2]])
P1 = ParamSpec("P1", default=())
P1 = ParamSpec("P1", default=[])
P2 = ParamSpec("P2", default=(int, str, None, int | None))
P2 = ParamSpec("P2", default=[int, str, None, int | None])
P3 = ParamSpec("P3", default=(int, S1))
P3 = ParamSpec("P3", default=[int, S1])
P4 = ParamSpec("P4", default=(int, ))
P4 = ParamSpec("P4", default=[int])
P5 = ParamSpec("P5", default=...)
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
P6 = ParamSpec("P6", default=int)
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
P7 = ParamSpec("P7", default=3)
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
P8 = ParamSpec("P8", default=(1, int))
P9 = ParamSpec("P9", default=P0)

View File

@ -62,29 +62,30 @@ class ClassTs9[*Ts = Unpack[tuple[T1, T1]]]: ...
class ClassTs10[*Ts = ...]: ...
class ClassP1[**P = (int, )]: ...
class ClassP1[**P = [int]]: ...
class ClassP2[**P = ...]: ...
class ClassP3[**P = ()]: ...
class ClassP3[**P = []]: ...
class ClassP4[**P = (int, str, None, int | None)]: ...
class ClassP4[**P = [int, str, None, int | None]]: ...
# This should generate an error because T1 isn't legal here.
class ClassP5[**P = (T1, )]: ...
class ClassP5[**P = [T1]]: ...
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
class ClassP6[**P = int]: ...
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
class ClassP7[**P = 3]: ...
# This should generate an error because ParamSpec must be a tuple of types.
class ClassP8[**P = (1, int)]: ...
# This should generate an error because ParamSpec must be a list of types.
class ClassP8[**P = [1, int]]: ...
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because it combines a traditional ParamSpec
# with a new-style (PEP 695) ParamSpec.
class ClassP9[**P = P1]: ...
# This should generate an error because ParamSpec must be a tuple of types.
# This should generate an error because ParamSpec must be a list of types.
class ClassP10[**P = Ts1]: ...

View File

@ -38,7 +38,7 @@ def func_a2(
P1 = ParamSpec("P1")
P2 = ParamSpec("P2", default=(int, str))
P2 = ParamSpec("P2", default=[int, str])
P3 = ParamSpec("P3", default=...)

View File

@ -12,7 +12,10 @@ T3 = TypeVar("T3", default=list[T2])
T4 = TypeVar("T4", default=dict[T1, T2])
T5 = TypeVar("T5", default="T5")
class ClassA(dict[T1, T2]): ...
class ClassA(dict[T1, T2]):
...
a1 = ClassA[int]()
reveal_type(a1, expected_text="ClassA[int, int]")
@ -22,9 +25,13 @@ reveal_type(a2, expected_text="ClassA[str, str]")
# This should generate an error because T2 depends on T1.
class ClassC(Generic[T2, T1]): ...
class ClassC(Generic[T2, T1]):
...
class ClassD(dict[T2, T1], Generic[T1, T2]):
...
class ClassD(dict[T2, T1], Generic[T1, T2]): ...
d1 = ClassD[int]()
reveal_type(d1, expected_text="ClassD[int, int]")
@ -33,9 +40,13 @@ d2 = ClassD()
reveal_type(d2, expected_text="ClassD[str, str]")
# This should generate an error because T5 refers to itself.
class ClassE(Generic[T5]): ...
class ClassE(Generic[T5]):
...
class ClassH(Generic[T1, T2, T3]):
...
class ClassH(Generic[T1, T2, T3]): ...
h1 = ClassH()
reveal_type(h1, expected_text="ClassH[str, str, list[str]]")
@ -47,21 +58,33 @@ h3 = ClassH[int, float]()
reveal_type(h3, expected_text="ClassH[int, float, list[float]]")
# This should generate an error because T2 depends on T1.
class ClassI(Generic[T2]): ...
class ClassI(Generic[T2]):
...
# This should generate an error because T4 depends on T2.
class ClassJ(Generic[T1, T4]): ...
class ClassJ(Generic[T1, T4]):
...
class ClassK(Generic[T1]):
# This should generate an error because T2 depends on T1, which
# is defined in an outer scope.
class ClassL(Generic[T2]): ...
class ClassL(Generic[T2]):
...
class ClassMChild1(Generic[T1]):
a: T1
class ClassMChild2(Generic[T1]):
b: T1
class ClassM(ClassMChild1[T1], ClassMChild2[T2]): ...
class ClassM(ClassMChild1[T1], ClassMChild2[T2]):
...
m1 = ClassM[int]()
reveal_type(m1.a, expected_text="int")
@ -71,9 +94,14 @@ m2 = ClassM()
reveal_type(m2.a, expected_text="str")
reveal_type(m2.b, expected_text="str")
class ClassNChild(Generic[T1]):
a: T1
class ClassN(ClassNChild): ...
class ClassN(ClassNChild):
...
n1 = ClassN()
reveal_type(n1.a, expected_text="str")
@ -82,9 +110,12 @@ reveal_type(n1.a, expected_text="str")
P1 = ParamSpec("P1", default=...)
P2 = ParamSpec("P2", default=P1)
P3 = ParamSpec("P3", default=P2)
P4 = ParamSpec("P4", default=(int, T1, ))
P4 = ParamSpec("P4", default=[int, T1])
class ClassPA(Generic[P1, P2, P3]):
...
class ClassPA(Generic[P1, P2, P3]): ...
pa1 = ClassPA()
reveal_type(pa1, expected_text="ClassPA[(...), (...), (...)]")
@ -100,9 +131,13 @@ reveal_type(pa4, expected_text="ClassPA[(...), (int, int), (float)]")
# This should generate an error because P1 depends on P2.
class ClassPB(Generic[P2, P1]): ...
class ClassPB(Generic[P2, P1]):
...
class ClassPC(Generic[T1, P4]):
...
class ClassPC(Generic[T1, P4]): ...
pc1 = ClassPC()
reveal_type(pc1, expected_text="ClassPC[str, (int, str)]")
@ -115,13 +150,17 @@ reveal_type(pc3, expected_text="ClassPC[float, (...)]")
# This should generate an error because P4 depends on T1.
class ClassPD(Generic[P4, T1]): ...
class ClassPD(Generic[P4, T1]):
...
Ts1 = TypeVarTuple("Ts1", default=Unpack[tuple[T1, T2]])
Ts2 = TypeVarTuple("Ts2", default=Unpack[tuple[T1, ...]])
class ClassTA(Generic[T1, T2, *Ts1]): ...
class ClassTA(Generic[T1, T2, *Ts1]):
...
ta1 = ClassTA()
reveal_type(ta1, expected_text="ClassTA[str, str, str, str]")
@ -136,9 +175,13 @@ ta4 = ClassTA[int, float, *tuple[None, ...]]()
reveal_type(ta4, expected_text="ClassTA[int, float, *tuple[None, ...]]")
# This should generate an error because Ts1 depends on T2.
class ClassTB(Generic[T1, *Ts1, T2]): ...
class ClassTB(Generic[T1, *Ts1, T2]):
...
class ClassTC(Generic[T1, *Ts2]):
...
class ClassTC(Generic[T1, *Ts2]): ...
tc1 = ClassTC()
reveal_type(tc1, expected_text="ClassTC[str, *tuple[str, ...]]")
@ -151,4 +194,3 @@ reveal_type(tc3, expected_text="ClassTC[int]")
tc4 = ClassTC[int, *tuple[None]]()
reveal_type(tc4, expected_text="ClassTC[int, None]")

View File

@ -68,7 +68,7 @@ reveal_type(pa4, expected_text="ClassPA[(...), (int, int), (float)]")
# This should generate an error because P1 depends on P2.
class ClassPB[**P2=P1, **P1=...]: ...
class ClassPC[T1=str, **P4=(int, T1)]: ...
class ClassPC[T1=str, **P4=[int, T1]]: ...
pc1 = ClassPC()
reveal_type(pc1, expected_text="ClassPC[str, (int, str)]")
@ -81,7 +81,7 @@ reveal_type(pc3, expected_text="ClassPC[float, (...)]")
# This should generate an error because P4 depends on T1.
class ClassPD[**P4=(int, T1), T1=str]: ...
class ClassPD[**P4=[int, T1], T1=str]: ...
class ClassTA[T1=str, T2=T1, *Ts1=Unpack[tuple[T1, T2]]]: ...

View File

@ -6,9 +6,11 @@ from typing import Callable, Generic, ParamSpec, TypeVar, TypeVarTuple, Unpack
T = TypeVar("T", default=str)
def func1(x: int | T) -> list[T]:
...
v1_1 = func1(3.4)
reveal_type(v1_1, expected_text="list[float]")
@ -16,18 +18,22 @@ v1_2 = func1(3)
reveal_type(v1_2, expected_text="list[str]")
P = ParamSpec("P", default=(int, str, str))
P = ParamSpec("P", default=[int, str, str])
class ClassA(Generic[P]):
def __init__(self, x: Callable[P, None]) -> None:
...
def func2(x: int | ClassA[P]) -> ClassA[P]:
...
def callback1(x: str) -> None:
...
v2_1 = func2(ClassA(callback1))
reveal_type(v2_1, expected_text="ClassA[(x: str)]")
@ -38,12 +44,13 @@ reveal_type(v2_2, expected_text="ClassA[(int, str, str)]")
Ts = TypeVarTuple("Ts", default=Unpack[tuple[int, str, float]])
def func3(x: int | Callable[[*Ts], None]) -> tuple[*Ts]:
...
v3_1 = func3(callback1)
reveal_type(v3_1, expected_text="tuple[str]")
v3_2 = func3(3)
reveal_type(v3_2, expected_text="tuple[int, str, float]")

View File

@ -22,6 +22,7 @@ def func_a1(a: TA1, b: TA1[float], c: TA1[float, float]):
TA2: TypeAlias = dict[T1, T2] | list[T3]
def func_a2(a: TA2, b: TA2[float], c: TA2[float, float], d: TA2[float, float, float]):
reveal_type(a, expected_text="dict[Unknown, int] | list[str]")
reveal_type(b, expected_text="dict[float, int] | list[str]")
@ -30,11 +31,12 @@ def func_a2(a: TA2, b: TA2[float], c: TA2[float, float], d: TA2[float, float, fl
P1 = ParamSpec("P1")
P2 = ParamSpec("P2", default=(int, str))
P2 = ParamSpec("P2", default=[int, str])
P3 = ParamSpec("P3", default=...)
TA3: TypeAlias = Callable[P2, Any] | Callable[P3, Any]
def func_b1(a: TA3, b: TA3[[float]], c: TA3[[float], [list[float]]]):
reveal_type(a, expected_text="((int, str) -> Any) | ((...) -> Any)")
reveal_type(b, expected_text="((float) -> Any) | ((...) -> Any)")
@ -52,15 +54,18 @@ TA5: TypeAlias = tuple[T3, *Ts3]
TA6: TypeAlias = tuple[T3, *Ts4]
def func_c1(a: TA4, b: TA4[*tuple[float]]):
reveal_type(a, expected_text="tuple[int, str]")
reveal_type(b, expected_text="tuple[float]")
def func_c2(a: TA5, b: TA5[int], c: TA5[int, *tuple[()]]):
reveal_type(a, expected_text="tuple[str, *tuple[float, ...]]")
reveal_type(b, expected_text="tuple[int, *tuple[float, ...]]")
reveal_type(c, expected_text="tuple[int]")
def func_c3(a: TA6, b: TA6[int], c: TA6[int, *tuple[float]]):
reveal_type(a, expected_text="tuple[str]")
reveal_type(b, expected_text="tuple[int]")

View File

@ -13,10 +13,12 @@ T5 = TypeVar("T5", default="T5")
TA_A = dict[T1, T2]
def func1(a1: TA_A[int], a2: TA_A):
reveal_type(a1, expected_text="dict[int, int]")
reveal_type(a2, expected_text="dict[str, str]")
# This should generate an error because T2 depends on T1.
TA_B = dict[T2, T1]
@ -25,17 +27,20 @@ TA_C = list[T5]
TA_D = tuple[T1, T2, T3]
def func2(d1: TA_D, d2: TA_D[int], d3: TA_D[int, float]):
reveal_type(d1, expected_text="tuple[str, str, list[str]]")
reveal_type(d2, expected_text="tuple[int, int, list[int]]")
reveal_type(d3, expected_text="tuple[int, float, list[float]]")
# This should generate an error because T2 depends on T1.
TA_E = list[T2]
# This should generate an error because T4 depends on T2.
TA_F = dict[T2, T4]
class ClassK(Generic[T1]):
# This should generate an error because T2 depends on T1, which
# is defined in an outer scope.
@ -45,21 +50,33 @@ class ClassK(Generic[T1]):
P1 = ParamSpec("P1", default=...)
P2 = ParamSpec("P2", default=P1)
P3 = ParamSpec("P3", default=P2)
P4 = ParamSpec("P4", default=(int, T1, ))
P4 = ParamSpec("P4", default=[int, T1])
TA_PA = tuple[Callable[P1, None], Callable[P2, None], Callable[P3, None]]
def func3(pa1: TA_PA, pa2: TA_PA[[str]], pa3: TA_PA[..., [float]], pa4: TA_PA[..., [int, int], [float]]):
def func3(
pa1: TA_PA,
pa2: TA_PA[[str]],
pa3: TA_PA[..., [float]],
pa4: TA_PA[..., [int, int], [float]],
):
reveal_type(pa1, expected_text="tuple[(...) -> None, (...) -> None, (...) -> None]")
reveal_type(pa2, expected_text="tuple[(str) -> None, (str) -> None, (str) -> None]")
reveal_type(pa3, expected_text="tuple[(...) -> None, (float) -> None, (float) -> None]")
reveal_type(pa4, expected_text="tuple[(...) -> None, (int, int) -> None, (float) -> None]")
reveal_type(
pa3, expected_text="tuple[(...) -> None, (float) -> None, (float) -> None]"
)
reveal_type(
pa4, expected_text="tuple[(...) -> None, (int, int) -> None, (float) -> None]"
)
# This should generate an error because P1 depends on P2.
TA_PB = tuple[Callable[P2, None], Callable[P1, None]]
TA_PC = T1 | Callable[P4, T1]
def func4(pc1: TA_PC, pc2: TA_PC[float], pc3: TA_PC[float, ...]):
reveal_type(pc1, expected_text="str | ((int, str) -> str)")
reveal_type(pc2, expected_text="float | ((int, float) -> float)")
@ -73,26 +90,44 @@ TA_PD = Callable[P4, T1]
Ts1 = TypeVarTuple("Ts1", default=Unpack[tuple[T1, T2]])
Ts2 = TypeVarTuple("Ts2", default=Unpack[tuple[T1, ...]])
class ClassTA(Generic[T1, T2, *Ts1]): ...
class ClassTA(Generic[T1, T2, *Ts1]):
...
TA_TA = ClassTA[T1, T2, *Ts1]
def func5(ta1: TA_TA, ta2: TA_TA[int], ta3: TA_TA[int, float], ta4: TA_TA[int, float, *tuple[None, ...]]):
def func5(
ta1: TA_TA,
ta2: TA_TA[int],
ta3: TA_TA[int, float],
ta4: TA_TA[int, float, *tuple[None, ...]],
):
reveal_type(ta1, expected_text="ClassTA[str, str, str, str]")
reveal_type(ta2, expected_text="ClassTA[int, int, int, int]")
reveal_type(ta3, expected_text="ClassTA[int, float, int, float]")
reveal_type(ta4, expected_text="ClassTA[int, float, *tuple[None, ...]]")
# This should generate an error because Ts1 depends on T2.
TA_TB = tuple[T1, *Ts1, T2]
class ClassTC(Generic[T1, *Ts2]): ...
class ClassTC(Generic[T1, *Ts2]):
...
TA_TC = ClassTC[T1, *Ts2]
def func6(tc1: TA_TC, tc2: TA_TC[int], tc3: TA_TC[int, *tuple[()]], tc4: TA_TC[int, *tuple[None]]):
def func6(
tc1: TA_TC,
tc2: TA_TC[int],
tc3: TA_TC[int, *tuple[()]],
tc4: TA_TC[int, *tuple[None]],
):
reveal_type(tc1, expected_text="ClassTC[str, *tuple[str, ...]]")
reveal_type(tc2, expected_text="ClassTC[int, *tuple[int, ...]]")
reveal_type(tc3, expected_text="ClassTC[int]")
reveal_type(tc4, expected_text="ClassTC[int, None]")

View File

@ -48,7 +48,7 @@ def func3(pa1: TA_PA, pa2: TA_PA[[str]], pa3: TA_PA[..., [float]], pa4: TA_PA[..
# This should generate an error because P1 depends on P2.
type TA_PB[**P2=P1, **P1=...] = tuple[Callable[P2, None], Callable[P1, None]]
type TA_PC[T1=str, **P4=(int, T1, )] = T1 | Callable[P4, T1]
type TA_PC[T1=str, **P4=[int, T1, ]] = T1 | Callable[P4, T1]
def func4(pc1: TA_PC, pc2: TA_PC[float], pc3: TA_PC[float, ...]):
reveal_type(pc1, expected_text="str | ((int, str) -> str)")
@ -57,7 +57,7 @@ def func4(pc1: TA_PC, pc2: TA_PC[float], pc3: TA_PC[float, ...]):
# This should generate an error because P4 depends on T1.
type TA_PD[**P4=(int, T1, ), T1=str] = Callable[P4, T1]
type TA_PD[**P4=[int, T1], T1=str] = Callable[P4, T1]
class ClassTA[T1, T2, *Ts1]: ...