Skip to content

Commit

Permalink
Reproducer and fix for issue encountered in smart_holder update. (#4228)
Browse files Browse the repository at this point in the history
* Reproducer for issue encountered in smart_holder update.

* clang-tidy compatibility (untested).

* Add `enable_if_t` to workaround.

* Bug fix: Move `PYBIND11_USING_WORKAROUND_FOR_CUDA_11_4_THROUGH_8` determination to detail/common.h

So that it actually is defined in pybind11.h

* Try using the workaround (which is nicer than the original code) universally.

* Reduce reproducer for CUDA 11.7 issue encountered in smart_holder update.

This commit tested in isolation on top of current master + first version of reproducer (62311eb).

Succeeds with Debian Clang 14.0.6 C++17 (and probably all other compilers).

Fails for CUDA 11.7:

```
cd /build/tests && /usr/local/cuda/bin/nvcc -forward-unknown-to-host-compiler -Dpybind11_tests_EXPORTS -I/mounted_pybind11/include -isystem=/usr/include/python3.10 -g --generate-code=arch=compute_52,code=[compute_52,sm_52] -Xcompiler=-fPIC -Xcompiler=-fvisibility=hidden -Werror all-warnings -std=c++17 -MD -MT tests/CMakeFiles/pybind11_tests.dir/test_class.cpp.o -MF CMakeFiles/pybind11_tests.dir/test_class.cpp.o.d -x cu -c /mounted_pybind11/tests/test_class.cpp -o CMakeFiles/pybind11_tests.dir/test_class.cpp.o
/mounted_pybind11/tests/test_class.cpp(53): error: more than one instance of overloaded function "pybind11::class_<type_, options...>::def [with type_=test_class::pr4220_tripped_over_this::Empty0, options=<>]" matches the argument list:
            function template "pybind11::class_<test_class::pr4220_tripped_over_this::Empty0> &pybind11::class_<type_, options...>::def(const char *, Func &&, const Extra &...) [with type_=test_class::pr4220_tripped_over_this::Empty0, options=<>]"
/mounted_pybind11/include/pybind11/pybind11.h(1557): here
            function template "pybind11::class_<test_class::pr4220_tripped_over_this::Empty0> &pybind11::class_<type_, options...>::def(const T &, const Extra &...) [with type_=test_class::pr4220_tripped_over_this::Empty0, options=<>]"
/mounted_pybind11/include/pybind11/pybind11.h(1586): here
            argument types are: (const char [8], <unknown-type>)
            object type is: pybind11::class_<test_class::pr4220_tripped_over_this::Empty0>

1 error detected in the compilation of "/mounted_pybind11/tests/test_class.cpp".
```
  • Loading branch information
Ralf W. Grosse-Kunstleve authored Oct 10, 2022
1 parent 7c6f2f8 commit da104a9
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 19 deletions.
1 change: 1 addition & 0 deletions include/pybind11/operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct op_impl {};
/// Operator implementation generator
template <op_id id, op_type ot, typename L, typename R>
struct op_ {
static constexpr bool op_enable_if_hook = true;
template <typename Class, typename... Extra>
void execute(Class &cl, const Extra &...extra) const {
using Base = typename Class::type;
Expand Down
21 changes: 2 additions & 19 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -1578,34 +1578,17 @@ class class_ : public detail::generic_type {
return *this;
}

// Nvidia's NVCC is broken between 11.4.0 and 11.8.0
// https://github.com/pybind/pybind11/issues/4193
#if defined(__CUDACC__) && (__CUDACC_VER_MAJOR__ == 11) && (__CUDACC_VER_MINOR__ >= 4) \
&& (__CUDACC_VER_MINOR__ <= 8)
template <typename T, typename... Extra>
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
class_ &def(const T &op, const Extra &...extra) {
op.execute(*this, extra...);
return *this;
}

template <typename T, typename... Extra>
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
class_ &def_cast(const T &op, const Extra &...extra) {
op.execute_cast(*this, extra...);
return *this;
}
#else
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
op.execute(*this, extra...);
return *this;
}

template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
class_ &def_cast(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
op.execute_cast(*this, extra...);
return *this;
}
#endif

template <typename... Args, typename... Extra>
class_ &def(const detail::initimpl::constructor<Args...> &init, const Extra &...extra) {
Expand Down
22 changes: 22 additions & 0 deletions tests/test_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ struct NoBraceInitialization {
std::vector<int> vec;
};

namespace test_class {
namespace pr4220_tripped_over_this { // PR #4227

template <int>
struct SoEmpty {};

template <typename T>
std::string get_msg(const T &) {
return "This is really only meant to exercise successful compilation.";
}

using Empty0 = SoEmpty<0x0>;

void bind_empty0(py::module_ &m) {
py::class_<Empty0>(m, "Empty0").def(py::init<>()).def("get_msg", get_msg<Empty0>);
}

} // namespace pr4220_tripped_over_this
} // namespace test_class

TEST_SUBMODULE(class_, m) {
// test_instance
struct NoConstructor {
Expand Down Expand Up @@ -517,6 +537,8 @@ TEST_SUBMODULE(class_, m) {
py::class_<OtherDuplicateNested>(gt, "OtherDuplicateNested");
py::class_<OtherDuplicateNested>(gt, "YetAnotherDuplicateNested");
});

test_class::pr4220_tripped_over_this::bind_empty0(m);
}

template <int N>
Expand Down
7 changes: 7 additions & 0 deletions tests/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,3 +469,10 @@ class ClassScope:
m.register_duplicate_nested_class_type(ClassScope)
expected = 'generic_type: type "YetAnotherDuplicateNested" is already registered!'
assert str(exc_info.value) == expected


def test_pr4220_tripped_over_this():
assert (
m.Empty0().get_msg()
== "This is really only meant to exercise successful compilation."
)

0 comments on commit da104a9

Please sign in to comment.