Repository: python/mypy

Issue:
Crash on yield inside lambda
I've encountered a crash on the following input:

```python
(lambda: (yield))
```

With this output:

```
error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues
Traceback (most recent call last):
  File "/usr/local/bin/mypy", line 6, in <module>
    main(__file__)
  File "/usr/local/lib/python3.6/site-packages/mypy/main.py", line 42, in main
    res = type_check_only(sources, bin_dir, options)
  File "/usr/local/lib/python3.6/site-packages/mypy/main.py", line 86, in type_check_only
    options=options)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 183, in build
    dispatch(sources, manager)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1531, in dispatch
    process_graph(graph, manager)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1768, in process_graph
    process_stale_scc(graph, scc)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1847, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1453, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/usr/local/lib/python3.6/site-packages/mypy/checker.py", line 167, in check_first_pass
    self.accept(d)
  File "/usr/local/lib/python3.6/site-packages/mypy/checker.py", line 233, in accept
    stmt.accept(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/nodes.py", line 792, in accept
    return visitor.visit_expression_stmt(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/checker.py", line 1683, in visit_expression_stmt
    self.expr_checker.accept(s.expr)
  File "/usr/local/lib/python3.6/site-packages/mypy/checkexpr.py", line 2015, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/nodes.py", line 1507, in accept
    return visitor.visit_func_expr(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/checkexpr.py", line 1769, in visit_func_expr
    ret_type = self.accept(e.expr())
  File "/usr/local/lib/python3.6/site-packages/mypy/checkexpr.py", line 2015, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/nodes.py", line 1284, in accept
    return visitor.visit_yield_expr(self)
  File "/usr/local/lib/python3.6/site-packages/mypy/checkexpr.py", line 2088, in visit_yield_expr
    return_type = self.chk.return_types[-1]
IndexError: list index out of range
```


Discussion:
Confirmed, I also see the same crash.
This is weird code, removing the priority.
We use it in micropython to get the type of a generator function, as it's the most efficient way:

```python
type_genfunc = type((lambda: (yield)))
```
Another possible use case is something like generator-based promises(?):
```python
def force(promise: Iterator[T]) -> T:
    ...
force(lambda: (yield 5))
```
But in fact I had put the label since I think being able to unconditionally crash mypy with something as simple as ``lambda: (yield)`` is bad.
You can still fix it if you want. :-)

Resolving patch:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -1936,12 +1936,15 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type:
         """Type check lambda expression."""
         inferred_type, type_override = self.infer_lambda_type_using_context(e)
         if not inferred_type:
+            self.chk.return_types.append(AnyType())
             # No useful type context.
             ret_type = self.accept(e.expr(), allow_none_return=True)
             fallback = self.named_type('builtins.function')
+            self.chk.return_types.pop()
             return callable_type(e, fallback, ret_type)
         else:
             # Type context available.
+            self.chk.return_types.append(inferred_type.ret_type)
             self.chk.check_func_item(e, type_override=type_override)
             if e.expr() not in self.chk.type_map:
                 self.accept(e.expr(), allow_none_return=True)
@@ -1950,7 +1953,9 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type:
                 # For "lambda ...: None", just use type from the context.
                 # Important when the context is Callable[..., None] which
                 # really means Void. See #1425.
+                self.chk.return_types.pop()
                 return inferred_type
+            self.chk.return_types.pop()
             return replace_callable_return_type(inferred_type, ret_type)
 
     def infer_lambda_type_using_context(self, e: LambdaExpr) -> Tuple[Optional[CallableType],


Test patch:
diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test
--- a/test-data/unit/check-expressions.test
+++ b/test-data/unit/check-expressions.test
@@ -1208,6 +1208,20 @@ def void() -> None:
     pass
 x = lambda: void() # type: typing.Callable[[], None]
 
+[case testNoCrashOnLambdaGenerator]
+from typing import Iterator, Callable
+
+# These should not crash
+lambda: (yield)
+
+gen: Callable[[], Iterator[str]]
+gen = (lambda: (yield 1))  # E: Incompatible types in yield (actual type "int", expected type "str")
+
+def fun(cb: Callable[[], Iterator[str]]) -> None:
+    pass
+fun(lambda: (yield from [1]))  # E: Incompatible types in "yield from" (actual type "int", expected type "str")
+[builtins fixtures/list.pyi]
+[out]
 
 -- List comprehensions
 -- -------------------