Skip to content

[ty] Fix loop-header reachability cycles in conditional unpacking - #24006

Merged
charliermarsh merged 1 commit into
mainfrom
charlie/loop-panic
Mar 23, 2026
Merged

[ty] Fix loop-header reachability cycles in conditional unpacking#24006
charliermarsh merged 1 commit into
mainfrom
charlie/loop-panic

Conversation

@charliermarsh

@charliermarsh charliermarsh commented Mar 16, 2026

Copy link
Copy Markdown
Member

Summary

Closes astral-sh/ty#3057.

Closes astral-sh/ty#3104.

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Mar 16, 2026
@charliermarsh charliermarsh added the bug Something isn't working label Mar 16, 2026
@astral-sh-bot

astral-sh-bot Bot commented Mar 16, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 85.38%. The percentage of expected errors that received a diagnostic held steady at 78.70%. The number of fully passing files held steady at 64/132.

@astral-sh-bot

astral-sh-bot Bot commented Mar 16, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented Mar 16, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Full report with detailed diff (timing results)


LoopHeaderReachability {
has_defined_bindings: self.has_defined_bindings,
deleted_reachability: self.deleted_reachability,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it would be equivalent to change this to self.has_defined_bindings || previous.has_defined_bindings? Do we also need to update deleted_reachability here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't want to do that because it would over-estimate unboundness, though I can't come up with a test impacted by changing that.

@ibraheemdev ibraheemdev Mar 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this diff:

- deleted_reachability: self.deleted_reachability,
+ deleted_reachability: self.deleted_reachability.or(previous.deleted_reachability),

The following example emits a warning:

x = 1
# warning[possibly-unresolved-reference]:
while x < 10:
    # warning[possibly-unresolved-reference]:
    if x == 4:
        del x

So I think leaving it is correct (though it is possible it may prevent cycle convergence in some cases, but if we don't have a reproduction we can leave it for now). As @carljm points out, I think this means that your change also has the same problem of over-estimating the definedness of bindings within the loop, but I think it's fine to land for now to fix the cycle panics.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added both tests, thank you!

@carljm

carljm commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

This might be the unavoidable cost of fixing these cycles (I'd have to think harder about what else we could do to avoid it), but Codex observes that this branch means we now infer Literal[0, 2] for x = 0; while random(): reveal_type(x); if x == 1: x = 2, whereas on main we correctly reveal Literal[0].

Of course, no other type checker is able to reveal Literal[0] here, which is another indication that this regression might be acceptable.

@charliermarsh

Copy link
Copy Markdown
Member Author

I'll need to dig deeper to figure out if there's a fix that would retain the current behavior, but we might want to err on the side of merging this since we now have two panic reports.

@ibraheemdev ibraheemdev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to land this for now to fix the panics, but it would be helpful to add @carljm's example as a regression test.

@charliermarsh
charliermarsh enabled auto-merge (squash) March 23, 2026 00:18
@charliermarsh
charliermarsh merged commit bc7cf14 into main Mar 23, 2026
48 checks passed
@charliermarsh
charliermarsh deleted the charlie/loop-panic branch March 23, 2026 00:22
ibraheemdev added a commit that referenced this pull request Mar 23, 2026
Improves #24006 by ignoring loop
bindings generated by the first few cycle iterations, similar to
#23563.
KotlinIsland pushed a commit to KotlinIsland/basedpython that referenced this pull request May 1, 2026
Improves astral-sh/ruff#24006 by ignoring loop
bindings generated by the first few cycle iterations, similar to
astral-sh/ruff#23563.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[panic] too many cycle iterations in 0.0.24 (regression from 0.0.23) [panic] new panic in 0.0.23

3 participants