# HG changeset patch # User Yuya Nishihara <y...@tcha.org> # Date 1570875051 -32400 # Sat Oct 12 19:10:51 2019 +0900 # Node ID da6ae3bc571609faeb2bd6696efc7869b0420f6a # Parent cfe3e9159c6c4eb5b7775a7b813f7f22f55a1f88 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. diff --git a/rust/hg-cpython/src/dirstate/copymap.rs b/rust/hg-cpython/src/dirstate/copymap.rs --- a/rust/hg-cpython/src/dirstate/copymap.rs +++ b/rust/hg-cpython/src/dirstate/copymap.rs @@ -12,7 +12,7 @@ use cpython::{PyBytes, PyClone, PyDict, 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 @@ impl CopyMap { 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)> ); diff --git a/rust/hg-cpython/src/dirstate/dirs_multiset.rs b/rust/hg-cpython/src/dirstate/dirs_multiset.rs --- a/rust/hg-cpython/src/dirstate/dirs_multiset.rs +++ b/rust/hg-cpython/src/dirstate/dirs_multiset.rs @@ -17,7 +17,7 @@ use cpython::{ }; 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 @@ impl Dirs { py_shared_iterator!( DirsMultisetKeysIterator, - PyLeakedRef<DirsMultisetIter<'static>>, + PyLeaked<DirsMultisetIter<'static>>, Dirs::translate_key, Option<PyBytes> ); diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs b/rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs @@ -20,7 +20,7 @@ use cpython::{ 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_ref!(DirstateMap, RustDirstate 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)> ); diff --git a/rust/hg-cpython/src/ref_sharing.rs b/rust/hg-cpython/src/ref_sharing.rs --- a/rust/hg-cpython/src/ref_sharing.rs +++ b/rust/hg-cpython/src/ref_sharing.rs @@ -186,12 +186,12 @@ impl<'a, T> PySharedRef<'a, T> { } /// 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 @@ macro_rules! py_shared_ref { } /// 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 @@ impl<T> PyLeakedRef<T> { /// /// 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> PyLeakedRef<T> { } } -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 @@ impl<T> Drop for PyLeakedRef<T> { 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 @@ impl<T> Drop for PyLeakedRef<T> { /// /// 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)> /// ); _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel