cyclic control flow for loops
Currently we don't even model control flow back edges in loops (because they will often lead to inference cycles). Once we have fixpoint iteration support in Salsa, we need to add these back edges and tests for them, including cases where we have to fallback to avoid runaway fixpoint iteration, e.g.:
x = 0
for _ in range(y):
x += 1
I've seen multiple real world examples where missing support for loop control flow leads to an incorrect reachability analysis for large blocks of code within loops, because we observe a type that is too narrow. For example:
first_iteration = True
for x in xs:
if not first_iteration:
# this whole block is considered unreachable
# more code
first_iteration = False
I just encountered the exact same problem as David:
https://play.ty.dev/9214d74c-f4de-46df-80d0-44b3262d1ff4
some_list: list[int] = [0, 1]
first_part = True
for j in range(0, 10):
if first_part:
first_part = False
continue
# ty infers `val: Never` here!?
# (many other results now infer to Unknown)
val = some_list[0]
And because we don't respect first_part: bool there's no (non-tedious) way to tell ty to chill.
And because we don't respect
first_part: boolthere's no (non-tedious) way to tell ty to chill.
Obviously not ideal, but a cast always helps as a workaround in these situations (first_part = cast(bool, True)).