Skip to content

Commit

Permalink
Fix type inference for tuples in iterable context (#13406)
Browse files Browse the repository at this point in the history
It is a minor change to fix the example in python/typeshed#7904
  • Loading branch information
ilevkivskyi authored Aug 14, 2022
1 parent c8a2289 commit 234b161
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
5 changes: 3 additions & 2 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
)
from mypy.types import (
LITERAL_TYPE_NAMES,
TUPLE_LIKE_INSTANCE_NAMES,
AnyType,
CallableType,
DeletedType,
Expand Down Expand Up @@ -3848,7 +3849,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
t
for t in get_proper_types(type_context.items)
if (isinstance(t, TupleType) and len(t.items) == len(e.items))
or is_named_instance(t, "builtins.tuple")
or is_named_instance(t, TUPLE_LIKE_INSTANCE_NAMES)
]
if len(tuples_in_context) == 1:
type_context = tuples_in_context[0]
Expand All @@ -3859,7 +3860,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:

if isinstance(type_context, TupleType):
type_context_items = type_context.items
elif type_context and is_named_instance(type_context, "builtins.tuple"):
elif type_context and is_named_instance(type_context, TUPLE_LIKE_INSTANCE_NAMES):
assert isinstance(type_context, Instance)
if type_context.args:
type_context_items = [type_context.args[0]] * len(e.items)
Expand Down
16 changes: 16 additions & 0 deletions test-data/unit/check-inference.test
Original file line number Diff line number Diff line change
Expand Up @@ -3248,3 +3248,19 @@ reveal_type(x) # N: Revealed type is "builtins.bytes"
if x:
reveal_type(x) # N: Revealed type is "builtins.bytes"
[builtins fixtures/dict.pyi]

[case testTupleContextFromIterable]
from typing import TypeVar, Iterable, List, Union

T = TypeVar("T")

def foo(x: List[T]) -> List[T]: ...
x: Iterable[List[Union[int, str]]] = (foo([1]), foo(["a"]))
[builtins fixtures/tuple.pyi]

[case testTupleContextFromIterable2]
from typing import Dict, Iterable, Tuple, Union

def foo(x: Union[Tuple[str, Dict[str, int], str], Iterable[object]]) -> None: ...
foo(("a", {"a": "b"}, "b"))
[builtins fixtures/dict.pyi]
18 changes: 18 additions & 0 deletions test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -1612,3 +1612,21 @@ class Foo(Enum):
_testEnumValueWithPlaceholderNodeType.py:5: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
_testEnumValueWithPlaceholderNodeType.py:6: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
_testEnumValueWithPlaceholderNodeType.py:6: error: Name "Missing" is not defined

[case testTypeshedRecursiveTypesExample]
# flags: --enable-recursive-aliases
from typing import List, Union

Recursive = Union[str, List["Recursive"]]

def foo(r: Recursive) -> None:
if not isinstance(r, str):
if r:
foo(r[0])
if not isinstance(r, list):
r.casefold()

foo("")
foo(list(""))
foo(list((list(""), "")))
[out]

0 comments on commit 234b161

Please sign in to comment.