[WIP] Towards a solution for custom-type rvalue arguments by rhaschke · Pull Request #2047 · pybind/pybind11 (original) (raw)

See also: #2583

Does not build with upstream master or #2047, but builds with https://github.com/RobotLocomotion/pybind11 and almost runs:

Running tests in directory "/usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests":
================================================================================= test session starts =================================================================================
platform linux -- Python 3.8.5, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests, inifile: pytest.ini
collected 2 items

test_unique_ptr_member.py .F                                                                                                                                                    [100%]

====================================================================================== FAILURES =======================================================================================
_____________________________________________________________________________ test_pointee_and_ptr_owner ______________________________________________________________________________

    def test_pointee_and_ptr_owner():
        obj = m.pointee()
        assert obj.get_int() == 213
        m.ptr_owner(obj)
        with pytest.raises(ValueError) as exc_info:
>           obj.get_int()
E           Failed: DID NOT RAISE <class 'ValueError'>

test_unique_ptr_member.py:17: Failed
============================================================================= 1 failed, 1 passed in 0.06s =============================================================================

https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder

Systematically exercising returning and passing unique_ptr, shared_ptr with unique_ptr, shared_ptr holder.

Observations:

test_holder_unique_ptr: make_unique_pointee OK pass_unique_pointee BUILD_FAIL (as documented) make_shared_pointee Abort free(): double free detected pass_shared_pointee RuntimeError: Unable to load a custom holder type from a default-holder instance

test_holder_shared_ptr: make_unique_pointee Segmentation fault (#1138) pass_unique_pointee BUILD_FAIL (as documented) make_shared_pointee OK pass_shared_pointee OK

https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder

Systematically exercising casting between shared_ptr, shared_ptr.

Based on https://godbolt.org/z/4fdjaW by jorgbrown@ (thanks Jorg!).

(This demo does NOT involve smart pointers at all, unlike the otherwise similar test_smart_ptr_private_first_base.)

See new bullet point in comment section near the top.

The variable was also renamed to reflect its function more accurately.

Open question, with respect to the original code: https://github.com/pybind/pybind11/blob/76a160070b369f8d82b945c97924227e8b835c94/include/pybind11/pybind11.h#L1510 To me it looks like the exact situation marked as std::shared_ptr<Good> gp1 = not_so_good.getptr(); here: https://en.cppreference.com/w/cpp/memory/enable_shared_from_this The comment there is: // undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17) Does the existing code have UB pre C++17?

I'll leave handling of enable_shared_from_this for later, as the need arises.

rwgk/rwgk_tbx@a2c2f88

These tests are from experimenting, and for demonstrating UB in pybind11 multiple inheritance handling ("first_base"), to be fixed later.

The user-facing macro is now PYBIND11_SMART_HOLDER_TYPE_CASTERS.

With this test_class.cpp builds and even mostly runs, except test_multiple_instances_with_same_pointer, which segfaults because it is using a unique_ptr holder but smart_holder type_caster.

Also adding static_asserts to generate build errors for such situations, but guarding with #if 0 to first pivot to test_factory_constructors.cpp.

This version of the code is ASAN clean with unique_ptr or smart_holder as the default.

This change needs to be reverted after adopting the existing move-only-if-refcount-is-1 logic used by type_caster_base.

[skip ci]

[skip ci]

Tested using github.com/rwgk/pybind11_scons and Google-internal build system. Sorry, no cmake support at the moment.

First results: https://docs.google.com/spreadsheets/d/1InapCYws2Gt-stmFf_Bwl33eOMo3aLE_gc9adveY7RU/edit#gid=0

[skip ci]

[skip ci]