You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Return type of "__eq__" incompatible with supertype "object" #2783
Return type of "__eq__" incompatible with supertype "object"
Return type of "__ne__" incompatible with supertype "object"
As far as I understand Python data model doesn't require rich comparison methods to return bool. Is it Mypy specific requirement or is there something wrong with my class definition?
This is because of the return type of object.__eq__ in typeshed. Formally you are right that any return type is accepted at runtime, but changing the static type could hide some "design errors" that are otherwise difficult to catch.
Any is a possible solution. However, using #type: ignore comments on those two particular lines could be more strict, since mypy will catch errors below in code:
classExpr:
def__eq__(self, other: Any) ->'Expr': # type: ignorereturnExpr()
def__ne__(self, other: Any) ->'Expr': # type: ignorereturn42# Error: Incompatible return value type (got "int", expected "Expr")x=Expr() ==0x.bad# Error: "Expr" has no attribute "bad"
while with Any such error will be unnoticed by mypy.
I wonder if the return type of object.__eq__ in typeshed should be object, since the bool return type is not quite correct. The same applies to __lt__ and friends.
@ilevkivskyi Using your suggestion of appending # type: ignore to the line does indeed work quite well. But I find it personally very counter-intuitive, seeing a line with type-hints and an additional type: ignore annotation. It makes it look like the type is completely ignored on that line.
@JukkaL commented on Feb 1, 2017
I wonder if the return type of object.__eq__ in typeshed should be object, since the bool return type is not quite correct. The same applies to __lt__ and friends.
Given the implementation, I would suggest the return type should be Union[NoReturn, Any]. object.__eq__ always throws a NotImplementedError (hence the NoReturn) and Any allows sub-classes to override the return type to anything they like.
Glancing at the CPython code, I don't think object.__eq__ can throw a NotImplementedError, it only returns bools (assuming it's not overridden in a subclass). I could be reading this wrong or looking in the wrong place though.
The union with NoReturn isn't necessary, as that's implied on every function (see discussions in other issues).
If we make it return Any, then x == y loses all type information, which isnt desirable for 99% of use cases, so existing signatures should remain bool.
That said, I agree with you that we need to broaden the use cases that are supported. I like the unsafe override decorator proposal in #5704, and I think that that along with addressing some usability issues would go a long way.
* Glancing at the CPython code, I don't think `object.__eq__` can throw a `NotImplementedError`, it only returns bools
I am so sorry, you are right! It does not throw NotImplementedError, instead it returns NotImplemented:
assertobject().__eq__(object()) ==NotImplemented
Which would be fine, because it is consistent with Any. But for the reasons mentioned above, the type annotation in typeshed is bool which makes it more restrictive than it needs to be.
Some related discussion in #6710, which is more about the unexpected downstream effects of the # type: ignore.
Thanks a lot for linking to this! It is a difficult problem and I am happy to see you and the maintainers of mypy give it well-deserved attention.
Now it's possible to use # type: ignore[override], which is more explicit and safer than # type: ignore. Closing this issue on the assumption that this is good enough (better documentation would be useful, however).
Reacted by Saul Shanabrook, Lawrence Chan, Marat Sharafutdinov and Christopher Peisert
Activity
ilevkivskyi commentedon Jan 31, 2017
This is because of the return type of
object.__eq__intypeshed. Formally you are right that any return type is accepted at runtime, but changing the static type could hide some "design errors" that are otherwise difficult to catch.zero323 commentedon Jan 31, 2017
Thank you for a quick response @ilevkivskyi. How would you proceed in case like this? I thought about
Any:which is a bit suboptimal but seems acceptable. Does it make sense to you?
ilevkivskyi commentedon Feb 1, 2017
Anyis a possible solution. However, using#type: ignorecomments on those two particular lines could be more strict, since mypy will catch errors below in code:while with
Anysuch error will be unnoticed by mypy.EDIT: extended the example.
JukkaL commentedon Feb 1, 2017
I wonder if the return type of
object.__eq__in typeshed should beobject, since theboolreturn type is not quite correct. The same applies to__lt__and friends.zero323 commentedon Feb 1, 2017
Thanks @ilevkivskyi
exhuma commentedon Sep 12, 2018
@ilevkivskyi Using your suggestion of appending
# type: ignoreto the line does indeed work quite well. But I find it personally very counter-intuitive, seeing a line with type-hints and an additionaltype: ignoreannotation. It makes it look like the type is completely ignored on that line.mvaled commentedon Sep 25, 2018
I got this is issue by looking for: Argument 1 of "eq" incompatible with supertype "object"
In this case, I tried to put the '# type: ignore' in the same line as the comment type annotation without luck.
msullivan commentedon Sep 25, 2018
It needs to be on the line with the function declaration
Add type ignores for dunder eq/ne methods
Victor-Savu commentedon May 1, 2019
Given the implementation, I would suggest the return type should be
Union[NoReturn, Any].object.__eq__always throws aNotImplementedError(hence theNoReturn) andAnyallows sub-classes to override the return type to anything they like.llchan commentedon May 1, 2019
object.__eq__can throw aNotImplementedError, it only returns bools (assuming it's not overridden in a subclass). I could be reading this wrong or looking in the wrong place though.NoReturnisn't necessary, as that's implied on every function (see discussions in other issues).Any, thenx == yloses all type information, which isnt desirable for 99% of use cases, so existing signatures should remainbool.That said, I agree with you that we need to broaden the use cases that are supported. I like the unsafe override decorator proposal in #5704, and I think that that along with addressing some usability issues would go a long way.
llchan commentedon May 1, 2019
Some related discussion in #6710, which is more about the unexpected downstream effects of the
# type: ignore.Victor-Savu commentedon May 2, 2019
I am so sorry, you are right! It does not throw NotImplementedError, instead it returns NotImplemented:
Which would be fine, because it is consistent with
Any. But for the reasons mentioned above, the type annotation in typeshed isboolwhich makes it more restrictive than it needs to be.Thanks a lot for linking to this! It is a difficult problem and I am happy to see you and the maintainers of mypy give it well-deserved attention.
JukkaL commentedon Jan 29, 2020
Now it's possible to use
# type: ignore[override], which is more explicit and safer than# type: ignore. Closing this issue on the assumption that this is good enough (better documentation would be useful, however).