Repository: python/mypy

Issue:
RuntimeError on visit_erased_type when using sorted(..., key=lambda...)
Running mypy --py2 on this code:

```
def func():
    # type: () -> List[float]
    source = [5, 7, 2, -3, -2.6, 4.8, 6, 6.0]
    weird_sort = sorted(
        source,
        # By absolute value, ints first though.
        key=lambda a: (abs(a), 0 if isinstance(a, int) else 1)
    )
    return weird_sort

print func()
```

hits a runtime error:

```
$ python3 -m mypy --py2 rt6.py
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main
    "__main__", mod_spec)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/__main__.py", line 5, in <module>
    main(None)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/main.py", line 54, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/main.py", line 102, in type_check_only
    python_path=options.python_path)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/build.py", line 209, in build
    dispatch(sources, manager)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/build.py", line 1255, in dispatch
    process_graph(graph, manager)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/build.py", line 1386, in process_graph
    process_stale_scc(graph, scc)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/build.py", line 1416, in process_stale_scc
    graph[id].type_check()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/build.py", line 1235, in type_check
    manager.type_checker.visit_file(self.tree, self.xpath)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 419, in visit_file
    self.accept(d)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 462, in accept
    return visitor.visit_func_def(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 573, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 631, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 739, in check_func_def
    self.accept_in_frame(item.body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 475, in accept_in_frame
    answer = self.accept(node, type_context)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 715, in accept
    return visitor.visit_block(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 1132, in visit_block
    self.accept(s)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 753, in accept
    return visitor.visit_assignment_stmt(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/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 "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 1191, in check_assignment
    self.infer_variable_type(inferred, lvalue, self.accept(rvalue),
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 1174, in accept
    return visitor.visit_call_expr(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 1980, in visit_call_expr
    return self.expr_checker.visit_call_expr(e)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 141, in visit_call_expr
    return self.check_call_expr_with_callee_type(callee_type, e)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 192, in check_call_expr_with_callee_type
    e.arg_names, callable_node=e.callee)[0]
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 232, in check_call
    callee, args, arg_kinds, formal_to_actual, context)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 400, in infer_function_type_arguments
    callee_type, args, arg_kinds, formal_to_actual)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 330, in infer_arg_types_in_context2
    res[ai] = self.accept(args[ai], callee.arg_types[i])
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 1458, in accept
    return self.chk.accept(node, context)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 1396, in accept
    return visitor.visit_func_expr(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 2105, in visit_func_expr
    return self.expr_checker.visit_func_expr(e)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 1269, in visit_func_expr
    self.chk.check_func_item(e, type_override=inferred_type)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 631, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 739, in check_func_def
    self.accept_in_frame(item.body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 475, in accept_in_frame
    answer = self.accept(node, type_context)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 715, in accept
    return visitor.visit_block(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 1132, in visit_block
    self.accept(s)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 812, in accept
    return visitor.visit_return_stmt(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 1566, in visit_return_stmt
    typ = self.accept(s.expr, return_type)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 1443, in accept
    return visitor.visit_tuple_expr(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 2096, in visit_tuple_expr
    return self.expr_checker.visit_tuple_expr(e)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 1221, in visit_tuple_expr
    tt = self.accept(item)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 1458, in accept
    return self.chk.accept(node, context)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/nodes.py", line 1538, in accept
    return visitor.visit_conditional_expr(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 2123, in visit_conditional_expr
    return self.expr_checker.visit_conditional_expr(e)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checkexpr.py", line 1415, in visit_conditional_expr
    self.chk.typing_mode_weak())
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/checker.py", line 2350, in find_isinstance_check
    if is_proper_subtype(vartype, type):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/subtypes.py", line 352, in is_proper_subtype
    return sametypes.is_same_type(t, s)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/sametypes.py", line 27, in is_same_type
    return left.accept(SameTypeVisitor(right))
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/types.py", line 244, in accept
    return visitor.visit_erased_type(self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mypy/sametypes.py", line 74, in visit_erased_type
    raise RuntimeError()
RuntimeError: 

*** INTERNAL ERROR ***

rt6.py:7: error: Internal error -- please report a bug at https://github.com/python/mypy/issues
```



Discussion:

Resolving patch:
diff --git a/mypy/sametypes.py b/mypy/sametypes.py
--- a/mypy/sametypes.py
+++ b/mypy/sametypes.py
@@ -74,8 +74,11 @@ def visit_uninhabited_type(self, t: UninhabitedType) -> bool:
         return isinstance(self.right, UninhabitedType)
 
     def visit_erased_type(self, left: ErasedType) -> bool:
-        # Should not get here.
-        raise RuntimeError()
+        # We can get here when isinstance is used inside a lambda
+        # whose type is being inferred. In any event, we have no reason
+        # to think that an ErasedType will end up being the same as
+        # any other type, even another ErasedType.
+        return False
 
     def visit_deleted_type(self, left: DeletedType) -> bool:
         return isinstance(self.right, DeletedType)


Test patch:
diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test
--- a/test-data/unit/check-inference-context.test
+++ b/test-data/unit/check-inference-context.test
@@ -618,6 +618,22 @@ def g(x: Callable[[], int]) -> None: pass
 f(lambda: None)
 g(lambda: None)
 
+[case testIsinstanceInInferredLambda]
+from typing import TypeVar, Callable
+T = TypeVar('T')
+S = TypeVar('S')
+class A: pass
+class B(A): pass
+class C(A): pass
+def f(func: Callable[[T], S], *z: T, r: S = None) -> S: pass
+f(lambda x: 0 if isinstance(x, B) else 1) # E: Cannot infer type argument 1 of "f"
+f(lambda x: 0 if isinstance(x, B) else 1, A())() # E: "int" not callable
+f(lambda x: x if isinstance(x, B) else B(), A(), r=B())() # E: "B" not callable
+f( # E: Argument 1 to "f" has incompatible type Callable[[A], A]; expected Callable[[A], B]
+    lambda x: B() if isinstance(x, B) else x, # E: Incompatible return value type (got "A", expected "B")
+    A(), r=B())
+[builtins fixtures/isinstance.py]
+
 
 -- Overloads + generic functions
 -- -----------------------------