False positive `redundant-expr`, but only for `if x and y:`, not for `if x: if y:`
Open
Nobody has claimed this yet.
bug
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
In the code below
if not _is_seq_of(a, Cat) and not _is_seq_of(a, int):
is treated differently to
if not _is_seq_of(a, Cat):
if not _is_seq_of(a, int):
To Reproduce
from typing import TypeIs, TypeVar, Sequence, Any, Self, reveal_type, Iterable, TypeAlias
class Cat:
def foo(self) -> Self: # type: ignore[empty-body]
...
MyType = TypeVar('MyType', int, str, Cat)
T = TypeVar('T')
def _is_seq_of(seq: Sequence[Any], tp: type[T]) -> TypeIs[Sequence[T]]: # type: ignore[empty-body]
...
def main1(a: Sequence[MyType], how: str) -> MyType:
if how.startswith('align'):
if not _is_seq_of(a, Cat) and not _is_seq_of(a, int):
msg = 'unexpected'
raise TypeError(msg)
return a[0]
def main2(a: Sequence[MyType], how: str) -> MyType:
if how.startswith('align'):
if not _is_seq_of(a, Cat):
if not _is_seq_of(a, int):
msg = 'unexpected'
raise TypeError(msg)
return a[0]
Mypy accepts main2 just fine, but for main1, it reports
$ mypy --enable-error-code redundant-expr t.py
t.py:17: error: Left operand of "and" is always true [redundant-expr]
Found 1 error in 1 file (checked 1 source file)
Expected Behavior
I think main1 and main2 should be treated the same. My expectation is that they should both pass (not report any errors)
Actual Behavior
$ mypy --enable-error-code redundant-expr t.py
t.py:17: error: Left operand of "and" is always true [redundant-expr]
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 2.1.0
- Mypy command-line flags: --enable-error-code redundant-expr
- Mypy configuration options from
mypy.ini(and other config files): - Python version used: 3.14.4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked mypy-play reproduction and run the reported command with --enable-error-code redundant-expr. Compare the narrowing behavior of the combined and nested conditions, then verify that both examples produce the expected diagnostics without the false positive.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100