Skip to content

Commit da1853f

Browse files
sobolevnikonst
andauthored
Correctly narrow types for tuple[type[X], ...] (#15691)
`flatten_types` forgot about the second way we represent `tuple` inside. Closes #15443 --------- Co-authored-by: Ilya Priven <[email protected]>
1 parent a8467c4 commit da1853f

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

mypy/checker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7146,6 +7146,8 @@ def flatten_types(t: Type) -> list[Type]:
71467146
t = get_proper_type(t)
71477147
if isinstance(t, TupleType):
71487148
return [b for a in t.items for b in flatten_types(a)]
7149+
elif is_named_instance(t, "builtins.tuple"):
7150+
return [t.args[0]]
71497151
else:
71507152
return [t]
71517153

test-data/unit/check-narrowing.test

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,3 +1261,50 @@ def g() -> None:
12611261
def foo(): ...
12621262
foo()
12631263
[builtins fixtures/dict.pyi]
1264+
1265+
1266+
[case testNarrowingWithTupleOfTypes]
1267+
from typing import Tuple, Type
1268+
1269+
class Base: ...
1270+
1271+
class Impl1(Base): ...
1272+
class Impl2(Base): ...
1273+
1274+
impls: Tuple[Type[Base], ...] = (Impl1, Impl2)
1275+
some: object
1276+
1277+
if isinstance(some, impls):
1278+
reveal_type(some) # N: Revealed type is "__main__.Base"
1279+
else:
1280+
reveal_type(some) # N: Revealed type is "builtins.object"
1281+
1282+
raw: Tuple[type, ...]
1283+
if isinstance(some, raw):
1284+
reveal_type(some) # N: Revealed type is "builtins.object"
1285+
else:
1286+
reveal_type(some) # N: Revealed type is "builtins.object"
1287+
[builtins fixtures/dict.pyi]
1288+
1289+
1290+
[case testNarrowingWithTupleOfTypesPy310Plus]
1291+
# flags: --python-version 3.10
1292+
class Base: ...
1293+
1294+
class Impl1(Base): ...
1295+
class Impl2(Base): ...
1296+
1297+
some: int | Base
1298+
1299+
impls: tuple[type[Base], ...] = (Impl1, Impl2)
1300+
if isinstance(some, impls):
1301+
reveal_type(some) # N: Revealed type is "__main__.Base"
1302+
else:
1303+
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"
1304+
1305+
raw: tuple[type, ...]
1306+
if isinstance(some, raw):
1307+
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"
1308+
else:
1309+
reveal_type(some) # N: Revealed type is "Union[builtins.int, __main__.Base]"
1310+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)