Overloaded templated and untemplated member functions cause Cython Compiler Crash #1583

Open
scopatz opened this Issue Jan 17, 2017 · 3 comments

Projects

None yet

2 participants

@scopatz
scopatz commented Jan 17, 2017

When trying to wrap a C++ class that has a templates member function and a non-templated member function of the same name, the Cython compiler will crash on the first instance of either form being called. For example, in mostly valid Cython,

cdef extern from "toolkit/res_buf.h" namespace "cyclus::toolkit":

    cdef cppclass ResBuf[T]:
        void Push(shared_ptr[Resource])
        void Push[B](vector[B])

cdef class Wrapper:
    ResBuf[Resource] ptx

    def push(self, Resource r):
        self.ptx.Push(r.ptx)

    def push_all(self, rs):
        cdef std_vector[shared_ptr[Resource]] v
        for r in rs:
            v.push_back((<Resource> r).ptx)
        self.ptx.Push(v)

The first wrapper, push(), will crash with,

Error compiling Cython file:
------------------------------------------------------------
...
        rtn = r
        return rtn

    def push(self, _Material r):
        """Pushes a single resource object to the buffer."""
        self.ptx.Push(r.ptx)
                    ^
------------------------------------------------------------

/home/scopatz/cyclus/cyclus/typesystem.pyx:604:21: Compiler crash in AnalyseExpressionsTransform

ModuleNode.body = StatListNode(typesystem.pyx:9:0)
StatListNode.stats[23] = StatListNode(typesystem.pyx:494:5)
StatListNode.stats[0] = CClassDefNode(typesystem.pyx:494:5,
    as_name = '_ResBufMaterial',
    class_name = '_ResBufMaterial',
    module_name = '',
    visibility = 'private')
CClassDefNode.body = StatListNode(typesystem.pyx:496:4)
StatListNode.stats[13] = DefNode(typesystem.pyx:602:4,
    doc = 'Pushes a single resource object to the buffer.',
    modifiers = [...]/0,
    name = 'push',
    num_required_args = 2,
    py_wrapper_required = True,
    reqd_kw_flags_cname = '0',
    used = True)
File 'Nodes.py', line 430, in analyse_expressions: StatListNode(typesystem.pyx:603:8)
File 'Nodes.py', line 4746, in analyse_expressions: ExprStatNode(typesystem.pyx:604:21)
File 'ExprNodes.py', line 519, in analyse_expressions: SimpleCallNode(typesystem.pyx:604:21,
    analysed = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 5132, in analyse_types: SimpleCallNode(typesystem.pyx:604:21,
    analysed = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 5187, in analyse_c_function_call: SimpleCallNode(typesystem.pyx:604:21,
    analysed = True,
    use_managed_ref = True)

Compiler crash traceback from this point on:
  File "/home/scopatz/miniconda/lib/python3.5/site-packages/Cython/Compiler/ExprNodes.py", line 5187, in analyse_c_function_call
    [arg.type for arg in args], alternatives, self.pos, env, args)
  File "/home/scopatz/miniconda/lib/python3.5/site-packages/Cython/Compiler/PyrexTypes.py", line 4083, in best_match
    errors.append((func, "Unable to deduce type parameters for %s given %s" % (pattern.type, actual)))
NameError: name 'pattern' is not defined
cyclus/CMakeFiles/py_typesystem_.dir/build.make:62: recipe for target 'cyclus/py_typesystem_.cxx' failed

Note that the member function is templated on B, which is separate from the class template of T.

@robertwb
Contributor

Your code snippet seems to be missing several definitions. Could you provide a minimal, self-contained example?

@scopatz
scopatz commented Jan 21, 2017

As requested, here is a simple minimal example,

from libcpp.vector cimport vector

cdef extern from "example.h":

    cdef cppclass Wrapped[T]:
        void Push(T)
        void Push[T](vector[T])

cdef class Wrapper:
    cdef Wrapped[int]* ptx

    def push(self, int r):
        self.ptx.Push(r)

    def push_all(self, rs):
        cdef vector[int] v
        for r in rs:
            v.push_back(<int> r)
        self.ptx.Push(v)

Which fails with the following error for me,

scopatz@andromache ~/temp $ cython example.pyx 

Error compiling Cython file:
------------------------------------------------------------
...

    def push_all(self, rs):
        cdef vector[int] v
        for r in rs:
            v.push_back(<int> r)
        self.ptx.Push(v)                    ^
------------------------------------------------------------

example.pyx:19:21: Compiler crash in AnalyseExpressionsTransform

ModuleNode.body = StatListNode(example.pyx:1:0)
StatListNode.stats[1] = CClassDefNode(example.pyx:9:5,
    as_name = 'Wrapper',
    class_name = 'Wrapper',
    module_name = '',
    visibility = 'private')
CClassDefNode.body = StatListNode(example.pyx:10:4)
StatListNode.stats[1] = DefNode(example.pyx:15:4,
    modifiers = [...]/0,
    name = 'push_all',
    num_required_args = 2,
    py_wrapper_required = True,
    reqd_kw_flags_cname = '0',
    used = True)
File 'Nodes.py', line 430, in analyse_expressions: StatListNode(example.pyx:16:8)
File 'Nodes.py', line 4746, in analyse_expressions: ExprStatNode(example.pyx:19:21)
File 'ExprNodes.py', line 519, in analyse_expressions: SimpleCallNode(example.pyx:19:21,
    analysed = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 5132, in analyse_types: SimpleCallNode(example.pyx:19:21,
    analysed = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 5187, in analyse_c_function_call: SimpleCallNode(example.pyx:19:21,
    analysed = True,
    use_managed_ref = True)

Compiler crash traceback from this point on:
  File "/home/scopatz/miniconda/lib/python3.5/site-packages/Cython/Compiler/ExprNodes.py", line 5187, in analyse_c_function_call
    [arg.type for arg in args], alternatives, self.pos, env, args)
  File "/home/scopatz/miniconda/lib/python3.5/site-packages/Cython/Compiler/PyrexTypes.py", line 4088, in best_match
    type_list = [deductions[param] for param in func_type.templates]
  File "/home/scopatz/miniconda/lib/python3.5/site-packages/Cython/Compiler/PyrexTypes.py", line 4088, in <listcomp>
    type_list = [deductions[param] for param in func_type.templates]
KeyError: <Cython.Compiler.PyrexTypes.TemplatePlaceholderType object at 0x7f0a8b848898>
@scopatz
scopatz commented Jan 21, 2017

And if instead I use,

    def push_all(self, rs):
        cdef vector[int] v
        for r in rs:
            v.push_back(<int> r)
        self.ptx.Push[int](v)

which errors with

scopatz@andromache ~/temp $ cython example.pyx 

Error compiling Cython file:
------------------------------------------------------------
...

    def push_all(self, rs):
        cdef vector[int] v
        for r in rs:
            v.push_back(<int> r)
        self.ptx.Push[int](v)                    ^
------------------------------------------------------------

example.pyx:19:21: Can only parameterize template functions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment