Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-cpython/src/revlog.rs @ 51276:24d3298189d7
rust-index: document safety invariants being upheld for every `unsafe` block
We've added a lot of `unsafe` code that shares Rust structs with Python.
While this is unfortunate, it is also unavoidable, so let's at least
systematically explain why each call to `unsafe` is sound.
If any of the unsafe code ends up being wrong (because everyone screws up
at some point), this change at least continues the unspoken rule of always
explaining the need for `unsafe`, so we at least get a chance to think.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 23 Nov 2023 03:41:58 +0100 |
parents | f94c10334bcb |
children | 8b89f7cc953a |
line wrap: on
line diff
--- a/rust/hg-cpython/src/revlog.rs Sun Oct 29 12:18:03 2023 +0100 +++ b/rust/hg-cpython/src/revlog.rs Thu Nov 23 03:41:58 2023 +0100 @@ -42,6 +42,7 @@ ) -> PyResult<UnsafePyLeaked<PySharedIndex>> { let midx = index.extract::<Index>(py)?; let leaked = midx.index(py).leak_immutable(); + // Safety: we don't leak the "faked" reference out of the `UnsafePyLeaked` Ok(unsafe { leaked.map(py, |idx| PySharedIndex { inner: idx }) }) } @@ -975,6 +976,7 @@ /// been meanwhile mutated. def is_invalidated(&self) -> PyResult<bool> { let leaked = self.index(py).borrow(); + // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` let result = unsafe { leaked.try_borrow(py) }; // two cases for result to be an error: // - the index has previously been mutably borrowed @@ -986,6 +988,7 @@ def insert(&self, rev: PyRevision) -> PyResult<PyObject> { let leaked = self.index(py).borrow(); + // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` let index = &*unsafe { leaked.try_borrow(py)? }; let rev = UncheckedRevision(rev.0); @@ -1020,6 +1023,7 @@ let nt = self.nt(py).borrow(); let leaked = self.index(py).borrow(); + // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` let index = &*unsafe { leaked.try_borrow(py)? }; Ok(nt.find_bin(index, prefix) @@ -1031,6 +1035,7 @@ def shortest(&self, node: PyBytes) -> PyResult<usize> { let nt = self.nt(py).borrow(); let leaked = self.index(py).borrow(); + // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` let idx = &*unsafe { leaked.try_borrow(py)? }; match nt.unique_prefix_len_node(idx, &node_from_py_bytes(py, &node)?) {