Skip to content

Commit 162041e

Browse files
authored
Add implementation of GhostBorrow and GhostBorrowMut for arrays of references
* Changes: - Add implementation of GhostBorrow for arrays of references to GhostCell - Add implementation of GhostBorrowMut for arrays of references to GhostCell. - Various comments and documentation nits. * Motivation: More flexibility. * Implementation Note: Due to `mem::transmute` not working well with const generics (as per rust-lang/rust#61956), `ptr::read` is used instead of `mem::transmute`. This is expected to be safe, if verbose.
1 parent 434d1b6 commit 162041e

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

src/ghost_borrow.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! provides.
55
66
use core::mem;
7+
use core::ptr;
78

89
use crate::ghost_cell::*;
910

@@ -54,12 +55,24 @@ impl<'a, 'brand, T, const N: usize> GhostBorrow<'a, 'brand> for &'a [GhostCell<'
5455

5556
fn borrow(self, _: &'a GhostToken<'brand>) -> Self::Result {
5657
// Safety:
57-
// - Exclusive access to the `GhostToken` ensures exclusive access to the cells' content.
58+
// - Shared access to the `GhostToken` ensures shared access to the cells' content.
5859
// - `GhostCell` is `repr(transparent)`, hence `T` and `GhostCell<T>` have the same memory representation.
5960
unsafe { mem::transmute::<Self, Self::Result>(self) }
6061
}
6162
}
6263

64+
impl<'a, 'brand, T, const N: usize> GhostBorrow<'a, 'brand> for [&'a GhostCell<'brand, T>; N] {
65+
type Result = [&'a T; N];
66+
67+
fn borrow(self, _: &'a GhostToken<'brand>) -> Self::Result {
68+
// Safety:
69+
// - `[&'a GhostCell<'brand, T>; N]` and `[&'a T; N]` have the same size.
70+
// - `[&'a GhostCell<'brand, T>; N]` implements `Copy`, so no `mem::forget` is needed.
71+
// - We can't use `mem::transmute`, because of https://github.com/rust-lang/rust/issues/61956.
72+
unsafe { ptr::read(&self as *const _ as *const Self::Result) }
73+
}
74+
}
75+
6376
macro_rules! generate_public_instance {
6477
( $($name:ident),* ; $($type_letter:ident),* ) => {
6578
impl<'a, 'brand, $($type_letter,)*> GhostBorrow<'a, 'brand> for

src/ghost_borrow_mut.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! The feature is experimental, to enable, use the feature "experimental-multiple-mutable-borrows".
1818
1919
use core::mem;
20+
use core::ptr;
2021

2122
use crate::ghost_cell::*;
2223

@@ -147,6 +148,36 @@ impl<'a, 'brand, T, const N: usize> GhostBorrowMut<'a, 'brand> for &'a [GhostCel
147148
}
148149
}
149150

151+
152+
impl<'a, 'brand, T, const N: usize> GhostBorrowMut<'a, 'brand> for [&'a GhostCell<'brand, T>; N] {
153+
type Result = [&'a mut T; N];
154+
type Error = GhostAliasingError;
155+
156+
fn borrow_mut(self, token: &'a mut GhostToken<'brand>) -> Result<Self::Result, Self::Error> {
157+
// We require that the types are `Sized`, so no fat pointer problems.
158+
// Safety:
159+
// - `[&'a GhostCell<'brand, T>; N]` and `[*const (); N]` have the same size.
160+
// - `[&'a GhostCell<'brand, T>; N]` implements `Copy`, so no `mem::forget` is needed.
161+
// - We can't use `mem::transmute`, because of https://github.com/rust-lang/rust/issues/61956.
162+
check_distinct(unsafe { ptr::read(&self as *const _ as *const [*const (); N]) })?;
163+
164+
// Safety:
165+
// - The cells were checked to be distinct.
166+
Ok(unsafe { self.borrow_mut_unchecked(token) })
167+
}
168+
169+
unsafe fn borrow_mut_unchecked(self, _: &'a mut GhostToken<'brand>) -> Self::Result {
170+
// Safety:
171+
// - Exclusive access to the `GhostToken` ensures exclusive access to the cells' content, if unaliased.
172+
// - The caller guarantees the cells are not aliased.
173+
// - `[&'a GhostCell<'brand, T>; N]` and `[&'a mut T; N]` have the same size.
174+
// - `[&'a GhostCell<'brand, T>; N]` implements `Copy`, so no `mem::forget` is needed.
175+
// - We can't use `mem::transmute`, because of https://github.com/rust-lang/rust/issues/61956.
176+
ptr::read(&self as *const _ as *const Self::Result)
177+
}
178+
}
179+
180+
150181
macro_rules! generate_public_instance {
151182
( $($name:ident),* ; $($type_letter:ident),* ) => {
152183
impl<'a, 'brand, $($type_letter,)*> GhostBorrowMut<'a, 'brand> for
@@ -171,7 +202,6 @@ macro_rules! generate_public_instance {
171202

172203
// Safety:
173204
// - Exclusive access to the `GhostToken` ensures exclusive access to the cells' content, if unaliased.
174-
// - `GhostCell` is `repr(transparent)`, hence `T` and `GhostCell<T>` have the same memory representation.
175205
// - The caller guarantees the cells are not aliased.
176206
( $( &mut * $name.as_ptr(),)* )
177207
}

0 commit comments

Comments
 (0)