Skip to content

Commit dc1da75

Browse files
committed
type-context aware literal promotion
1 parent f054b8a commit dc1da75

File tree

17 files changed

+387
-138
lines changed

17 files changed

+387
-138
lines changed

crates/ty_python_semantic/resources/mdtest/assignment/annotations.md

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,9 @@ type IntList = list[int]
130130
m: IntList = [1, 2, 3]
131131
reveal_type(m) # revealed: list[int]
132132

133-
# TODO: this should type-check and avoid literal promotion
134-
# error: [invalid-assignment] "Object of type `list[Unknown | int]` is not assignable to `list[Literal[1, 2, 3]]`"
135133
n: list[typing.Literal[1, 2, 3]] = [1, 2, 3]
136134
reveal_type(n) # revealed: list[Literal[1, 2, 3]]
137135

138-
# TODO: this should type-check and avoid literal promotion
139-
# error: [invalid-assignment] "Object of type `list[Unknown | str]` is not assignable to `list[LiteralString]`"
140136
o: list[typing.LiteralString] = ["a", "b", "c"]
141137
reveal_type(o) # revealed: list[LiteralString]
142138

@@ -160,6 +156,66 @@ a: list[str] = [1, 2, 3]
160156
b: set[int] = {1, 2, "3"}
161157
```
162158

159+
## Literal annnotations are respected
160+
161+
```toml
162+
[environment]
163+
python-version = "3.12"
164+
```
165+
166+
```py
167+
from enum import Enum
168+
from typing_extensions import Literal, LiteralString
169+
170+
a: list[Literal[1]] = [1]
171+
reveal_type(a) # revealed: list[Literal[1]]
172+
173+
b: list[Literal[True]] = [True]
174+
reveal_type(b) # revealed: list[Literal[True]]
175+
176+
c: list[Literal["a"]] = ["a"]
177+
reveal_type(c) # revealed: list[Literal["a"]]
178+
179+
d: list[LiteralString] = ["a", "b", "c"]
180+
reveal_type(d) # revealed: list[LiteralString]
181+
182+
e: list[list[Literal[1]]] = [[1]]
183+
reveal_type(e) # revealed: list[list[Literal[1]]]
184+
185+
class Color(Enum):
186+
RED = "red"
187+
188+
f: dict[list[Literal[1]], list[Literal[Color.RED]]] = {[1]: [Color.RED, Color.RED]}
189+
reveal_type(f) # revealed: dict[list[Literal[1]], list[Literal[Color.RED]]]
190+
191+
class X[T]:
192+
def __init__(cls, value: T):
193+
...
194+
195+
g: X[Literal[1]] = X(1)
196+
reveal_type(g) # revealed: X[Literal[1]]
197+
198+
h: dict[list[X[Literal[1]]], set[Literal[b"a"]]] = {[X(1)]: {b"a"}}
199+
reveal_type(h) # revealed: dict[list[X[Literal[1]]], set[Literal[b"a"]]]
200+
201+
i: list[Literal[1, 2, 3]] = [1, 2, 3]
202+
reveal_type(i) # revealed: list[Literal[1, 2, 3]]
203+
204+
j: list[Literal[1] | Literal[2] | Literal[3]] = [1, 2, 3]
205+
reveal_type(j) # revealed: list[Literal[1, 2, 3]]
206+
207+
type Y[T] = list[T]
208+
209+
k: Y[Y[Literal[1]]] = [[1]]
210+
reveal_type(k) # revealed: list[list[Literal[1]]]
211+
212+
l: list[tuple[Literal[1], Literal[2], Literal[3]]] = [(1, 2, 3)]
213+
reveal_type(l) # revealed: list[tuple[Literal[1], Literal[2], Literal[3]]]
214+
215+
m: list[tuple[Literal[1], ...]] = [(1, 1, 1)]
216+
reveal_type(m) # revealed: list[tuple[Literal[1], ...]]
217+
```
218+
163219
## PEP-604 annotations are supported
164220

165221
```py

crates/ty_python_semantic/resources/mdtest/type_compendium/tuple.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -525,10 +525,6 @@ from typing import Literal
525525
reveal_type(list((1, 2, 3))) # revealed: list[int]
526526
reveal_type(list(((1, 2, 3),))) # revealed: list[tuple[int, int, int]]
527527

528-
# TODO: we could bidirectionally infer that the user does not want literals to be promoted here,
529-
# and avoid this diagnostic
530-
#
531-
# error: [invalid-assignment] "`list[int]` is not assignable to `list[Literal[1, 2, 3]]`"
532528
x: list[Literal[1, 2, 3]] = list((1, 2, 3))
533529
reveal_type(x) # revealed: list[Literal[1, 2, 3]]
534530
```

0 commit comments

Comments
 (0)