crates/ty_python_semantic/resources/mdtest/assignment/annotations.md
x = 1
x: int
y = x
reveal_type(y) # revealed: Literal[1]
x: int = "foo" # error: [invalid-assignment] "Object of type `Literal["foo"]` is not assignable to `int`"
from numbers import Number
# snapshot: invalid-assignment
a: Number = 1
error[invalid-assignment]: Object of type `Literal[1]` is not assignable to `Number`
--> src/mdtest_snippet.py:4:4
|
4 | a: Number = 1
| ------ ^ Incompatible value of type `Literal[1]`
| |
| Declared type
|
info: Types from the `numbers` module aren't supported for static type checking
help: Consider using a protocol instead, such as `typing.SupportsFloat`
x: int
x = "foo" # error: [invalid-assignment] "Object of type `Literal["foo"]` is not assignable to `int`"
[environment]
python-version = "3.12"
module.py:
from typing_extensions import Unpack
a: tuple[()] = ()
b: tuple[int] = (42,)
c: tuple[str, int] = ("42", 42)
d: tuple[tuple[str, str], tuple[int, int]] = (("foo", "foo"), (42, 42))
e: tuple[str, ...] = ()
f: tuple[str, *tuple[int, ...], bytes] = ("42", b"42")
g: tuple[str, Unpack[tuple[int, ...]], bytes] = ("42", b"42")
h: tuple[list[int], list[int]] = ([], [])
i: tuple[str | int, str | int] = (42, 42)
j: tuple[str | int] = (42,)
script.py:
from module import a, b, c, d, e, f, g, h, i, j
reveal_type(a) # revealed: tuple[()]
reveal_type(b) # revealed: tuple[int]
reveal_type(c) # revealed: tuple[str, int]
reveal_type(d) # revealed: tuple[tuple[str, str], tuple[int, int]]
reveal_type(e) # revealed: tuple[str, ...]
reveal_type(f) # revealed: tuple[str, *tuple[int, ...], bytes]
reveal_type(g) # revealed: tuple[str, *tuple[int, ...], bytes]
reveal_type(h) # revealed: tuple[list[int], list[int]]
reveal_type(i) # revealed: tuple[str | int, str | int]
reveal_type(j) # revealed: tuple[str | int]
# error: [invalid-assignment] "Object of type `tuple[Literal[1], Literal[2]]` is not assignable to `tuple[()]`"
a: tuple[()] = (1, 2)
# error: [invalid-assignment] "Object of type `tuple[Literal["foo"]]` is not assignable to `tuple[int]`"
b: tuple[int] = ("foo",)
# error: [invalid-assignment]
c: tuple[str | int, str] = ([], "foo")
# error: [invalid-assignment] "Object of type `list[str | int]` is not assignable to `list[str]`"
a: list[str] = [1, 2, 3]
# error: [invalid-assignment] "Object of type `set[int | str]` is not assignable to `set[int]`"
b: set[int] = {1, 2, "3"}
When an annotated assignment has a value whose inferred type is assignable to the declared type, the binding uses the declared type if the declared type is also assignable back to the inferred type. This indicates that we are dealing with difference in precision (graduality) rather than a narrowed static type; in that case we want to prefer the user's annotation.
The actual inferred type of the right-hand side is still used to validate the assignment.
from typing import Any
def returns_list_any() -> list[Any]:
return [1]
def returns_list_int() -> list[int]:
return [1]
def returns_any() -> Any:
return 1
v1: Any = 1
reveal_type(v1) # revealed: Any
v2: int = returns_any()
reveal_type(v2) # revealed: int
v3: list[Any] = returns_list_int()
reveal_type(v3) # revealed: list[Any]
v4: list[int] = returns_list_any()
reveal_type(v4) # revealed: list[int]
v4: object = returns_list_int()
reveal_type(v4) # revealed: list[int]
# error: [invalid-assignment] "Object of type `list[int]` is not assignable to `list[str]`"
invalid: list[str] = returns_list_int()
def foo(v: str | int | None, w: str | str | None, x: str | str):
reveal_type(v) # revealed: str | int | None
reveal_type(w) # revealed: str | None
reveal_type(x) # revealed: str
import builtins
int = "foo"
a: builtins.int = 42
# error: [invalid-assignment] "Object of type `Literal["bar"]` is not assignable to `int`"
b: builtins.int = "bar"
c: builtins.tuple[builtins.tuple[builtins.int, builtins.int], builtins.int] = ((42, 42), 42)
# error: [invalid-assignment] "Object of type `Literal["foo"]` is not assignable to `tuple[tuple[int, int], int]`"
c: builtins.tuple[builtins.tuple[builtins.int, builtins.int], builtins.int] = "foo"
from __future__ import annotations
x: Foo
class Foo: ...
x = Foo()
reveal_type(x) # revealed: Foo
x: Foo
class Foo: ...
x = Foo()
reveal_type(x) # revealed: Foo
[environment]
python-version = "3.14"
x: Foo
class Foo: ...
x = Foo()
reveal_type(x) # revealed: Foo
x: int = 1
reveal_type(x) # revealed: Literal[1]
Regression test for #1611.
<!-- fmt:off --># error: [invalid-syntax]
# error: [invalid-syntax-in-forward-annotation]
a:'