Infer common basetype for extension types.
authorRobert Bradshaw <robertwb@math.washington.edu>
Fri, 12 Feb 2010 10:31:57 +0000 (02:31 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Fri, 12 Feb 2010 10:31:57 +0000 (02:31 -0800)
Cython/Compiler/PyrexTypes.py
tests/run/type_inference.pyx

index d2e1666304aa11b5004e3a3dad2728afd3868eba..e9c4ff384e5ef5f1c83e31669c43d3766b622a30 100755 (executable)
@@ -2366,6 +2366,17 @@ def spanning_type(type1, type2):
         return widest_numeric_type(type1, c_double_type)
     elif type1.is_pyobject ^ type2.is_pyobject:
         return py_object_type
+    elif type1.is_extension_type and type2.is_extension_type:
+        if type1.typeobj_is_imported() or type2.typeobj_is_imported():
+            return py_object_type
+        while True:
+            if type1.subtype_of(type2):
+                return type2
+            elif type2.subtype_of(type1):
+                return type1
+            type1, type2 = type1.base_type, type2.base_type
+            if type1 is None or type2 is None:
+                return py_object_type
     elif type1.assignable_from(type2):
         if type1.is_extension_type and type1.typeobj_is_imported():
             # external types are unsafe, so we use PyObject instead
index 8ef4e2b4cb27238dd6c7c35511c2b7f6b3ee6183..b61cf191ac724d130262efe779c158790067ff7b 100644 (file)
@@ -304,3 +304,36 @@ def args_tuple_keywords_reassign_pyobjects(*args, **kwargs):
 
     args = []
     kwargs = "test"
+
+#                 / A -> AA -> AAA
+# Base0 -> Base -
+#                 \ B -> BB
+# C -> CC
+
+cdef class Base0: pass
+cdef class Base(Base0): pass
+cdef class A(Base): pass
+cdef class AA(A): pass
+cdef class AAA(AA): pass
+cdef class B(Base): pass
+cdef class BB(B): pass
+cdef class C: pass
+cdef class CC(C): pass
+
+@infer_types(None)
+def common_extension_type_base():
+    """
+    >>> common_extension_type_base()
+    """
+    x = A()
+    x = AA()
+    assert typeof(x) == "A", typeof(x)
+    y = A()
+    y = B()
+    assert typeof(y) == "Base", typeof(y)
+    z = AAA()
+    z = BB()
+    assert typeof(z) == "Base", typeof(z)
+    w = A()
+    w = CC()
+    assert typeof(w) == "Python object", typeof(w)