Skip to content

Commit

Permalink
Fix type inference with iterable initializer
Browse files Browse the repository at this point in the history
  • Loading branch information
JukkaL committed Aug 18, 2013
1 parent affc8e0 commit 6ecbd1f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
23 changes: 14 additions & 9 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,12 @@ def infer_variable_type(self, names: List[Var], lvalues: List[Node],
self.msg.incompatible_value_count_in_assignment(
len(names), len(init_type.items), context)
elif (isinstance(init_type, Instance) and
cast(Instance, init_type).type.fullname() ==
'builtins.list'):
# Initializer with an array type.
item_type = cast(Instance, init_type).args[0]
is_subtype(init_type,
self.named_generic_type('builtins.Iterable',
[AnyType()]))):
# Initializer with an iterable type.
item_type = self.iterable_item_type(cast(Instance,
init_type))
for i in range(len(names)):
self.set_inferred_type(names[i], lvalues[i], item_type)
elif isinstance(init_type, AnyType):
Expand Down Expand Up @@ -614,18 +616,15 @@ def check_multi_assignment(self, lvalue_types: List[Type],
[AnyType()])) and
isinstance(rvalue_type, Instance)):
# Rvalue is iterable.
iterable = map_instance_to_supertype(
cast(Instance, rvalue_type),
self.lookup_typeinfo('builtins.Iterable'))
item_type = iterable.args[0]
item_type = self.iterable_item_type(cast(Instance, rvalue_type))
for k in range(len(lvalue_types)):
self.check_single_assignment(lvalue_types[k],
index_lvalues[k],
self.temp_node(item_type),
context, msg)
else:
self.fail(msg, context)

def check_single_assignment(self,
lvalue_type: Type, index_lvalue: IndexExpr,
rvalue: Node, context: Context,
Expand Down Expand Up @@ -1158,6 +1157,12 @@ def fail(self, msg: str, context: Context) -> None:
"""Produce an error message."""
self.msg.fail(msg, context)

def iterable_item_type(self, instance: Instance) -> Type:
iterable = map_instance_to_supertype(
instance,
self.lookup_typeinfo('builtins.Iterable'))
return iterable.args[0]


def map_type_from_supertype(typ: Type, sub_info: TypeInfo,
super_info: TypeInfo) -> Type:
Expand Down
15 changes: 13 additions & 2 deletions mypy/test/data/check-inference.test
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ class A: pass
main: In function "f":


-- Inferring local variable types in multiple definition
-- -----------------------------------------------------
-- Inferring variable types in multiple definition
-- -----------------------------------------------


[case testInferringLvarTypesInMultiDef]
Expand Down Expand Up @@ -270,6 +270,17 @@ def f(d: Any) -> None:
a.x
b.x

[case testInferringTypesFromIterable]
from typing import Iterable
class Nums(Iterable[int]):
def __iter__(self): pass
def __next__(self): pass
a, b = Nums()
a = b = 1
a = '' # E: Incompatible types in assignment
b = '' # E: Incompatible types in assignment
[builtins fixtures/for.py]


-- Type variable inference for generic functions
-- ---------------------------------------------
Expand Down

0 comments on commit 6ecbd1f

Please sign in to comment.