3.0 KiB
3.0 KiB
While loops
Basic while loop
def _(flag: bool):
x = 1
while flag:
x = 2
reveal_type(x) # revealed: Literal[1, 2]
while with else (no break)
def _(flag: bool):
x = 1
while flag:
x = 2
else:
reveal_type(x) # revealed: Literal[1, 2]
x = 3
reveal_type(x) # revealed: Literal[3]
while with else (may break)
def _(flag: bool, flag2: bool):
x = 1
y = 0
while flag:
x = 2
if flag2:
y = 4
break
else:
y = x
x = 3
reveal_type(x) # revealed: Literal[2, 3]
reveal_type(y) # revealed: Literal[4, 1, 2]
Nested while loops
def flag() -> bool:
return True
x = 1
while flag():
x = 2
while flag():
x = 3
if flag():
break
else:
x = 4
if flag():
break
else:
x = 5
reveal_type(x) # revealed: Literal[3, 4, 5]
Boundness
Make sure that the boundness information is correctly tracked in while loop control flow.
Basic while loop
def _(flag: bool):
while flag:
x = 1
# error: [possibly-unresolved-reference]
x
while with else (no break)
def _(flag: bool):
while flag:
y = 1
else:
x = 1
# no error, `x` is always bound
x
# error: [possibly-unresolved-reference]
y
while with else (may break)
def _(flag: bool, flag2: bool):
while flag:
x = 1
if flag2:
break
else:
y = 1
# error: [possibly-unresolved-reference]
x
# error: [possibly-unresolved-reference]
y
Condition with object that implements __bool__ incorrectly
class NotBoolable:
__bool__: int = 3
# error: [unsupported-bool-conversion] "Boolean conversion is not supported for type `NotBoolable`"
while NotBoolable():
...
Cyclic control flow
def random() -> bool:
return False
i = 0
reveal_type(i) # revealed: Literal[0]
while random():
i += 1
reveal_type(i) # revealed: int
A more complex example, where the loop condition narrows both the loop-back value and the end-of-loop value.
x = "A"
while x != "C":
reveal_type(x) # revealed: Literal["A", "B"]
if random():
x = "B"
else:
x = "C"
reveal_type(x) # revealed: Literal["B", "C"]
reveal_type(x) # revealed: Literal["C"]
The same thing, but nested loops.
x = "A"
while x != "E":
reveal_type(x) # revealed: Literal["A", "B", "D"]
while x != "C":
reveal_type(x) # revealed: Literal["A", "B", "D"]
if random():
x = "B"
else:
x = "C"
reveal_type(x) # revealed: Literal["B", "C", "D"]
reveal_type(x) # revealed: Literal["C"]
if random():
x = "D"
else:
x = "E"
reveal_type(x) # revealed: Literal["D", "E"]
reveal_type(x) # revealed: Literal["E"]