@@ -498,14 +498,92 @@ f(**m)
498498g(**m) # E: Argument 1 to "g" has incompatible type "**Mapping[str, object]"; expected "int"
499499[builtins fixtures/dict.pyi]
500500
501- [case testTupleExpressionWithUnionStarArgs ]
501+ [case testTupleConversionWithUnionStarArgs ]
502502from typing import Union, List, Set, Tuple, Unpack, TypeVarTuple
503503
504504class A: pass
505505class B: pass
506506class C: pass
507507class D: pass
508508
509+ Ts = TypeVarTuple('Ts')
510+ def as_tuple(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]:
511+ return (*args,)
512+
513+ def test_union_same_size_tuple(
514+ x1: Union[tuple[A, B], tuple[None, None]],
515+ x2: Union[tuple[A, B], tuple[None, Unpack[tuple[None]]]],
516+ x3: Union[tuple[A, B], tuple[None, None, Unpack[tuple[()]]]],
517+ xx: tuple[Union[A, None], Union[B, None]], # reference type
518+ ) -> None:
519+ reveal_type( as_tuple(*x1) ) # N: Revealed type is "tuple[Union[__main__.A, None], Union[__main__.B, None]]"
520+ reveal_type( as_tuple(*x2) ) # N: Revealed type is "tuple[Union[__main__.A, None], Union[__main__.B, None]]"
521+ reveal_type( as_tuple(*x3) ) # N: Revealed type is "tuple[Union[__main__.A, None], Union[__main__.B, None]]"
522+ reveal_type( as_tuple(*xx) ) # N: Revealed type is "tuple[Union[__main__.A, None], Union[__main__.B, None]]"
523+
524+ def test_union_different_size_tuple(
525+ y1: Union[tuple[A, B], tuple[None, None, None]],
526+ y2: Union[tuple[A, B], tuple[None]],
527+ y3: Union[tuple[A, B], tuple[None, None, None, Unpack[tuple[()]]]],
528+ yy: tuple[Union[A, B, None], ...], # reference type
529+ ) -> None:
530+ reveal_type( as_tuple(*y1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, None], ...]"
531+ reveal_type( as_tuple(*y2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, None], ...]"
532+ reveal_type( as_tuple(*y2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, None], ...]"
533+ reveal_type( as_tuple(*yy) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, None], ...]"
534+
535+ def test_union_fixed_size_and_variadic_tuple(
536+ z1: Union[tuple[A, B, C], tuple[None, ...]],
537+ z2: Union[tuple[A, B, C], tuple[None, Unpack[tuple[None, ...]], None]],
538+ zz: tuple[Union[A, B, C, None], ...], # reference type
539+ ) -> None:
540+ reveal_type( as_tuple(*z1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, __main__.C, None], ...]"
541+ reveal_type( as_tuple(*z2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, __main__.C, None], ...]"
542+ reveal_type( as_tuple(*zz) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, __main__.C, None], ...]"
543+
544+ def test_union_variable_size_tuples(
545+ # same + subtype
546+ tt1: Union[Tuple[Union[A, None], ...], Tuple[A, ...]],
547+ ll1: Union[List[Union[A, None]], List[A]],
548+ ss1: Union[Set[Union[A, None]], Set[A]],
549+ # mixed + subtype
550+ tl1: Union[Tuple[Union[A, None], ...], List[A]],
551+ ts1: Union[Tuple[Union[A, None], ...], Set[A]],
552+ ls1: Union[List[Union[A, None]], Set[A]],
553+ # same + not subtype
554+ tt2: Union[Tuple[A, ...], Tuple[B, ...]],
555+ ll2: Union[List[A], List[B]],
556+ ss2: Union[Set[A], Set[B]],
557+ # mixed + not subtype
558+ tl2: Union[Tuple[A, ...], List[B]],
559+ ts2: Union[Tuple[A, ...], Set[B]],
560+ ls2: Union[List[A], Set[B]],
561+ ) -> None:
562+ reveal_type( as_tuple(*tt1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
563+ reveal_type( as_tuple(*ll1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
564+ reveal_type( as_tuple(*ss1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
565+ reveal_type( as_tuple(*tl1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
566+ reveal_type( as_tuple(*ts1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
567+ reveal_type( as_tuple(*ls1) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, None], ...]"
568+ reveal_type( as_tuple(*tt2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
569+ reveal_type( as_tuple(*ll2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
570+ reveal_type( as_tuple(*ss2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
571+ reveal_type( as_tuple(*tl2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
572+ reveal_type( as_tuple(*ts2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
573+ reveal_type( as_tuple(*ls2) ) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B], ...]"
574+
575+ NESTED = Union[str, list[NESTED]]
576+ def test_union_recursive(x: Union[list[Union[NESTED, None]], list[NESTED]]) -> None:
577+ reveal_type( as_tuple(*x) ) # N: Revealed type is "builtins.tuple[Union[builtins.str, builtins.list[Union[builtins.str, builtins.list[...]]], None], ...]"
578+ [builtins fixtures/primitives.pyi]
579+
580+ [case testTupleExpressionWithUnionStarArgs]
581+ from typing import Union, List, Set, Tuple, Unpack
582+
583+ class A: pass
584+ class B: pass
585+ class C: pass
586+ class D: pass
509587
510588def test_union_same_size_tuple(
511589 x1: Union[tuple[A, B], tuple[None, None]],
@@ -576,7 +654,7 @@ def test_union_recursive(x: Union[list[Union[NESTED, None]], list[NESTED]]) -> N
576654
577655
578656[case testListExpressionWithUnionStarArgs]
579- from typing import Union, List, Set, Tuple, Unpack, TypeVarTuple
657+ from typing import Union, List, Set, Tuple, Unpack
580658
581659class A: pass
582660class B: pass
@@ -652,7 +730,7 @@ def test_union_recursive(x: Union[list[Union[NESTED, None]], list[NESTED]]) -> N
652730
653731
654732[case testSetExpressionWithUnionStarArgs]
655- from typing import Union, List, Set, Tuple, Unpack, TypeVarTuple
733+ from typing import Union, List, Set, Tuple, Unpack
656734
657735class A: pass
658736class B: pass
@@ -727,22 +805,48 @@ def test_union_recursive(x: Union[list[Union[NESTED, None]], list[NESTED]]) -> N
727805[builtins fixtures/primitives.pyi]
728806
729807
730- [case testStarArgsWithUnionTypeVarTuple-xfail ]
808+ [case testStarArgsWithPaddedTypeVarTuple ]
731809# https://github.com/python/mypy/issues/19659
732810from typing import Union, TypeVarTuple
733811
734812class A: pass
735813Ts = TypeVarTuple('Ts')
736814
737815def test_union_typevartuple(
738- tt1: Union[tuple[A, *Ts, A], tuple[None, None, None]],
816+ padded_tuple: tuple[A, *Ts, A],
817+ padded_union: Union[tuple[A, *Ts, A], tuple[None, None, None]],
739818) -> None:
740819 # technically, this should be ``typ[A | None | Union[*Ts]]``
741- reveal_type( (*tt1,) ) # N: Revealed type is "builtins.tuple[Any, ...]"
742- reveal_type( [*tt1] ) # N: Revealed type is "builtins.list[Any]"
743- reveal_type( {*tt1} ) # N: Revealed type is "builtins.set[Any]"
820+ reveal_type( (*padded_tuple,) ) # N: Revealed type is "tuple[__main__.A, Unpack[Ts`-1], __main__.A]"
821+ reveal_type( [*padded_tuple] ) # N: Revealed type is "builtins.list[builtins.object]"
822+ reveal_type( {*padded_tuple} ) # N: Revealed type is "builtins.set[builtins.object]"
823+ reveal_type( (*padded_union,) ) # N: Revealed type is "builtins.tuple[builtins.object, ...]"
824+ reveal_type( [*padded_union] ) # N: Revealed type is "builtins.list[builtins.object]"
825+ reveal_type( {*padded_union} ) # N: Revealed type is "builtins.set[builtins.object]"
744826[builtins fixtures/primitives.pyi]
745827
828+ [case testStarArgsWithParamSpec]
829+ # https://github.com/python/mypy/issues/19663
830+ from typing import Union, ParamSpec, Callable
831+
832+ P = ParamSpec('P')
833+
834+ def test_paramspec(
835+ a: A, # E: Name "A" is not defined
836+ dummy: Callable[P, None], # ensure P is bound
837+ /,
838+ *args: P.args,
839+ **kwargs: P.kwargs,
840+ ) -> None:
841+ # technically, this should be ``typ[A | None | Union[*Ts]]``
842+ reveal_type( args ) # N: Revealed type is "P.args`-1"
843+ reveal_type( (*args,) ) # N: Revealed type is "builtins.tuple[P.args`-1, ...]"
844+ reveal_type( [*args] ) # N: Revealed type is "builtins.list[P.args`-1]"
845+ reveal_type( {*args} ) # N: Revealed type is "builtins.set[P.args`-1]"
846+
847+ # test padded tuple expression
848+ reveal_type( (a, *args, a) ) # N: Revealed type is "builtins.tuple[__main__.A, Unpack[builtins.tuple[P.args`-1, ...]], __main__.A]"
849+ [builtins fixtures/primitives.pyi]
746850
747851[case testStarArgsWithUnion]
748852from typing import Union
0 commit comments