mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-21 15:52:34 +00:00
[ty] Use separate Rust types for bound and unbound type variables (#19796)
This PR creates separate Rust types for bound and unbound type variables, as proposed in https://github.com/astral-sh/ty/issues/926. Closes https://github.com/astral-sh/ty/issues/926 --------- Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
parent
f3f4db7104
commit
dc84645c36
23 changed files with 846 additions and 560 deletions
|
@ -102,7 +102,7 @@ def silence[T: type[BaseException]](
|
|||
try:
|
||||
func()
|
||||
except exception_type as e:
|
||||
reveal_type(e) # revealed: T'instance
|
||||
reveal_type(e) # revealed: T'instance@silence
|
||||
|
||||
def silence2[T: (
|
||||
type[ValueError],
|
||||
|
@ -111,7 +111,7 @@ def silence2[T: (
|
|||
try:
|
||||
func()
|
||||
except exception_type as e:
|
||||
reveal_type(e) # revealed: T'instance
|
||||
reveal_type(e) # revealed: T'instance@silence2
|
||||
```
|
||||
|
||||
## Invalid exception handlers
|
||||
|
|
|
@ -432,3 +432,26 @@ def NamedTemporaryFile(suffix: T | None, prefix: T | None) -> None:
|
|||
def f(x: str):
|
||||
NamedTemporaryFile(prefix=x, suffix=".tar.gz") # Fine
|
||||
```
|
||||
|
||||
## Nested functions see typevars bound in outer function
|
||||
|
||||
```py
|
||||
from typing import TypeVar, overload
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
def outer(t: T) -> None:
|
||||
def inner(t: T) -> None: ...
|
||||
|
||||
inner(t)
|
||||
|
||||
@overload
|
||||
def overloaded_outer() -> None: ...
|
||||
@overload
|
||||
def overloaded_outer(t: T) -> None: ...
|
||||
def overloaded_outer(t: T | None = None) -> None:
|
||||
def inner(t: T) -> None: ...
|
||||
|
||||
if t is not None:
|
||||
inner(t)
|
||||
```
|
||||
|
|
|
@ -20,7 +20,7 @@ from typing import TypeVar
|
|||
|
||||
T = TypeVar("T")
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar
|
||||
reveal_type(T) # revealed: typing.TypeVar("T")
|
||||
reveal_type(T.__name__) # revealed: Literal["T"]
|
||||
```
|
||||
|
||||
|
@ -79,6 +79,8 @@ python-version = "3.13"
|
|||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T", default=int)
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", default=int)
|
||||
reveal_type(T.__default__) # revealed: int
|
||||
reveal_type(T.__bound__) # revealed: None
|
||||
reveal_type(T.__constraints__) # revealed: tuple[()]
|
||||
|
@ -113,6 +115,8 @@ class Invalid(Generic[U]): ...
|
|||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T", bound=int)
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", bound=int)
|
||||
reveal_type(T.__bound__) # revealed: int
|
||||
reveal_type(T.__constraints__) # revealed: tuple[()]
|
||||
|
||||
|
@ -126,6 +130,8 @@ reveal_type(S.__bound__) # revealed: None
|
|||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T", int, str)
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", int, str)
|
||||
reveal_type(T.__constraints__) # revealed: tuple[int, str]
|
||||
|
||||
S = TypeVar("S")
|
||||
|
|
|
@ -433,3 +433,24 @@ def f[T: (str, bytes)](suffix: T | None, prefix: T | None):
|
|||
def g(x: str):
|
||||
f(prefix=x, suffix=".tar.gz")
|
||||
```
|
||||
|
||||
## Nested functions see typevars bound in outer function
|
||||
|
||||
```py
|
||||
from typing import overload
|
||||
|
||||
def outer[T](t: T) -> None:
|
||||
def inner[T](t: T) -> None: ...
|
||||
|
||||
inner(t)
|
||||
|
||||
@overload
|
||||
def overloaded_outer() -> None: ...
|
||||
@overload
|
||||
def overloaded_outer[T](t: T) -> None: ...
|
||||
def overloaded_outer[T](t: T | None = None) -> None:
|
||||
def inner(t: T) -> None: ...
|
||||
|
||||
if t is not None:
|
||||
inner(t)
|
||||
```
|
||||
|
|
|
@ -17,7 +17,7 @@ instances of `typing.TypeVar`, just like legacy type variables.
|
|||
```py
|
||||
def f[T]():
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar
|
||||
reveal_type(T) # revealed: typing.TypeVar("T")
|
||||
reveal_type(T.__name__) # revealed: Literal["T"]
|
||||
```
|
||||
|
||||
|
@ -32,6 +32,8 @@ python-version = "3.13"
|
|||
|
||||
```py
|
||||
def f[T = int]():
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", default=int)
|
||||
reveal_type(T.__default__) # revealed: int
|
||||
reveal_type(T.__bound__) # revealed: None
|
||||
reveal_type(T.__constraints__) # revealed: tuple[()]
|
||||
|
@ -63,6 +65,8 @@ class Invalid[S = T]: ...
|
|||
|
||||
```py
|
||||
def f[T: int]():
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", bound=int)
|
||||
reveal_type(T.__bound__) # revealed: int
|
||||
reveal_type(T.__constraints__) # revealed: tuple[()]
|
||||
|
||||
|
@ -74,6 +78,8 @@ def g[S]():
|
|||
|
||||
```py
|
||||
def f[T: (int, str)]():
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar("T", int, str)
|
||||
reveal_type(T.__constraints__) # revealed: tuple[int, str]
|
||||
reveal_type(T.__bound__) # revealed: None
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ static_assert(is_subtype_of(Never, Never))
|
|||
static_assert(not is_subtype_of(int, Never))
|
||||
|
||||
T = TypeVar("T", bound=Never)
|
||||
static_assert(is_subtype_of(T, Never))
|
||||
|
||||
def _(t: T):
|
||||
static_assert(is_subtype_of(T, Never))
|
||||
```
|
||||
|
||||
## `Never` is assignable to every type
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue