mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
[ty] Specialize bound methods and nominal instances (#17865)
Fixes https://github.com/astral-sh/ruff/pull/17832#issuecomment-2851224968. We had a comment that we did not need to apply specializations to generic aliases, or to the bound `self` of a bound method, because they were already specialized. But they might be specialized with a type variable, which _does_ need to be specialized, in the case of a "multi-step" specialization, such as: ```py class LinkedList[T]: ... class C[U]: def method(self) -> LinkedList[U]: return LinkedList[U]() ``` --------- Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
9a6633da0b
commit
47e3aa40b3
6 changed files with 106 additions and 13 deletions
|
@ -145,7 +145,7 @@ def f(x: int) -> int:
|
|||
return x**2
|
||||
|
||||
# TODO: Should be `_lru_cache_wrapper[int]`
|
||||
reveal_type(f) # revealed: _lru_cache_wrapper[_T]
|
||||
reveal_type(f) # revealed: _lru_cache_wrapper[Unknown]
|
||||
|
||||
# TODO: Should be `int`
|
||||
reveal_type(f(1)) # revealed: Unknown
|
||||
|
|
|
@ -361,6 +361,40 @@ c: C[int] = C[int]()
|
|||
reveal_type(c.method("string")) # revealed: Literal["string"]
|
||||
```
|
||||
|
||||
## Specializations propagate
|
||||
|
||||
In a specialized generic alias, the specialization is applied to the attributes and methods of the
|
||||
class.
|
||||
|
||||
```py
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
U = TypeVar("U")
|
||||
|
||||
class LinkedList(Generic[T]): ...
|
||||
|
||||
class C(Generic[T, U]):
|
||||
x: T
|
||||
y: U
|
||||
|
||||
def method1(self) -> T:
|
||||
return self.x
|
||||
|
||||
def method2(self) -> U:
|
||||
return self.y
|
||||
|
||||
def method3(self) -> LinkedList[T]:
|
||||
return LinkedList[T]()
|
||||
|
||||
c = C[int, str]()
|
||||
reveal_type(c.x) # revealed: int
|
||||
reveal_type(c.y) # revealed: str
|
||||
reveal_type(c.method1()) # revealed: int
|
||||
reveal_type(c.method2()) # revealed: str
|
||||
reveal_type(c.method3()) # revealed: LinkedList[int]
|
||||
```
|
||||
|
||||
## Cyclic class definitions
|
||||
|
||||
### F-bounded quantification
|
||||
|
|
|
@ -305,6 +305,35 @@ c: C[int] = C[int]()
|
|||
reveal_type(c.method("string")) # revealed: Literal["string"]
|
||||
```
|
||||
|
||||
## Specializations propagate
|
||||
|
||||
In a specialized generic alias, the specialization is applied to the attributes and methods of the
|
||||
class.
|
||||
|
||||
```py
|
||||
class LinkedList[T]: ...
|
||||
|
||||
class C[T, U]:
|
||||
x: T
|
||||
y: U
|
||||
|
||||
def method1(self) -> T:
|
||||
return self.x
|
||||
|
||||
def method2(self) -> U:
|
||||
return self.y
|
||||
|
||||
def method3(self) -> LinkedList[T]:
|
||||
return LinkedList[T]()
|
||||
|
||||
c = C[int, str]()
|
||||
reveal_type(c.x) # revealed: int
|
||||
reveal_type(c.y) # revealed: str
|
||||
reveal_type(c.method1()) # revealed: int
|
||||
reveal_type(c.method2()) # revealed: str
|
||||
reveal_type(c.method3()) # revealed: LinkedList[int]
|
||||
```
|
||||
|
||||
## Cyclic class definitions
|
||||
|
||||
### F-bounded quantification
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue