ruff/crates/red_knot_python_semantic/resources/mdtest/unpacking.md
InSync 155d34bbb9
[red-knot] Infer precise types for len() calls (#14599)
## Summary

Resolves #14598.

## Test Plan

Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2024-12-04 11:16:53 -08:00

7 KiB

Unpacking

Tuple

Simple tuple

(a, b, c) = (1, 2, 3)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: Literal[3]

Simple list

[a, b, c] = (1, 2, 3)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: Literal[3]

Simple mixed

[a, (b, c), d] = (1, (2, 3), 4)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: Literal[3]
reveal_type(d)  # revealed: Literal[4]

Multiple assignment

a, b = c = 1, 2
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: tuple[Literal[1], Literal[2]]

Nested tuple with unpacking

(a, (b, c), d) = (1, (2, 3), 4)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: Literal[3]
reveal_type(d)  # revealed: Literal[4]

Nested tuple without unpacking

(a, b, c) = (1, (2, 3), 4)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: tuple[Literal[2], Literal[3]]
reveal_type(c)  # revealed: Literal[4]

Uneven unpacking (1)

# TODO: Add diagnostic (there aren't enough values to unpack)
(a, b, c) = (1, 2)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
reveal_type(c)  # revealed: Unknown

Uneven unpacking (2)

# TODO: Add diagnostic (too many values to unpack)
(a, b) = (1, 2, 3)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]

Starred expression (1)

# TODO: Add diagnostic (need more values to unpack)
[a, *b, c, d] = (1, 2)
reveal_type(a)  # revealed: Literal[1]
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: Literal[2]
reveal_type(d)  # revealed: Unknown

Starred expression (2)

[a, *b, c] = (1, 2)
reveal_type(a)  # revealed: Literal[1]
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: Literal[2]

Starred expression (3)

[a, *b, c] = (1, 2, 3)
reveal_type(a)  # revealed: Literal[1]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: Literal[3]

Starred expression (4)

[a, *b, c, d] = (1, 2, 3, 4, 5, 6)
reveal_type(a)  # revealed: Literal[1]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: Literal[5]
reveal_type(d)  # revealed: Literal[6]

Starred expression (5)

[a, b, *c] = (1, 2, 3, 4)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Literal[2]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(c)  # revealed: @Todo(starred unpacking)

Starred expression (6)

# TODO: Add diagnostic (need more values to unpack)
(a, b, c, *d, e, f) = (1,)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: Unknown
reveal_type(c)  # revealed: Unknown
reveal_type(d)  # revealed: @Todo(starred unpacking)
reveal_type(e)  # revealed: Unknown
reveal_type(f)  # revealed: Unknown

Non-iterable unpacking

# error: "Object of type `Literal[1]` is not iterable"
a, b = 1
reveal_type(a)  # revealed: Unknown
reveal_type(b)  # revealed: Unknown

Custom iterator unpacking

class Iterator:
    def __next__(self) -> int:
        return 42

class Iterable:
    def __iter__(self) -> Iterator:
        return Iterator()

(a, b) = Iterable()
reveal_type(a)  # revealed: int
reveal_type(b)  # revealed: int

Custom iterator unpacking nested

class Iterator:
    def __next__(self) -> int:
        return 42

class Iterable:
    def __iter__(self) -> Iterator:
        return Iterator()

(a, (b, c), d) = (1, Iterable(), 2)
reveal_type(a)  # revealed: Literal[1]
reveal_type(b)  # revealed: int
reveal_type(c)  # revealed: int
reveal_type(d)  # revealed: Literal[2]

String

Simple unpacking

a, b = "ab"
reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: LiteralString

Uneven unpacking (1)

# TODO: Add diagnostic (there aren't enough values to unpack)
a, b, c = "ab"
reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: LiteralString
reveal_type(c)  # revealed: Unknown

Uneven unpacking (2)

# TODO: Add diagnostic (too many values to unpack)
a, b = "abc"
reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: LiteralString

Starred expression (1)

# TODO: Add diagnostic (need more values to unpack)
(a, *b, c, d) = "ab"
reveal_type(a)  # revealed: LiteralString
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: LiteralString
reveal_type(d)  # revealed: Unknown

Starred expression (2)

(a, *b, c) = "ab"
reveal_type(a)  # revealed: LiteralString
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: LiteralString

Starred expression (3)

(a, *b, c) = "abc"
reveal_type(a)  # revealed: LiteralString
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: LiteralString

Starred expression (4)

(a, *b, c, d) = "abcdef"
reveal_type(a)  # revealed: LiteralString
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b)  # revealed: @Todo(starred unpacking)
reveal_type(c)  # revealed: LiteralString
reveal_type(d)  # revealed: LiteralString

Starred expression (5)

(a, b, *c) = "abcd"
reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: LiteralString
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(c)  # revealed: @Todo(starred unpacking)

Unicode

# TODO: Add diagnostic (need more values to unpack)
(a, b) = "é"

reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: Unknown

Unicode escape (1)

# TODO: Add diagnostic (need more values to unpack)
(a, b) = "\u9E6C"

reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: Unknown

Unicode escape (2)

# TODO: Add diagnostic (need more values to unpack)
(a, b) = "\U0010FFFF"

reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: Unknown

Surrogates

(a, b) = "\uD800\uDFFF"

reveal_type(a)  # revealed: LiteralString
reveal_type(b)  # revealed: LiteralString