Repository: python/mypy

Issue:
Crash in --py2 mode when returning sorted(x, key=lambda (a, b): ...)
Shortest repro so far:

```
def foo() -> None:
    x = []
    return sorted(x, key=lambda (a, b): a)
```

It only crashes if:
- it's in an annotated function **(EDIT)**
- it's in a return statement
- there's a lambda with a tuple argument

Traceback:

```
Traceback (most recent call last):
  File "/Users/guido/v3/bin/mypy", line 6, in <module>
    main(__file__)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/main.py", line 52, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/main.py", line 100, in type_check_only
    python_path=options.python_path)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/build.py", line 208, in build
    dispatch(sources, manager)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/build.py", line 1251, in dispatch
    process_graph(graph, manager)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/build.py", line 1382, in process_graph
    process_stale_scc(graph, scc)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/build.py", line 1412, in process_stale_scc
    graph[id].type_check()
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/build.py", line 1231, in type_check
    manager.type_checker.visit_file(self.tree, self.xpath)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 419, in visit_file
    self.accept(d)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/nodes.py", line 462, in accept
    return visitor.visit_func_def(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 573, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 631, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 739, in check_func_def
    self.accept_in_frame(item.body)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 475, in accept_in_frame
    answer = self.accept(node, type_context)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/nodes.py", line 715, in accept
    return visitor.visit_block(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 1133, in visit_block
    self.accept(s)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/nodes.py", line 812, in accept
    return visitor.visit_return_stmt(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 1565, in visit_return_stmt
    typ = self.accept(s.expr, return_type)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/nodes.py", line 1174, in accept
    return visitor.visit_call_expr(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 1974, in visit_call_expr
    return self.expr_checker.visit_call_expr(e)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 145, in visit_call_expr
    return self.check_call_expr_with_callee_type(callee_type, e)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 196, in check_call_expr_with_callee_type
    e.arg_names, callable_node=e.callee)[0]
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 239, in check_call
    callee, args, arg_kinds, formal_to_actual)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 334, in infer_arg_types_in_context2
    res[ai] = self.accept(args[ai], callee.arg_types[i])
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 1459, in accept
    return self.chk.accept(node, context)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 460, in accept
    typ = node.accept(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/nodes.py", line 1396, in accept
    return visitor.visit_func_expr(self)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checker.py", line 2099, in visit_func_expr
    return self.expr_checker.visit_func_expr(e)
  File "/Users/guido/v3/lib/python3.5/site-packages/mypy/checkexpr.py", line 1275, in visit_func_expr
    ret_type = self.chk.type_map[e.expr()]
KeyError: <mypy.nodes.NameExpr object at 0x106139e48>
```



Discussion:

Resolving patch:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -1267,6 +1267,8 @@ def visit_func_expr(self, e: FuncExpr) -> Type:
         else:
             # Type context available.
             self.chk.check_func_item(e, type_override=inferred_type)
+            if e.expr() not in self.chk.type_map:
+                self.accept(e.expr())
             ret_type = self.chk.type_map[e.expr()]
             return replace_callable_return_type(inferred_type, ret_type)
 


Test patch:
diff --git a/mypy/test/data/check-python2.test b/mypy/test/data/check-python2.test
--- a/mypy/test/data/check-python2.test
+++ b/mypy/test/data/check-python2.test
@@ -193,3 +193,11 @@ def f((x,)): return x
 def g((x)): return x
 f(0) + g(0)
 [out]
+
+[case testLambdaAsSortKeyForTuplePython2]
+from typing import Any, Tuple, Callable
+def bar(key: Callable[[Tuple[int, int]], int]) -> int:
+    pass
+def foo() -> int:
+    return bar(key=lambda (a, b): a)
+[out]