Commit 8d8795c6 authored by Matti Picus's avatar Matti Picus Committed by Stefan Behnel

Emit init code before body code (GH-3166)

The test crash in cdef_multiple_inheritance has to do with a change in the method assignment. In the old version, the code

cdef class Both(CBase, PyBase):
    cdef dict __dict__
    cdef c_method(self):
        return "Both"
    cpdef cp_method(self):
        return "Both"
    def call_c_method(self):
        return self.c_method()

would assign cp_method and call_c_method to a PyMethodDef struct. In the new code only call_c_method is assigned in the PyMethodDef struct, but both are assigned to the __pyx_ptype...Both->tp_dict inside __Pyx_Init_Globals which happens while __pyx_ptype...Both is still NULL. The assignment __pyx_ptype...Both = &__pyx_type...Both happens in the next fragment, a few lines down.

This PR reorders the fragments so that __pyx_type...Both is set up before the method assignments and does not seem to cause any new test failures.
parent 08cdad19
...@@ -5036,8 +5036,6 @@ class CClassDefNode(ClassDefNode): ...@@ -5036,8 +5036,6 @@ class CClassDefNode(ClassDefNode):
# This is needed to generate evaluation code for # This is needed to generate evaluation code for
# default values of method arguments. # default values of method arguments.
code.mark_pos(self.pos) code.mark_pos(self.pos)
if self.body:
self.body.generate_execution_code(code)
if not self.entry.type.early_init: if not self.entry.type.early_init:
if self.type_init_args: if self.type_init_args:
self.type_init_args.generate_evaluation_code(code) self.type_init_args.generate_evaluation_code(code)
...@@ -5065,6 +5063,8 @@ class CClassDefNode(ClassDefNode): ...@@ -5065,6 +5063,8 @@ class CClassDefNode(ClassDefNode):
self.type_init_args.free_temps(code) self.type_init_args.free_temps(code)
self.generate_type_ready_code(self.entry, code, True) self.generate_type_ready_code(self.entry, code, True)
if self.body:
self.body.generate_execution_code(code)
# Also called from ModuleNode for early init types. # Also called from ModuleNode for early init types.
@staticmethod @staticmethod
......
cimport cython
cdef class CBase(object): cdef class CBase(object):
cdef int a cdef int a
cdef c_method(self): cdef c_method(self):
...@@ -9,7 +11,8 @@ class PyBase(object): ...@@ -9,7 +11,8 @@ class PyBase(object):
def py_method(self): def py_method(self):
return "PyBase" return "PyBase"
cdef class Both(CBase, PyBase): @cython.binding(True)
cdef class BothBound(CBase, PyBase):
cdef dict __dict__ cdef dict __dict__
""" """
>>> b = Both() >>> b = Both()
...@@ -32,7 +35,7 @@ cdef class Both(CBase, PyBase): ...@@ -32,7 +35,7 @@ cdef class Both(CBase, PyBase):
def call_c_method(self): def call_c_method(self):
return self.c_method() return self.c_method()
cdef class BothSub(Both): cdef class BothSub(BothBound):
""" """
>>> b = BothSub() >>> b = BothSub()
>>> b.py_method() >>> b.py_method()
...@@ -43,3 +46,27 @@ cdef class BothSub(Both): ...@@ -43,3 +46,27 @@ cdef class BothSub(Both):
'Both' 'Both'
""" """
pass pass
@cython.binding(False)
cdef class BothUnbound(CBase, PyBase):
cdef dict __dict__
"""
>>> b = Both()
>>> b.py_method()
'PyBase'
>>> b.cp_method()
'Both'
>>> b.call_c_method()
'Both'
>>> isinstance(b, CBase)
True
>>> isinstance(b, PyBase)
True
"""
cdef c_method(self):
return "Both"
cpdef cp_method(self):
return "Both"
def call_c_method(self):
return self.c_method()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment