rust-cpython: rename PyLeakedRef to PyLeaked
This series will make PyLeaked* behave more like a Python iterator, which
means mutation of the owner object will be allowed and the leaked reference
(i.e. the iterator) will be invalidated instead.
I'll add PyLeakedRef/PyLeakedRefMut structs which will represent a "borrowed"
state, and prevent the underlying value from being mutably borrowed while the
leaked reference is in use:
let shared = self.inner_shared(py);
let leaked = shared.leak_immutable();
{
let leaked_ref: PyLeakedRef<_> = leaked.borrow(py);
shared.borrow_mut(); // panics since the underlying value is borrowed
}
shared.borrow_mut(); // allowed
The relation between PyLeaked* structs is quite similar to RefCell/Ref/RefMut,
but the implementation can't be reused because the borrowing state will have
to be shared across objects having no lifetime relation.
PyLeaked isn't named as PyLeakedCell since it isn't actually a cell in that
leaked.borrow_mut() will require &mut self.
--- a/rust/hg-cpython/src/dirstate/copymap.rs Fri Oct 18 11:18:41 2019 -0400
+++ b/rust/hg-cpython/src/dirstate/copymap.rs Sat Oct 12 19:10:51 2019 +0900
@@ -12,7 +12,7 @@
use std::cell::RefCell;
use crate::dirstate::dirstate_map::DirstateMap;
-use crate::ref_sharing::PyLeakedRef;
+use crate::ref_sharing::PyLeaked;
use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
py_class!(pub class CopyMap |py| {
@@ -104,14 +104,14 @@
py_shared_iterator!(
CopyMapKeysIterator,
- PyLeakedRef<CopyMapIter<'static>>,
+ PyLeaked<CopyMapIter<'static>>,
CopyMap::translate_key,
Option<PyBytes>
);
py_shared_iterator!(
CopyMapItemsIterator,
- PyLeakedRef<CopyMapIter<'static>>,
+ PyLeaked<CopyMapIter<'static>>,
CopyMap::translate_key_value,
Option<(PyBytes, PyBytes)>
);
--- a/rust/hg-cpython/src/dirstate/dirs_multiset.rs Fri Oct 18 11:18:41 2019 -0400
+++ b/rust/hg-cpython/src/dirstate/dirs_multiset.rs Sat Oct 12 19:10:51 2019 +0900
@@ -17,7 +17,7 @@
};
use crate::dirstate::extract_dirstate;
-use crate::ref_sharing::{PyLeakedRef, PySharedRefCell};
+use crate::ref_sharing::{PyLeaked, PySharedRefCell};
use hg::{
utils::hg_path::{HgPath, HgPathBuf},
DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
@@ -123,7 +123,7 @@
py_shared_iterator!(
DirsMultisetKeysIterator,
- PyLeakedRef<DirsMultisetIter<'static>>,
+ PyLeaked<DirsMultisetIter<'static>>,
Dirs::translate_key,
Option<PyBytes>
);
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs Fri Oct 18 11:18:41 2019 -0400
+++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs Sat Oct 12 19:10:51 2019 +0900
@@ -20,7 +20,7 @@
use crate::{
dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
dirstate::{dirs_multiset::Dirs, make_dirstate_tuple},
- ref_sharing::{PyLeakedRef, PySharedRefCell},
+ ref_sharing::{PyLeaked, PySharedRefCell},
};
use hg::{
utils::hg_path::{HgPath, HgPathBuf},
@@ -483,14 +483,14 @@
py_shared_iterator!(
DirstateMapKeysIterator,
- PyLeakedRef<StateMapIter<'static>>,
+ PyLeaked<StateMapIter<'static>>,
DirstateMap::translate_key,
Option<PyBytes>
);
py_shared_iterator!(
DirstateMapItemsIterator,
- PyLeakedRef<StateMapIter<'static>>,
+ PyLeaked<StateMapIter<'static>>,
DirstateMap::translate_key_value,
Option<(PyBytes, PyObject)>
);
--- a/rust/hg-cpython/src/ref_sharing.rs Fri Oct 18 11:18:41 2019 -0400
+++ b/rust/hg-cpython/src/ref_sharing.rs Sat Oct 12 19:10:51 2019 +0900
@@ -186,12 +186,12 @@
}
/// Returns a leaked reference.
- pub fn leak_immutable(&self) -> PyResult<PyLeakedRef<&'static T>> {
+ pub fn leak_immutable(&self) -> PyResult<PyLeaked<&'static T>> {
let state = &self.data.py_shared_state;
unsafe {
let (static_ref, static_state_ref) =
state.leak_immutable(self.py, self.data)?;
- Ok(PyLeakedRef::new(
+ Ok(PyLeaked::new(
self.py,
self.owner,
static_ref,
@@ -307,16 +307,16 @@
}
/// Manage immutable references to `PyObject` leaked into Python iterators.
-pub struct PyLeakedRef<T> {
+pub struct PyLeaked<T> {
inner: PyObject,
data: Option<T>,
py_shared_state: &'static PySharedState,
}
-// DO NOT implement Deref for PyLeakedRef<T>! Dereferencing PyLeakedRef
+// DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked
// without taking Python GIL wouldn't be safe.
-impl<T> PyLeakedRef<T> {
+impl<T> PyLeaked<T> {
/// # Safety
///
/// The `py_shared_state` must be owned by the `inner` Python object.
@@ -355,19 +355,19 @@
///
/// The lifetime of the object passed in to the function `f` is cheated.
/// It's typically a static reference, but is valid only while the
- /// corresponding `PyLeakedRef` is alive. Do not copy it out of the
+ /// corresponding `PyLeaked` is alive. Do not copy it out of the
/// function call.
pub unsafe fn map<U>(
mut self,
py: Python,
f: impl FnOnce(T) -> U,
- ) -> PyLeakedRef<U> {
+ ) -> PyLeaked<U> {
// f() could make the self.data outlive. That's why map() is unsafe.
// In order to make this function safe, maybe we'll need a way to
// temporarily restrict the lifetime of self.data and translate the
// returned object back to Something<'static>.
let new_data = f(self.data.take().unwrap());
- PyLeakedRef {
+ PyLeaked {
inner: self.inner.clone_ref(py),
data: Some(new_data),
py_shared_state: self.py_shared_state,
@@ -375,7 +375,7 @@
}
}
-impl<T> Drop for PyLeakedRef<T> {
+impl<T> Drop for PyLeaked<T> {
fn drop(&mut self) {
// py_shared_state should be alive since we do have
// a Python reference to the owner object. Taking GIL makes
@@ -383,7 +383,7 @@
let gil = Python::acquire_gil();
let py = gil.python();
if self.data.is_none() {
- return; // moved to another PyLeakedRef
+ return; // moved to another PyLeaked
}
self.py_shared_state.decrease_leak_count(py, false);
}
@@ -439,7 +439,7 @@
///
/// py_shared_iterator!(
/// MyTypeItemsIterator,
-/// PyLeakedRef<HashMap<'static, Vec<u8>, Vec<u8>>>,
+/// PyLeaked<HashMap<'static, Vec<u8>, Vec<u8>>>,
/// MyType::translate_key_value,
/// Option<(PyBytes, PyBytes)>
/// );