Skip to content

Conflation of NotImplemented and NotImplementedError #419

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

Closed
OddCoincidence opened this issue Feb 9, 2019 · 2 comments
Closed

Conflation of NotImplemented and NotImplementedError #419

OddCoincidence opened this issue Feb 9, 2019 · 2 comments

Comments

@OddCoincidence
Copy link
Contributor

OddCoincidence commented Feb 9, 2019

The contract for binary methods such as __add__, __eq__, etc. is such that they are expected to return NotImplemented error to signal lack of support for a particular type, in which case the interpreter will try flipping the operands, and finally fall back to object comparison (in the case of ==).

I believe that VirtualMachine::call_or_unsupported is RustPython's implementation of this behavior, but instead of using the NotImplemented built-in constant, it expects implementors to raise a NotImplementedError. This can be seen by calling the magic methods directly:

RustPython:

>>>>> (3).__sub__('')
Traceback (most recent call last):
  File <unknown>, line 0, in <module>
NotImplementedError: Cannot substract 'int' object and 'str' object

CPython:

>>> (3).__sub__('')
NotImplemented

This was discovered in #410.

@OddCoincidence
Copy link
Contributor Author

I have a fix for this, just waiting for #410 to be merged which adds the NotImplemented constant.

@silmeth
Copy link
Contributor

silmeth commented Feb 10, 2019

Some methods (mainly arithmetic ones?) also raise TypeErrors instead of returning NotImplemented.

Eg. in CPython:

>>> (12).__mul__('s')
NotImplemented

RustPython:

>>>>> (12).__mul__('s')
Traceback (most recent call last):
  File <stdin>, line 0, in <module>
TypeError: Cannot multiply 'int' object and 'str' object

or CPython:

>>> (12).__divmod__('s')
NotImplemented

RustPython:

>>>>> (12).__divmod__('s')
Traceback (most recent call last):
  File <stdin>, line 0, in <module>
TypeError: Cannot divmod power 'int' object and 'str' object

While some others just have implementation when they probably shouldn’t. Eg. comparing anything to int which isn’t an int or a float will return False:

CPython:

>>> (12).__eq__('s')
NotImplemented

RustPython:

>>>>> (12).__eq__('s')
False

This makes it impossible to implement custom types that can be equal to built-in ones, eg. in CPython:

>>> class Foo:
...   def __init__(self, payload):
...     self.payload = payload
...   def __eq__(self, other):
...     return self.payload == other
... 
>>> Foo(3) == 3
True
>>> 3 == Foo(3)
True 

So there is going to be some work needed cleaning all the methods…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants