Introducing check_is_smart_holder_type_caster() function for runtime check, and reinterpreting record.default_holder as "uses_unique_ptr_holder". With this test_smart_ptr succeeds. (All 42 tests build, 35 tests succeed, 5 run but have some failures, 2 segfault.)

This commit is contained in:
Ralf W. Grosse-Kunstleve 2021-02-05 13:37:06 -08:00
parent 357266db8d
commit 3cc0a8a598
3 changed files with 18 additions and 8 deletions

View File

@ -1201,11 +1201,18 @@ struct smart_holder_type_caster_class_hooks {
}
};
template <typename T>
inline bool check_is_smart_holder_type_caster();
template <typename T>
struct smart_holder_type_caster_load {
using holder_type = pybindit::memory::smart_holder;
bool load(handle src, bool convert) {
if (!check_is_smart_holder_type_caster<T>()) {
throw cast_error(
"Unable to load a smart-pointer type from a non-smart_holder instance.");
}
load_impl = modified_type_caster_generic_load_impl(typeid(T));
if (!load_impl.load(src, convert))
return false;
@ -2404,6 +2411,11 @@ struct is_smart_holder_type_caster<
T,
enable_if_t<type_caster<T>::is_smart_holder_type_caster::value, void>> : std::true_type {};
template <typename T>
inline bool check_is_smart_holder_type_caster() {
return detail::is_smart_holder_type_caster<T>::value;
}
// Detect whether returning a `type` from a cast on type's type_caster is going to result in a
// reference or pointer to a local variable of the type_caster. Basically, only
// non-reference/pointer `type`s and reference/pointers from a type_caster_generic are safe;

View File

@ -1307,11 +1307,10 @@ public:
record.holder_size = sizeof(holder_type);
record.init_instance = init_instance;
record.dealloc = dealloc;
#ifndef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT
// A better name would be uses_unique_ptr_holder.
record.default_holder = detail::is_instantiation<std::unique_ptr, holder_type>::value;
#else
record.default_holder = holder_is_smart_holder;
#endif
set_operator_new<type>(&record);
/* Register base classes specified via template arguments to class_, if any */

View File

@ -302,10 +302,9 @@ def test_smart_ptr_from_default():
instance = m.HeldByDefaultHolder()
with pytest.raises(RuntimeError) as excinfo:
m.HeldByDefaultHolder.load_shared_ptr(instance)
assert (
"Unable to load a custom holder type from a "
"default-holder instance" in str(excinfo.value)
)
assert str(excinfo.value) in (
"Unable to load a smart-pointer type from a non-smart_holder instance.",
"Unable to load a custom holder type from a default-holder instance")
def test_shared_ptr_gc():