diff --git a/rust/hg-cpython/src/exceptions.rs b/rust/hg-cpython/src/exceptions.rs --- a/rust/hg-cpython/src/exceptions.rs +++ b/rust/hg-cpython/src/exceptions.rs @@ -40,5 +40,3 @@ impl GraphError { } py_exception!(rustext, HgPathPyError, RuntimeError); - -py_exception!(shared_ref, AlreadyBorrowed, RuntimeError); 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 @@ -22,10 +22,10 @@ //! Macros for use in the `hg-cpython` bridge library. -use crate::exceptions::AlreadyBorrowed; use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python}; -use std::cell::{Ref, RefCell, RefMut}; +use std::cell::{BorrowMutError, Ref, RefCell, RefMut}; use std::ops::{Deref, DerefMut}; +use std::result; use std::sync::atomic::{AtomicUsize, Ordering}; /// Manages the shared state between Python and Rust @@ -139,17 +139,14 @@ impl PySharedRefCell { fn try_borrow_mut<'a>( &'a self, py: Python<'a>, - ) -> PyResult> { + ) -> result::Result, BorrowMutError> { if self.py_shared_state.current_borrow_count(py) > 0 { - return Err(AlreadyBorrowed::new( - py, - "Cannot borrow mutably while immutably borrowed", - )); + // propagate borrow-by-leaked state to inner to get BorrowMutError + let _dummy = self.inner.borrow(); + self.inner.try_borrow_mut()?; + unreachable!("BorrowMutError must be returned"); } - let inner_ref = self - .inner - .try_borrow_mut() - .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?; + let inner_ref = self.inner.try_borrow_mut()?; self.py_shared_state.increment_generation(py); Ok(inner_ref) } @@ -191,7 +188,9 @@ impl<'a, T> PySharedRef<'a, T> { /// Mutably borrows the wrapped value, returning an error if the value /// is currently borrowed. - pub fn try_borrow_mut(&self) -> PyResult> { + pub fn try_borrow_mut( + &self, + ) -> result::Result, BorrowMutError> { self.data.try_borrow_mut(self.py) }