do not generate vtable for subtypes of builtin types that do not define methods thems...
authorStefan Behnel <scoder@users.berlios.de>
Tue, 14 Dec 2010 10:01:48 +0000 (11:01 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Tue, 14 Dec 2010 10:01:48 +0000 (11:01 +0100)
Cython/Compiler/Symtab.py
tests/run/builtin_type_inheritance_T608.pyx

index 571dbb1070b09f94c7c200135610e976f014f0b7..4573b3c38281a587b957b4ecaa7b2a1fccf4452d 100644 (file)
@@ -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:
index dcf04fe6fc125409a305b5bba0c0360e79475db0..8229a3829f9039148cae27d3e06b085280849ebf 100644 (file)
@@ -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}