Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support Bound for classmethod and pass_module #3831

Merged
merged 4 commits into from
Feb 16, 2024

Conversation

davidhewitt
Copy link
Member

This is a tidied-up copy of #3744 without any attempts to change #[pymodule].

This PR focuses on updating #[classmethod] and #[pyfunction(pass_module)] to accept &Bound<PyType> and &Bound<PyModule> respectively. It allows them to accept GIL Refs for backwards compatibility.

We were already using Into for these conversions, so I created a new helper type BoundRef(&Bound<T>) which implements the Into conversions for &T, &Bound<T>, and Py<T>. The reason for the new helper type was because I didn't want to support From<&Bound<T>> for &T.

@@ -179,11 +179,11 @@ error: macros cannot be used as items in `#[pymethods]` impl blocks
197 | macro_invocation!();
| ^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `i32: From<&PyType>` is not satisfied
error[E0277]: the trait bound `i32: From<BoundRef<'_, '_, PyType>>` is not satisfied
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is notably worse than it was before, but I think once we remove the GIL Ref compatibility and go back to just &Bound<PyType> it improves. I can live with it being a bit janky for a couple of releases. If reviewers feel strongly that we should try to make this nicer I can experiment at cost of making the implementation more complex.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(One upside of a more complex implementation is that I might be able to emit deprecation warnings for using GIL Refs in these positions.)

@davidhewitt davidhewitt added the CI-skip-changelog Skip checking changelog entry label Feb 13, 2024
tests/test_class_basics.rs Outdated Show resolved Hide resolved
src/instance.rs Outdated
@@ -138,6 +138,14 @@ impl<'py> Bound<'py, PyAny> {
) -> PyResult<Self> {
Py::from_owned_ptr_or_err(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj)))
}

#[inline]
pub(crate) unsafe fn from_ref_to_ptr<'a>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really get this name. How about from_borrowed_ptr?

Same on BoundRef

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, I couldn't work out a good name either. I didn't feel borrowed is quite right here because that's got a very specific meaning in the Python C API to refer to a pointer return value which doesn't carry ownership.

How about just from_raw?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think this API will remain crate-private for the foreseeable future, so the name doesn't have to be perfect 😄)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, since this is internal its not super important. I'm also fine with from_raw. I think I also get now that you were intending to reference this (unusual) construct & *mut _, but yesterday i read it like it was turning a reference into a pointer, while it was doing kind of the opposite 🙈

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see why the from_x_to_y bit reads wrong.

On reflection I think Bound::from_raw isn't quite the right name for this API. I still can't think of anything better. from_shared_ref_ptr? from_borrow_on_raw_pointer? from_ptr_shared_ref?

I'm kinda ok with a clumsy name here given this is an internal API really only intended to give a lifetime 'a in &'a Bound<'_, PyAny>.

I think of the options I wrote above, from_ptr_shared_ref might make the most sense to me. Any of those which you like?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I have a particular preference among these. If i had to pick i would probably choose between from_shared_ref_ptr and from_ptr_shared_ref. So I'm fine with your preference. Another option that came to my mind was something like ref_from_ptr or shared_from_ptr, but I dont't feel strongly about these either.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quite like ref_from_ptr, let's go with that 👍

Copy link
Contributor

@Icxolu Icxolu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍

@davidhewitt
Copy link
Member Author

Thanks for the review! I decided to add a doc to ref_from_ptr and will proceed to merge 👍

Copy link

codspeed-hq bot commented Feb 16, 2024

CodSpeed Performance Report

Merging #3831 will degrade performances by 15.02%

Comparing davidhewitt:bound-classmethod-pass-module (ebfc2c3) with main (f3ddd02)

Summary

❌ 2 regressions
✅ 77 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark main davidhewitt:bound-classmethod-pass-module Change
list_via_downcast 157.2 ns 185 ns -15.02%
not_a_list_via_downcast 216.7 ns 244.4 ns -11.36%

@davidhewitt davidhewitt added this pull request to the merge queue Feb 16, 2024
Merged via the queue into PyO3:main with commit ec6d587 Feb 16, 2024
37 of 39 checks passed
@davidhewitt davidhewitt deleted the bound-classmethod-pass-module branch February 16, 2024 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI-skip-changelog Skip checking changelog entry
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants