Fix crash with yield in comprehension (#12048)

Fixes #10189

Produce an error when encountering a yield expression (both `yield` and `yield from` clauses) in comprehensions and generator expressions. The latter is a syntax error in python 3.8+; see #10189 and also [python issue 10544](https://bugs.python.org/issue10544).
diff --git a/mypy/semanal.py b/mypy/semanal.py
index a7c5eda..2a24c12 100644
--- a/mypy/semanal.py
+++ b/mypy/semanal.py
@@ -3830,13 +3830,15 @@
             expr.expr.accept(self)
 
     def visit_yield_from_expr(self, e: YieldFromExpr) -> None:
-        if not self.is_func_scope():  # not sure
+        if not self.is_func_scope():
             self.fail('"yield from" outside function', e, serious=True, blocker=True)
+        elif self.is_comprehension_stack[-1]:
+            self.fail('"yield from" inside comprehension or generator expression',
+                      e, serious=True, blocker=True)
+        elif self.function_stack[-1].is_coroutine:
+            self.fail('"yield from" in async function', e, serious=True, blocker=True)
         else:
-            if self.function_stack[-1].is_coroutine:
-                self.fail('"yield from" in async function', e, serious=True, blocker=True)
-            else:
-                self.function_stack[-1].is_generator = True
+            self.function_stack[-1].is_generator = True
         if e.expr:
             e.expr.accept(self)
 
@@ -4214,20 +4216,22 @@
         if analyzed is not None:
             expr.type = analyzed
 
-    def visit_yield_expr(self, expr: YieldExpr) -> None:
+    def visit_yield_expr(self, e: YieldExpr) -> None:
         if not self.is_func_scope():
-            self.fail('"yield" outside function', expr, serious=True, blocker=True)
-        else:
-            if self.function_stack[-1].is_coroutine:
-                if self.options.python_version < (3, 6):
-                    self.fail('"yield" in async function', expr, serious=True, blocker=True)
-                else:
-                    self.function_stack[-1].is_generator = True
-                    self.function_stack[-1].is_async_generator = True
+            self.fail('"yield" outside function', e, serious=True, blocker=True)
+        elif self.is_comprehension_stack[-1]:
+            self.fail('"yield" inside comprehension or generator expression',
+                      e, serious=True, blocker=True)
+        elif self.function_stack[-1].is_coroutine:
+            if self.options.python_version < (3, 6):
+                self.fail('"yield" in async function', e, serious=True, blocker=True)
             else:
                 self.function_stack[-1].is_generator = True
-        if expr.expr:
-            expr.expr.accept(self)
+                self.function_stack[-1].is_async_generator = True
+        else:
+            self.function_stack[-1].is_generator = True
+        if e.expr:
+            e.expr.accept(self)
 
     def visit_await_expr(self, expr: AwaitExpr) -> None:
         if not self.is_func_scope():
diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py
index 7e18794..d935252 100644
--- a/mypy/semanal_main.py
+++ b/mypy/semanal_main.py
@@ -307,7 +307,7 @@
     Return tuple with these items:
     - list of deferred targets
     - was some definition incomplete (need to run another pass)
-    - were any new names were defined (or placeholders replaced)
+    - were any new names defined (or placeholders replaced)
     """
     state.manager.processed_targets.append(target)
     tree = state.tree
diff --git a/test-data/unit/check-semanal-error.test b/test-data/unit/check-semanal-error.test
index f91e3b1..c6cf45d 100644
--- a/test-data/unit/check-semanal-error.test
+++ b/test-data/unit/check-semanal-error.test
@@ -77,10 +77,47 @@
 
 [case testYieldOutsideFunction]
 yield # E: "yield" outside function
-
-[case testYieldFromOutsideFunction]
 x = 1
 yield from x # E: "yield from" outside function
+[(yield 1) for _ in x] # E: "yield" inside comprehension or generator expression
+{(yield 1) for _ in x} # E: "yield" inside comprehension or generator expression
+{i: (yield 1) for i in x} # E: "yield" inside comprehension or generator expression
+((yield 1) for _ in x) # E: "yield" inside comprehension or generator expression
+y = 1
+[(yield from x) for _ in y] # E: "yield from" inside comprehension or generator expression
+{(yield from x) for _ in y} # E: "yield from" inside comprehension or generator expression
+{i: (yield from x) for i in y} # E: "yield from" inside comprehension or generator expression
+((yield from x) for _ in y) # E: "yield from" inside comprehension or generator expression
+def f(y):
+    [x for x in (yield y)]
+    {x for x in (yield y)}
+    {x: x for x in (yield y)}
+    (x for x in (yield y))
+    [x for x in (yield from y)]
+    {x for x in (yield from y)}
+    {x: x for x in (yield from y)}
+    (x for x in (yield from y))
+def g(y):
+    [(yield 1) for _ in y] # E: "yield" inside comprehension or generator expression
+    {(yield 1) for _ in y} # E: "yield" inside comprehension or generator expression
+    {i: (yield 1) for i in y} # E: "yield" inside comprehension or generator expression
+    ((yield 1) for _ in y) # E: "yield" inside comprehension or generator expression
+    lst = 1
+    [(yield from lst) for _ in y] # E: "yield from" inside comprehension or generator expression
+    {(yield from lst) for _ in y} # E: "yield from" inside comprehension or generator expression
+    {i: (yield from lst) for i in y} # E: "yield from" inside comprehension or generator expression
+    ((yield from lst) for _ in y) # E: "yield from" inside comprehension or generator expression
+def h(y):
+    lst = 1
+    [x for x in lst if (yield y)] # E: "yield" inside comprehension or generator expression
+    {x for x in lst if (yield y)} # E: "yield" inside comprehension or generator expression
+    {x: x for x in lst if (yield y)} # E: "yield" inside comprehension or generator expression
+    (x for x in lst if (yield y)) # E: "yield" inside comprehension or generator expression
+    lst = 1
+    [x for x in lst if (yield from y)] # E: "yield from" inside comprehension or generator expression
+    {x for x in lst if (yield from y)} # E: "yield from" inside comprehension or generator expression
+    {x: x for x in lst if (yield from y)} # E: "yield from" inside comprehension or generator expression
+    (x for x in lst if (yield from y)) # E: "yield from" inside comprehension or generator expression
 
 [case testImportFuncDup]