Skip to content

Optional bytes type not narrowed after asserting equality #20701

@p-sawicki

Description

@p-sawicki

Bug Report

cc @hauntsaninja
Starting from e64a84b mypy no longer narrows the type of an optional bytes object into a non-optional after asserting that it's equal to a non-optional.

From the linked commit I understand that this is the expected behavior for types with custom equality but it makes the bytes builtin work differently from others like int or str so it might make sense to special-case it. Example:

def comp_opt(b: bytes | None, s: str | None, i: int | None):
    assert b == b"bytes"
    assert s == "str"
    assert i == 42
    reveal_type(b)  # note: Revealed type is "builtins.bytes | None"
    reveal_type(s)  # note: Revealed type is "builtins.str"
    reveal_type(i)  # note: Revealed type is "builtins.int"

To Reproduce

def comp_opt_bytes(b: bytes | None, c: bytes):
    assert b == c
    reveal_type(b)

Expected Behavior

The revealed type should probably be builtins.bytes.

Actual Behavior

note: Revealed type is "builtins.bytes | None"

Your Environment

  • Mypy version used: mypy 1.20.0+dev.e64a84b118bb338ec6efd428d398e6ebd5b79bfc and up
  • Mypy command-line flags: mypy ~/test.py
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.13.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions