Repository: python/mypy

Issue:
RuntimeError with Iterator input
```
from itertools import groupby
from typing import Iterator, TypeVar, Callable, Tuple, Any

X = TypeVar('X')
Key = TypeVar('Key')
def sorted_groupby(sequence: Iterator[X], key: Callable[[X], Key]) -> Iterator[Tuple[Key, Iterator[X]]]:
    return groupby(sorted(sequence, key=key), key=key)

def foo() -> Any:
    baz = next(sorted_groupby([1], key=lambda x: x))
```

I know that `Iterator` is not the best/correct choice for the type of `sequence` (and the same problem doesn't happen with `Iterable`), but I get the following stacktrace with mypy 0.4.1

```
Traceback (most recent call last):
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/bin/.mypy-wrapped", line 7, in <module>
    main(__file__)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/main.py", line 54, in main
    res = type_check_only(sources, bin_dir, options)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/main.py", line 102, in type_check_only
    python_path=options.python_path)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/build.py", line 209, in build
    dispatch(sources, manager)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/build.py", line 1255, in dispatch
    process_graph(graph, manager)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/build.py", line 1386, in process_graph
    process_stale_scc(graph, scc)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/build.py", line 1416, in process_stale_scc
    graph[id].type_check()
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/build.py", line 1235, in type_check
    manager.type_checker.visit_file(self.tree, self.xpath)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 419, in visit_file
    self.accept(d)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/nodes.py", line 462, in accept
    return visitor.visit_func_def(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 573, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 631, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 739, in check_func_def
    self.accept_in_frame(item.body)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 475, in accept_in_frame
    answer = self.accept(node, type_context)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/nodes.py", line 715, in accept
    return visitor.visit_block(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 1132, in visit_block
    self.accept(s)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/nodes.py", line 753, in accept
    return visitor.visit_assignment_stmt(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 1141, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 1192, in check_assignment
    rvalue)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 1424, in infer_variable_type
    elif not is_valid_inferred_type(init_type):
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 2549, in is_valid_inferred_type
    if not is_valid_inferred_type(item):
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/checker.py", line 2541, in is_valid_inferred_type
    if is_same_type(typ, NoneTyp()):
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/sametypes.py", line 27, in is_same_type
    return left.accept(SameTypeVisitor(right))
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/types.py", line 244, in accept
    return visitor.visit_erased_type(self)
  File "/nix/store/czly6jrafckfvwm9mjc6wvandc2ddwi9-python3.5-mypy-lang-0.4.1/lib/python3.5/site-packages/mypy/sametypes.py", line 74, in visit_erased_type
    raise RuntimeError()
RuntimeError: 

*** INTERNAL ERROR ***
```



Discussion:
Smaller test case:

``` python
from typing import Iterator, TypeVar, Callable, Any

X = TypeVar('X')

def f(x: Callable[[X], Any]) -> Iterator[X]: pass
def g(x: Iterator[X]) -> X: pass
bax = g(f(lambda x: x))
```

Even more reduced:

``` py
from typing import TypeVar, Callable

X = TypeVar('X')

def f(x: Callable[[X], X]) -> X: pass
bax = f(lambda x: x)
```


Resolving patch:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -306,7 +306,7 @@ def infer_arg_types_in_context(self, callee: CallableType,
                     arg_type = self.accept(arg, callee.arg_types[-1])
                 else:
                     arg_type = self.accept(arg)
-            if isinstance(arg_type, ErasedType):
+            if has_erased_component(arg_type):
                 res.append(NoneTyp())
             else:
                 res.append(arg_type)
@@ -464,7 +464,7 @@ def infer_function_type_arguments_pass2(
         # information to infer the argument. Replace them with None values so
         # that they are not applied yet below.
         for i, arg in enumerate(inferred_args):
-            if isinstance(arg, NoneTyp) or isinstance(arg, ErasedType):
+            if isinstance(arg, NoneTyp) or has_erased_component(arg):
                 inferred_args[i] = None
 
         callee_type = cast(CallableType, self.apply_generic_arguments(
@@ -506,7 +506,7 @@ def apply_inferred_arguments(self, callee_type: CallableType,
         # case assume that all variables have type Any to avoid extra
         # bogus error messages.
         for i, inferred_type in enumerate(inferred_args):
-            if not inferred_type:
+            if not inferred_type or has_erased_component(inferred_type):
                 # Could not infer a non-trivial type for a type variable.
                 self.msg.could_not_infer_type_arguments(
                     callee_type, i + 1, context)


Test patch:
diff --git a/mypy/test/data/check-inference.test b/mypy/test/data/check-inference.test
--- a/mypy/test/data/check-inference.test
+++ b/mypy/test/data/check-inference.test
@@ -1026,6 +1026,21 @@ class A: pass
 class B: pass
 [builtins fixtures/list.py]
 
+[case testUninferableLambda]
+from typing import TypeVar, Callable
+X = TypeVar('X')
+def f(x: Callable[[X], X]) -> X: pass
+y = f(lambda x: x) # E: Cannot infer type argument 1 of "f"
+
+[case testUninferableLambdaWithTypeError]
+from typing import TypeVar, Callable
+X = TypeVar('X')
+def f(x: Callable[[X], X], y: str) -> X: pass
+y = f(lambda x: x, 1) # Fail
+[out]
+main:4: error: Cannot infer type argument 1 of "f"
+main:4: error: Argument 2 to "f" has incompatible type "int"; expected "str"
+
 
 -- Boolean operators
 -- -----------------