ruff/crates/red_knot_python_semantic/resources/mdtest/narrow/boolean.md
Dhruv Manilawala d082c1b202
[red-knot] Add missing imports in mdtests (#15869)
## Summary

Related to #15848, this PR adds the imports explicitly as we'll now flag
these symbols as undefined.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-03 09:27:29 +00:00

2.1 KiB

Narrowing in boolean expressions

In or expressions, the right-hand side is evaluated only if the left-hand side is falsy. So when the right-hand side is evaluated, we know the left side has failed.

Similarly, in and expressions, the right-hand side is evaluated only if the left-hand side is truthy. So when the right-hand side is evaluated, we know the left side has succeeded.

Narrowing in or

def _(flag: bool):
    class A: ...
    x: A | None = A() if flag else None

    isinstance(x, A) or reveal_type(x)  # revealed: None
    x is None or reveal_type(x)  # revealed: A
    reveal_type(x)  # revealed: A | None

Narrowing in and

def _(flag: bool):
    class A: ...
    x: A | None = A() if flag else None

    isinstance(x, A) and reveal_type(x)  # revealed: A
    x is None and reveal_type(x)  # revealed: None
    reveal_type(x)  # revealed: A | None

Multiple and arms

def _(flag1: bool, flag2: bool, flag3: bool, flag4: bool):
    class A: ...
    x: A | None = A() if flag1 else None

    flag2 and isinstance(x, A) and reveal_type(x)  # revealed: A
    isinstance(x, A) and flag2 and reveal_type(x)  # revealed: A
    reveal_type(x) and isinstance(x, A) and flag3  # revealed: A | None

Multiple or arms

def _(flag1: bool, flag2: bool, flag3: bool, flag4: bool):
    class A: ...
    x: A | None = A() if flag1 else None

    flag2 or isinstance(x, A) or reveal_type(x)  # revealed: None
    isinstance(x, A) or flag3 or reveal_type(x)  # revealed: None
    reveal_type(x) or isinstance(x, A) or flag4  # revealed: A | None

Multiple predicates

from typing import Literal

def _(flag1: bool, flag2: bool):
    class A: ...
    x: A | None | Literal[1] = A() if flag1 else None if flag2 else 1

    x is None or isinstance(x, A) or reveal_type(x)  # revealed: Literal[1]

Mix of and and or

from typing import Literal

def _(flag1: bool, flag2: bool):
    class A: ...
    x: A | None | Literal[1] = A() if flag1 else None if flag2 else 1

    isinstance(x, A) or x is not None and reveal_type(x)  # revealed: Literal[1]