From 5c1056953658f6400ea82dfb416e14396f454a37 Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Sat, 22 Jan 2022 00:59:30 -0500 Subject: [PATCH] Fix smart_holder multiple inheritance tests The original pybind11 holder supported multiple inheritance by recursively creating type casters until it finds one for the source type, then converting each value in turn to the next type via typeinfo->implicit_cast The smart_holder only stored the last implicit_cast, which was incorrect. This commit changes it to create a list of implicit_cast functions that are appended to during the recursive type caster creation, and when the time comes to cast to the destination type, it calls all of them in the correct order. --- .../pybind11/detail/smart_holder_type_casters.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/pybind11/detail/smart_holder_type_casters.h b/include/pybind11/detail/smart_holder_type_casters.h index 6eb5ef2773..17c40a3f23 100644 --- a/include/pybind11/detail/smart_holder_type_casters.h +++ b/include/pybind11/detail/smart_holder_type_casters.h @@ -90,7 +90,9 @@ class modified_type_caster_generic_load_impl { } loaded_v_h = sub_caster.loaded_v_h; loaded_v_h_cpptype = cast.first; - implicit_cast = cast.second; + // the sub_caster is being discarded, so steal its vector + implicit_casts = std::move(sub_caster.implicit_casts); + implicit_casts.emplace_back(cast.second); return true; } } @@ -149,7 +151,7 @@ class modified_type_caster_generic_load_impl { } loaded_v_h = foreign_loader->loaded_v_h; loaded_v_h_cpptype = foreign_loader->loaded_v_h_cpptype; - implicit_cast = foreign_loader->implicit_cast; + implicit_casts = foreign_loader->implicit_casts; // TODO: should this be a copy or move? return true; } return false; @@ -251,7 +253,7 @@ class modified_type_caster_generic_load_impl { const std::type_info *cpptype = nullptr; void *unowned_void_ptr_from_direct_conversion = nullptr; const std::type_info *loaded_v_h_cpptype = nullptr; - void *(*implicit_cast)(void *) = nullptr; + std::vector implicit_casts; value_and_holder loaded_v_h; bool reinterpret_cast_deemed_ok = false; // Magic number intentionally hard-coded, to guard against class_ holder mixups. @@ -521,8 +523,10 @@ struct smart_holder_type_caster_load { T *convert_type(void *void_ptr) const { if (void_ptr != nullptr && load_impl.loaded_v_h_cpptype != nullptr - && !load_impl.reinterpret_cast_deemed_ok && load_impl.implicit_cast != nullptr) { - void_ptr = load_impl.implicit_cast(void_ptr); + && !load_impl.reinterpret_cast_deemed_ok && !load_impl.implicit_casts.empty()) { + for (auto implicit_cast: load_impl.implicit_casts) { + void_ptr = implicit_cast(void_ptr); + } } return static_cast(void_ptr); }