mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00

## Summary Adds meta information to `Type::Todo`, allowing developers to easily trace back the origin of a particular `@Todo` type they encounter. Instead of `Type::Todo`, we now write either `type_todo!()` which creates a `@Todo[path/to/source.rs:123]` type with file and line information, or using `type_todo!("PEP 604 unions not supported")`, which creates a variant with a custom message. `Type::Todo` now contains a `TodoType` field. In release mode, this is just a zero-sized struct, in order not to create any overhead. In debug mode, this is an `enum` that contains the meta information. `Type` implements `Copy`, which means that `TodoType` also needs to be copyable. This limits the design space. We could intern `TodoType`, but I discarded this option, as it would require us to have access to the salsa DB everywhere we want to use `Type::Todo`. And it would have made the macro invocations less ergonomic (requiring us to pass `db`). So for now, the meta information is simply a `&'static str` / `u32` for the file/line variant, or a `&'static str` for the custom message. Anything involving a chain/backtrace of several `@Todo`s or similar is therefore currently not implemented. Also because we currently don't see any direct use cases for this, and because all of this will eventually go away. Note that the size of `Type` increases from 16 to 24 bytes, but only in debug mode. ## Test Plan - Observed the changes in Markdown tests. - Added custom messages for all `Type::Todo`s that were revealed in the tests - Ran red knot in release and debug mode on the following Python file: ```py def f(x: int) -> int: reveal_type(x) ``` Prints `@Todo` in release mode and `@Todo(function parameter type)` in debug mode.
1.6 KiB
1.6 KiB
Bytes subscripts
Indexing
b = b"\x00abc\xff"
reveal_type(b[0]) # revealed: Literal[b"\x00"]
reveal_type(b[1]) # revealed: Literal[b"a"]
reveal_type(b[4]) # revealed: Literal[b"\xff"]
reveal_type(b[-1]) # revealed: Literal[b"\xff"]
reveal_type(b[-2]) # revealed: Literal[b"c"]
reveal_type(b[-5]) # revealed: Literal[b"\x00"]
reveal_type(b[False]) # revealed: Literal[b"\x00"]
reveal_type(b[True]) # revealed: Literal[b"a"]
x = b[5] # error: [index-out-of-bounds] "Index 5 is out of bounds for bytes literal `Literal[b"\x00abc\xff"]` with length 5"
reveal_type(x) # revealed: Unknown
y = b[-6] # error: [index-out-of-bounds] "Index -6 is out of bounds for bytes literal `Literal[b"\x00abc\xff"]` with length 5"
reveal_type(y) # revealed: Unknown
def int_instance() -> int:
return 42
a = b"abcde"[int_instance()]
# TODO: Support overloads... Should be `bytes`
reveal_type(a) # revealed: @Todo(return type)
Slices
b = b"\x00abc\xff"
reveal_type(b[0:2]) # revealed: Literal[b"\x00a"]
reveal_type(b[-3:]) # revealed: Literal[b"bc\xff"]
b[0:4:0] # error: [zero-stepsize-in-slice]
b[:4:0] # error: [zero-stepsize-in-slice]
b[0::0] # error: [zero-stepsize-in-slice]
b[::0] # error: [zero-stepsize-in-slice]
def int_instance() -> int: ...
byte_slice1 = b[int_instance() : int_instance()]
# TODO: Support overloads... Should be `bytes`
reveal_type(byte_slice1) # revealed: @Todo(return type)
def bytes_instance() -> bytes: ...
byte_slice2 = bytes_instance()[0:5]
# TODO: Support overloads... Should be `bytes`
reveal_type(byte_slice2) # revealed: @Todo(return type)