Skip to content

Commit

Permalink
Correctly narrow types for tuple[type[X], ...] (#15691)
Browse files Browse the repository at this point in the history
`flatten_types` forgot about the second way we represent `tuple` inside.

Closes #15443

---------

Co-authored-by: Ilya Priven <[email protected]>
  • Loading branch information
sobolevn and ikonst authored Jul 29, 2023
1 parent a8467c4 commit da1853f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
2 changes: 2 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7146,6 +7146,8 @@ def flatten_types(t: Type) -> list[Type]:
t = get_proper_type(t)
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]

Expand Down
47 changes: 47 additions & 0 deletions test-data/unit/check-narrowing.test
Original file line number Diff line number Diff line change
Expand Up @@ -1261,3 +1261,50 @@ def g() -> None:
def foo(): ...
foo()
[builtins fixtures/dict.pyi]


[case testNarrowingWithTupleOfTypes]
from typing import Tuple, Type

class Base: ...

class Impl1(Base): ...
class Impl2(Base): ...

impls: Tuple[Type[Base], ...] = (Impl1, Impl2)
some: object

if isinstance(some, impls):
reveal_type(some) # N: Revealed type is "__main__.Base"
else:
reveal_type(some) # N: Revealed type is "builtins.object"

raw: Tuple[type, ...]
if isinstance(some, raw):
reveal_type(some) # N: Revealed type is "builtins.object"
else:
reveal_type(some) # N: Revealed type is "builtins.object"
[builtins fixtures/dict.pyi]


[case testNarrowingWithTupleOfTypesPy310Plus]
# flags: --python-version 3.10
class Base: ...

class Impl1(Base): ...
class Impl2(Base): ...

some: int | Base

impls: tuple[type[Base], ...] = (Impl1, Impl2)
if isinstance(some, impls):
reveal_type(some) # N: Revealed type is "__main__.Base"
else:
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"

raw: tuple[type, ...]
if isinstance(some, raw):
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"
else:
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"
[builtins fixtures/dict.pyi]

0 comments on commit da1853f

Please sign in to comment.