Skip to content

Never put None in TupleType items #4051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1769,7 +1769,10 @@ def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type],
lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True)
self.store_type(lvalue, lvalue_type)
elif isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr):
types = [self.check_lvalue(sub_expr)[0] for sub_expr in lvalue.items]
types = [self.check_lvalue(sub_expr)[0] or
# This type will be used as a context for further inference of rvalue,
# we put Uninhabited if there is no information available from lvalue.
UninhabitedType() for sub_expr in lvalue.items]
lvalue_type = TupleType(types, self.named_type('builtins.tuple'))
else:
lvalue_type = self.expr_checker.accept(lvalue)
Expand Down
15 changes: 14 additions & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ def infer_function_type_arguments_using_context(
# Only substitute non-Uninhabited and non-erased types.
new_args = [] # type: List[Optional[Type]]
for arg in args:
if isinstance(arg, UninhabitedType) or has_erased_component(arg):
if has_uninhabited_component(arg) or has_erased_component(arg):
new_args.append(None)
else:
new_args.append(arg)
Expand Down Expand Up @@ -2768,6 +2768,19 @@ def visit_erased_type(self, t: ErasedType) -> bool:
return True


def has_uninhabited_component(t: Optional[Type]) -> bool:
return t is not None and t.accept(HasUninhabitedComponentsQuery())


class HasUninhabitedComponentsQuery(types.TypeQuery[bool]):
"""Visitor for querying whether a type has an UninhabitedType component."""
def __init__(self) -> None:
super().__init__(any)

def visit_uninhabited_type(self, t: UninhabitedType) -> bool:
return True


def overload_arg_similarity(actual: Type, formal: Type) -> int:
"""Return if caller argument (actual) is compatible with overloaded signature arg (formal).

Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-inference.test
Original file line number Diff line number Diff line change
Expand Up @@ -1927,3 +1927,18 @@ x = None
(x, x) = f('')
reveal_type(x) # E: Revealed type is 'builtins.str'
[out]

[case testInferenceNestedTuplesFromGenericIterable]
from typing import Tuple, TypeVar

T = TypeVar('T')

def make_tuple(elem: T) -> Tuple[T]:
return (elem,)

def main() -> None:
((a, b),) = make_tuple((1, 2))
reveal_type(a) # E: Revealed type is 'builtins.int'
reveal_type(b) # E: Revealed type is 'builtins.int'
[builtins fixtures/tuple.pyi]
[out]
15 changes: 15 additions & 0 deletions test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -1402,3 +1402,18 @@ o: object = p
it2: Iterable[int] = p
[out]
_testCanConvertTypedDictToAnySuperclassOfMapping.py:11: error: Incompatible types in assignment (expression has type "Point", variable has type "Iterable[int]")

[case testAsyncioGatherPreciseType]
import asyncio
from typing import Tuple

async def get_location(arg: str) -> Tuple[str, str]:
return arg, arg

async def main() -> None:
((a_x, a_y),) = await asyncio.gather(get_location('start'))
reveal_type(a_x)
reveal_type(a_y)
[out]
_testAsyncioGatherPreciseType.py:9: error: Revealed type is 'builtins.str'
_testAsyncioGatherPreciseType.py:10: error: Revealed type is 'builtins.str'