pythoncythonstatic-typing

Cython function pointer with fused type input: Invalid use of fused types, type cannot be specialized


Differ from earlier post, I work with all cdef function here. If I work with function pointer of fused_type input, it will raise "Invalid use of fused types, type cannot be specialized". On the contrary, the function pointer with built-in type works well. Why?

cimport cython


# raise error
ctypedef fused fused_type:
   float
   int

ctypedef fused_type (* _func_pointer) (fused_type[:])

cdef fused_type base_func(fused_type[:] arg1):
   return arg1[0]

cdef fused_type c_entry(fused_type[:] arg1, _func_pointer func):
   return func(arg1)

cdef fused_type base_wrapper(fused_type[:] arg1):
   return c_entry(arg1, base_func)

""" -------   """
# works
cdef int base_func(int[:] arg1):
   return arg1[0]

cdef int c_entry(int[:] arg1, _func_pointer func):
   return func(arg1)

cdef int base_wrapper(int[:] arg1):
   return c_entry(arg1, base_func)


Solution

  • You need to change it to

    cdef fused_type base_wrapper(fused_type[:] arg1):
       return c_entry(arg1, base_func[fused_type])
    

    When base_wrapper is specialized, that selects the specialization of base_func for whatever fused_type currently is in base_wrapper.


    The rough explanation of why:

    ctypedef fused_type (* _func_pointer) (fused_type[:])
    

    This doesn't define a function pointer type that takes and returns fused_type. Instead it defines a fused type with containing two types:

    float (*)(float[:])
    int (*)(int[:])
    

    When you do base_func on its own it isn't a "real" function - you get one of the specializations either by calling it, or my manually selecting it (e.g. base_func[int]).

    Therefore in base_wrapper the line return c_entry(arg1, base_func) doesn't know which specialization of base_func it should be using, and therefore can't pick which of the two types of _func_pointer it should match.

    The Cython fused type system is fairly dump and doesn't make too much of an effort to resolve confusion - it's either an unambiguous exact match or no match at all.