mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-21 07:41:53 +00:00
[ty] impl VarianceInferable
for KnownInstanceType
(#20924)
## Summary Derived from #20900 Implement `VarianceInferable` for `KnownInstanceType` (especially for `KnownInstanceType::TypeAliasType`). The variance of a type alias matches its value type. In normal usage, type aliases are expanded to value types, so the variance of a type alias can be obtained without implementing this. However, for example, if we want to display the variance when hovering over a type alias, we need to be able to obtain the variance of the type alias itself (cf. #20900). ## Test Plan I couldn't come up with a way to test this in mdtest, so I'm testing it in a test submodule at the end of `types.rs`. I also added a test to `mdtest/generics/pep695/variance.md`, but it passes without the changes in this PR.
This commit is contained in:
parent
6e7ff07065
commit
e4384fc212
2 changed files with 183 additions and 9 deletions
|
@ -790,6 +790,65 @@ static_assert(not is_assignable_to(C[B], C[A]))
|
|||
static_assert(not is_assignable_to(C[A], C[B]))
|
||||
```
|
||||
|
||||
## Type aliases
|
||||
|
||||
The variance of the type alias matches the variance of the value type (RHS type).
|
||||
|
||||
```py
|
||||
from ty_extensions import static_assert, is_subtype_of
|
||||
from typing import Literal
|
||||
|
||||
class Covariant[T]:
|
||||
def get(self) -> T:
|
||||
raise ValueError
|
||||
|
||||
type CovariantLiteral1 = Covariant[Literal[1]]
|
||||
type CovariantInt = Covariant[int]
|
||||
type MyCovariant[T] = Covariant[T]
|
||||
|
||||
static_assert(is_subtype_of(CovariantLiteral1, CovariantInt))
|
||||
static_assert(is_subtype_of(MyCovariant[Literal[1]], MyCovariant[int]))
|
||||
|
||||
class Contravariant[T]:
|
||||
def set(self, value: T):
|
||||
pass
|
||||
|
||||
type ContravariantLiteral1 = Contravariant[Literal[1]]
|
||||
type ContravariantInt = Contravariant[int]
|
||||
type MyContravariant[T] = Contravariant[T]
|
||||
|
||||
static_assert(is_subtype_of(ContravariantInt, ContravariantLiteral1))
|
||||
static_assert(is_subtype_of(MyContravariant[int], MyContravariant[Literal[1]]))
|
||||
|
||||
class Invariant[T]:
|
||||
def get(self) -> T:
|
||||
raise ValueError
|
||||
|
||||
def set(self, value: T):
|
||||
pass
|
||||
|
||||
type InvariantLiteral1 = Invariant[Literal[1]]
|
||||
type InvariantInt = Invariant[int]
|
||||
type MyInvariant[T] = Invariant[T]
|
||||
|
||||
static_assert(not is_subtype_of(InvariantInt, InvariantLiteral1))
|
||||
static_assert(not is_subtype_of(InvariantLiteral1, InvariantInt))
|
||||
static_assert(not is_subtype_of(MyInvariant[Literal[1]], MyInvariant[int]))
|
||||
static_assert(not is_subtype_of(MyInvariant[int], MyInvariant[Literal[1]]))
|
||||
|
||||
class Bivariant[T]:
|
||||
pass
|
||||
|
||||
type BivariantLiteral1 = Bivariant[Literal[1]]
|
||||
type BivariantInt = Bivariant[int]
|
||||
type MyBivariant[T] = Bivariant[T]
|
||||
|
||||
static_assert(is_subtype_of(BivariantInt, BivariantLiteral1))
|
||||
static_assert(is_subtype_of(BivariantLiteral1, BivariantInt))
|
||||
static_assert(is_subtype_of(MyBivariant[Literal[1]], MyBivariant[int]))
|
||||
static_assert(is_subtype_of(MyBivariant[int], MyBivariant[Literal[1]]))
|
||||
```
|
||||
|
||||
## Inheriting from generic classes with inferred variance
|
||||
|
||||
When inheriting from a generic class with our type variable substituted in, we count its occurrences
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue