Skip to content

Conversation

Icxolu
Copy link
Contributor

@Icxolu Icxolu commented Aug 10, 2025

This adds PyClassGuard(Mut)::map to map the borrow to some component of the pyclass. This borrows some ideas from #4203.

Given that these are still unreleased types, I skipped the changelog.

@Icxolu Icxolu added the CI-skip-changelog Skip checking changelog entry label Aug 10, 2025
Copy link

codspeed-hq bot commented Aug 10, 2025

CodSpeed Performance Report

Merging #5311 will not alter performance

Comparing Icxolu:pyclassguard/map (38b4e0a) with main (c366646)

Summary

✅ 95 untouched benchmarks

@davidhewitt
Copy link
Member

Awesome, I've wanted this for a long time! Will probably review on Friday 👍

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Very nice, this looks good to me, thanks!

I was hoping that this would be a way forward to be able to write #[getter] functions which return borrowed data to a #[pyclass] struct Inner from a #[pyclass] struct Outer, in such a way that we could safely build a "shallow copy" inner which just points at the data stored in Outer.

But looking at test_pyclassguard_map_unrelated, I'm now not so sure. It feels to me that this might allow users to incorrectly tie arbitrary data (such as a reference to some #[pyclass] struct C) which has the same lifetime but no actual relation to Outer.

/// # Ok::<_, PyErr>(())
/// # }).unwrap();
/// ```
pub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, true>
Copy link
Member

Choose a reason for hiding this comment

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

For what it's worth, I wondered if this should be &mut self here, but I think you would run into pain with the fact that would prevent writing a function which takes a PyClassGuardMut and returns a PyClassGuardMap, for example.

This also matches how other MutexGuard types have implemented map, presumably for similar reasons or something else I've not yet thought of.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I think it makes sense to be consistent with the rest of the ecosystem here. Also I imagine that something like
obj.borrow().map(|v| &v.field) might be a common use case, which does only work if we consume the guard and store it inline.

Comment on lines +976 to +977
// It is possible to return something not borrowing from the guard, but that shouldn't
// matter. `RefCell` has the same behaviour
Copy link
Member

Choose a reason for hiding this comment

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

Haha interesting 😂

@Icxolu Icxolu added this pull request to the merge queue Aug 15, 2025
Merged via the queue into PyO3:main with commit 700b4cc Aug 16, 2025
43 of 44 checks passed
@Icxolu Icxolu deleted the pyclassguard/map branch August 16, 2025 03:28
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