mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
[ty] Handle typevars that have other typevars as a default (#17956)
It's possible for a typevar to list another typevar as its default value: ```py class C[T, U = T]: ... ``` When specializing this class, if a type isn't provided for `U`, we would previously use the default as-is, leaving an unspecialized `T` typevar in the specialization. Instead, we want to use what `T` is mapped to as the type of `U`. ```py reveal_type(C()) # revealed: C[Unknown, Unknown] reveal_type(C[int]()) # revealed: C[int, int] reveal_type(C[int, str]()) # revealed: C[int, str] ``` This is especially important for the `slice` built-in type.
This commit is contained in:
parent
f51f1f7153
commit
b705664d49
11 changed files with 226 additions and 102 deletions
|
@ -1945,7 +1945,7 @@ reveal_type(C.a_complex) # revealed: int | float | complex
|
|||
reveal_type(C.a_tuple) # revealed: tuple[int]
|
||||
reveal_type(C.a_range) # revealed: range
|
||||
# TODO: revealed: slice[Any, Literal[1], Any]
|
||||
reveal_type(C.a_slice) # revealed: slice[Any, _StartT_co, _StartT_co | _StopT_co]
|
||||
reveal_type(C.a_slice) # revealed: slice[Any, Any, Any]
|
||||
reveal_type(C.a_type) # revealed: type
|
||||
reveal_type(C.a_none) # revealed: None
|
||||
```
|
||||
|
|
|
@ -86,6 +86,26 @@ S = TypeVar("S")
|
|||
reveal_type(S.__default__) # revealed: NoDefault
|
||||
```
|
||||
|
||||
### Using other typevars as a default
|
||||
|
||||
```py
|
||||
from typing import Generic, TypeVar, Union
|
||||
|
||||
T = TypeVar("T")
|
||||
U = TypeVar("U", default=T)
|
||||
V = TypeVar("V", default=Union[T, U])
|
||||
|
||||
class Valid(Generic[T, U, V]): ...
|
||||
|
||||
reveal_type(Valid()) # revealed: Valid[Unknown, Unknown, Unknown]
|
||||
reveal_type(Valid[int]()) # revealed: Valid[int, int, int]
|
||||
reveal_type(Valid[int, str]()) # revealed: Valid[int, str, int | str]
|
||||
reveal_type(Valid[int, str, None]()) # revealed: Valid[int, str, None]
|
||||
|
||||
# TODO: error, default value for U isn't available in the generic context
|
||||
class Invalid(Generic[U]): ...
|
||||
```
|
||||
|
||||
### Type variables with an upper bound
|
||||
|
||||
```py
|
||||
|
|
|
@ -40,6 +40,25 @@ def g[S]():
|
|||
reveal_type(S.__default__) # revealed: NoDefault
|
||||
```
|
||||
|
||||
### Using other typevars as a default
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.13"
|
||||
```
|
||||
|
||||
```py
|
||||
class Valid[T, U = T, V = T | U]: ...
|
||||
|
||||
reveal_type(Valid()) # revealed: Valid[Unknown, Unknown, Unknown]
|
||||
reveal_type(Valid[int]()) # revealed: Valid[int, int, int]
|
||||
reveal_type(Valid[int, str]()) # revealed: Valid[int, str, int | str]
|
||||
reveal_type(Valid[int, str, None]()) # revealed: Valid[int, str, None]
|
||||
|
||||
# error: [unresolved-reference]
|
||||
class Invalid[S = T]: ...
|
||||
```
|
||||
|
||||
### Type variables with an upper bound
|
||||
|
||||
```py
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue