Skip to content

Commit 92a4428

Browse files
committed
Only report unreachability once
1 parent f3ba149 commit 92a4428

File tree

3 files changed

+12
-3
lines changed

3 files changed

+12
-3
lines changed

mypy/binder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def __init__(self, id: int, conditional_frame: bool = False) -> None:
6666
self.unreachable = False
6767
self.conditional_frame = conditional_frame
6868
self.suppress_unreachable_warnings = False
69+
self.unreachable_warning_emitted = False
6970

7071
def __repr__(self) -> str:
7172
return f"Frame({self.id}, {self.types}, {self.unreachable}, {self.conditional_frame})"
@@ -186,6 +187,9 @@ def unreachable(self) -> None:
186187
def suppress_unreachable_warnings(self) -> None:
187188
self.frames[-1].suppress_unreachable_warnings = True
188189

190+
def emitted_unreachable_warning(self) -> None:
191+
self.frames[-1].unreachable_warning_emitted = True
192+
189193
def get(self, expr: Expression) -> Type | None:
190194
key = literal_hash(expr)
191195
assert key is not None, "Internal error: binder tried to get non-literal"
@@ -202,6 +206,9 @@ def is_unreachable(self) -> bool:
202206
def is_unreachable_warning_suppressed(self) -> bool:
203207
return any(f.suppress_unreachable_warnings for f in self.frames)
204208

209+
def is_unreachable_warning_emitted(self) -> bool:
210+
return any(f.unreachable_warning_emitted for f in self.frames)
211+
205212
def cleanse(self, expr: Expression) -> None:
206213
"""Remove all references to a Node from the binder."""
207214
key = literal_hash(expr)

mypy/checker.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ def check_first_pass(self) -> None:
467467
reported_unreachable = True
468468
elif not self.is_noop_for_reachability(d):
469469
self.msg.unreachable_statement(d)
470+
self.binder.emitted_unreachable_warning()
470471
reported_unreachable = True
471472
self.accept(d)
472473

@@ -3060,6 +3061,7 @@ def visit_block(self, b: Block) -> None:
30603061
reported_unreachable = True
30613062
elif not self.is_noop_for_reachability(s):
30623063
self.msg.unreachable_statement(s)
3064+
self.binder.emitted_unreachable_warning()
30633065
reported_unreachable = True
30643066
self.accept(s)
30653067

@@ -3069,6 +3071,7 @@ def should_report_unreachable_issues(self) -> bool:
30693071
and self.options.warn_unreachable
30703072
and not self.current_node_deferred
30713073
and not self.binder.is_unreachable_warning_suppressed()
3074+
and not self.binder.is_unreachable_warning_emitted()
30723075
)
30733076

30743077
def is_noop_for_reachability(self, s: Statement) -> bool:

test-data/unit/check-isinstance.test

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ while 2:
393393
x.b # E: "A" has no attribute "b"
394394
break
395395
_ = "unreachable" # E: Statement is unreachable
396-
x.b # E: Statement is unreachable
396+
x.b
397397

398398
[case testUnionTryFinally6]
399399
class A: pass
@@ -733,9 +733,8 @@ while bool():
733733
if isinstance(x, int):
734734
x + 1
735735
break
736-
# TODO: only report unreachability once
737736
elif isinstance(x, str): # E: Statement is unreachable
738-
_ = "unreachable" # E: Statement is unreachable
737+
_ = "unreachable"
739738
x + 'a'
740739
break
741740
_ = "unreachable" # E: Statement is unreachable

0 commit comments

Comments
 (0)