ruff/crates/ty_python_semantic/src
David Peter dc66019fbc
[ty] Expansion of enums into unions of literals (#19382)
## 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
2025-07-21 19:37:55 +02:00
..
module_resolver [ty] Add support for `@warnings.deprecated` (#19376) 2025-07-18 23:50:29 +00:00
semantic_index [ty] make `del x` force local resolution of `x` in the current scope (#19389) 2025-07-18 14:58:32 -07:00
types [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
util [ty] Use python version and path from Python extension (#19012) 2025-07-14 09:47:27 +00:00
ast_node_ref.rs [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
db.rs [ty] Track open files in the server (#19264) 2025-07-18 19:33:35 +05:30
dunder_all.rs [ty] Remove `ScopedExpressionId` (#19019) 2025-07-02 17:57:32 +02:00
lib.rs [ty] Implemented "go to definition" support for import statements (#19428) 2025-07-19 11:22:07 -07:00
lint.rs [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
list.rs [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
module_name.rs [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
node_key.rs [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
place.rs [ty] add support for `nonlocal` statements 2025-07-11 09:44:54 -07:00
program.rs [ty] Use python version and path from Python extension (#19012) 2025-07-14 09:47:27 +00:00
pull_types.rs Update Rust toolchain to 1.88 and MSRV to 1.86 (#19011) 2025-06-28 20:24:00 +02:00
python_platform.rs Hug closing `}` when f-string expression has a format specifier (#18704) 2025-06-17 07:39:42 +02:00
semantic_index.rs [ty] Initial implementation of declaration and definition providers. (#19371) 2025-07-16 15:07:24 -07:00
semantic_model.rs [ty] Add caching for submodule completion suggestions (#19408) 2025-07-18 11:54:27 -04:00
site_packages.rs [ty] Use python version and path from Python extension (#19012) 2025-07-14 09:47:27 +00:00
suppression.rs [ty] Reduce number of inline stored definitions per place (#19409) 2025-07-18 18:28:46 +02:00
types.rs [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
unpack.rs [ty] Remove countme from salsa-structs (#19257) 2025-07-10 11:45:09 +00:00