Skip to content

Commit 5c354c4

Browse files
ilevkivskyiJukkaL
authored andcommitted
Fix missing meet case exposed by len narrowing (#16470)
Fixes #16468 The fix is straightforward. Btw when fixing this I noticed that we disregard type arguments when narrowing, for example: ```python x: Sequence[int] if isinstance(x, tuple): reveal_type(x) # tuple[Any, ...], but should be `tuple[int, ...]` ``` I guess fixing this may be tricky, and it is quite old behavior.
1 parent 88791ca commit 5c354c4

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

mypy/meet.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from mypy.typeops import is_recursive_pair, make_simplified_union, tuple_fallback
1717
from mypy.types import (
1818
MYPYC_NATIVE_INT_NAMES,
19+
TUPLE_LIKE_INSTANCE_NAMES,
1920
AnyType,
2021
CallableType,
2122
DeletedType,
@@ -936,7 +937,7 @@ def visit_tuple_type(self, t: TupleType) -> ProperType:
936937
return TupleType(items, tuple_fallback(t))
937938
elif isinstance(self.s, Instance):
938939
# meet(Tuple[t1, t2, <...>], Tuple[s, ...]) == Tuple[meet(t1, s), meet(t2, s), <...>].
939-
if self.s.type.fullname == "builtins.tuple" and self.s.args:
940+
if self.s.type.fullname in TUPLE_LIKE_INSTANCE_NAMES and self.s.args:
940941
return t.copy_modified(items=[meet_types(it, self.s.args[0]) for it in t.items])
941942
elif is_proper_subtype(t, self.s):
942943
# A named tuple that inherits from a normal class

test-data/unit/check-narrowing.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,3 +1910,16 @@ if len(x) == a:
19101910
else:
19111911
reveal_type(x) # N: Revealed type is "Union[Tuple[builtins.int, builtins.int], Tuple[builtins.int, builtins.int, builtins.int]]"
19121912
[builtins fixtures/len.pyi]
1913+
1914+
[case testNarrowingLenUnionWithUnreachable]
1915+
from typing import Union, Sequence
1916+
1917+
def f(x: Union[int, Sequence[int]]) -> None:
1918+
if (
1919+
isinstance(x, tuple)
1920+
and len(x) == 2
1921+
and isinstance(x[0], int)
1922+
and isinstance(x[1], int)
1923+
):
1924+
reveal_type(x) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
1925+
[builtins fixtures/len.pyi]

test-data/unit/fixtures/len.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class object:
1010
class type:
1111
def __init__(self, x) -> None: pass
1212

13-
class tuple(Generic[T]):
13+
class tuple(Sequence[T]):
1414
def __len__(self) -> int: pass
1515

1616
class list(Sequence[T]): pass

0 commit comments

Comments
 (0)