diff --git a/mypy/argmap.py b/mypy/argmap.py index 28fad1f093dd..363d76cb7322 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -16,6 +16,7 @@ TypedDictType, TypeOfAny, TypeVarTupleType, + UnionType, UnpackType, get_proper_type, ) @@ -211,6 +212,18 @@ def expand_actual_type( # Just return `Any`, other parts of code would raise # a different error for improper use. return AnyType(TypeOfAny.from_error) + elif isinstance(actual_type, UnionType): + item_types = [ + self.expand_actual_type( + item, + actual_kind=actual_kind, + formal_name=formal_name, + formal_kind=formal_kind, + allow_unpack=allow_unpack, + ) + for item in actual_type.items + ] + return UnionType.make_union(item_types) elif isinstance(actual_type, TupleType): # Get the next tuple item of a tuple *arg. if self.tuple_index >= len(actual_type.items): diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 7fa34a398ea0..683d9c90ee22 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3708,3 +3708,20 @@ foo(*args) # E: Argument 1 to "foo" has incompatible type "*list[object]"; expe kwargs: dict[str, object] foo(**kwargs) # E: Argument 1 to "foo" has incompatible type "**dict[str, object]"; expected "P" [builtins fixtures/dict.pyi] + +[case testUnpackUnionStarArgs] +from __future__ import annotations +from typing import TypeVar +T = TypeVar("T") + +def f(*args: T) -> T: ... + +def star_union_list(x: list[str | None] | list[str]): + reveal_type([*x]) # N: Revealed type is "builtins.list[Union[builtins.str, None]]" + reveal_type(f(*x)) # N: Revealed type is "Union[builtins.str, None]" + +def star_union_list_tuple(x: list[str | None] | tuple[int, int]): + reveal_type([*x]) # N: Revealed type is "builtins.list[Union[builtins.str, None, builtins.int]]" + reveal_type(f(*x)) # N: Revealed type is "Union[builtins.str, None, builtins.int]" + +[builtins fixtures/tuple.pyi]