diff --git a/mypy/checker.py b/mypy/checker.py index 38301f89c815..038cec0fd349 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3168,6 +3168,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() diff --git a/test-data/unit/check-bound.test b/test-data/unit/check-bound.test index bf13ef874579..eb97bde32e1f 100644 --- a/test-data/unit/check-bound.test +++ b/test-data/unit/check-bound.test @@ -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] diff --git a/test-data/unit/check-typevar-unbound.test b/test-data/unit/check-typevar-unbound.test index a233a9c7af13..8761cd94027e 100644 --- a/test-data/unit/check-typevar-unbound.test +++ b/test-data/unit/check-typevar-unbound.test @@ -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