python / python/mypy

Attribute narrowing isn't aware of side effects

Open
#9,457 15 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-enum topic-literal-types topic-reachability topic-type-narrowing
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

This code:

class Foo:
    def __init__(self) -> None:
        self.dirty = False


def test_source() -> None:
    foo = Foo()

    def bar() -> None:
        foo.dirty = True

    assert foo.dirty is False

    bar()

    assert foo.dirty is True
    print("unreachable?")

produces the warning: main.py:17: error: Statement is unreachable, when running mypy --warn-unreachable test.py on 0.780.

Running the same through mypy 0.770 works fine and doesn't produce a warning.

(Also, running the example with pytest -s test.py prints unreachable?, because obviously this line is not unreachable when running the code in python).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the supplied example with mypy 0.780 and 0.770 using --warn-unreachable, then trace the attribute-narrowing logic involved in the closure that assigns foo.dirty. Compare the handling of side effects between those versions; done means the current behavior no longer reports print("unreachable?") as unreachable while preserving valid narrowing.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.