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
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)