ruff/crates/red_knot_python_semantic/resources/mdtest/subscript/tuple.md
David Peter 56c796acee
[red-knot] Slice expression types & subscript expressions with slices (#13917)
## Summary

- Add a new `Type::SliceLiteral` variant
- Infer `SliceLiteral` types for slice expressions, such as
`<int-literal>:<int-literal>:<int-literal>`.
- Infer "sliced" literal types for subscript expressions using slices,
such as `<string-literal>[<slice-literal>]`.
- Infer types for expressions involving slices of tuples:
`<tuple>[<slice-literal>]`.

closes #13853

## Test Plan

- Unit tests for indexing/slicing utility functions
- Markdown-based tests for
  - Subscript expressions `tuple[slice]`
  - Subscript expressions `string_literal[slice]`
  - Subscript expressions `bytes_literal[slice]`
2024-10-29 10:17:31 +01:00

2.8 KiB

Tuple subscripts

Indexing

t = (1, "a", "b")

reveal_type(t[0])  # revealed: Literal[1]
reveal_type(t[1])  # revealed: Literal["a"]
reveal_type(t[-1])  # revealed: Literal["b"]
reveal_type(t[-2])  # revealed: Literal["a"]

reveal_type(t[False])  # revealed: Literal[1]
reveal_type(t[True])  # revealed: Literal["a"]

a = t[4]  # error: [index-out-of-bounds]
reveal_type(a)  # revealed: Unknown

b = t[-4]  # error: [index-out-of-bounds]
reveal_type(b)  # revealed: Unknown

Slices

t = (1, "a", None, b"b")

reveal_type(t[0:0])  # revealed: tuple[()]
reveal_type(t[0:1])  # revealed: tuple[Literal[1]]
reveal_type(t[0:2])  # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[0:4])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[0:5])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[1:3])  # revealed: tuple[Literal["a"], None]

reveal_type(t[-2:4])  # revealed: tuple[None, Literal[b"b"]]
reveal_type(t[-3:-1])  # revealed: tuple[Literal["a"], None]
reveal_type(t[-10:10])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]

reveal_type(t[0:])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[2:])  # revealed: tuple[None, Literal[b"b"]]
reveal_type(t[4:])  # revealed: tuple[()]
reveal_type(t[:0])  # revealed: tuple[()]
reveal_type(t[:2])  # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[:10])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[:])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]

reveal_type(t[::-1])  # revealed: tuple[Literal[b"b"], None, Literal["a"], Literal[1]]
reveal_type(t[::2])  # revealed: tuple[Literal[1], None]
reveal_type(t[-2:-5:-1])  # revealed: tuple[None, Literal["a"], Literal[1]]
reveal_type(t[::-2])  # revealed: tuple[Literal[b"b"], Literal["a"]]
reveal_type(t[-1::-3])  # revealed: tuple[Literal[b"b"], Literal[1]]

reveal_type(t[None:2:None])  # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[1:None:1])  # revealed: tuple[Literal["a"], None, Literal[b"b"]]
reveal_type(t[None:None:None])  # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]

start = 1
stop = None
step = 2
reveal_type(t[start:stop:step])  # revealed: tuple[Literal["a"], Literal[b"b"]]

reveal_type(t[False:True])  # revealed: tuple[Literal[1]]
reveal_type(t[True:3])  # revealed: tuple[Literal["a"], None]

t[0:4:0]  # error: [zero-stepsize-in-slice]
t[:4:0]  # error: [zero-stepsize-in-slice]
t[0::0]  # error: [zero-stepsize-in-slice]
t[::0]  # error: [zero-stepsize-in-slice]

def int_instance() -> int: ...

tuple_slice = t[int_instance() : int_instance()]
# TODO: Support overloads... Should be `tuple[Literal[1, 'a', b"b"] | None, ...]`
reveal_type(tuple_slice)  # revealed: @Todo