mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-25 07:14:50 +00:00
[skip ci] test: reject shared_ptr casts for custom holders (#6069)
Lock down the current behavior discussed in issue #6064: py::cast() from std::shared_ptr<T> remains rejected for custom holder bindings that are not std::shared_ptr or py::smart_holder. This extracts the incompatible-holder coverage from PR #6068 and adds a test shaped like issue #6064, while PR #6065 and PR #6066 explore alternative support paths.
This commit is contained in:
committed by
GitHub
parent
3160c82392
commit
28bbda9ddf
@@ -83,6 +83,24 @@ private:
|
||||
// for demonstration purpose only, this imitates smart pointer with a const-only pointer
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class shared_ptr_as_custom_holder {
|
||||
std::shared_ptr<T> ptr_;
|
||||
|
||||
public:
|
||||
using element_type = T;
|
||||
|
||||
shared_ptr_as_custom_holder() = default;
|
||||
|
||||
explicit shared_ptr_as_custom_holder(T *) {
|
||||
throw std::runtime_error("invalid shared_ptr_as_custom_holder constructor call");
|
||||
}
|
||||
|
||||
explicit shared_ptr_as_custom_holder(std::shared_ptr<T> ptr) : ptr_(std::move(ptr)) {}
|
||||
|
||||
T *get() const { return ptr_.get(); }
|
||||
};
|
||||
|
||||
// Custom object with builtin reference counting (see 'object.h' for the implementation)
|
||||
class MyObject1 : public Object {
|
||||
public:
|
||||
@@ -239,6 +257,17 @@ struct SharedFromThisRef {
|
||||
std::shared_ptr<B> shared = std::make_shared<B>();
|
||||
};
|
||||
|
||||
class Issue6064UnsafePath {
|
||||
public:
|
||||
static std::shared_ptr<Issue6064UnsafePath> create() {
|
||||
return {new Issue6064UnsafePath(), [](Issue6064UnsafePath *ptr) { delete ptr; }};
|
||||
}
|
||||
|
||||
private:
|
||||
Issue6064UnsafePath() = default;
|
||||
~Issue6064UnsafePath() = default;
|
||||
};
|
||||
|
||||
// Issue #865: shared_from_this doesn't work with virtual inheritance
|
||||
struct SharedFromThisVBase : std::enable_shared_from_this<SharedFromThisVBase> {
|
||||
SharedFromThisVBase() = default;
|
||||
@@ -341,6 +370,7 @@ struct holder_helper<ref<T>> {
|
||||
// Make pybind aware of the ref-counted wrapper type (s):
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>, true)
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, const_only_shared_ptr<T>, true)
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_as_custom_holder<T>)
|
||||
// The following is not required anymore for std::shared_ptr, but it should compile without error:
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>)
|
||||
@@ -501,6 +531,10 @@ TEST_SUBMODULE(smart_ptr, m) {
|
||||
.def(py::init([](const std::string &value) { return MyObject6::createObject(value); }))
|
||||
.def_property_readonly("value", &MyObject6::value);
|
||||
|
||||
py::class_<Issue6064UnsafePath, shared_ptr_as_custom_holder<Issue6064UnsafePath>>(
|
||||
m, "Issue6064UnsafePath");
|
||||
m.def("get_issue6064_unsafe_path_shared_ptr", []() { return Issue6064UnsafePath::create(); });
|
||||
|
||||
// test_shared_ptr_and_references
|
||||
using A = SharedPtrRef::A;
|
||||
py::class_<A, std::shared_ptr<A>>(m, "A");
|
||||
@@ -559,6 +593,7 @@ TEST_SUBMODULE(smart_ptr, m) {
|
||||
py::class_<C, custom_unique_ptr<C>>(m, "TypeWithMoveOnlyHolder")
|
||||
.def_static("make", []() { return custom_unique_ptr<C>(new C); })
|
||||
.def_static("make_as_object", []() { return py::cast(custom_unique_ptr<C>(new C)); });
|
||||
m.def("get_type_with_move_only_holder_shared_ptr", []() { return std::make_shared<C>(); });
|
||||
|
||||
// test_holder_with_addressof_operator
|
||||
using HolderWithAddressOf = shared_ptr_with_addressof_operator<TypeForHolderWithAddressOf>;
|
||||
|
||||
@@ -368,3 +368,27 @@ def test_move_only_holder_caster_shared_ptr_with_smart_holder_support_enabled():
|
||||
def test_const_only_holder():
|
||||
o = m.MyObject6("my_data")
|
||||
assert o.value == "my_data"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"cast_shared_ptr",
|
||||
[
|
||||
pytest.param(
|
||||
m.get_type_with_move_only_holder_shared_ptr,
|
||||
id="incompatible-custom-holder",
|
||||
),
|
||||
pytest.param(
|
||||
m.get_issue6064_unsafe_path_shared_ptr,
|
||||
id="issue6064-unsafe-path",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_shared_ptr_cast_for_custom_holder_throws(cast_shared_ptr):
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match=(
|
||||
"Unable to convert std::shared_ptr<T> to Python when the bound type does not use"
|
||||
" std::shared_ptr or py::smart_holder as its holder type"
|
||||
),
|
||||
):
|
||||
cast_shared_ptr()
|
||||
|
||||
Reference in New Issue
Block a user