python / python/mypy

Get rid of the "flipping behaviour" in narrowign by equality/identity

Open
#21,365 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs discussion topic-type-narrowing
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

We have this code that makes sure that if the intersection of declared and narrowed is not representable, then we prefer the narrowed. I added this logic a while ago, since this is what a user usually expects in case of e.g. an assignment or even an isinstance() check.

However, the recent effort to make equality/identity narrowing symmetric also caused this to result in a "flipping" behavior, when sides exchange types after a comparison, see e.g. testNarrowGenericCallableEquality. Although such cases are rare, I think the resulting behavior is really weird/confusing.

So I propose to add a flag to each restriction in binder (similar to from_assignment), say prefer_declared that would be set to True for right-most operand in equality/identity. This flag would override the fallback mentioned above. So that after something like assert x == y == a, the type of a will not change if the intersection is not representable.

I understand this breaks the symmetry, but this is purely practical thing, this is why people write x == 2 and not 2 == x.

cc @hauntsaninja

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 with the fallback logic in mypy/checkexpr.py around lines 6494-6499, then trace how restrictions are represented and applied in the binder. Run the testNarrowGenericCallableEquality case to reproduce the flipping behavior and inspect nearby equality/identity narrowing tests. Done means the right-most operand keeps its declared type when the intersection is not representable, without changing ordinary narrowing behavior.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.