Commit 33707f2e authored by Stefan Behnel's avatar Stefan Behnel

Avoid generating a tp_new() function for extension types that do not need their own one.

See #1555.
parent 85d2424f
......@@ -60,6 +60,11 @@ Bugs fixed
semantics. It now passes through the Mapping protocol first when supported.
(Github issue #1807)
* Extension types that do not need their own ``tp_new`` implementation (because
they have no object attributes etc.) directly inherit the implementation of
their parent type if that is available in the same module.
(Github issue #1555)
* The ``Py_hash_t`` type failed to accept arbitrary "index" values.
(Github issue #2752)
......
......@@ -1270,8 +1270,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.empty_declaration_code()))
def generate_new_function(self, scope, code, cclass_entry):
tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
tp_slot = TypeSlots.ConstructorSlot("tp_new", "__cinit__")
slot_func = scope.mangle_internal("tp_new")
if tp_slot.slot_code(scope) != slot_func:
return # never used
type = scope.parent_type
base_type = type.base_type
......@@ -1554,7 +1557,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_usr_dealloc_call(self, scope, code):
entry = scope.lookup_here("__dealloc__")
if not entry:
if not entry or not entry.is_special:
return
code.putln("{")
......
......@@ -362,17 +362,17 @@ class GCClearReferencesSlot(GCDependentSlot):
class ConstructorSlot(InternalMethodSlot):
# Descriptor for tp_new and tp_dealloc.
def __init__(self, slot_name, method, **kargs):
def __init__(self, slot_name, method=None, **kargs):
InternalMethodSlot.__init__(self, slot_name, **kargs)
self.method = method
def slot_code(self, scope):
entry = scope.lookup_here(self.method)
if (self.slot_name != 'tp_new'
and scope.parent_type.base_type
entry = scope.lookup_here(self.method) if self.method else None
if (scope.parent_type.base_type
and not scope.has_pyobject_attrs
and not scope.has_memoryview_attrs
and not scope.has_cpp_class_attrs
and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)
and not (entry and entry.is_special)):
# if the type does not have object attributes, it can
# delegate GC methods to its parent - iff the parent
......@@ -382,8 +382,6 @@ class ConstructorSlot(InternalMethodSlot):
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if entry.visibility != 'extern':
return self.slot_code(parent_type_scope)
if entry and not entry.is_special:
return "0"
return InternalMethodSlot.slot_code(self, scope)
......@@ -877,7 +875,7 @@ slot_table = (
MethodSlot(initproc, "tp_init", "__init__"),
EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
InternalMethodSlot("tp_new"),
ConstructorSlot("tp_new", "__cinit__"),
EmptySlot("tp_free"),
EmptySlot("tp_is_gc"),
......
# mode: run
# tag: exttype, tpnew
from __future__ import print_function
from cpython.object cimport PyTypeObject
cdef gobble(a, b):
print a, b
print(a, b)
def tp_new_ptr(exttype):
assert isinstance(exttype, type)
tp = <PyTypeObject*> exttype
return <unsigned long long><void*>tp.tp_new
cdef class Empty:
"""
>>> n = Empty()
>>> isinstance(n, Empty)
True
>>> tp_new_ptr(Empty) != 0
True
"""
cdef class EmptySubclass(Empty):
"""
>>> n = EmptySubclass()
>>> isinstance(n, EmptySubclass)
True
>>> tp_new_ptr(EmptySubclass) != 0
True
>>> tp_new_ptr(EmptySubclass) == tp_new_ptr(Empty)
True
"""
cdef class CInit:
"""
>>> c = CInit()
>>> isinstance(c, CInit)
True
"""
def __cinit__(self):
assert self is not None
cdef class Spam:
"""
......@@ -21,6 +67,7 @@ cdef class Spam:
def eat(self):
gobble(self.eggs, self.ham)
def f(Spam spam):
"""
>>> s = Spam(12)
......
# mode: run
# tag: exttype, tpnew
# ticket: 808
cimport cython
......
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