This commit is contained in:
David Peter 2025-12-16 15:41:29 +01:00 committed by GitHub
commit 1ded830fde
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 82 additions and 1 deletions

View File

@ -11,17 +11,36 @@ valid type for use in a type expression:
```py ```py
MyInt = int MyInt = int
reveal_type(MyInt) # revealed: <class 'int'>
reveal_type(MyInt(1)) # revealed: int
def f(x: MyInt): def f(x: MyInt):
reveal_type(x) # revealed: int reveal_type(x) # revealed: int
f(1) f(1)
``` ```
This also works for generic aliases:
```py
ListOfStr = list[str]
reveal_type(ListOfStr) # revealed: <class 'list[str]'>
reveal_type(ListOfStr(["a", "b"])) # revealed: list[str]
def g(x: ListOfStr):
reveal_type(x) # revealed: list[str]
g(["a", "b"])
```
## None ## None
```py ```py
MyNone = None MyNone = None
reveal_type(MyNone) # revealed: None
def g(x: MyNone): def g(x: MyNone):
reveal_type(x) # revealed: None reveal_type(x) # revealed: None
@ -211,6 +230,13 @@ def _(int_or_int: IntOrInt, list_of_int_or_list_of_int: ListOfIntOrListOfInt):
reveal_type(list_of_int_or_list_of_int) # revealed: list[int] reveal_type(list_of_int_or_list_of_int) # revealed: list[int]
``` ```
`types.UnionType` instances can not be instantiated:
```py
# error: [call-non-callable] "Object of type `UnionType` is not callable"
IntOrStr()
```
`NoneType` has no special or-operator behavior, so this is an error: `NoneType` has no special or-operator behavior, so this is an error:
```py ```py
@ -926,7 +952,7 @@ def _(weird: IntLiteral1[int]):
## `Annotated` ## `Annotated`
Basic usage: ### Basic usage
```py ```py
from typing import Annotated from typing import Annotated
@ -952,10 +978,61 @@ class C:
reveal_type(C().old) # revealed: int reveal_type(C().old) # revealed: int
``` ```
### Special members
The `__origin__` attribute on an instance of `Annotated` can be used to access the underlying type.
We currently do not model this precisely:
```py
from typing import Annotated
StrWithMetadata = Annotated[str, "metadata", 1, 2, 3]
reveal_type(StrWithMetadata.__origin__) # revealed: type | TypeAliasType
```
At runtime, the `__metadata__` attribute contains the metadata elements `('metadata', 1, 2, 3)`, but
we do not model the type of this attribute precisely:
```py
reveal_type(StrWithMetadata.__metadata__) # revealed: Any
```
### Attribute access and instantiation
A class can be instantiated through an `Annotated` alias, and attributes can be accessed on the
created instance:
```py
from __future__ import annotations
from typing import Annotated, Union
class Foo:
attribute: int = 1
FooWithMetadata = Annotated[Foo, "metadata"]
c = FooWithMetadata()
reveal_type(c) # revealed: Foo
reveal_type(c.attribute) # revealed: int
```
However, accessing attributes on the alias itself currently yields `Any`, instead of the attribute's
type:
```py
reveal_type(FooWithMetadata.attribute) # revealed: Any
```
### Error cases
If the metadata argument is missing, we emit an error (because this code fails at runtime), but If the metadata argument is missing, we emit an error (because this code fails at runtime), but
still use the first element as the type, when used in annotations: still use the first element as the type, when used in annotations:
```py ```py
from typing import Annotated
# error: [invalid-type-form] "Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)" # error: [invalid-type-form] "Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)"
WronglyAnnotatedInt = Annotated[int] WronglyAnnotatedInt = Annotated[int]

View File

@ -6433,6 +6433,10 @@ impl<'db> Type<'db> {
) )
.into(), .into(),
Type::KnownInstance(KnownInstanceType::Annotated(ty)) => {
ty.inner(db).to_meta_type(db).bindings(db)
}
Type::KnownInstance(known_instance) => { Type::KnownInstance(known_instance) => {
known_instance.instance_fallback(db).bindings(db) known_instance.instance_fallback(db).bindings(db)
} }