Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5345,6 +5345,11 @@ def visit_if_stmt(self, s: IfStmt) -> None:
# Fall-through to the original frame is handled explicitly in each block.
with self.binder.frame_context(can_skip=False, conditional_frame=True, fall_through=0):
for e, b in zip(s.expr, s.body):
# If condition is 'x and y' and body always raises,
# suppress false redundant-expr warning (see issue #21533)
if isinstance(e, OpExpr) and e.op == "and":
if b.body and all(self.is_noop_for_reachability(s) for s in b.body):
e.right_always = True
t = get_proper_type(self.expr_checker.accept(e))

if isinstance(t, DeletedType):
Expand Down
24 changes: 24 additions & 0 deletions test-data/unit/check-narrowing.test
Original file line number Diff line number Diff line change
Expand Up @@ -4281,3 +4281,27 @@ def func(y: H) -> H:
else:
return y
[builtins fixtures/primitives.pyi]

[case testRedundantExprAndWithRaise]
# flags: --enable-error-code redundant-expr
from typing_extensions import TypeIs
from typing import TypeVar, Sequence, Any

class Cat: ...

T = TypeVar('T')
MyType = TypeVar('MyType', int, str, Cat)

def _is_seq_of(seq: Sequence[Any], tp: type[T]) -> TypeIs[Sequence[T]]: ...

def main1(a: Sequence[MyType]) -> MyType:
if not _is_seq_of(a, Cat) and not _is_seq_of(a, int):
raise Exception("unexpected")
return a[0]

def main2(a: Sequence[MyType]) -> MyType:
if not _is_seq_of(a, Cat):
if not _is_seq_of(a, int):
raise Exception("unexpected")
return a[0]
[builtins fixtures/exception.pyi]
Loading