Skip to content

Commit c8a2be8

Browse files
THIS IS THE ISSUE: Revert "stl.h: propagate return value policies to type-specific casters (pybind#1455)"
This reverts commit cbd16a8.
1 parent 4d26a6e commit c8a2be8

File tree

6 files changed

+13
-43
lines changed

6 files changed

+13
-43
lines changed

include/pybind11/cast.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,13 +1869,9 @@ template <typename type> using cast_is_temporary_value_reference = bool_constant
18691869

18701870
// When a value returned from a C++ function is being cast back to Python, we almost always want to
18711871
// force `policy = move`, regardless of the return value policy the function/method was declared
1872-
// with.
1872+
// with. Some classes (most notably Eigen::Ref and related) need to avoid this, and so can do so by
1873+
// specializing this struct.
18731874
template <typename Return, typename SFINAE = void> struct return_value_policy_override {
1874-
static return_value_policy policy(return_value_policy p) { return p; }
1875-
};
1876-
1877-
template <typename Return> struct return_value_policy_override<Return,
1878-
detail::enable_if_t<std::is_base_of<type_caster_generic, make_caster<Return>>::value, void>> {
18791875
static return_value_policy policy(return_value_policy p) {
18801876
return !std::is_lvalue_reference<Return>::value && !std::is_pointer<Return>::value
18811877
? return_value_policy::move : p;

include/pybind11/eigen.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,14 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
458458
Type value;
459459
};
460460

461+
// Eigen Ref/Map classes have slightly different policy requirements, meaning we don't want to force
462+
// `move` when a Ref/Map rvalue is returned; we treat Ref<> sort of like a pointer (we care about
463+
// the underlying data, not the outer shell).
464+
template <typename Return>
465+
struct return_value_policy_override<Return, enable_if_t<is_eigen_dense_map<Return>::value>> {
466+
static return_value_policy policy(return_value_policy p) { return p; }
467+
};
468+
461469
// Base class for casting reference/map/block/etc. objects back to python.
462470
template <typename MapType> struct eigen_map_caster {
463471
private:

include/pybind11/pybind11.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class cpp_function : public function {
148148
capture *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
149149

150150
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
151-
return_value_policy policy = return_value_policy_override<Return>::policy(call.func.policy);
151+
const auto policy = return_value_policy_override<Return>::policy(call.func.policy);
152152

153153
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
154154
using Guard = extract_guard_t<Extra...>;

include/pybind11/stl.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ template <typename Type, typename Key> struct set_caster {
8383

8484
template <typename T>
8585
static handle cast(T &&src, return_value_policy policy, handle parent) {
86-
policy = return_value_policy_override<Key>::policy(policy);
8786
pybind11::set s;
8887
for (auto &&value : src) {
8988
auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
@@ -119,11 +118,9 @@ template <typename Type, typename Key, typename Value> struct map_caster {
119118
template <typename T>
120119
static handle cast(T &&src, return_value_policy policy, handle parent) {
121120
dict d;
122-
return_value_policy policy_key = return_value_policy_override<Key>::policy(policy);
123-
return_value_policy policy_value = return_value_policy_override<Value>::policy(policy);
124121
for (auto &&kv : src) {
125-
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
126-
auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
122+
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy, parent));
123+
auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy, parent));
127124
if (!key || !value)
128125
return handle();
129126
d[key] = value;
@@ -161,7 +158,6 @@ template <typename Type, typename Value> struct list_caster {
161158
public:
162159
template <typename T>
163160
static handle cast(T &&src, return_value_policy policy, handle parent) {
164-
policy = return_value_policy_override<Value>::policy(policy);
165161
list l(src.size());
166162
size_t index = 0;
167163
for (auto &&value : src) {
@@ -256,7 +252,6 @@ template<typename T> struct optional_caster {
256252
static handle cast(T_ &&src, return_value_policy policy, handle parent) {
257253
if (!src)
258254
return none().inc_ref();
259-
policy = return_value_policy_override<typename T::value_type>::policy(policy);
260255
return value_conv::cast(*std::forward<T_>(src), policy, parent);
261256
}
262257

@@ -361,7 +356,6 @@ struct variant_caster<V<Ts...>> {
361356
template <typename... Ts>
362357
struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { };
363358
#endif
364-
365359
NAMESPACE_END(detail)
366360

367361
inline std::ostream &operator<<(std::ostream &os, const handle &obj) {

tests/test_stl.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
#include "pybind11_tests.h"
11-
#include "constructor_stats.h"
1211
#include <pybind11/stl.h>
1312

1413
// Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14
@@ -236,21 +235,4 @@ TEST_SUBMODULE(stl, m) {
236235

237236
// test_stl_pass_by_pointer
238237
m.def("stl_pass_by_pointer", [](std::vector<int>* v) { return *v; }, "v"_a=nullptr);
239-
240-
class Placeholder {
241-
public:
242-
Placeholder() { print_created(this); }
243-
Placeholder(const Placeholder &) = delete;
244-
~Placeholder() { print_destroyed(this); }
245-
};
246-
py::class_<Placeholder>(m, "Placeholder");
247-
248-
/// test_stl_vector_ownership
249-
m.def("test_stl_ownership",
250-
[]() {
251-
std::vector<Placeholder *> result;
252-
result.push_back(new Placeholder());
253-
return result;
254-
},
255-
py::return_value_policy::take_ownership);
256238
}

tests/test_stl.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from pybind11_tests import stl as m
44
from pybind11_tests import UserType
5-
from pybind11_tests import ConstructorStats
65

76

87
def test_vector(doc):
@@ -199,12 +198,3 @@ def test_missing_header_message():
199198
with pytest.raises(TypeError) as excinfo:
200199
cm.missing_header_return()
201200
assert expected_message in str(excinfo.value)
202-
203-
204-
def test_stl_ownership():
205-
cstats = ConstructorStats.get(m.Placeholder)
206-
assert cstats.alive() == 0
207-
r = m.test_stl_ownership()
208-
assert len(r) == 1
209-
del r
210-
assert cstats.alive() == 0

0 commit comments

Comments
 (0)