Check for Python instance is uninitialized/disowned in type_caster_base.h. CRUDE intermediate state, needs refactoring.

All 4 remaining BAKEIN_BREAK removed from test_class_sh_basic.py. With that both test_class_sh_basic.cpp and test_class_sh_basic.py are identical to the smart_holder branch.

All unit tests pass ASAN and MSAN testing with the Google-internal toolchain.
This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-07-05 00:20:23 -07:00
parent fd1afdb2b9
commit 0b7a628a04
3 changed files with 24 additions and 4 deletions

View File

@ -411,6 +411,7 @@ private:
holder_type &holder() const { return loaded_v_h.holder<holder_type>(); }
// BAKEIN_WIP: This needs to be factored out: see type_caster_base.h
// have_holder() must be true or this function will fail.
void throw_if_uninitialized_or_disowned_holder(const char *typeid_name) const {
static const std::string missing_value_msg = "Missing value for wrapped C++ type `";

View File

@ -13,6 +13,7 @@
#include "common.h"
#include "descr.h"
#include "internals.h"
#include "smart_holder_poc.h"
#include "typeid.h"
#include <cstdint>
@ -632,6 +633,24 @@ public:
// Base methods for generic caster; there are overridden in copyable_holder_caster
void load_value(value_and_holder &&v_h) {
if (typeinfo->default_holder) {
// BAKEIN_WIP: This needs to be factored out:
// throw_if_uninitialized_or_disowned_holder()
if (v_h.vh != nullptr && v_h.holder_constructed()) {
using h_t = pybindit::memory::smart_holder;
h_t &holder = v_h.holder<h_t>();
static const std::string missing_value_msg
= "Missing value for wrapped C++ type `";
if (!holder.is_populated) {
throw value_error(missing_value_msg + clean_type_id(typeid(cpptype).name())
+ "`: Python instance is uninitialized.");
}
if (!holder.has_pointee()) {
throw value_error(missing_value_msg + clean_type_id(typeid(cpptype).name())
+ "`: Python instance was disowned.");
}
}
}
auto *&vptr = v_h.value_ptr();
// Lazy allocation for unallocated values:
if (vptr == nullptr) {

View File

@ -168,10 +168,10 @@ def test_unique_ptr_cref_roundtrip():
@pytest.mark.parametrize(
("pass_f", "rtrn_f", "moved_out", "moved_in"),
[
# BAKEIN_BREAK (m.uconsumer.pass_valu, m.uconsumer.rtrn_valu, True, True),
# BAKEIN_BREAK (m.uconsumer.pass_rref, m.uconsumer.rtrn_valu, True, True),
# BAKEIN_BREAK (m.uconsumer.pass_valu, m.uconsumer.rtrn_lref, True, False),
# BAKEIN_BREAK (m.uconsumer.pass_valu, m.uconsumer.rtrn_cref, True, False),
(m.uconsumer.pass_valu, m.uconsumer.rtrn_valu, True, True),
(m.uconsumer.pass_rref, m.uconsumer.rtrn_valu, True, True),
(m.uconsumer.pass_valu, m.uconsumer.rtrn_lref, True, False),
(m.uconsumer.pass_valu, m.uconsumer.rtrn_cref, True, False),
],
)
def test_unique_ptr_consumer_roundtrip(pass_f, rtrn_f, moved_out, moved_in):