mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:24:57 +00:00
[ty] Add Top[] and Bottom[] special forms, replacing top_materialization_of() function (#20054)
Some checks failed
CI / mkdocs (push) Has been cancelled
CI / Determine changes (push) Has been cancelled
CI / cargo fmt (push) Has been cancelled
CI / cargo build (release) (push) Has been cancelled
CI / python package (push) Has been cancelled
CI / pre-commit (push) Has been cancelled
[ty Playground] Release / publish (push) Has been cancelled
CI / cargo clippy (push) Has been cancelled
CI / cargo test (linux) (push) Has been cancelled
CI / cargo test (linux, release) (push) Has been cancelled
CI / cargo test (windows) (push) Has been cancelled
CI / cargo test (wasm) (push) Has been cancelled
CI / formatter instabilities and black similarity (push) Has been cancelled
CI / cargo build (msrv) (push) Has been cancelled
CI / cargo fuzz build (push) Has been cancelled
CI / fuzz parser (push) Has been cancelled
CI / test scripts (push) Has been cancelled
CI / ecosystem (push) Has been cancelled
CI / Fuzz for new ty panics (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / test ruff-lsp (push) Has been cancelled
CI / check playground (push) Has been cancelled
CI / benchmarks-instrumented (push) Has been cancelled
CI / benchmarks-walltime (push) Has been cancelled
Some checks failed
CI / mkdocs (push) Has been cancelled
CI / Determine changes (push) Has been cancelled
CI / cargo fmt (push) Has been cancelled
CI / cargo build (release) (push) Has been cancelled
CI / python package (push) Has been cancelled
CI / pre-commit (push) Has been cancelled
[ty Playground] Release / publish (push) Has been cancelled
CI / cargo clippy (push) Has been cancelled
CI / cargo test (linux) (push) Has been cancelled
CI / cargo test (linux, release) (push) Has been cancelled
CI / cargo test (windows) (push) Has been cancelled
CI / cargo test (wasm) (push) Has been cancelled
CI / formatter instabilities and black similarity (push) Has been cancelled
CI / cargo build (msrv) (push) Has been cancelled
CI / cargo fuzz build (push) Has been cancelled
CI / fuzz parser (push) Has been cancelled
CI / test scripts (push) Has been cancelled
CI / ecosystem (push) Has been cancelled
CI / Fuzz for new ty panics (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / test ruff-lsp (push) Has been cancelled
CI / check playground (push) Has been cancelled
CI / benchmarks-instrumented (push) Has been cancelled
CI / benchmarks-walltime (push) Has been cancelled
Part of astral-sh/ty#994 ## Summary Add new special forms to `ty_extensions`, `Top[T]` and `Bottom[T]`. Remove `ty_extensions.top_materialization` and `ty_extensions.bottom_materialization`. ## Test Plan Converted the existing `materialization.md` mdtest to the new syntax. Added some tests for invalid use of the new special form.
This commit is contained in:
parent
e7237652a9
commit
ec86a4e960
8 changed files with 288 additions and 182 deletions
|
@ -29,22 +29,25 @@ The dynamic type at the top-level is replaced with `object`.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
from ty_extensions import Unknown, top_materialization
|
from ty_extensions import Unknown, Top
|
||||||
|
|
||||||
reveal_type(top_materialization(Any)) # revealed: object
|
def _(top_any: Top[Any], top_unknown: Top[Unknown]):
|
||||||
reveal_type(top_materialization(Unknown)) # revealed: object
|
reveal_type(top_any) # revealed: object
|
||||||
|
reveal_type(top_unknown) # revealed: object
|
||||||
```
|
```
|
||||||
|
|
||||||
The contravariant position is replaced with `Never`.
|
The contravariant position is replaced with `Never`.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(top_materialization(Callable[[Any], None])) # revealed: (Never, /) -> None
|
def _(top_callable: Top[Callable[[Any], None]]):
|
||||||
|
reveal_type(top_callable) # revealed: (Never, /) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
The invariant position is replaced with an unresolved type variable.
|
The invariant position is replaced with an unresolved type variable.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(top_materialization(list[Any])) # revealed: list[T_all]
|
def _(top_list: Top[list[Any]]):
|
||||||
|
reveal_type(top_list) # revealed: list[T_all]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Bottom materialization
|
### Bottom materialization
|
||||||
|
@ -53,24 +56,26 @@ The dynamic type at the top-level is replaced with `Never`.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
from ty_extensions import Unknown, bottom_materialization
|
from ty_extensions import Unknown, Bottom
|
||||||
|
|
||||||
reveal_type(bottom_materialization(Any)) # revealed: Never
|
def _(bottom_any: Bottom[Any], bottom_unknown: Bottom[Unknown]):
|
||||||
reveal_type(bottom_materialization(Unknown)) # revealed: Never
|
reveal_type(bottom_any) # revealed: Never
|
||||||
|
reveal_type(bottom_unknown) # revealed: Never
|
||||||
```
|
```
|
||||||
|
|
||||||
The contravariant position is replaced with `object`.
|
The contravariant position is replaced with `object`.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
# revealed: (object, object, /) -> None
|
def _(bottom_callable: Bottom[Callable[[Any, Unknown], None]]):
|
||||||
reveal_type(bottom_materialization(Callable[[Any, Unknown], None]))
|
reveal_type(bottom_callable) # revealed: (object, object, /) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
The invariant position is replaced in the same way as the top materialization, with an unresolved
|
The invariant position is replaced in the same way as the top materialization, with an unresolved
|
||||||
type variable.
|
type variable.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(bottom_materialization(list[Any])) # revealed: list[T_all]
|
def _(bottom_list: Bottom[list[Any]]):
|
||||||
|
reveal_type(bottom_list) # revealed: list[T_all]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Fully static types
|
## Fully static types
|
||||||
|
@ -79,30 +84,30 @@ The top / bottom (and only) materialization of any fully static type is just its
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
from ty_extensions import TypeOf, bottom_materialization, top_materialization
|
from ty_extensions import TypeOf, Bottom, Top, is_equivalent_to, static_assert
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
class Answer(Enum):
|
class Answer(Enum):
|
||||||
NO = 0
|
NO = 0
|
||||||
YES = 1
|
YES = 1
|
||||||
|
|
||||||
reveal_type(top_materialization(int)) # revealed: int
|
static_assert(is_equivalent_to(Top[int], int))
|
||||||
reveal_type(bottom_materialization(int)) # revealed: int
|
static_assert(is_equivalent_to(Bottom[int], int))
|
||||||
|
|
||||||
reveal_type(top_materialization(Literal[1])) # revealed: Literal[1]
|
static_assert(is_equivalent_to(Top[Literal[1]], Literal[1]))
|
||||||
reveal_type(bottom_materialization(Literal[1])) # revealed: Literal[1]
|
static_assert(is_equivalent_to(Bottom[Literal[1]], Literal[1]))
|
||||||
|
|
||||||
reveal_type(top_materialization(Literal[True])) # revealed: Literal[True]
|
static_assert(is_equivalent_to(Top[Literal[True]], Literal[True]))
|
||||||
reveal_type(bottom_materialization(Literal[True])) # revealed: Literal[True]
|
static_assert(is_equivalent_to(Bottom[Literal[True]], Literal[True]))
|
||||||
|
|
||||||
reveal_type(top_materialization(Literal["abc"])) # revealed: Literal["abc"]
|
static_assert(is_equivalent_to(Top[Literal["abc"]], Literal["abc"]))
|
||||||
reveal_type(bottom_materialization(Literal["abc"])) # revealed: Literal["abc"]
|
static_assert(is_equivalent_to(Bottom[Literal["abc"]], Literal["abc"]))
|
||||||
|
|
||||||
reveal_type(top_materialization(Literal[Answer.YES])) # revealed: Literal[Answer.YES]
|
static_assert(is_equivalent_to(Top[Literal[Answer.YES]], Literal[Answer.YES]))
|
||||||
reveal_type(bottom_materialization(Literal[Answer.YES])) # revealed: Literal[Answer.YES]
|
static_assert(is_equivalent_to(Bottom[Literal[Answer.YES]], Literal[Answer.YES]))
|
||||||
|
|
||||||
reveal_type(top_materialization(int | str)) # revealed: int | str
|
static_assert(is_equivalent_to(Top[int | str], int | str))
|
||||||
reveal_type(bottom_materialization(int | str)) # revealed: int | str
|
static_assert(is_equivalent_to(Bottom[int | str], int | str))
|
||||||
```
|
```
|
||||||
|
|
||||||
We currently treat function literals as fully static types, so they remain unchanged even though the
|
We currently treat function literals as fully static types, so they remain unchanged even though the
|
||||||
|
@ -114,11 +119,17 @@ def function(x: Any) -> None: ...
|
||||||
class A:
|
class A:
|
||||||
def method(self, x: Any) -> None: ...
|
def method(self, x: Any) -> None: ...
|
||||||
|
|
||||||
reveal_type(top_materialization(TypeOf[function])) # revealed: def function(x: Any) -> None
|
def _(
|
||||||
reveal_type(bottom_materialization(TypeOf[function])) # revealed: def function(x: Any) -> None
|
top_func: Top[TypeOf[function]],
|
||||||
|
bottom_func: Bottom[TypeOf[function]],
|
||||||
|
top_meth: Top[TypeOf[A().method]],
|
||||||
|
bottom_meth: Bottom[TypeOf[A().method]],
|
||||||
|
):
|
||||||
|
reveal_type(top_func) # revealed: def function(x: Any) -> None
|
||||||
|
reveal_type(bottom_func) # revealed: def function(x: Any) -> None
|
||||||
|
|
||||||
reveal_type(top_materialization(TypeOf[A().method])) # revealed: bound method A.method(x: Any) -> None
|
reveal_type(top_meth) # revealed: bound method A.method(x: Any) -> None
|
||||||
reveal_type(bottom_materialization(TypeOf[A().method])) # revealed: bound method A.method(x: Any) -> None
|
reveal_type(bottom_meth) # revealed: bound method A.method(x: Any) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
## Callable
|
## Callable
|
||||||
|
@ -126,27 +137,30 @@ reveal_type(bottom_materialization(TypeOf[A().method])) # revealed: bound metho
|
||||||
For a callable, the parameter types are in a contravariant position, and the return type is in a
|
For a callable, the parameter types are in a contravariant position, and the return type is in a
|
||||||
covariant position.
|
covariant position.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
from ty_extensions import TypeOf, Unknown, bottom_materialization, top_materialization
|
from ty_extensions import TypeOf, Unknown, Bottom, Top
|
||||||
|
|
||||||
def _(callable: Callable[[Any, Unknown], Any]) -> None:
|
type C1 = Callable[[Any, Unknown], Any]
|
||||||
# revealed: (Never, Never, /) -> object
|
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
|
||||||
|
|
||||||
# revealed: (object, object, /) -> Never
|
def _(top: Top[C1], bottom: Bottom[C1]) -> None:
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(top) # revealed: (Never, Never, /) -> object
|
||||||
|
reveal_type(bottom) # revealed: (object, object, /) -> Never
|
||||||
```
|
```
|
||||||
|
|
||||||
The parameter types in a callable inherits the contravariant position.
|
The parameter types in a callable inherits the contravariant position.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def _(callable: Callable[[int, tuple[int | Any]], tuple[Any]]) -> None:
|
type C2 = Callable[[int, tuple[int | Any]], tuple[Any]]
|
||||||
# revealed: (int, tuple[int], /) -> tuple[object]
|
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
|
||||||
|
|
||||||
# revealed: (int, tuple[object], /) -> Never
|
def _(top: Top[C2], bottom: Bottom[C2]) -> None:
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(top) # revealed: (int, tuple[int], /) -> tuple[object]
|
||||||
|
reveal_type(bottom) # revealed: (int, tuple[object], /) -> Never
|
||||||
```
|
```
|
||||||
|
|
||||||
But, if the callable itself is in a contravariant position, then the variance is flipped i.e., if
|
But, if the callable itself is in a contravariant position, then the variance is flipped i.e., if
|
||||||
|
@ -154,30 +168,37 @@ the outer variance is covariant, it's flipped to contravariant, and if it's cont
|
||||||
flipped to covariant, invariant remains invariant.
|
flipped to covariant, invariant remains invariant.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def _(callable: Callable[[Any, Callable[[Unknown], Any]], Callable[[Any, int], Any]]) -> None:
|
type C3 = Callable[[Any, Callable[[Unknown], Any]], Callable[[Any, int], Any]]
|
||||||
|
|
||||||
|
def _(top: Top[C3], bottom: Bottom[C3]) -> None:
|
||||||
# revealed: (Never, (object, /) -> Never, /) -> (Never, int, /) -> object
|
# revealed: (Never, (object, /) -> Never, /) -> (Never, int, /) -> object
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
reveal_type(top)
|
||||||
|
|
||||||
# revealed: (object, (Never, /) -> object, /) -> (object, int, /) -> Never
|
# revealed: (object, (Never, /) -> object, /) -> (object, int, /) -> Never
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(bottom)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tuple
|
## Tuple
|
||||||
|
|
||||||
All positions in a tuple are covariant.
|
All positions in a tuple are covariant.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any, Never
|
||||||
from ty_extensions import Unknown, bottom_materialization, top_materialization
|
from ty_extensions import Unknown, Bottom, Top, is_equivalent_to, static_assert
|
||||||
|
|
||||||
reveal_type(top_materialization(tuple[Any, int])) # revealed: tuple[object, int]
|
static_assert(is_equivalent_to(Top[tuple[Any, int]], tuple[object, int]))
|
||||||
reveal_type(bottom_materialization(tuple[Any, int])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[tuple[Any, int]], Never))
|
||||||
|
|
||||||
reveal_type(top_materialization(tuple[Unknown, int])) # revealed: tuple[object, int]
|
static_assert(is_equivalent_to(Top[tuple[Unknown, int]], tuple[object, int]))
|
||||||
reveal_type(bottom_materialization(tuple[Unknown, int])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[tuple[Unknown, int]], Never))
|
||||||
|
|
||||||
reveal_type(top_materialization(tuple[Any, int, Unknown])) # revealed: tuple[object, int, object]
|
static_assert(is_equivalent_to(Top[tuple[Any, int, Unknown]], tuple[object, int, object]))
|
||||||
reveal_type(bottom_materialization(tuple[Any, int, Unknown])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[tuple[Any, int, Unknown]], Never))
|
||||||
```
|
```
|
||||||
|
|
||||||
Except for when the tuple itself is in a contravariant position, then all positions in the tuple
|
Except for when the tuple itself is in a contravariant position, then all positions in the tuple
|
||||||
|
@ -187,43 +208,59 @@ inherit the contravariant position.
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from ty_extensions import TypeOf
|
from ty_extensions import TypeOf
|
||||||
|
|
||||||
def _(callable: Callable[[tuple[Any, int], tuple[str, Unknown]], None]) -> None:
|
type C = Callable[[tuple[Any, int], tuple[str, Unknown]], None]
|
||||||
# revealed: (Never, Never, /) -> None
|
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
|
||||||
|
|
||||||
# revealed: (tuple[object, int], tuple[str, object], /) -> None
|
def _(top: Top[C], bottom: Bottom[C]) -> None:
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(top) # revealed: (Never, Never, /) -> None
|
||||||
|
reveal_type(bottom) # revealed: (tuple[object, int], tuple[str, object], /) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
And, similarly for an invariant position.
|
And, similarly for an invariant position.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(top_materialization(list[tuple[Any, int]])) # revealed: list[tuple[T_all, int]]
|
type LTAnyInt = list[tuple[Any, int]]
|
||||||
reveal_type(bottom_materialization(list[tuple[Any, int]])) # revealed: list[tuple[T_all, int]]
|
type LTStrUnknown = list[tuple[str, Unknown]]
|
||||||
|
type LTAnyIntUnknown = list[tuple[Any, int, Unknown]]
|
||||||
|
|
||||||
reveal_type(top_materialization(list[tuple[str, Unknown]])) # revealed: list[tuple[str, T_all]]
|
def _(
|
||||||
reveal_type(bottom_materialization(list[tuple[str, Unknown]])) # revealed: list[tuple[str, T_all]]
|
top_ai: Top[LTAnyInt],
|
||||||
|
bottom_ai: Bottom[LTAnyInt],
|
||||||
|
top_su: Top[LTStrUnknown],
|
||||||
|
bottom_su: Bottom[LTStrUnknown],
|
||||||
|
top_aiu: Top[LTAnyIntUnknown],
|
||||||
|
bottom_aiu: Bottom[LTAnyIntUnknown],
|
||||||
|
):
|
||||||
|
reveal_type(top_ai) # revealed: list[tuple[T_all, int]]
|
||||||
|
reveal_type(bottom_ai) # revealed: list[tuple[T_all, int]]
|
||||||
|
|
||||||
reveal_type(top_materialization(list[tuple[Any, int, Unknown]])) # revealed: list[tuple[T_all, int, T_all]]
|
reveal_type(top_su) # revealed: list[tuple[str, T_all]]
|
||||||
reveal_type(bottom_materialization(list[tuple[Any, int, Unknown]])) # revealed: list[tuple[T_all, int, T_all]]
|
reveal_type(bottom_su) # revealed: list[tuple[str, T_all]]
|
||||||
|
|
||||||
|
reveal_type(top_aiu) # revealed: list[tuple[T_all, int, T_all]]
|
||||||
|
reveal_type(bottom_aiu) # revealed: list[tuple[T_all, int, T_all]]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Union
|
## Union
|
||||||
|
|
||||||
All positions in a union are covariant.
|
All positions in a union are covariant.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from ty_extensions import Unknown, bottom_materialization, top_materialization
|
from ty_extensions import Unknown, Bottom, Top, static_assert, is_equivalent_to
|
||||||
|
|
||||||
reveal_type(top_materialization(Any | int)) # revealed: object
|
static_assert(is_equivalent_to(Top[Any | int], object))
|
||||||
reveal_type(bottom_materialization(Any | int)) # revealed: int
|
static_assert(is_equivalent_to(Bottom[Any | int], int))
|
||||||
|
|
||||||
reveal_type(top_materialization(Unknown | int)) # revealed: object
|
static_assert(is_equivalent_to(Top[Unknown | int], object))
|
||||||
reveal_type(bottom_materialization(Unknown | int)) # revealed: int
|
static_assert(is_equivalent_to(Bottom[Unknown | int], int))
|
||||||
|
|
||||||
reveal_type(top_materialization(int | str | Any)) # revealed: object
|
static_assert(is_equivalent_to(Top[int | str | Any], object))
|
||||||
reveal_type(bottom_materialization(int | str | Any)) # revealed: int | str
|
static_assert(is_equivalent_to(Bottom[int | str | Any], int | str))
|
||||||
```
|
```
|
||||||
|
|
||||||
Except for when the union itself is in a contravariant position, then all positions in the union
|
Except for when the union itself is in a contravariant position, then all positions in the union
|
||||||
|
@ -234,24 +271,29 @@ from typing import Callable
|
||||||
from ty_extensions import TypeOf
|
from ty_extensions import TypeOf
|
||||||
|
|
||||||
def _(callable: Callable[[Any | int, str | Unknown], None]) -> None:
|
def _(callable: Callable[[Any | int, str | Unknown], None]) -> None:
|
||||||
# revealed: (int, str, /) -> None
|
static_assert(is_equivalent_to(Top[TypeOf[callable]], Callable[[int, str], None]))
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
static_assert(is_equivalent_to(Bottom[TypeOf[callable]], Callable[[object, object], None]))
|
||||||
|
|
||||||
# revealed: (object, object, /) -> None
|
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And, similarly for an invariant position.
|
And, similarly for an invariant position.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(top_materialization(list[Any | int])) # revealed: list[T_all | int]
|
def _(
|
||||||
reveal_type(bottom_materialization(list[Any | int])) # revealed: list[T_all | int]
|
top_ai: Top[list[Any | int]],
|
||||||
|
bottom_ai: Bottom[list[Any | int]],
|
||||||
|
top_su: Top[list[str | Unknown]],
|
||||||
|
bottom_su: Bottom[list[str | Unknown]],
|
||||||
|
top_aiu: Top[list[Any | int | Unknown]],
|
||||||
|
bottom_aiu: Bottom[list[Any | int | Unknown]],
|
||||||
|
):
|
||||||
|
reveal_type(top_ai) # revealed: list[T_all | int]
|
||||||
|
reveal_type(bottom_ai) # revealed: list[T_all | int]
|
||||||
|
|
||||||
reveal_type(top_materialization(list[str | Unknown])) # revealed: list[str | T_all]
|
reveal_type(top_su) # revealed: list[str | T_all]
|
||||||
reveal_type(bottom_materialization(list[str | Unknown])) # revealed: list[str | T_all]
|
reveal_type(bottom_su) # revealed: list[str | T_all]
|
||||||
|
|
||||||
reveal_type(top_materialization(list[Any | int | Unknown])) # revealed: list[T_all | int]
|
reveal_type(top_aiu) # revealed: list[T_all | int]
|
||||||
reveal_type(bottom_materialization(list[Any | int | Unknown])) # revealed: list[T_all | int]
|
reveal_type(bottom_aiu) # revealed: list[T_all | int]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Intersection
|
## Intersection
|
||||||
|
@ -260,24 +302,26 @@ All positions in an intersection are covariant.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from ty_extensions import Intersection, Unknown, bottom_materialization, top_materialization
|
from typing_extensions import Never
|
||||||
|
from ty_extensions import Intersection, Unknown, Bottom, Top, static_assert, is_equivalent_to
|
||||||
|
|
||||||
reveal_type(top_materialization(Intersection[Any, int])) # revealed: int
|
static_assert(is_equivalent_to(Top[Intersection[Any, int]], int))
|
||||||
reveal_type(bottom_materialization(Intersection[Any, int])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[Intersection[Any, int]], Never))
|
||||||
|
|
||||||
# Here, the top materialization of `Any | int` is `object` and the intersection of it with tuple
|
# Here, the top materialization of `Any | int` is `object` and the intersection of it with tuple
|
||||||
# revealed: tuple[str, object]
|
static_assert(is_equivalent_to(Top[Intersection[Any | int, tuple[str, Unknown]]], tuple[str, object]))
|
||||||
reveal_type(top_materialization(Intersection[Any | int, tuple[str, Unknown]]))
|
static_assert(is_equivalent_to(Bottom[Intersection[Any | int, tuple[str, Unknown]]], Never))
|
||||||
# revealed: Never
|
|
||||||
reveal_type(bottom_materialization(Intersection[Any | int, tuple[str, Unknown]]))
|
|
||||||
|
|
||||||
class Foo: ...
|
class Foo: ...
|
||||||
|
|
||||||
# revealed: Foo & tuple[str]
|
static_assert(is_equivalent_to(Bottom[Intersection[Any | Foo, tuple[str]]], Intersection[Foo, tuple[str]]))
|
||||||
reveal_type(bottom_materialization(Intersection[Any | Foo, tuple[str]]))
|
|
||||||
|
|
||||||
reveal_type(top_materialization(Intersection[list[Any], list[int]])) # revealed: list[T_all] & list[int]
|
def _(
|
||||||
reveal_type(bottom_materialization(Intersection[list[Any], list[int]])) # revealed: list[T_all] & list[int]
|
top: Top[Intersection[list[Any], list[int]]],
|
||||||
|
bottom: Bottom[Intersection[list[Any], list[int]]],
|
||||||
|
):
|
||||||
|
reveal_type(top) # revealed: list[T_all] & list[int]
|
||||||
|
reveal_type(bottom) # revealed: list[T_all] & list[int]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Negation (via `Not`)
|
## Negation (via `Not`)
|
||||||
|
@ -286,38 +330,44 @@ All positions in a negation are contravariant.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from ty_extensions import Not, Unknown, bottom_materialization, top_materialization
|
from typing_extensions import Never
|
||||||
|
from ty_extensions import Not, Unknown, Bottom, Top, static_assert, is_equivalent_to
|
||||||
|
|
||||||
# ~Any is still Any, so the top materialization is object
|
# ~Any is still Any, so the top materialization is object
|
||||||
reveal_type(top_materialization(Not[Any])) # revealed: object
|
static_assert(is_equivalent_to(Top[Not[Any]], object))
|
||||||
reveal_type(bottom_materialization(Not[Any])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[Not[Any]], Never))
|
||||||
|
|
||||||
# tuple[Any, int] is in a contravariant position, so the
|
# tuple[Any, int] is in a contravariant position, so the
|
||||||
# top materialization is Never and the negation of it
|
# top materialization is Never and the negation of it
|
||||||
# revealed: object
|
static_assert(is_equivalent_to(Top[Not[tuple[Any, int]]], object))
|
||||||
reveal_type(top_materialization(Not[tuple[Any, int]]))
|
static_assert(is_equivalent_to(Bottom[Not[tuple[Any, int]]], Not[tuple[object, int]]))
|
||||||
# revealed: ~tuple[object, int]
|
|
||||||
reveal_type(bottom_materialization(Not[tuple[Any, int]]))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## `type`
|
## `type`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from ty_extensions import Unknown, bottom_materialization, top_materialization
|
from typing_extensions import Never
|
||||||
|
from ty_extensions import Unknown, Bottom, Top, static_assert, is_equivalent_to
|
||||||
|
|
||||||
reveal_type(top_materialization(type[Any])) # revealed: type
|
static_assert(is_equivalent_to(Top[type[Any]], type))
|
||||||
reveal_type(bottom_materialization(type[Any])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[type[Any]], Never))
|
||||||
|
|
||||||
reveal_type(top_materialization(type[Unknown])) # revealed: type
|
static_assert(is_equivalent_to(Top[type[Unknown]], type))
|
||||||
reveal_type(bottom_materialization(type[Unknown])) # revealed: Never
|
static_assert(is_equivalent_to(Bottom[type[Unknown]], Never))
|
||||||
|
|
||||||
reveal_type(top_materialization(type[int | Any])) # revealed: type
|
static_assert(is_equivalent_to(Top[type[int | Any]], type))
|
||||||
reveal_type(bottom_materialization(type[int | Any])) # revealed: type[int]
|
static_assert(is_equivalent_to(Bottom[type[int | Any]], type[int]))
|
||||||
|
|
||||||
# Here, `T` has an upper bound of `type`
|
# Here, `T` has an upper bound of `type`
|
||||||
reveal_type(top_materialization(list[type[Any]])) # revealed: list[T_all]
|
def _(top: Top[list[type[Any]]], bottom: Bottom[list[type[Any]]]):
|
||||||
reveal_type(bottom_materialization(list[type[Any]])) # revealed: list[T_all]
|
reveal_type(top) # revealed: list[T_all]
|
||||||
|
reveal_type(bottom) # revealed: list[T_all]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Type variables
|
## Type variables
|
||||||
|
@ -329,26 +379,19 @@ python-version = "3.12"
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Never, TypeVar
|
from typing import Any, Never, TypeVar
|
||||||
from ty_extensions import (
|
from ty_extensions import Unknown, Bottom, Top, static_assert, is_subtype_of
|
||||||
TypeOf,
|
|
||||||
Unknown,
|
|
||||||
bottom_materialization,
|
|
||||||
top_materialization,
|
|
||||||
static_assert,
|
|
||||||
is_subtype_of,
|
|
||||||
)
|
|
||||||
|
|
||||||
def bounded_by_gradual[T: Any](t: T) -> None:
|
def bounded_by_gradual[T: Any](t: T) -> None:
|
||||||
# Top materialization of `T: Any` is `T: object`
|
# Top materialization of `T: Any` is `T: object`
|
||||||
|
|
||||||
# Bottom materialization of `T: Any` is `T: Never`
|
# Bottom materialization of `T: Any` is `T: Never`
|
||||||
static_assert(is_subtype_of(TypeOf[bottom_materialization(T)], Never))
|
static_assert(is_subtype_of(Bottom[T], Never))
|
||||||
|
|
||||||
def constrained_by_gradual[T: (int, Any)](t: T) -> None:
|
def constrained_by_gradual[T: (int, Any)](t: T) -> None:
|
||||||
# Top materialization of `T: (int, Any)` is `T: (int, object)`
|
# Top materialization of `T: (int, Any)` is `T: (int, object)`
|
||||||
|
|
||||||
# Bottom materialization of `T: (int, Any)` is `T: (int, Never)`
|
# Bottom materialization of `T: (int, Any)` is `T: (int, Never)`
|
||||||
static_assert(is_subtype_of(TypeOf[bottom_materialization(T)], int))
|
static_assert(is_subtype_of(Bottom[T], int))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generics
|
## Generics
|
||||||
|
@ -361,9 +404,14 @@ variable itself.
|
||||||
- If the type variable is contravariant, the materialization happens as per the surrounding
|
- If the type variable is contravariant, the materialization happens as per the surrounding
|
||||||
variance, but the variance is flipped
|
variance, but the variance is flipped
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any, Generic, TypeVar
|
from typing import Any, Generic, TypeVar, Never
|
||||||
from ty_extensions import bottom_materialization, top_materialization
|
from ty_extensions import Bottom, Top, static_assert, is_equivalent_to
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
T_co = TypeVar("T_co", covariant=True)
|
T_co = TypeVar("T_co", covariant=True)
|
||||||
|
@ -378,14 +426,15 @@ class GenericCovariant(Generic[T_co]):
|
||||||
class GenericContravariant(Generic[T_contra]):
|
class GenericContravariant(Generic[T_contra]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
reveal_type(top_materialization(GenericInvariant[Any])) # revealed: GenericInvariant[T_all]
|
def _(top: Top[GenericInvariant[Any]], bottom: Bottom[GenericInvariant[Any]]):
|
||||||
reveal_type(bottom_materialization(GenericInvariant[Any])) # revealed: GenericInvariant[T_all]
|
reveal_type(top) # revealed: GenericInvariant[T_all]
|
||||||
|
reveal_type(bottom) # revealed: GenericInvariant[T_all]
|
||||||
|
|
||||||
reveal_type(top_materialization(GenericCovariant[Any])) # revealed: GenericCovariant[object]
|
static_assert(is_equivalent_to(Top[GenericCovariant[Any]], GenericCovariant[object]))
|
||||||
reveal_type(bottom_materialization(GenericCovariant[Any])) # revealed: GenericCovariant[Never]
|
static_assert(is_equivalent_to(Bottom[GenericCovariant[Any]], GenericCovariant[Never]))
|
||||||
|
|
||||||
reveal_type(top_materialization(GenericContravariant[Any])) # revealed: GenericContravariant[Never]
|
static_assert(is_equivalent_to(Top[GenericContravariant[Any]], GenericContravariant[Never]))
|
||||||
reveal_type(bottom_materialization(GenericContravariant[Any])) # revealed: GenericContravariant[object]
|
static_assert(is_equivalent_to(Bottom[GenericContravariant[Any]], GenericContravariant[object]))
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameters in callable are contravariant, so the variance should be flipped:
|
Parameters in callable are contravariant, so the variance should be flipped:
|
||||||
|
@ -394,24 +443,52 @@ Parameters in callable are contravariant, so the variance should be flipped:
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from ty_extensions import TypeOf
|
from ty_extensions import TypeOf
|
||||||
|
|
||||||
def invariant(callable: Callable[[GenericInvariant[Any]], None]) -> None:
|
type InvariantCallable = Callable[[GenericInvariant[Any]], None]
|
||||||
# revealed: (GenericInvariant[T_all], /) -> None
|
type CovariantCallable = Callable[[GenericCovariant[Any]], None]
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
type ContravariantCallable = Callable[[GenericContravariant[Any]], None]
|
||||||
|
|
||||||
# revealed: (GenericInvariant[T_all], /) -> None
|
def invariant(top: Top[InvariantCallable], bottom: Bottom[InvariantCallable]) -> None:
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(top) # revealed: (GenericInvariant[T_all], /) -> None
|
||||||
|
reveal_type(bottom) # revealed: (GenericInvariant[T_all], /) -> None
|
||||||
|
|
||||||
def covariant(callable: Callable[[GenericCovariant[Any]], None]) -> None:
|
def covariant(top: Top[CovariantCallable], bottom: Bottom[CovariantCallable]) -> None:
|
||||||
# revealed: (GenericCovariant[Never], /) -> None
|
reveal_type(top) # revealed: (GenericCovariant[Never], /) -> None
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
reveal_type(bottom) # revealed: (GenericCovariant[object], /) -> None
|
||||||
|
|
||||||
# revealed: (GenericCovariant[object], /) -> None
|
def contravariant(top: Top[ContravariantCallable], bottom: Bottom[ContravariantCallable]) -> None:
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
reveal_type(top) # revealed: (GenericContravariant[object], /) -> None
|
||||||
|
reveal_type(bottom) # revealed: (GenericContravariant[Never], /) -> None
|
||||||
def contravariant(callable: Callable[[GenericContravariant[Any]], None]) -> None:
|
```
|
||||||
# revealed: (GenericContravariant[object], /) -> None
|
|
||||||
reveal_type(top_materialization(TypeOf[callable]))
|
## Invalid use
|
||||||
|
|
||||||
# revealed: (GenericContravariant[Never], /) -> None
|
`Top[]` and `Bottom[]` are special forms that take a single argument.
|
||||||
reveal_type(bottom_materialization(TypeOf[callable]))
|
|
||||||
|
It is invalid to use them without a type argument.
|
||||||
|
|
||||||
|
```py
|
||||||
|
from ty_extensions import Bottom, Top
|
||||||
|
|
||||||
|
def _(
|
||||||
|
just_top: Top, # error: [invalid-type-form]
|
||||||
|
just_bottom: Bottom, # error: [invalid-type-form]
|
||||||
|
): ...
|
||||||
|
```
|
||||||
|
|
||||||
|
It is also invalid to use multiple arguments:
|
||||||
|
|
||||||
|
```py
|
||||||
|
def _(
|
||||||
|
top_two: Top[int, str], # error: [invalid-type-form]
|
||||||
|
bottom_two: Bottom[int, str], # error: [invalid-type-form]
|
||||||
|
): ...
|
||||||
|
```
|
||||||
|
|
||||||
|
The argument must be a type expression:
|
||||||
|
|
||||||
|
```py
|
||||||
|
def _(
|
||||||
|
top_1: Top[1], # error: [invalid-type-form]
|
||||||
|
bottom_1: Bottom[1], # error: [invalid-type-form]
|
||||||
|
): ...
|
||||||
```
|
```
|
||||||
|
|
|
@ -4143,21 +4143,6 @@ impl<'db> Type<'db> {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KnownFunction::TopMaterialization | KnownFunction::BottomMaterialization) => {
|
|
||||||
Binding::single(
|
|
||||||
self,
|
|
||||||
Signature::new(
|
|
||||||
Parameters::new([Parameter::positional_only(Some(Name::new_static(
|
|
||||||
"type",
|
|
||||||
)))
|
|
||||||
.type_form()
|
|
||||||
.with_annotated_type(Type::any())]),
|
|
||||||
Some(Type::any()),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(KnownFunction::AssertType) => Binding::single(
|
Some(KnownFunction::AssertType) => Binding::single(
|
||||||
self,
|
self,
|
||||||
Signature::new(
|
Signature::new(
|
||||||
|
@ -5741,6 +5726,8 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
SpecialFormType::Optional
|
SpecialFormType::Optional
|
||||||
| SpecialFormType::Not
|
| SpecialFormType::Not
|
||||||
|
| SpecialFormType::Top
|
||||||
|
| SpecialFormType::Bottom
|
||||||
| SpecialFormType::TypeOf
|
| SpecialFormType::TypeOf
|
||||||
| SpecialFormType::TypeIs
|
| SpecialFormType::TypeIs
|
||||||
| SpecialFormType::TypeGuard
|
| SpecialFormType::TypeGuard
|
||||||
|
|
|
@ -726,18 +726,6 @@ impl<'db> Bindings<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KnownFunction::TopMaterialization) => {
|
|
||||||
if let [Some(ty)] = overload.parameter_types() {
|
|
||||||
overload.set_return_type(ty.top_materialization(db));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(KnownFunction::BottomMaterialization) => {
|
|
||||||
if let [Some(ty)] = overload.parameter_types() {
|
|
||||||
overload.set_return_type(ty.bottom_materialization(db));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(KnownFunction::Len) => {
|
Some(KnownFunction::Len) => {
|
||||||
if let [Some(first_arg)] = overload.parameter_types() {
|
if let [Some(first_arg)] = overload.parameter_types() {
|
||||||
if let Some(len_ty) = first_arg.len(db) {
|
if let Some(len_ty) = first_arg.len(db) {
|
||||||
|
|
|
@ -192,6 +192,8 @@ impl<'db> ClassBase<'db> {
|
||||||
| SpecialFormType::ReadOnly
|
| SpecialFormType::ReadOnly
|
||||||
| SpecialFormType::Optional
|
| SpecialFormType::Optional
|
||||||
| SpecialFormType::Not
|
| SpecialFormType::Not
|
||||||
|
| SpecialFormType::Top
|
||||||
|
| SpecialFormType::Bottom
|
||||||
| SpecialFormType::Intersection
|
| SpecialFormType::Intersection
|
||||||
| SpecialFormType::TypeOf
|
| SpecialFormType::TypeOf
|
||||||
| SpecialFormType::CallableTypeOf
|
| SpecialFormType::CallableTypeOf
|
||||||
|
|
|
@ -1168,10 +1168,6 @@ pub enum KnownFunction {
|
||||||
AllMembers,
|
AllMembers,
|
||||||
/// `ty_extensions.has_member`
|
/// `ty_extensions.has_member`
|
||||||
HasMember,
|
HasMember,
|
||||||
/// `ty_extensions.top_materialization`
|
|
||||||
TopMaterialization,
|
|
||||||
/// `ty_extensions.bottom_materialization`
|
|
||||||
BottomMaterialization,
|
|
||||||
/// `ty_extensions.reveal_protocol_interface`
|
/// `ty_extensions.reveal_protocol_interface`
|
||||||
RevealProtocolInterface,
|
RevealProtocolInterface,
|
||||||
}
|
}
|
||||||
|
@ -1232,8 +1228,6 @@ impl KnownFunction {
|
||||||
| Self::IsSingleValued
|
| Self::IsSingleValued
|
||||||
| Self::IsSingleton
|
| Self::IsSingleton
|
||||||
| Self::IsSubtypeOf
|
| Self::IsSubtypeOf
|
||||||
| Self::TopMaterialization
|
|
||||||
| Self::BottomMaterialization
|
|
||||||
| Self::GenericContext
|
| Self::GenericContext
|
||||||
| Self::DunderAllNames
|
| Self::DunderAllNames
|
||||||
| Self::EnumMembers
|
| Self::EnumMembers
|
||||||
|
@ -1569,8 +1563,6 @@ pub(crate) mod tests {
|
||||||
| KnownFunction::IsSingleValued
|
| KnownFunction::IsSingleValued
|
||||||
| KnownFunction::IsAssignableTo
|
| KnownFunction::IsAssignableTo
|
||||||
| KnownFunction::IsEquivalentTo
|
| KnownFunction::IsEquivalentTo
|
||||||
| KnownFunction::TopMaterialization
|
|
||||||
| KnownFunction::BottomMaterialization
|
|
||||||
| KnownFunction::HasMember
|
| KnownFunction::HasMember
|
||||||
| KnownFunction::RevealProtocolInterface
|
| KnownFunction::RevealProtocolInterface
|
||||||
| KnownFunction::AllMembers => KnownModule::TyExtensions,
|
| KnownFunction::AllMembers => KnownModule::TyExtensions,
|
||||||
|
|
|
@ -10599,6 +10599,54 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
|
||||||
}
|
}
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
SpecialFormType::Top => {
|
||||||
|
let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
|
||||||
|
&*tuple.elts
|
||||||
|
} else {
|
||||||
|
std::slice::from_ref(arguments_slice)
|
||||||
|
};
|
||||||
|
let num_arguments = arguments.len();
|
||||||
|
let arg = if num_arguments == 1 {
|
||||||
|
self.infer_type_expression(&arguments[0])
|
||||||
|
} else {
|
||||||
|
for argument in arguments {
|
||||||
|
self.infer_type_expression(argument);
|
||||||
|
}
|
||||||
|
report_invalid_argument_number_to_special_form(
|
||||||
|
&self.context,
|
||||||
|
subscript,
|
||||||
|
special_form,
|
||||||
|
num_arguments,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
Type::unknown()
|
||||||
|
};
|
||||||
|
arg.top_materialization(db)
|
||||||
|
}
|
||||||
|
SpecialFormType::Bottom => {
|
||||||
|
let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
|
||||||
|
&*tuple.elts
|
||||||
|
} else {
|
||||||
|
std::slice::from_ref(arguments_slice)
|
||||||
|
};
|
||||||
|
let num_arguments = arguments.len();
|
||||||
|
let arg = if num_arguments == 1 {
|
||||||
|
self.infer_type_expression(&arguments[0])
|
||||||
|
} else {
|
||||||
|
for argument in arguments {
|
||||||
|
self.infer_type_expression(argument);
|
||||||
|
}
|
||||||
|
report_invalid_argument_number_to_special_form(
|
||||||
|
&self.context,
|
||||||
|
subscript,
|
||||||
|
special_form,
|
||||||
|
num_arguments,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
Type::unknown()
|
||||||
|
};
|
||||||
|
arg.bottom_materialization(db)
|
||||||
|
}
|
||||||
SpecialFormType::TypeOf => {
|
SpecialFormType::TypeOf => {
|
||||||
let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
|
let arguments = if let ast::Expr::Tuple(tuple) = arguments_slice {
|
||||||
&*tuple.elts
|
&*tuple.elts
|
||||||
|
|
|
@ -77,6 +77,10 @@ pub enum SpecialFormType {
|
||||||
TypeOf,
|
TypeOf,
|
||||||
/// The symbol `ty_extensions.CallableTypeOf`
|
/// The symbol `ty_extensions.CallableTypeOf`
|
||||||
CallableTypeOf,
|
CallableTypeOf,
|
||||||
|
/// The symbol `ty_extensions.Top`
|
||||||
|
Top,
|
||||||
|
/// The symbol `ty_extensions.Bottom`
|
||||||
|
Bottom,
|
||||||
/// The symbol `typing.Callable`
|
/// The symbol `typing.Callable`
|
||||||
/// (which can also be found as `typing_extensions.Callable` or as `collections.abc.Callable`)
|
/// (which can also be found as `typing_extensions.Callable` or as `collections.abc.Callable`)
|
||||||
Callable,
|
Callable,
|
||||||
|
@ -151,6 +155,8 @@ impl SpecialFormType {
|
||||||
| Self::TypeIs
|
| Self::TypeIs
|
||||||
| Self::TypeOf
|
| Self::TypeOf
|
||||||
| Self::Not
|
| Self::Not
|
||||||
|
| Self::Top
|
||||||
|
| Self::Bottom
|
||||||
| Self::Intersection
|
| Self::Intersection
|
||||||
| Self::CallableTypeOf
|
| Self::CallableTypeOf
|
||||||
| Self::Protocol // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
| Self::Protocol // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
||||||
|
@ -247,6 +253,8 @@ impl SpecialFormType {
|
||||||
| Self::AlwaysTruthy
|
| Self::AlwaysTruthy
|
||||||
| Self::AlwaysFalsy
|
| Self::AlwaysFalsy
|
||||||
| Self::Not
|
| Self::Not
|
||||||
|
| Self::Top
|
||||||
|
| Self::Bottom
|
||||||
| Self::Intersection
|
| Self::Intersection
|
||||||
| Self::TypeOf
|
| Self::TypeOf
|
||||||
| Self::CallableTypeOf => module.is_ty_extensions(),
|
| Self::CallableTypeOf => module.is_ty_extensions(),
|
||||||
|
@ -291,6 +299,8 @@ impl SpecialFormType {
|
||||||
| Self::AlwaysTruthy
|
| Self::AlwaysTruthy
|
||||||
| Self::AlwaysFalsy
|
| Self::AlwaysFalsy
|
||||||
| Self::Not
|
| Self::Not
|
||||||
|
| Self::Top
|
||||||
|
| Self::Bottom
|
||||||
| Self::Intersection
|
| Self::Intersection
|
||||||
| Self::TypeOf
|
| Self::TypeOf
|
||||||
| Self::CallableTypeOf
|
| Self::CallableTypeOf
|
||||||
|
@ -352,6 +362,8 @@ impl SpecialFormType {
|
||||||
SpecialFormType::Intersection => "ty_extensions.Intersection",
|
SpecialFormType::Intersection => "ty_extensions.Intersection",
|
||||||
SpecialFormType::TypeOf => "ty_extensions.TypeOf",
|
SpecialFormType::TypeOf => "ty_extensions.TypeOf",
|
||||||
SpecialFormType::CallableTypeOf => "ty_extensions.CallableTypeOf",
|
SpecialFormType::CallableTypeOf => "ty_extensions.CallableTypeOf",
|
||||||
|
SpecialFormType::Top => "ty_extensions.Top",
|
||||||
|
SpecialFormType::Bottom => "ty_extensions.Bottom",
|
||||||
SpecialFormType::Protocol => "typing.Protocol",
|
SpecialFormType::Protocol => "typing.Protocol",
|
||||||
SpecialFormType::Generic => "typing.Generic",
|
SpecialFormType::Generic => "typing.Generic",
|
||||||
SpecialFormType::NamedTuple => "typing.NamedTuple",
|
SpecialFormType::NamedTuple => "typing.NamedTuple",
|
||||||
|
|
|
@ -24,6 +24,12 @@ Not: _SpecialForm
|
||||||
Intersection: _SpecialForm
|
Intersection: _SpecialForm
|
||||||
TypeOf: _SpecialForm
|
TypeOf: _SpecialForm
|
||||||
CallableTypeOf: _SpecialForm
|
CallableTypeOf: _SpecialForm
|
||||||
|
# Top[T] evaluates to the top materialization of T, a type that is a supertype
|
||||||
|
# of every materialization of T.
|
||||||
|
Top: _SpecialForm
|
||||||
|
# Bottom[T] evaluates to the bottom materialization of T, a type that is a subtype
|
||||||
|
# of every materialization of T.
|
||||||
|
Bottom: _SpecialForm
|
||||||
|
|
||||||
# ty treats annotations of `float` to mean `float | int`, and annotations of `complex`
|
# ty treats annotations of `float` to mean `float | int`, and annotations of `complex`
|
||||||
# to mean `complex | float | int`. This is to support a typing-system special case [1].
|
# to mean `complex | float | int`. This is to support a typing-system special case [1].
|
||||||
|
@ -56,12 +62,6 @@ def dunder_all_names(module: Any) -> Any: ...
|
||||||
# List all members of an enum.
|
# List all members of an enum.
|
||||||
def enum_members[E: type[Enum]](enum: E) -> tuple[str, ...]: ...
|
def enum_members[E: type[Enum]](enum: E) -> tuple[str, ...]: ...
|
||||||
|
|
||||||
# Returns the type that's an upper bound of materializing the given (gradual) type.
|
|
||||||
def top_materialization(type: Any) -> Any: ...
|
|
||||||
|
|
||||||
# Returns the type that's a lower bound of materializing the given (gradual) type.
|
|
||||||
def bottom_materialization(type: Any) -> Any: ...
|
|
||||||
|
|
||||||
# Returns a tuple of all members of the given object, similar to `dir(obj)` and
|
# Returns a tuple of all members of the given object, similar to `dir(obj)` and
|
||||||
# `inspect.getmembers(obj)`, with at least the following differences:
|
# `inspect.getmembers(obj)`, with at least the following differences:
|
||||||
#
|
#
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue