Skip to content

False positive - Type narrowing of class attributes #17537

Open
@Tinche

Description

@Tinche

I'm not super sure if this is a bug or not, but the behavior is different in Mypy and pyright so probably worth discussing it.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.12&gist=3a34812b38b40ca5cb913ee48daf2c49

from dataclasses import dataclass
from enum import Enum

from typing_extensions import reveal_type


class E(Enum):
    ONE: int = 1
    TWO: int = 2


@dataclass
class Test:
    a: E

    def set_a(self, value: E) -> None:
        self.a = value


a = Test(E.ONE)
reveal_type(a.a)
assert a.a == E.ONE
reveal_type(a.a)
a.set_a(E.TWO)
reveal_type(a.a)

I ran into this while trying to enable strict_equality on a codebase.

The problem is the last reveal_type call - Mypy claims the type is still Literal[E.ONE], but it's obviously Literal[E.TWO] (or at least E). If strict_equality is enabled, this will cause a type error when asserting in a test, for example.

Pyright doesn't seem to narrow here, claiming the type of a.a is E always.

I don't know what the correct answer is here. Maybe allow narrowing only on local variables? 🤷

  • Mypy version used: 1.10.1
  • Python version used: 3.8

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions