From f0399966143e7f2d5864362305b1dcb47f24b276 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 28 Jan 2026 22:59:04 -0800 Subject: [PATCH] Fix isinstance with unions of tuples --- mypy/checker.py | 5 +++-- test-data/unit/check-isinstance.test | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 69551d341834..90318f2beb2a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -8643,12 +8643,13 @@ def flatten(t: Expression) -> list[Expression]: def flatten_types(t: Type) -> list[Type]: """Flatten a nested sequence of tuples into one list of nodes.""" t = get_proper_type(t) + if isinstance(t, UnionType): + return [b for a in t.items for b in flatten_types(a)] if isinstance(t, TupleType): return [b for a in t.items for b in flatten_types(a)] elif is_named_instance(t, "builtins.tuple"): return [t.args[0]] - else: - return [t] + return [t] def expand_func(defn: FuncItem, map: dict[TypeVarId, Type]) -> FuncItem: diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 5db71b8fa430..f27d90577976 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -2938,3 +2938,26 @@ def foo(x: object, t: type[Any]): if isinstance(x, t): reveal_type(x) # N: Revealed type is "Any" [builtins fixtures/isinstance.pyi] + +[case testIsInstanceUnionOfTuples] +# flags: --strict-equality --warn-unreachable +from __future__ import annotations +from typing import TypeVar, Iterator + +T1 = TypeVar("T1") +T2 = TypeVar("T2") +T3 = TypeVar("T3") + +def extract( + values: object, + ts: ( + tuple[type[T1]] + | tuple[type[T1], type[T2]] + | tuple[type[T1], type[T2], type[T3]] + ) +) -> Iterator[T1 | T2 | T3]: + if isinstance(values, ts): + reveal_type(values) # N: Revealed type is "T1`-1 | T2`-2 | T3`-3" + yield values + raise +[builtins fixtures/primitives.pyi]