From be27ae98e76825796cbf02a4ec378b72da9c71b5 Mon Sep 17 00:00:00 2001 From: Weijian He <230282609+Madin-H23@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:47:55 +0800 Subject: [PATCH 1/2] Fix crash on union replacement when expanding a variadic tuple unpack Expanding *Ts with a union replacement (e.g. tuple[*tuple[Any, ...]] | Any inferred from a conditional expression used as a type argument) raised RuntimeError from expand_unpack, since unions were not handled there. Carry the union over into the expansion instead, same as the existing Any/Never fallback above. (GH#22108) --- mypy/expandtype.py | 4 +++- mypy/test/testtypes.py | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index fd507216a6be9..af436c3b465f4 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -392,9 +392,11 @@ def expand_unpack(self, t: UnpackType) -> list[Type]: or isinstance(repl, TypeVarTupleType) ): return [UnpackType(typ=repl)] - elif isinstance(repl, (AnyType, UninhabitedType)): + elif isinstance(repl, (AnyType, UninhabitedType, UnionType)): # Replace *Ts = Any with *Ts = *tuple[Any, ...] and same for Never. # These types may appear here as a result of user error or failed inference. + # Unions may be inferred from e.g. conditional expressions used as type + # arguments (GH#22108) — carry them over instead of crashing. return [UnpackType(t.type.tuple_fallback.copy_modified(args=[repl]))] else: raise RuntimeError(f"Invalid type replacement to expand: {repl}") diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index b287e82b3d4af..dc667787c583b 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -297,6 +297,15 @@ def test_expand_naked_type_var(self) -> None: self.assert_expand(self.fx.t, [(self.fx.t.id, self.fx.a)], self.fx.a) self.assert_expand(self.fx.t, [(self.fx.s.id, self.fx.a)], self.fx.t) + def test_expand_unpack_union_replacement(self) -> None: + # GH#22108: expanding *Ts with a union replacement (e.g. inferred from a + # conditional expression) must not crash expand_unpack — the union is + # carried over into the expansion, same as the Any/Never replacements. + union_repl = UnionType([self.tuple(UnpackType(self.tuple(self.fx.anyt))), self.fx.anyt]) + orig = self.tuple(UnpackType(self.fx.ts)) + exp = mypy.expandtype.expand_type(orig, {self.fx.ts.id: union_repl}) + self.assertIn("Any", str(exp)) + def test_expand_basic_generic_types(self) -> None: self.assert_expand(self.fx.gt, [(self.fx.t.id, self.fx.a)], self.fx.ga) From 8aacec2f1741fe904fc1ffb7213df79246ef72eb Mon Sep 17 00:00:00 2001 From: H23 Date: Mon, 5 Oct 2026 16:21:22 +0800 Subject: [PATCH 2/2] Trigger CI re-run: previous run lost runner communication (infra failure)