ruff/crates/ty_python_semantic/resources/mdtest/call
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
..
annotation.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
builtins.md [ty] Surface matched overload diagnostic directly (#18452) 2025-06-20 08:36:49 +05:30
callable_instance.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
constructor.md [ty] Rename call-possibly-unbound-method to possibly-unbound-implicit-call (#18017) 2025-05-22 15:25:51 +00:00
dunder.md [ty] Allow declared-only class-level attributes to be accessed on the class (#19071) 2025-07-02 18:03:56 +02:00
dunder_import.md [ty] Add special-cased inference for __import__(name) and importlib.import_module(name) (#19008) 2025-06-29 11:49:23 +01:00
function.md [ty] eliminate is_fully_static (#18799) 2025-06-24 18:02:05 -07:00
getattr_static.md [ty] eliminate is_fully_static (#18799) 2025-06-24 18:02:05 -07:00
invalid_syntax.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
methods.md [ty] Fix descriptor lookups for most types that overlap with None (#19120) 2025-07-05 19:34:23 +01:00
never.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
overloads.md [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
str_startswith.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
subclass_of.md [ty] Include synthesized arguments in displayed counts for too-many-positional-arguments (#18098) 2025-05-14 22:51:23 -04:00
union.md [ty] eliminate is_fully_static (#18799) 2025-06-24 18:02:05 -07:00