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
In particular, for (c) the primer actually looks really good. We have ~50 fixed Unused "type: ignore" comment errors, and 16 suprious [override] errors eliminated, without any new errors.
Previous (partial) discussion: #3685. I still believe that implementations that intentionally violate the contract of __eq__ (which makes sense when building a DSL) should explicitly use # type: ignore.
I agree, I think it's an important soundness check, and I wouldn't want to hinder type checkers' ability to provide that soundness check. While there are some established libraries that do this, and it might make sense in certain very narrow situations in new code, I think these are the exceptions rather than the rule. I think it's overall very desirable for type checkers to complain about __eq__ methods that accept a narrower type than object or return a non-bool. That's usually a mistake that will have bad consequences and mean that type checkers are unable to spot bugs in your code elsewhere.
What about at least allowing Any for the argument type, and leaving the return type as-is?
As far as I understand it, type-checkers have more or less settled for interpreting the argument annotation of __eq__ as the types for which the method will not return NotImplemented.
So for instance if my class only supports __eq__ with Self | float and otherwise would return NotImplemented, I'd like to annotate it as such, but this will trigger override, even if th return is bool.
What about at least allowing Any for the argument type, and leaving the return type as-is?
But I think having an incorrect argument type is usually the way that most people write unsound __eq__ methods. If we made this change, type checkers wouldn't emit any errors on this snippet, even though it fails at runtime:
The last example by @AlexWaygood is instructive, this makes me think that there's nothing that typeshed currently can do about the situation.
However, I do want to point out that many DSLs, like for example polars.Series already break this.
Moreover, I think it is likely that people who make this mistake in the first place will likely either:
Activity
srittau commentedon Jan 30, 2026
Previous (partial) discussion: #3685. I still believe that implementations that intentionally violate the contract of
__eq__(which makes sense when building a DSL) should explicitly use# type: ignore.AlexWaygood commentedon Jan 30, 2026
I agree, I think it's an important soundness check, and I wouldn't want to hinder type checkers' ability to provide that soundness check. While there are some established libraries that do this, and it might make sense in certain very narrow situations in new code, I think these are the exceptions rather than the rule. I think it's overall very desirable for type checkers to complain about
__eq__methods that accept a narrower type thanobjector return a non-bool. That's usually a mistake that will have bad consequences and mean that type checkers are unable to spot bugs in your code elsewhere.randolf-scholz commentedon Jan 30, 2026
What about at least allowing
Anyfor the argument type, and leaving the return type as-is?As far as I understand it, type-checkers have more or less settled for interpreting the argument annotation of
__eq__as the types for which the method will not returnNotImplemented.So for instance if my class only supports
__eq__withSelf | floatand otherwise would returnNotImplemented, I'd like to annotate it as such, but this will triggeroverride, even if th return isbool.AlexWaygood commentedon Jan 30, 2026
But I think having an incorrect argument type is usually the way that most people write unsound
__eq__methods. If we made this change, type checkers wouldn't emit any errors on this snippet, even though it fails at runtime:randolf-scholz commentedon Feb 2, 2026
The last example by @AlexWaygood is instructive, this makes me think that there's nothing that typeshed currently can do about the situation.
However, I do want to point out that many DSLs, like for example
polars.Seriesalready break this.Moreover, I think it is likely that people who make this mistake in the first place will likely either:
use a bad
type: igore[override]break the design of operators by doing
rather than