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

[BUG] classmethods don't compile using the limited api #5797

Closed
ap-- opened this issue Nov 5, 2023 · 0 comments · Fixed by #5800
Closed

[BUG] classmethods don't compile using the limited api #5797

ap-- opened this issue Nov 5, 2023 · 0 comments · Fixed by #5800
Assignees
Milestone

Comments

@ap--
Copy link
Contributor

ap-- commented Nov 5, 2023

Describe the bug

Hello everyone,

When compiling a class with a classmethod using the limited API I get the following error:

clang -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -DCYTHON_LIMITED_API=1 -DPy_LIMITED_API=0x030B0000 -I/private/var/folders/l4/gpyzwv455hzbmbv78x05555h0000gn/T/build-env-ok8opy1u/include -I/opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include/python3.11 -c limited_classmethod.cpp -o build/temp.macosx-14-arm64-cpython-311/limited_classmethod.o
limited_classmethod.cpp:6876:5: error: no matching function for call to 'Py_TYPE'
    __Pyx_PyHeapTypeObject_GC_Del(m);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
limited_classmethod.cpp:971:26: note: expanded from macro '__Pyx_PyHeapTypeObject_GC_Del'
    PyTypeObject *type = Py_TYPE(obj);\
                         ^~~~~~~
/opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include/python3.11/object.h:132:29: note: candidate function not viable: no known conversion from '__pyx_CyFunctionObject *' to 'PyObject *' (aka '_object *') for 1st argument
static inline PyTypeObject* Py_TYPE(PyObject *ob) {
                            ^
limited_classmethod.cpp:7396:9: error: use of undeclared identifier 'PyMethodDescrObject'; did you mean 'PyMethodDescr_Type'?
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
        ^~~~~~~~~~~~~~~~~~~
        PyMethodDescr_Type
/opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include/python3.11/descrobject.h:22:26: note: 'PyMethodDescr_Type' declared here
PyAPI_DATA(PyTypeObject) PyMethodDescr_Type;
                         ^
limited_classmethod.cpp:7396:39: error: use of undeclared identifier 'PyMethodDescrObject'; did you mean 'PyMethodDescr_Type'?
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
                                      ^~~~~~~~~~~~~~~~~~~
                                      PyMethodDescr_Type
/opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include/python3.11/descrobject.h:22:26: note: 'PyMethodDescr_Type' declared here
PyAPI_DATA(PyTypeObject) PyMethodDescr_Type;
                         ^
limited_classmethod.cpp:7396:60: error: expected expression
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
                                                           ^
limited_classmethod.cpp:7396:30: error: use of undeclared identifier 'descr'
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
                             ^
limited_classmethod.cpp:7400:32: error: use of undeclared identifier 'descr'
        PyTypeObject *d_type = descr->d_common.d_type;
                               ^
limited_classmethod.cpp:7402:47: error: use of undeclared identifier 'descr'
        return PyDescr_NewClassMethod(d_type, descr->d_method);
                                              ^
limited_classmethod.cpp:7405:14: error: use of undeclared identifier 'PyMethod_Check'
    else if (PyMethod_Check(method)) {
             ^
limited_classmethod.cpp:7406:34: error: use of undeclared identifier 'PyMethod_GET_FUNCTION'
        return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
                                 ^
limited_classmethod.cpp:7409:16: error: use of undeclared identifier 'PyClassMethod_New'
        return PyClassMethod_New(method);
               ^
10 errors generated.

Code to reproduce the behaviour:

# limited_classmethod.pyx

cdef class A:
    @classmethod
    def method(cls):
        pass

Expected behaviour

It should compile.

OS

No response

Python version

No response

Cython version

No response

Additional context

classmethod implementation:

//////////////////// ClassMethod.proto ////////////////////
#include "descrobject.h"
CYTHON_UNUSED static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
//////////////////// ClassMethod ////////////////////
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
#if CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM <= 0x05080000
if (PyObject_TypeCheck(method, &PyWrapperDescr_Type)) {
// cdef classes
return PyClassMethod_New(method);
}
#else
#if CYTHON_COMPILING_IN_PYPY
// special C-API function only in PyPy >= 5.9
if (PyMethodDescr_Check(method))
#else
#if PY_MAJOR_VERSION == 2
// PyMethodDescr_Type is not exposed in the CPython C-API in Py2.
static PyTypeObject *methoddescr_type = NULL;
if (unlikely(methoddescr_type == NULL)) {
PyObject *meth = PyObject_GetAttrString((PyObject*)&PyList_Type, "append");
if (unlikely(!meth)) return NULL;
methoddescr_type = Py_TYPE(meth);
Py_DECREF(meth);
}
#else
PyTypeObject *methoddescr_type = &PyMethodDescr_Type;
#endif
if (__Pyx_TypeCheck(method, methoddescr_type))
#endif
{
// cdef classes
PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
#if PY_VERSION_HEX < 0x03020000
PyTypeObject *d_type = descr->d_type;
#else
PyTypeObject *d_type = descr->d_common.d_type;
#endif
return PyDescr_NewClassMethod(d_type, descr->d_method);
}
#endif
else if (PyMethod_Check(method)) {
// python classes
return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
}
else {
return PyClassMethod_New(method);
}
}

@da-woods da-woods assigned da-woods and unassigned da-woods Nov 5, 2023
da-woods added a commit to da-woods/cython that referenced this issue Nov 5, 2023
Except for the class where binding=False, which I don't think
we can easily do. I don't care that much given that binding=True
works correctly.

Fixes cython#5797
@da-woods da-woods added this to the 3.1 milestone May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants