Bug Report
While testing fixes for #21566 , I tried to set strict_dunder_typing=True which allowed me to somewhat narrow the issue down, and I've sinced removed this bool. However it did expose a seemingly other issue.
When mypyc implicitly generates __ne__ from a user-defined __eq__ with strict_dunder_typing=True, the generated __ne__ appears to use the type of self as the type of its right-hand-side argument.
I may be misunderstanding the intended behavior of strict_dunder_typing, but my expectation is that the generated __ne__ should mirror the argument type of __eq__'s other parameter. In other words, if __eq__ accepts a particular set of object types, then the generated __ne__ should also accept that same set of object types.
To Reproduce
Add this test case to mypyc/test-data/run-dunders.test:
[case testDundersImplicitNeWithNarrowRhs]
class Accepted:
pass
class Eq:
def __eq__(self, other: Accepted) -> bool: # type: ignore[override]
return True
def test_implicit_ne_with_narrow_rhs() -> None:
assert Eq() == Accepted()
assert not (Eq() != Accepted())
Run the strict dunder tests:
python -m pytest -q mypyc/test/test_run.py -k testDundersImplicitNeWithNarrowRhs
Expected Behavior
Both comparisons should work.
Since __eq__ is defined as:
def __eq__(self, other: Accepted) -> bool:
return True
the generated __ne__ should accept the same other type and behave as though it were approximately:
def __ne__(self, other: Accepted) -> bool:
return not self.__eq__(other)
So this should pass:
assert Eq() == Accepted()
assert not (Eq() != Accepted())
Actual Behavior
The == comparison succeeds, but the != comparison fails at runtime because the implicitly generated __ne__ expects the right-hand-side argument to be Eq.
In other words, the generated __ne__ appears to behave as though its RHS argument type came from self, not from __eq__'s other parameter.
Bug Report
While testing fixes for #21566 , I tried to set
strict_dunder_typing=Truewhich allowed me to somewhat narrow the issue down, and I've sinced removed this bool. However it did expose a seemingly other issue.When mypyc implicitly generates
__ne__from a user-defined__eq__withstrict_dunder_typing=True, the generated__ne__appears to use the type ofselfas the type of its right-hand-side argument.I may be misunderstanding the intended behavior of
strict_dunder_typing, but my expectation is that the generated__ne__should mirror the argument type of__eq__'s other parameter. In other words, if__eq__accepts a particular set of object types, then the generated__ne__should also accept that same set of object types.To Reproduce
Add this test case to
mypyc/test-data/run-dunders.test:Run the strict dunder tests:
Expected Behavior
Both comparisons should work.
Since
__eq__is defined as:the generated
__ne__should accept the same other type and behave as though it were approximately:So this should pass:
Actual Behavior
The
==comparison succeeds, but the!=comparison fails at runtime because the implicitly generated__ne__expects the right-hand-side argument to beEq.In other words, the generated
__ne__appears to behave as though its RHS argument type came fromself, not from__eq__'s other parameter.