Fix smart_holder multiple inheritance tests (#3635)

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.
This commit is contained in:
Dustin Spicuzza 2022-01-26 22:02:49 -05:00 committed by GitHub
parent b2f0b091c9
commit fd8265e28d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -99,7 +99,9 @@ public:
} }
loaded_v_h = sub_caster.loaded_v_h; loaded_v_h = sub_caster.loaded_v_h;
loaded_v_h_cpptype = cast.first; 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; return true;
} }
} }
@ -180,7 +182,7 @@ public:
} }
loaded_v_h = foreign_loader->loaded_v_h; loaded_v_h = foreign_loader->loaded_v_h;
loaded_v_h_cpptype = foreign_loader->loaded_v_h_cpptype; loaded_v_h_cpptype = foreign_loader->loaded_v_h_cpptype;
implicit_cast = foreign_loader->implicit_cast; implicit_casts = foreign_loader->implicit_casts; // SMART_HOLDER_WIP: should this be a copy or move?
return true; return true;
} }
return false; return false;
@ -286,7 +288,7 @@ public:
void *unowned_void_ptr_from_direct_conversion = nullptr; void *unowned_void_ptr_from_direct_conversion = nullptr;
void *unowned_void_ptr_from_void_ptr_capsule = nullptr; void *unowned_void_ptr_from_void_ptr_capsule = nullptr;
const std::type_info *loaded_v_h_cpptype = nullptr; const std::type_info *loaded_v_h_cpptype = nullptr;
void *(*implicit_cast)(void *) = nullptr; std::vector<void *(*)(void *)> implicit_casts;
value_and_holder loaded_v_h; value_and_holder loaded_v_h;
bool reinterpret_cast_deemed_ok = false; bool reinterpret_cast_deemed_ok = false;
// Magic number intentionally hard-coded, to guard against class_ holder mixups. // Magic number intentionally hard-coded, to guard against class_ holder mixups.
@ -567,8 +569,10 @@ private:
T *convert_type(void *void_ptr) const { T *convert_type(void *void_ptr) const {
if (void_ptr != nullptr && load_impl.loaded_v_h_cpptype != nullptr if (void_ptr != nullptr && load_impl.loaded_v_h_cpptype != nullptr
&& !load_impl.reinterpret_cast_deemed_ok && load_impl.implicit_cast != nullptr) { && !load_impl.reinterpret_cast_deemed_ok && !load_impl.implicit_casts.empty()) {
void_ptr = load_impl.implicit_cast(void_ptr); for (auto implicit_cast: load_impl.implicit_casts) {
void_ptr = implicit_cast(void_ptr);
}
} }
return static_cast<T *>(void_ptr); return static_cast<T *>(void_ptr);
} }