ruff/crates/ty_python_semantic/resources/mdtest/conditional/if_statement.md
2025-05-03 19:49:15 +02:00

2.4 KiB

If statements

Simple if

def _(flag: bool):
    y = 1
    y = 2

    if flag:
        y = 3

    reveal_type(y)  # revealed: Literal[2, 3]

Simple if-elif-else

def _(flag: bool, flag2: bool):
    y = 1
    y = 2

    if flag:
        y = 3
    elif flag2:
        y = 4
    else:
        r = y
        y = 5
        s = y
    x = y

    reveal_type(x)  # revealed: Literal[3, 4, 5]

    # revealed: Literal[2]
    # error: [possibly-unresolved-reference]
    reveal_type(r)

    # revealed: Literal[5]
    # error: [possibly-unresolved-reference]
    reveal_type(s)

Single symbol across if-elif-else

def _(flag: bool, flag2: bool):
    if flag:
        y = 1
    elif flag2:
        y = 2
    else:
        y = 3

    reveal_type(y)  # revealed: Literal[1, 2, 3]

if-elif-else without else assignment

def _(flag: bool, flag2: bool):
    y = 0

    if flag:
        y = 1
    elif flag2:
        y = 2
    else:
        pass

    reveal_type(y)  # revealed: Literal[0, 1, 2]

if-elif-else with intervening assignment

def _(flag: bool, flag2: bool):
    y = 0

    if flag:
        y = 1
        z = 3
    elif flag2:
        y = 2
    else:
        pass

    reveal_type(y)  # revealed: Literal[0, 1, 2]

Nested if statement

def _(flag: bool, flag2: bool):
    y = 0

    if flag:
        if flag2:
            y = 1

    reveal_type(y)  # revealed: Literal[0, 1]

if-elif without else

def _(flag: bool, flag2: bool):
    y = 1
    y = 2

    if flag:
        y = 3
    elif flag2:
        y = 4

    reveal_type(y)  # revealed: Literal[2, 3, 4]

if-elif with assignment expressions in tests

def check(x: int) -> bool:
    return bool(x)

if check(x := 1):
    x = 2
elif check(x := 3):
    x = 4

reveal_type(x)  # revealed: Literal[2, 3, 4]

constraints apply to later test expressions

def check(x) -> bool:
    return bool(x)

def _(flag: bool):
    x = 1 if flag else None
    y = 0

    if x is None:
        pass
    elif check(y := x):
        pass

    reveal_type(y)  # revealed: Literal[0, 1]

Condition with object that implements __bool__ incorrectly

class NotBoolable:
    __bool__: int = 3

# error: [unsupported-bool-conversion] "Boolean conversion is unsupported for type `NotBoolable`"
if NotBoolable():
    ...
# error: [unsupported-bool-conversion] "Boolean conversion is unsupported for type `NotBoolable`"
elif NotBoolable():
    ...