Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[ty] Avoid enum literal panic during cycle recovery#25237

Merged
charliermarsh merged 1 commit into
mainfrom
charlie/enum-literal
May 19, 2026
Merged

[ty] Avoid enum literal panic during cycle recovery#25237
charliermarsh merged 1 commit into
mainfrom
charlie/enum-literal

Conversation

@charliermarsh

Copy link
Copy Markdown
Member

Summary

Closes astral-sh/ty#3481.

@charliermarsh charliermarsh added bug Something isn't working ty Multi-file analysis & type inference labels May 19, 2026
@astral-sh-bot

astral-sh-bot Bot commented May 19, 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 89.36%. The percentage of expected errors that received a diagnostic held steady at 85.49%. The number of fully passing files held steady at 88/134.

@astral-sh-bot

astral-sh-bot Bot commented May 19, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented May 19, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Full report with detailed diff (timing results)

@charliermarsh charliermarsh force-pushed the charlie/enum-literal branch from c4a70f1 to 2e671bf Compare May 19, 2026 11:44
@charliermarsh charliermarsh marked this pull request as ready for review May 19, 2026 11:47
@charliermarsh charliermarsh merged commit fe61755 into main May 19, 2026
59 checks passed
@charliermarsh charliermarsh deleted the charlie/enum-literal branch May 19, 2026 11:56
Comment on lines +779 to +781
// Metadata is only needed for enum-wide simplifications; class identity
// is enough to preserve a precise set of enum literals during cycle
// recovery.

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 don't understand what this comment is trying to say. This function isn't specific to cycle recovery at all; it's a core part of the union builder. I think future readers of this code will probably be pretty confused by seeing a reference to cycle recovery 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 will fix this! On my TODO list.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we're revisiting this comment, I do wish we had a clearer idea why the example causes the previous expect to fail, and precisely what happens in cycle recovery that causes us to have a LiteralValueTypeKind::Enum wrapping a non-enum, and that were documented here and in the added test.

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.

Sure, I can add that. I looked at all of it when fixing the issue.

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.

It feels quite reminiscent to me of the situation discussed in astral-sh/ty#1587 (comment) and following comments on that issue thread.

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.

Yeah that looks very similar (I hadn't seen that issue before!). Although the more time I sink into this, the less I'm certain about what's going on. It's something like the following though.

On Python 3.14:

from enum import Enum
from typing import TypeVar

def fn1(x: T):
    pass

def fn2(x: T):
    pass

fn1()
fn2()

class C(Enum):
    a = 1
    b = 2

match m:
    case C.a:
        _()
    case _:
        _()

T = TypeVar

We hit a cycle around case C.a whereby we need to determine whether class C is reachable, which means we need to figure out whether fn1 and fn2 terminate, which means we need their signatures, which means we need to resolve T, which means we need to determine whether T = TypeVar is reachable, which means we go back into evaluating the match and re-infer infer_expression_type(C.a).

Then, across cycle iterations, we see enum_metadata return Some(...) in some case and None later during recovery. This last part I don't have a great grasp on, though it's similar to the comments in that linked issue.

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.

thejchap pushed a commit to thejchap/ruff that referenced this pull request May 23, 2026
thejchap pushed a commit to thejchap/ruff that referenced this pull request May 23, 2026
anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request May 28, 2026
anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request May 28, 2026
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: Class of enum literal is an enum

4 participants