Back to Ruff

Narrowing in `while` loops

crates/ty_python_semantic/resources/mdtest/narrow/while.md

0.15.121.3 KB
Original Source

Narrowing in while loops

We only make sure that narrowing works for while loops in general, we do not exhaustively test all narrowing forms here, as they are covered in other tests.

Note how type narrowing works subtly different from if ... else, because the negated constraint is retained after the loop.

Basic while loop

py
def next_item() -> int | None:
    return 1

x = next_item()

while x is not None:
    reveal_type(x)  # revealed: int
    x = next_item()

reveal_type(x)  # revealed: None

while loop with else

py
def next_item() -> int | None:
    return 1

x = next_item()

while x is not None:
    reveal_type(x)  # revealed: int
    x = next_item()
else:
    reveal_type(x)  # revealed: None

reveal_type(x)  # revealed: None

Nested while loops

py
from typing import Literal

def next_item() -> Literal[1, 2, 3]:
    raise NotImplementedError

x = next_item()

while x != 1:
    reveal_type(x)  # revealed: Literal[2, 3]

    while x != 2:
        reveal_type(x)  # revealed: Literal[3, 1]
        x = next_item()

    x = next_item()

With break statements

py
def next_item() -> int | None:
    return 1

while True:
    x = next_item()
    if x is not None:
        break

reveal_type(x)  # revealed: int