[ty] Track when type variables are inferable or not (#19786)
`Type::TypeVar` now distinguishes whether the typevar in question is
inferable or not.
A typevar is _not inferable_ inside the body of the generic class or
function that binds it:
```py
def f[T](t: T) -> T:
return t
```
The infered type of `t` in the function body is `TypeVar(T,
NotInferable)`. This represents how e.g. assignability checks need to be
valid for all possible specializations of the typevar. Most of the
existing assignability/etc logic only applies to non-inferable typevars.
Outside of the function body, the typevar is _inferable_:
```py
f(4)
```
Here, the parameter type of `f` is `TypeVar(T, Inferable)`. This
represents how e.g. assignability doesn't need to hold for _all_
specializations; instead, we need to find the constraints under which
this specific assignability check holds.
This is in support of starting to perform specialization inference _as
part of_ performing the assignability check at the call site.
In the [[POPL2015][]] paper, this concept is called _monomorphic_ /
_polymorphic_, but I thought _non-inferable_ / _inferable_ would be
clearer for us.
Depends on #19784
[POPL2015]: https://doi.org/10.1145/2676726.2676991
---------
Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
# Self
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
`Self` is treated as if it were a `TypeVar` bound to the class it's being used on.
|
||||
|
||||
`typing.Self` is only available in Python 3.11 and later.
|
||||
|
||||
## Methods
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import Self
|
||||
|
||||
@@ -74,11 +74,6 @@ reveal_type(C().method()) # revealed: C
|
||||
|
||||
## Class Methods
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import Self, TypeVar
|
||||
|
||||
@@ -101,11 +96,6 @@ reveal_type(Shape.bar()) # revealed: Unknown
|
||||
|
||||
## Attributes
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
TODO: The use of `Self` to annotate the `next_node` attribute should be
|
||||
[modeled as a property][self attribute], using `Self` in its parameter and return type.
|
||||
|
||||
@@ -127,11 +117,6 @@ reveal_type(LinkedList().next()) # revealed: LinkedList
|
||||
|
||||
## Generic Classes
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import Self, Generic, TypeVar
|
||||
|
||||
@@ -153,11 +138,6 @@ TODO: <https://typing.python.org/en/latest/spec/generics.html#use-in-protocols>
|
||||
|
||||
## Annotations
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import Self
|
||||
|
||||
@@ -171,11 +151,6 @@ class Shape:
|
||||
|
||||
`Self` cannot be used in the signature of a function or variable.
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import Self, Generic, TypeVar
|
||||
|
||||
@@ -218,4 +193,33 @@ class MyMetaclass(type):
|
||||
return super().__new__(cls)
|
||||
```
|
||||
|
||||
## Binding a method fixes `Self`
|
||||
|
||||
When a method is bound, any instances of `Self` in its signature are "fixed", since we now know the
|
||||
specific type of the bound parameter.
|
||||
|
||||
```py
|
||||
from typing import Self
|
||||
|
||||
class C:
|
||||
def instance_method(self, other: Self) -> Self:
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def class_method(cls) -> Self:
|
||||
return cls()
|
||||
|
||||
# revealed: bound method C.instance_method(other: C) -> C
|
||||
reveal_type(C().instance_method)
|
||||
# revealed: bound method <class 'C'>.class_method() -> C
|
||||
reveal_type(C.class_method)
|
||||
|
||||
class D(C): ...
|
||||
|
||||
# revealed: bound method D.instance_method(other: D) -> D
|
||||
reveal_type(D().instance_method)
|
||||
# revealed: bound method <class 'D'>.class_method() -> D
|
||||
reveal_type(D.class_method)
|
||||
```
|
||||
|
||||
[self attribute]: https://typing.python.org/en/latest/spec/generics.html#use-in-attribute-annotations
|
||||
|
||||
Reference in New Issue
Block a user