mirror of https://github.com/astral-sh/ruff
[ty] Remove `GenericAlias`-related todo type (#21728)
## Summary If you manage to create an `typing.GenericAlias` instance without us knowing how that was created, then we don't know what to do with this in a type annotation. So it's better to be explicit and show an error instead of failing silently with a `@Todo` type. ## Test Plan * New Markdown tests * Zero ecosystem impact
This commit is contained in:
parent
5358ddae88
commit
116fd7c7af
|
|
@ -0,0 +1,34 @@
|
||||||
|
# GenericAlias in type expressions
|
||||||
|
|
||||||
|
We recognize if a `types.GenericAlias` instance is created by specializing a generic class. We don't
|
||||||
|
explicitly mention it in our type display, but `list[int]` in the example below is a `GenericAlias`
|
||||||
|
instance at runtime:
|
||||||
|
|
||||||
|
```py
|
||||||
|
Numbers = list[int]
|
||||||
|
|
||||||
|
# At runtime, `Numbers` is an instance of `types.GenericAlias`. Showing
|
||||||
|
# this as `list[int]` is more helpful, though:
|
||||||
|
reveal_type(Numbers) # revealed: <class 'list[int]'>
|
||||||
|
|
||||||
|
def _(numbers: Numbers) -> None:
|
||||||
|
reveal_type(numbers) # revealed: list[int]
|
||||||
|
```
|
||||||
|
|
||||||
|
It is also valid to create `GenericAlias` instances manually:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from types import GenericAlias
|
||||||
|
|
||||||
|
Strings = GenericAlias(list, (str,))
|
||||||
|
|
||||||
|
reveal_type(Strings) # revealed: GenericAlias
|
||||||
|
```
|
||||||
|
|
||||||
|
However, using such a `GenericAlias` instance in a type expression is currently not supported:
|
||||||
|
|
||||||
|
```py
|
||||||
|
# error: [invalid-type-form] "Variable of type `GenericAlias` is not allowed in a type expression"
|
||||||
|
def _(strings: Strings) -> None:
|
||||||
|
reveal_type(strings) # revealed: Unknown
|
||||||
|
```
|
||||||
|
|
@ -1,24 +1,16 @@
|
||||||
# NewType
|
# NewType
|
||||||
|
|
||||||
## Valid forms
|
## Basic usage
|
||||||
|
|
||||||
|
`NewType` can be used to create distinct types that are based on existing types:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing_extensions import NewType
|
from typing_extensions import NewType
|
||||||
from types import GenericAlias
|
|
||||||
|
|
||||||
X = GenericAlias(type, ())
|
UserId = NewType("UserId", int)
|
||||||
A = NewType("A", int)
|
|
||||||
# TODO: typeshed for `typing.GenericAlias` uses `type` for the first argument. `NewType` should be special-cased
|
|
||||||
# to be compatible with `type`
|
|
||||||
# error: [invalid-argument-type] "Argument to function `__new__` is incorrect: Expected `type`, found `<NewType pseudo-class 'A'>`"
|
|
||||||
B = GenericAlias(A, ())
|
|
||||||
|
|
||||||
def _(
|
def _(user_id: UserId):
|
||||||
a: A,
|
reveal_type(user_id) # revealed: UserId
|
||||||
b: B,
|
|
||||||
):
|
|
||||||
reveal_type(a) # revealed: A
|
|
||||||
reveal_type(b) # revealed: @Todo(Support for `typing.GenericAlias` instances in type expressions)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Subtyping
|
## Subtyping
|
||||||
|
|
|
||||||
|
|
@ -7372,9 +7372,6 @@ impl<'db> Type<'db> {
|
||||||
Some(KnownClass::TypeVarTuple) => Ok(todo_type!(
|
Some(KnownClass::TypeVarTuple) => Ok(todo_type!(
|
||||||
"Support for `typing.TypeVarTuple` instances in type expressions"
|
"Support for `typing.TypeVarTuple` instances in type expressions"
|
||||||
)),
|
)),
|
||||||
Some(KnownClass::GenericAlias) => Ok(todo_type!(
|
|
||||||
"Support for `typing.GenericAlias` instances in type expressions"
|
|
||||||
)),
|
|
||||||
_ => Err(InvalidTypeExpressionError {
|
_ => Err(InvalidTypeExpressionError {
|
||||||
invalid_expressions: smallvec::smallvec_inline![
|
invalid_expressions: smallvec::smallvec_inline![
|
||||||
InvalidTypeExpression::InvalidType(*self, scope_id)
|
InvalidTypeExpression::InvalidType(*self, scope_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue