Introduce detail::both_t_and_d_use_type_caster_base<T, D> helper and use systematically in all property_cpp_function<> specializations.

This fixes a PyTorch build error (using the Google-internal toolchain):

```
In file included from third_party/py/torch/torch/csrc/distributed/c10d/init.cpp:15:
In file included from third_party/py/torch/torch/csrc/distributed/c10d/PyProcessGroup.hpp:4:
In file included from third_party/py/torch/torch/csrc/jit/python/pybind_utils.h:7:
In file included from third_party/pybind11/include/pybind11/complex.h:14:
In file included from third_party/pybind11/include/pybind11/pybind11.h:14:
In file included from third_party/pybind11/include/pybind11/detail/class.h:14:
In file included from third_party/pybind11/include/pybind11/detail/../attr.h:16:
third_party/pybind11/include/pybind11/detail/../cast.h:856:19: error: static assertion failed due to requirement 'std::is_base_of<pybind11::detail::type_caster_base<c10::intrusive_ptr<c10d::Store, c10::detail::intrusive_target_default_null_type<c10d::Store>>>, pybind11::detail::type_caster<c10::intrusive_ptr<c10d::Store, c10::detail::intrusive_target_default_null_type<c10d::Store>>, void>>::value': Holder classes are only supported for custom types
  856 |     static_assert(std::is_base_of<base, type_caster<type>>::value,
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
third_party/pybind11/include/pybind11/detail/../cast.h:982:48: note: in instantiation of template class 'pybind11::detail::copyable_holder_caster<c10::intrusive_ptr<c10d::Store>, std::shared_ptr<c10::intrusive_ptr<c10d::Store>>>' requested here
  982 | class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> {};
      |                                                ^
third_party/crosstool/v18/stable/src/libcxx/include/__type_traits/is_base_of.h:22:91: note: in instantiation of template class 'pybind11::detail::type_caster<std::shared_ptr<c10::intrusive_ptr<c10d::Store>>>' requested here
   22 | struct _LIBCPP_TEMPLATE_VIS is_base_of : public integral_constant<bool, __is_base_of(_Bp, _Dp)> {};
      |                                                                                           ^
third_party/pybind11/include/pybind11/detail/../cast.h:1382:30: note: in instantiation of template class 'std::is_base_of<pybind11::detail::type_caster_generic, pybind11::detail::type_caster<std::shared_ptr<c10::intrusive_ptr<c10d::Store>>>>' requested here
 1382 |     detail::enable_if_t<std::is_base_of<type_caster_generic, make_caster<Return>>::value, void>> {
      |                              ^
third_party/pybind11/include/pybind11/pybind11.h:287:19: note: during template argument deduction for class template partial specialization 'return_value_policy_override<Return, detail::enable_if_t<std::is_base_of<type_caster_generic, make_caster<Return>>::value, void>>' [with Return = std::shared_ptr<c10::intrusive_ptr<c10d::Store>>]
  287 |                 = return_value_policy_override<Return>::policy(call.func.policy);
      |                   ^
third_party/pybind11/include/pybind11/pybind11.h:287:19: note: in instantiation of template class 'pybind11::detail::return_value_policy_override<std::shared_ptr<c10::intrusive_ptr<c10d::Store>>>' requested here
third_party/pybind11/include/pybind11/pybind11.h:269:55: note: while substituting into a lambda expression here
  269 |         rec->impl = [](function_call &call) -> handle {
      |                                                       ^
third_party/pybind11/include/pybind11/pybind11.h:147:9: note: in instantiation of function template specialization 'pybind11::cpp_function::initialize<(lambda at third_party/pybind11/include/pybind11/pybind11.h:1714:17), std::shared_ptr<c10::intrusive_ptr<c10d::Store>>, pybind11::handle, pybind11::is_method>' requested here
  147 |         initialize(
      |         ^
third_party/pybind11/include/pybind11/pybind11.h:1713:20: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<(lambda at third_party/pybind11/include/pybind11/pybind11.h:1714:17), pybind11::is_method, void>' requested here
 1713 |             return cpp_function(
      |                    ^
third_party/pybind11/include/pybind11/pybind11.h:1964:54: note: in instantiation of function template specialization 'pybind11::property_cpp_function<c10d::DistributedBackendOptions, c10::intrusive_ptr<c10d::Store>>::read<c10::intrusive_ptr<c10d::Store> c10d::DistributedBackendOptions::*, 0>' requested here
 1964 |                      property_cpp_function<type, D>::read(pm, *this),
      |                                                      ^
third_party/py/torch/torch/csrc/distributed/c10d/init.cpp:945:8: note: in instantiation of function template specialization 'pybind11::class_<c10d::DistributedBackendOptions>::def_readwrite<c10d::DistributedBackendOptions, c10::intrusive_ptr<c10d::Store>>' requested here
  945 |       .def_readwrite("store", &::c10d::DistributedBackendOptions::store)
      |        ^
1 error generated.
```
This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-07-14 20:58:08 -07:00
parent 89da1e2ef7
commit ff3693f1bb

View File

@ -1623,6 +1623,23 @@ struct property_cpp_function {
}
};
PYBIND11_NAMESPACE_BEGIN(detail)
template <typename T, typename D, typename SFINAE = void>
struct both_t_and_d_use_type_caster_base : std::false_type {};
// `T` is assumed to be equivalent to `intrinsic_t<T>`.
// `D` is not.
template <typename T, typename D>
struct both_t_and_d_use_type_caster_base<
T,
D,
enable_if_t<all_of<std::is_base_of<type_caster_base<T>, type_caster<T>>,
std::is_base_of<type_caster_base<intrinsic_t<D>>, make_caster<D>>>::value>>
: std::true_type {};
PYBIND11_NAMESPACE_END(detail)
// BAKEIN_WIP: Rewrite comment.
// smart_holder specializations for raw pointer members.
// WARNING: Like the classic implementation, this implementation can lead to dangling pointers.
@ -1634,10 +1651,8 @@ template <typename T, typename D>
struct property_cpp_function<
T,
D,
detail::enable_if_t<
detail::all_of<std::is_base_of<detail::type_caster_generic, detail::type_caster<T>>,
std::is_base_of<detail::type_caster_generic, detail::make_caster<D>>,
std::is_pointer<D>>::value>> {
detail::enable_if_t<detail::all_of<std::is_pointer<D>,
detail::both_t_and_d_use_type_caster_base<T, D>>::value>> {
using drp = typename std::remove_pointer<D>::type;
@ -1679,16 +1694,14 @@ struct property_cpp_function<
// https://github.com/google/clif/blob/c371a6d4b28d25d53a16e6d2a6d97305fb1be25a/clif/python/instance.h#L233
// This prevents disowning of the Python object owning the member.
template <typename T, typename D>
struct property_cpp_function<
T,
struct property_cpp_function<T,
D,
detail::enable_if_t<
detail::all_of<std::is_base_of<detail::type_caster_generic, detail::type_caster<T>>,
std::is_base_of<detail::type_caster_generic, detail::make_caster<D>>,
detail::enable_if_t<detail::all_of<
detail::none_of<std::is_pointer<D>,
std::is_array<D>,
detail::is_instantiation<std::unique_ptr, D>,
detail::is_instantiation<std::shared_ptr, D>>>::value>> {
detail::is_instantiation<std::shared_ptr, D>>,
detail::both_t_and_d_use_type_caster_base<T, D>>::value>> {
template <typename PM, must_be_member_function_pointer<PM> = 0>
static cpp_function readonly(PM pm, const handle &hdl) {
@ -1742,11 +1755,9 @@ template <typename T, typename D>
struct property_cpp_function<
T,
D,
detail::enable_if_t<
detail::all_of<std::is_base_of<detail::type_caster_generic, detail::type_caster<T>>,
detail::enable_if_t<detail::all_of<
detail::is_instantiation<std::unique_ptr, D>,
std::is_base_of<detail::type_caster_generic,
detail::make_caster<typename D::element_type>>>::value>> {
detail::both_t_and_d_use_type_caster_base<T, typename D::element_type>>::value>> {
template <typename PM, must_be_member_function_pointer<PM> = 0>
static cpp_function readonly(PM, const handle &) {