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
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), sayprefer_declaredthat would be set toTruefor right-most operand in equality/identity. This flag would override the fallback mentioned above. So that after something likeassert x == y == a, the type ofawill 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 == 2and not2 == x.cc @hauntsaninja