Skip to content

Fix py::cast(std::shared_ptr<T>) for shared_ptr-compatible custom holders#6065

Draft
virtuald wants to merge 3 commits into
pybind:masterfrom
virtuald:custom-holder-shared-ptr
Draft

Fix py::cast(std::shared_ptr<T>) for shared_ptr-compatible custom holders#6065
virtuald wants to merge 3 commits into
pybind:masterfrom
virtuald:custom-holder-shared-ptr

Conversation

@virtuald
Copy link
Copy Markdown
Contributor

Description

Fixes #6064. I don't really like this approach, it seems like a lot of obscure code to support an edge case, and the thread_local is hard to follow.

Suggested changelog entry:

  • Placeholder.

virtuald and others added 3 commits May 17, 2026 03:51
This restores support for custom holders that are constructible from std::shared_ptr<T> without requiring user code changes or an internals ABI bump.

The fix keeps the safety check added in pybind#6008 for incompatible custom holders, but adds an internal path for compatible ones:
- py::cast(std::shared_ptr<T>) now recognizes bound types using custom holders
- it tunnels shared ownership through an internal thread-local payload
- non-smart-holder init_instance() consumes that payload and constructs the bound holder when Holder<T> is constructible from std::shared_ptr<T>

This preserves the regression fix for unsafe cases while allowing established patterns such as private-destructor types wrapped by shared_ptr-backed custom holders to keep working.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: py::cast() from std::shared_ptr throws with custom holder

1 participant