Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-pyo3/src/convert_cpython.rs @ 52445:233707101dae
rust-pyo3: simplified API to get core Index references
Given the amount of conversion and arcane internal detail, it
is easier for the caller and makes a better separation of concerns
to just introduce a new unsafe helper. It is actually possible that
it would be safe, and we can decide about that later.
Actually the reason given in the `cpython` crate for unsafety of the
`try_borrow()` method is the following:
```
// try_borrow() and try_borrow_mut() are unsafe because self.data may
// have a function returning the inner &'static reference.
// If T is &'static U, its lifetime can be easily coerced to &'a U, but
// how could we do that for Whatever<'static> in general?
```
Given that we coerce the Index reference to the GIL lifetime and that
it is unlikely that the inner data would contain a function returning the
a `'static` reference, it is possible that it is actually even safe.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Fri, 29 Nov 2024 23:35:31 +0100 |
parents | c2480ac4c5e2 |
children | 64a618048ba8 |
line wrap: on
line diff
--- a/rust/hg-pyo3/src/convert_cpython.rs Sat Nov 30 20:58:09 2024 +0100 +++ b/rust/hg-pyo3/src/convert_cpython.rs Fri Nov 29 23:35:31 2024 +0100 @@ -16,6 +16,7 @@ use cpython::PythonObject; use lazy_static::lazy_static; +use hg::revlog::index::Index as CoreIndex; use rusthg::revlog::{InnerRevlog, PySharedIndex}; /// Force cpython's GIL handle with the appropriate lifetime @@ -165,9 +166,21 @@ Ok(unsafe { leaked.map(py, |idx| PySharedIndex { inner: &idx.index }) }) } -pub(crate) fn proxy_index_extract<'py>( +/// Full extraction of the proxy index object as received in PyO3 to a +/// [`CoreIndex`] reference. +/// +/// The safety invariants to maintain are those of the underlying +/// [`UnsafePyLeaked::try_borrow`]: the caller must not leak the inner +/// reference. +pub(crate) unsafe fn proxy_index_extract<'py>( index_proxy: &Bound<'py, PyAny>, -) -> PyResult<(cpython::Python<'py>, cpython::UnsafePyLeaked<PySharedIndex>)> { +) -> PyResult<&'py CoreIndex> { let (py, idx_proxy) = to_cpython_py_object(index_proxy); - Ok((py, py_rust_index_to_graph(py, idx_proxy)?)) + let py_leaked = py_rust_index_to_graph(py, idx_proxy)?; + let py_shared = &*unsafe { + py_leaked + .try_borrow(py) + .map_err(|e| from_cpython_pyerr(py, e))? + }; + Ok(py_shared.inner) }