Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify what happens for binary operators (e.g. __add__) #1548

Open
gvanrossum opened this issue Dec 21, 2023 · 3 comments
Open

Specify what happens for binary operators (e.g. __add__) #1548

gvanrossum opened this issue Dec 21, 2023 · 3 comments
Labels
topic: typing spec For improving the typing spec

Comments

@gvanrossum
Copy link
Member

There's a subtle dance around __add__, __radd__, and NotImplemented. While most of the rules are in the language spec, I think we haven't specified carefully what the signature should be of e.g. the __add__ method, especially when annotations are inline. (At least, I didn't find any mention of NotImplemented in the spec.)

In typeshed we seem to ignore the "overload" __add__: (Any) -> Literal[NotImplemented] (to be loose with notation), but what do typecheckers do when they see a concrete __add__ or __eq__ implementation that can return NotImplemented?

@gvanrossum gvanrossum added the topic: typing spec For improving the typing spec label Dec 21, 2023
@superbobry
Copy link

I think type checkers can implement the semantics of NotImplemented without actually requiring it in the types. Specifically, given a + b,

  • if type(a).__add__(b) type checks, i.e. type(a) has an overload expecting b, -- use that,
  • otherwise fall back type(b).__radd__(a).

Note also that

  • Literal[NotImplemented] is not permitted because NotImplemented is not an enum nor a literal syntactically;
  • NotImplementedType could be used to describe instances of NotImplemented, but it is not currently available from pure python AFAICT;
  • Alternatively, we could handle NotImplemented similarly to None in that NotImplemented in a type annotation means NotImplementedType.

@gvanrossum
Copy link
Member Author

Those are not the exact rules. Sometimes __radd__ is called first (the rule is so complicated I don't recall offhand if that can be determined statically or not). And when both return NotImplemented, the interpreter issues the exception.

Anyway, we might still consider this, given that the convention in typeshed appears to be not to show NotImplemented. (This would only be a problem for direct callers of these overloads, which must be very rare.)

I am aware of the issues around Literal[NotImplemented], I just used as a shorthand (if it did work, it would be ideal :-).

@JelleZijlstra
Copy link
Member

NotImplemented is generally just ignored by the type system; in typeshed we treat it as being a subclass of Any

https://github.com/python/typeshed/blob/d4daff337fc8ac122a10cff21ea2e7c9f3a30a6d/stdlib/builtins.pyi#L1261

I think to move forward here we'd need:

  • A survey of what type checkers currently do
  • Some thinking about how we could make the behavior more useful. Are there plausible user mistakes that type checkers currently can't catch, but that could be caught if we came up with a better set of rules? Conversely, are there patterns that work at runtime that type checkers currently do not allow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: typing spec For improving the typing spec
Projects
None yet
Development

No branches or pull requests

3 participants