From ee759881e94103064fe0d5ebe617a7127cf4b932 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 14 Dec 2010 11:01:48 +0100 Subject: [PATCH] do not generate vtable for subtypes of builtin types that do not define methods themselves --- Cython/Compiler/Symtab.py | 13 ++++ tests/run/builtin_type_inheritance_T608.pyx | 68 +++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 571dbb10..4573b3c3 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -1121,6 +1121,19 @@ class ModuleScope(Scope): type.vtabslot_cname = "%s.%s" % ( Naming.obj_base_cname, type.base_type.vtabslot_cname) elif type.scope and type.scope.cfunc_entries: + # one special case here: when inheriting from builtin + # types, the methods may also be built-in, in which + # case they won't need a vtable + entry_count = len(type.scope.cfunc_entries) + base_type = type.base_type + while base_type: + # FIXME: this will break if we ever get non-inherited C methods + if not base_type.scope or entry_count > len(base_type.scope.cfunc_entries): + break + if base_type.is_builtin_type: + # builtin base type defines all methods => no vtable needed + return + base_type = base_type.base_type #print "...allocating vtabslot_cname because there are C methods" ### type.vtabslot_cname = Naming.vtabslot_cname if type.vtabslot_cname: diff --git a/tests/run/builtin_type_inheritance_T608.pyx b/tests/run/builtin_type_inheritance_T608.pyx index dcf04fe6..8229a382 100644 --- a/tests/run/builtin_type_inheritance_T608.pyx +++ b/tests/run/builtin_type_inheritance_T608.pyx @@ -8,6 +8,35 @@ cdef class MyInt(int): """ cdef readonly object attr +cdef class MyInt2(int): + """ + >>> MyInt2(2) == 2 + True + >>> MyInt2(2).attr is None + True + >>> MyInt2(2).test(3) + 5 + """ + cdef readonly object attr + + def test(self, arg): + return self._test(arg) + + cdef _test(self, arg): + return self + arg + +cdef class MyInt3(MyInt2): + """ + >>> MyInt3(2) == 2 + True + >>> MyInt3(2).attr is None + True + >>> MyInt3(2).test(3) + 6 + """ + cdef _test(self, arg): + return self + arg + 1 + cdef class MyFloat(float): """ >>> MyFloat(1.0)== 1.0 @@ -23,6 +52,8 @@ cdef class MyUnicode(unicode): """ >>> MyUnicode(ustring) == ustring True + >>> MyUnicode(ustring + ustring) == ustring + False >>> MyUnicode(ustring).attr is None True """ @@ -37,6 +68,43 @@ cdef class MyList(list): """ cdef readonly object attr +cdef class MyListOverride(list): + """ + >>> MyListOverride([1,2,3]) == [1,2,3] + True + >>> l = MyListOverride([1,2,3]) + >>> l.reverse() + >>> l + [1, 2, 3, 5] + >>> l._reverse() + >>> l + [1, 2, 3, 5, 5] + """ + # not doctested: + """ + >>> l = MyListOverride([1,2,3]) + >>> l.append(8) + >>> l + [1, 2, 3, 0, 8] + >>> l._append(9) + >>> l + [1, 2, 3, 0, 8, 0, 9] + """ + def reverse(self): + self[:] = self + [5] + + def _reverse(self): + self.reverse() + + ## FIXME: this doesn't currently work: + + ## cdef int append(self, value) except -1: + ## self[:] = self + [0] + [value] + ## return 0 + + ## def _append(self, value): + ## self.append(value) + cdef class MyDict(dict): """ >>> MyDict({1:2, 3:4}) == {1:2, 3:4} -- 2.26.2