pybind11 icon indicating copy to clipboard operation
pybind11 copied to clipboard

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

Open haykh opened this issue 8 months ago • 0 comments

Required prerequisites

  • [x] Make sure you've read the documentation. Your issue may be addressed there.
  • [x] Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
  • [ ] Consider asking first in the Gitter chat room or in a Discussion.

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

haykh avatar Mar 16 '25 19:03 haykh