|
132 | 132 | Var, |
133 | 133 | WhileStmt, |
134 | 134 | WithStmt, |
| 135 | + YieldExpr, |
135 | 136 | is_final_node, |
136 | 137 | ) |
137 | 138 | from mypy.options import Options |
@@ -1241,13 +1242,17 @@ def check_func_def( |
1241 | 1242 | new_frame.types[key] = narrowed_type |
1242 | 1243 | self.binder.declarations[key] = old_binder.declarations[key] |
1243 | 1244 | with self.scope.push_function(defn): |
1244 | | - # We suppress reachability warnings when we use TypeVars with value |
| 1245 | + # We suppress reachability warnings for empty generator functions |
| 1246 | + # (return; yield) which have a "yield" that's unreachable by definition |
| 1247 | + # since it's only there to promote the function into a generator function. |
| 1248 | + # |
| 1249 | + # We also suppress reachability warnings when we use TypeVars with value |
1245 | 1250 | # restrictions: we only want to report a warning if a certain statement is |
1246 | 1251 | # marked as being suppressed in *all* of the expansions, but we currently |
1247 | 1252 | # have no good way of doing this. |
1248 | 1253 | # |
1249 | 1254 | # TODO: Find a way of working around this limitation |
1250 | | - if len(expanded) >= 2: |
| 1255 | + if _is_empty_generator_function(item) or len(expanded) >= 2: |
1251 | 1256 | self.binder.suppress_unreachable_warnings() |
1252 | 1257 | self.accept(item.body) |
1253 | 1258 | unreachable = self.binder.is_unreachable() |
@@ -6968,6 +6973,22 @@ def is_literal_not_implemented(n: Expression) -> bool: |
6968 | 6973 | return isinstance(n, NameExpr) and n.fullname == "builtins.NotImplemented" |
6969 | 6974 |
|
6970 | 6975 |
|
| 6976 | +def _is_empty_generator_function(func: FuncItem) -> bool: |
| 6977 | + """ |
| 6978 | + Checks whether a function's body is 'return; yield' (the yield being added only |
| 6979 | + to promote the function into a generator function). |
| 6980 | + """ |
| 6981 | + body = func.body.body |
| 6982 | + return ( |
| 6983 | + len(body) == 2 |
| 6984 | + and isinstance(ret_stmt := body[0], ReturnStmt) |
| 6985 | + and (ret_stmt.expr is None or is_literal_none(ret_stmt.expr)) |
| 6986 | + and isinstance(expr_stmt := body[1], ExpressionStmt) |
| 6987 | + and isinstance(yield_expr := expr_stmt.expr, YieldExpr) |
| 6988 | + and (yield_expr.expr is None or is_literal_none(yield_expr.expr)) |
| 6989 | + ) |
| 6990 | + |
| 6991 | + |
6971 | 6992 | def builtin_item_type(tp: Type) -> Type | None: |
6972 | 6993 | """Get the item type of a builtin container. |
6973 | 6994 |
|
|
0 commit comments