[ty] Improve disjointness inference for NominalInstanceTypes and SubclassOfTypes (#18864)

Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
Alex Waygood
2025-06-24 21:27:37 +01:00
committed by GitHub
parent d89f75f9cc
commit 9d8cba4e8b
23 changed files with 1255 additions and 442 deletions

View File

@@ -192,16 +192,18 @@ def _(
from typing import Callable, Union
from ty_extensions import Intersection, Not
class Foo: ...
def _(
c: Intersection[Callable[[Union[int, str]], int], int],
d: Intersection[int, Callable[[Union[int, str]], int]],
e: Intersection[int, Callable[[Union[int, str]], int], str],
f: Intersection[Not[Callable[[int, str], Intersection[int, str]]]],
e: Intersection[int, Callable[[Union[int, str]], int], Foo],
f: Intersection[Not[Callable[[int, str], Intersection[int, Foo]]]],
):
reveal_type(c) # revealed: ((int | str, /) -> int) & int
reveal_type(d) # revealed: int & ((int | str, /) -> int)
reveal_type(e) # revealed: int & ((int | str, /) -> int) & str
reveal_type(f) # revealed: ~((int, str, /) -> int & str)
reveal_type(e) # revealed: int & ((int | str, /) -> int) & Foo
reveal_type(f) # revealed: ~((int, str, /) -> int & Foo)
```
## Nested

View File

@@ -88,3 +88,26 @@ def assigns_complex(x: complex):
def f(x: complex):
reveal_type(x) # revealed: int | float | complex
```
## Narrowing
`int`, `float` and `complex` are all disjoint, which means that the union `int | float` can easily
be narrowed to `int` or `float`:
```py
from typing_extensions import assert_type
from ty_extensions import JustFloat
def f(x: complex):
reveal_type(x) # revealed: int | float | complex
if isinstance(x, int):
reveal_type(x) # revealed: int
elif isinstance(x, float):
reveal_type(x) # revealed: float
else:
reveal_type(x) # revealed: complex
assert isinstance(x, float)
assert_type(x, JustFloat)
```