Skip to content

[BUG]: Compiling with enum_ on CUDA + GCC fails #5565

@haykh

Description

@haykh

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

stable

Problem description

I reduced the problem to a very simple snippet (see below; also see the repo with minimal example).

Which fails when cross-compiling with CUDA (I use the Kokkos cross-portability library). Weirdly, this works perfectly fine, if instead of GCC I use LLVM (still with CUDA support ON). If you think this is not a pybind11 issue -- feel free to close, but just wanted to throw this in, as perhaps there is an easy thing I'm overlooking.

Here's the error message with GCC 14 and CUDA 12.8:
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h: In instantiation of ‘pybind11::enum_<Type>::enum_(const pybind11::handle&, const char*, const Extra& ...) [with Extra = {pybind11::arithmetic}; Type = pybind11_init_enumtest(pybind11::module_&)::ScopedEnum]’:
/tmp/testenum/enumtest.cpp:9:70:   required from here
    9 |   py::enum_<ScopedEnum>(m, "ScopedEnum", py::arithmetic())
      |                                                                      ^
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h:2237:9: error: ambiguous template instantiation for ‘struct pybind11::detail::initimpl::factory<pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>, pybind11::detail::void_type (*)(), pybind11_init_enumtest(pybind11::module_&)::ScopedEnum(int), pybind11::detail::void_type()>’
 2237 |         def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/testenum/extern/pybind11/include/pybind11/detail/init.h:281:8: note: candidates are: ‘template<class Func, class Return, class ... Args> struct pybind11::detail::initimpl::factory<Func, pybind11::detail::void_type (*)(), Return(Args ...), __remove_pointer(__remove_reference(pybind11::detail::void_type (*)()))> [with Func = pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>; Return = pybind11_init_enumtest(pybind11::module_&)::ScopedEnum; Args = {int}]’
  281 | struct factory<Func, void_type (*)(), Return(Args...)> {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/testenum/extern/pybind11/include/pybind11/detail/init.h:320:8: note:                 ‘template<class CFunc, class AFunc, class CReturn, class ... CArgs, class AReturn, class ... AArgs> struct pybind11::detail::initimpl::factory<CFunc, AFunc, CReturn(CArgs ...), AReturn(AArgs ...)> [with CFunc = pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>; AFunc = pybind11::detail::void_type (*)(); CReturn = pybind11_init_enumtest(pybind11::module_&)::ScopedEnum; CArgs = {int}; AReturn = pybind11::detail::void_type; AArgs = {}]’
  320 | struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h:2237:9: error: invalid use of incomplete type ‘struct pybind11::detail::initimpl::factory<pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>, pybind11::detail::void_type (*)(), pybind11_init_enumtest(pybind11::module_&)::ScopedEnum(int), pybind11::detail::void_type()>’
 2237 |         def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/testenum/extern/pybind11/include/pybind11/detail/init.h:276:42: note: declaration of ‘struct pybind11::detail::initimpl::factory<pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>, pybind11::detail::void_type (*)(), pybind11_init_enumtest(pybind11::module_&)::ScopedEnum(int), pybind11::detail::void_type()>’
  276 |           typename = function_signature_t<AFunc>>
      |                                          ^~~~~~~
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h: In instantiation of ‘Ret pybind11::init(Func&&) [with Func = enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>; Ret = detail::initimpl::factory<enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&,
const char*, const pybind11::arithmetic&)::<lambda(enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>, detail::void_type (*)(), pybind11_init_enumtest(pybind11::module_&)::ScopedEnum(int), detail::void_type()>]’:
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h:2237:9:   required from ‘pybind11::enum_<Type>::enum_(const pybind11::handle&, const char*, const Extra& ...) [with Extra = {pybind11::arithmetic}; Type = pybind11_init_enumtest(pybind11::module_&)::ScopedEnum]’
 2237 |         def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/testenum/enumtest.cpp:9:70:   required from here
    9 |   py::enum_<ScopedEnum>(m, "ScopedEnum", py::arithmetic())
      |                                                                      ^
/tmp/testenum/extern/pybind11/include/pybind11/pybind11.h:1970:1: error: return type ‘struct pybind11::detail::initimpl::factory<pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::enum_<pybind11::arithmetic>(const pybind11::handle&, const char*, const pybind11::arithmetic&)::<lambda(pybind11::enum_<pybind11_init_enumtest(pybind11::module_&)::ScopedEnum>::Scalar)>, pybind11::detail::void_type (*)(), pybind11_init_enumtest(pybind11::module_&)::ScopedEnum(int), pybind11::detail::void_type()>’ is incomplete
 1970 | Ret init(Func &&f) {
      | ^~~~
make[2]: *** [CMakeFiles/enumtest.dir/build.make:79: CMakeFiles/enumtest.dir/enumtest.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:376: CMakeFiles/enumtest.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

Thanks in advance for you help, and for the cool library you've made!

Reproducible example code

#include <pybind11/pybind11.h>

namespace py = pybind11;

PYBIND11_MODULE(enumtest, m) {
  m.doc() = "Test simple enum";

  enum class ScopedEnum { Two = 2, Three };
  py::enum_<ScopedEnum>(m, "ScopedEnum", py::arithmetic())
      .value("Two", ScopedEnum::Two)
      .value("Three", ScopedEnum::Three);
}

Is this a regression? Put the last known working version here if it is.

Not a regression

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNew bug, unverified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions