Skip to content

Commit

Permalink
Allow unpacking from TypeVars with iterable bounds (python#13425)
Browse files Browse the repository at this point in the history
* Allow unpacking from TypeVars by resolving bounds

TypeVars aren't iterable, but their bounds might be!
Resolve a TypeVar to its bounds before trying to decide how to unpack
one of its instances.

Fixes python#13402.
  • Loading branch information
tdsmith authored and hauntsaninja committed Sep 10, 2022
1 parent e43dbb9 commit 64d3d04
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 0 deletions.
3 changes: 3 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3173,6 +3173,9 @@ def check_multi_assignment(
# TODO: maybe elsewhere; redundant.
rvalue_type = get_proper_type(rv_type or self.expr_checker.accept(rvalue))

if isinstance(rvalue_type, TypeVarType):
rvalue_type = get_proper_type(rvalue_type.upper_bound)

if isinstance(rvalue_type, UnionType):
# If this is an Optional type in non-strict Optional code, unwrap it.
relevant_items = rvalue_type.relevant_items()
Expand Down
10 changes: 10 additions & 0 deletions test-data/unit/check-bound.test
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,13 @@ if int():
b = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
twice(a) # E: Value of type variable "T" of "twice" cannot be "int"
[builtins fixtures/args.pyi]


[case testIterableBoundUnpacking]
from typing import Tuple, TypeVar
TupleT = TypeVar("TupleT", bound=Tuple[int, ...])
def f(t: TupleT) -> None:
a, *b = t
reveal_type(a) # N: Revealed type is "builtins.int"
reveal_type(b) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/tuple.pyi]
6 changes: 6 additions & 0 deletions test-data/unit/check-typevar-unbound.test
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,9 @@ def h(a: List[Union[Callable[..., T]]]) -> T:
def j(a: List[Union[Callable[..., Tuple[T, T]], int]]) -> T:
...
[builtins fixtures/tuple.pyi]

[case testUnboundedTypevarUnpacking]
from typing import TypeVar
T = TypeVar("T")
def f(t: T) -> None:
a, *b = t # E: "object" object is not iterable

0 comments on commit 64d3d04

Please sign in to comment.