Home > database >  Subtype Polymorphism is broken in Cython v30.0.0a11?
Subtype Polymorphism is broken in Cython v30.0.0a11?

Time:10-23

Trying to pass an instance of a derived class to a function which accepts instances of the superclass gives an error in Cython v3.0.0a11:

test.pyx:

class MyInt(int):
    pass

def takes_int(a: int):
    pass

try.py:

from test import takes_int, MyInt

takes_int(MyInt(1))

try.py OUTPUT:

Traceback (most recent call last):
  File "C:\Users\LENOVO PC\PycharmProjects\MyProject\cython_src\try.py", line 3, in <module>
    takes_int(MyInt(1))
TypeError: Argument 'a' has incorrect type (expected int, got MyInt)

Changing to v0.29.32, cleaning the generated C file and the object files, and re-running, gets rid of the error.

CodePudding user response:

This is (kind of) expected.

Cython has never allowed subtype polymorphism for builtin type arguments. See https://cython.readthedocs.io/en/latest/src/userguide/language_basics.html#types:

This requires an exact match of the class, it does not allow subclasses. This allows Cython to optimize code by accessing internals of the builtin class, which is the main reason for declaring builtin types in the first place.

This is a restriction which applies only to builtin types - for Cython defined cdef classes it works fine. It's also slightly different to the usual rule for annotations, but it's there because it's the only way that Cython can do much with these annotation.

What's changed is that an int annotation is interpreted as "any object" in Cython 0.29.x and a Python int in Cython 3. (Note that cdef int declares a C int though.) The reason for not using an int annotation in earlier versions of Cython is that Python 2 has two Python integer types, and it isn't easy to accept both of those and usefully use the types.

I'm not quite sure exactly what the final version of Cython 3 will end up doing with int annotations though.


If you don't want Cython to use the annotation (for example you would like your int class to be accepted) then you can turn off annotation_typing locally with the @cython.annotation_typing(False) decorator.

  • Related