mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-09 13:18:18 +00:00
![]() ## Summary Implement expansion of enums into unions of enum literals (and the reverse operation). For the enum below, this allows us to understand that `Color = Literal[Color.RED, Color.GREEN, Color.BLUE]`, or that `Color & ~Literal[Color.RED] = Literal[Color.GREEN, Color.BLUE]`. This helps in exhaustiveness checking, which is why we see some removed `assert_never` false positives. And since exhaustiveness checking also helps with understanding terminal control flow, we also see a few removed `invalid-return-type` and `possibly-unresolved-reference` false positives. This PR also adds expansion of enums in overload resolution and type narrowing constructs. ```py from enum import Enum from typing_extensions import Literal, assert_never from ty_extensions import Intersection, Not, static_assert, is_equivalent_to class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 type Red = Literal[Color.RED] type Green = Literal[Color.GREEN] type Blue = Literal[Color.BLUE] static_assert(is_equivalent_to(Red | Green | Blue, Color)) static_assert(is_equivalent_to(Intersection[Color, Not[Red]], Green | Blue)) def color_name(color: Color) -> str: # no error here (we detect that this can not implicitly return None) if color is Color.RED: return "Red" elif color is Color.GREEN: return "Green" elif color is Color.BLUE: return "Blue" else: assert_never(color) # no error here ``` ## Performance I avoided an initial regression here for large enums, but the `UnionBuilder` and `IntersectionBuilder` parts can certainly still be optimized. We might want to use the same technique that we also use for unions of other literals. I didn't see any problems in our benchmarks so far, so this is not included yet. ## Test Plan Many new Markdown tests |
||
---|---|---|
.. | ||
annotation.md | ||
builtins.md | ||
callable_instance.md | ||
constructor.md | ||
dunder.md | ||
dunder_import.md | ||
function.md | ||
getattr_static.md | ||
invalid_syntax.md | ||
methods.md | ||
never.md | ||
overloads.md | ||
str_startswith.md | ||
subclass_of.md | ||
union.md |