Skip to content

Commit 13d88a2

Browse files
committed
Added edge case for invalid control flow in except block nested inside except* block, other minor fixes
1 parent bde4749 commit 13d88a2

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

mypy/semanal.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -519,21 +519,21 @@ def allow_unbound_tvars_set(self) -> Iterator[None]:
519519

520520
@contextmanager
521521
def inside_except_star_block_set(
522-
self, value: bool, enteringLoop: bool = False
522+
self, value: bool, entering_loop: bool = False
523523
) -> Iterator[None]:
524524
old = self.inside_except_star_block
525525
self.inside_except_star_block = value
526526

527527
# Return statement would still be in except* scope if entering loops
528-
if not enteringLoop:
528+
if not entering_loop:
529529
old_return_stmt_flag = self.return_stmt_inside_except_star_block
530530
self.return_stmt_inside_except_star_block = value
531531

532532
try:
533533
yield
534534
finally:
535535
self.inside_except_star_block = old
536-
if not enteringLoop:
536+
if not entering_loop:
537537
self.return_stmt_inside_except_star_block = old_return_stmt_flag
538538

539539
#
@@ -5290,7 +5290,7 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
52905290
if not self.is_func_scope():
52915291
self.fail('"return" outside function', s)
52925292
if self.return_stmt_inside_except_star_block:
5293-
self.fail('"return" not allowed in except* block', s, serious=True, blocker=True)
5293+
self.fail('"return" not allowed in except* block', s, serious=True)
52945294
if s.expr:
52955295
s.expr.accept(self)
52965296

@@ -5324,7 +5324,7 @@ def visit_while_stmt(self, s: WhileStmt) -> None:
53245324
self.statement = s
53255325
s.expr.accept(self)
53265326
self.loop_depth[-1] += 1
5327-
with self.inside_except_star_block_set(value=False, enteringLoop=True):
5327+
with self.inside_except_star_block_set(value=False, entering_loop=True):
53285328
s.body.accept(self)
53295329
self.loop_depth[-1] -= 1
53305330
self.visit_block_maybe(s.else_body)
@@ -5349,7 +5349,7 @@ def visit_for_stmt(self, s: ForStmt) -> None:
53495349
s.index_type = analyzed
53505350

53515351
self.loop_depth[-1] += 1
5352-
with self.inside_except_star_block_set(value=False, enteringLoop=True):
5352+
with self.inside_except_star_block_set(value=False, entering_loop=True):
53535353
self.visit_block(s.body)
53545354
self.loop_depth[-1] -= 1
53555355
self.visit_block_maybe(s.else_body)
@@ -5359,14 +5359,14 @@ def visit_break_stmt(self, s: BreakStmt) -> None:
53595359
if self.loop_depth[-1] == 0:
53605360
self.fail('"break" outside loop', s, serious=True, blocker=True)
53615361
if self.inside_except_star_block:
5362-
self.fail('"break" not allowed in except* block', s, serious=True, blocker=True)
5362+
self.fail('"break" not allowed in except* block', s, serious=True)
53635363

53645364
def visit_continue_stmt(self, s: ContinueStmt) -> None:
53655365
self.statement = s
53665366
if self.loop_depth[-1] == 0:
53675367
self.fail('"continue" outside loop', s, serious=True, blocker=True)
53685368
if self.inside_except_star_block:
5369-
self.fail('"continue" not allowed in except* block', s, serious=True, blocker=True)
5369+
self.fail('"continue" not allowed in except* block', s, serious=True)
53705370

53715371
def visit_if_stmt(self, s: IfStmt) -> None:
53725372
self.statement = s
@@ -5387,7 +5387,7 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
53875387
type.accept(visitor)
53885388
if var:
53895389
self.analyze_lvalue(var)
5390-
with self.inside_except_star_block_set(s.is_star):
5390+
with self.inside_except_star_block_set(self.inside_except_star_block or s.is_star):
53915391
handler.accept(visitor)
53925392
if s.else_body:
53935393
s.else_body.accept(visitor)

test-data/unit/check-python311.test

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,38 @@ def foo():
196196
return # E: "return" not allowed in except* block
197197
[builtins fixtures/exception.pyi]
198198

199+
[case testContinueInExceptBlockNestedInExceptStarBlock]
200+
# flags: --python-version 3.11
201+
while True:
202+
try:
203+
...
204+
except* Exception:
205+
try:
206+
...
207+
except Exception:
208+
continue # E: "continue" not allowed in except* block
209+
continue # E: "continue" not allowed in except* block
210+
[builtins fixtures/exception.pyi]
211+
212+
[case testReturnInExceptBlockNestedInExceptStarBlock]
213+
# flags: --python-version 3.11
214+
def foo():
215+
try:
216+
...
217+
except* Exception:
218+
try:
219+
...
220+
except Exception:
221+
return # E: "return" not allowed in except* block
222+
return # E: "return" not allowed in except* block
223+
[builtins fixtures/exception.pyi]
224+
199225
[case testBreakContinueReturnInExceptStarBlock1]
200226
# flags: --python-version 3.11
201-
class range: pass
227+
from typing import Sequence
228+
class range(Sequence[int]):
229+
def __init__(self, __x: int, __y: int = ..., __z: int = ...) -> None: pass
230+
202231
def foo() -> None:
203232
for _ in range(5):
204233
try:

0 commit comments

Comments
 (0)