Skip to content

Commit

Permalink
[0.980 backport] Allow unpacking from TypeVars with iterable bounds (#…
Browse files Browse the repository at this point in the history
…13425) (#13644)

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 #13402

Co-authored-by: Tim D. Smith <github@tim-smith.us>
  • Loading branch information
hauntsaninja and tdsmith committed Sep 12, 2022
1 parent e43dbb9 commit 70bc348
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
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
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
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 70bc348

Please sign in to comment.