Skip to content

Commit 81fca33

Browse files
committed
[ty] Infer list[T] when unpacking non-literal list
1 parent 2289187 commit 81fca33

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

crates/ty_python_semantic/resources/mdtest/unpacking.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Unpacking
22

3-
If there are not enough or too many values ​​when unpacking, an error will occur and the types of
3+
If there are not enough or too many values when unpacking, an error will occur and the types of
44
all variables (if nested tuple unpacking fails, only the variables within the failed tuples) is
55
inferred to be `Unknown`.
66

@@ -207,6 +207,57 @@ reveal_type(c) # revealed: int
207207
reveal_type(d) # revealed: Literal[2]
208208
```
209209

210+
## List
211+
212+
### Literal unpacking
213+
214+
```py
215+
a, b = [1, 2]
216+
# TODO: should be `int` for both `a` and `b`
217+
reveal_type(a) # revealed: Unknown
218+
reveal_type(b) # revealed: Unknown
219+
```
220+
221+
### Simple unpacking
222+
223+
```py
224+
def _(value: list[int]):
225+
a, b = value
226+
reveal_type(a) # revealed: int
227+
reveal_type(b) # revealed: int
228+
```
229+
230+
### Nested unpacking
231+
232+
```py
233+
def _(value: list[list[int]]):
234+
a, (b, c) = value
235+
reveal_type(a) # revealed: list[int]
236+
reveal_type(b) # revealed: int
237+
reveal_type(c) # revealed: int
238+
```
239+
240+
### Invalid nested unpacking
241+
242+
```py
243+
def _(value: list[int]):
244+
# error: [not-iterable] "Object of type `int` is not iterable"
245+
a, (b, c) = value
246+
reveal_type(a) # revealed: int
247+
reveal_type(b) # revealed: Unknown
248+
reveal_type(c) # revealed: Unknown
249+
```
250+
251+
### Starred expression
252+
253+
```py
254+
def _(value: list[int]):
255+
a, *b, c = value
256+
reveal_type(a) # revealed: int
257+
reveal_type(b) # revealed: list[int]
258+
reveal_type(c) # revealed: int
259+
```
260+
210261
## String
211262

212263
### Simple unpacking
@@ -293,6 +344,18 @@ reveal_type(b) # revealed: LiteralString
293344
reveal_type(c) # revealed: list[LiteralString]
294345
```
295346

347+
### Starred expression (6)
348+
349+
```py
350+
from typing_extensions import LiteralString
351+
352+
def _(s: LiteralString):
353+
a, b, *c = s
354+
reveal_type(a) # revealed: LiteralString
355+
reveal_type(b) # revealed: LiteralString
356+
reveal_type(c) # revealed: list[LiteralString]
357+
```
358+
296359
### Unicode
297360

298361
```py

crates/ty_python_semantic/src/types/unpacker.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,15 @@ impl<'db> Unpacker<'db> {
192192
err.fallback_element_type(self.db())
193193
})
194194
};
195-
for target_type in &mut target_types {
196-
target_type.push(ty);
195+
// Both `elts` and `target_types` are guaranteed to have the same length.
196+
for (element, target_type) in elts.iter().zip(&mut target_types) {
197+
if element.is_starred_expr() {
198+
target_type.push(
199+
KnownClass::List.to_specialized_instance(self.db(), [ty]),
200+
);
201+
} else {
202+
target_type.push(ty);
203+
}
197204
}
198205
}
199206
}

0 commit comments

Comments
 (0)