deferred_reference/deferred.rs
1use core::ptr::NonNull;
2
3use crate::Reference;
4
5/// A smart pointer which holds a "deferred reference" to an instance of type `T: ?Sized`.
6/// It has all the properties of a normal reference (`&T` or `&mut T`),
7/// except that it does not hold an actual reference. This makes it possible pass
8/// around multiple deferred references in unsafe code, without triggering
9/// undefined behavior due to existence of aliased mutable references. `Deferred`
10/// aims to make it easier to reason about the validity and lifetime of pointers
11/// during the act of dereferencing.
12///
13/// # Invariant
14/// `Deferred` upholds the same guarantees as its referenceable counter-parts `&T`
15/// and `&mut T` (except that it doesn't occupy an actual reference!), it is possible
16/// to always dereference it:
17/// * The address that `Deferred` points to is guaranteed to be properly aligned.
18/// * `Deferred` is guaranteed to be non-dangling.
19/// * `Deferred` is guaranteed to be non-null.
20/// * `Deferred` is guaranteed to dereference to the same (stack-allocated) object.
21/// * The memory that `Deferred` points to is guaranteed to be properly initialized.
22/// * `Deferred` is guaranteed to be valid for the duration of its lifetime.
23///
24/// For mutable pointers, `Deferred<&mut T>` guarantees that no mutable reference(s) existed
25/// to (any part of) the `T` instance at the time the `Deferred` was constructed. After
26/// a mutable `Deferred<&mut T>` is created, mutable references may be constructed from it
27/// (safely or unsafely), but the Rust aliasing rules must always be respected, meaning
28/// no two live mutable references may point to overlapping regions in memory, ever.
29///
30/// # Safety
31/// Even though it is possible to work with `Deferred` from purely safe Rust, it also offers
32/// additional functionality in `unsafe` code and then the programmer must take special care when
33/// dereferencing the `Deferred` or its pointers in unsafe code regarding the usual Rust rules:
34/// * Don't create a mutable reference `&mut T` to regions of the memory which already
35/// hold an immutable reference `&T` or a mutable reference `&mut T`.
36/// The usual Rust aliasing rules still apply, even in unsafe code!
37/// * Don't create any reference, `&T` or `&mut T`, to regions of the memory which
38/// could be modified from other threads or processes.
39/// * Don't create any mutable reference `&mut T` to regions of the memory which
40/// could be aliased through a `&T` or `&mut T` from other threads or processes.
41/// * Creating immutable aliases `&T` to regions of the memory is fine as long as there
42/// are only readers for the same part of the slice, even if it is read from other
43/// threads or processes.
44#[repr(transparent)] // this is so that it can be casted to and from other pointers
45pub struct Deferred<T>
46where
47 T: Reference,
48{
49 /// The raw pointer. This pointer may never dangle and must always be valid.
50 ptr: NonNull<T::Target>,
51}
52
53/// # Constructors for deferred _immutable_ references
54/// There exist several ways to construct a deferred immutable reference `Deferred<&T>`, listed here in
55/// order of safety (lower in the list means it's more unsafe).
56/// 1. Through the [Deferred::new] method.
57/// 2. Through the [From]/[Into] traits implemented for `Deferred<&T>`.
58/// 3. Through the [Defer::defer](crate::Defer::defer) method on types that implement the [Defer](crate::Defer) trait.
59/// 4. Through the _unsafe_ [Deferred::from_raw] method.
60/// 5. Through the _extremely unsafe_ [`defer`](macro@defer) macro (not recommended).
61impl<'a, T: ?Sized> Deferred<&'a T> {
62 /// Construct a new deferred immutable reference from an existing immutable reference.
63 /// ```
64 /// use deferred_reference::Deferred;
65 /// let x = [1, 2, 3];
66 /// let deferred = Deferred::new(&x);
67 /// assert_eq!(2, deferred[1]);
68 /// ```
69 pub fn new(reference: &'a T) -> Self {
70 // SAFETY: an actual reference upholds the same guarantees as [Deferred], to this is safe.
71 unsafe {
72 Self::from_raw(reference)
73 }
74 }
75 /// Construct a new deferred immutable reference to an instance of `T: ?Sized` from a raw pointer.
76 /// This method is unsafe. For a safe alternative, use `Deferred::from(&T)` instead. If you don't
77 /// have access to a reference or don't want to create one, then this method (`Deferred::from_raw`)
78 /// is the method that you could use instead. Alternatively, another safe method is to call the
79 /// [Defer::defer](crate::Defer::defer) method on types that implement the [Defer](crate::Defer) trait.
80 ///
81 /// # Safety
82 /// The caller must uphold the invariant of [Deferred], which implies guaranteeing
83 /// largely the same safety guarantees as for regular immutable references.
84 /// Most importantly this means that the pointer must be derefenceable and may not contain
85 /// any part of memory which is left uninitialized. Referencing uninitialized memory of
86 /// any type is always instant undefined behavior (see the nomicon at
87 /// <https://doc.rust-lang.org/nomicon/uninitialized.html> for more details on this fact).
88 /// The caller must also ensure that the pointer remains valid for as long as the returned
89 /// `Deferred` exists. If the pointers refers to a shared memory (mapped) region which may
90 /// be modified somehow, then it is also the caller's reponsibility never to call safe
91 /// methods such as [`<Deferred as Deref>::deref`](core::ops::Deref::deref). This would
92 /// alias the entire memory region and is only safe if there are no writers at the same time.
93 ///
94 /// # Caveat
95 /// The lifetime for the returned [Deferred] is inferred from its usage. To prevent accidental misuse,
96 /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, such as
97 /// by providing a helper function taking the lifetime of a host value, or by explicit annotation.
98 /// ```
99 /// use deferred_reference::Deferred;
100 /// pub trait MemoryMappedBuffer {
101 /// fn as_ptr(&self) -> *const u8;
102 /// fn len(&self) -> usize;
103 /// }
104 /// fn defer<'a, T>(buffer: &'a T) -> Deferred<&'a [u8]>
105 /// where
106 /// T: MemoryMappedBuffer
107 /// {
108 /// let slice_ptr = core::ptr::slice_from_raw_parts(buffer.as_ptr(), buffer.len());
109 /// unsafe { Deferred::from_raw(slice_ptr) }
110 /// }
111 /// ```
112 ///
113 /// # Example
114 /// ```
115 /// use deferred_reference::Deferred;
116 /// let buffer = [0u8; 1024];
117 /// // SAFETY: `buffer` is not moved or mutably aliased after this.
118 /// let deferred = unsafe { Deferred::from_raw(core::ptr::addr_of!(buffer)) };
119 /// ```
120 pub unsafe fn from_raw(ptr: *const T) -> Self {
121 // note: this method must live in the impl for `&'a T`
122 // otherwise Rust can't infer the type properly.
123 Self {
124 // note: the pointer is casted from `*const T` to `*mut T`, but this is safe because
125 // this is not undefined behavior. dereferencing the `*mut T` would be UB,
126 // but there is no way to do this if it was constructed from a *const T,
127 // so this is still sound.
128 ptr: NonNull::new_unchecked(ptr as *mut T),
129 }
130 }
131}
132
133/// # Constructors for deferred _mutable_ references
134/// There exist several ways to construct a deferred mutable reference `Deferred<&mut T>`, listed here in
135/// order of safety (lower in the list means it's more unsafe).
136/// 1. Through the [Deferred::new_mut] method.
137/// 2. Through the [From]/[Into] traits implemented for `Deferred<&mut T>`.
138/// 3. Through the _unsafe_ [DeferMut::defer_mut](crate::DeferMut::defer_mut) method on types that implement the [DeferMut](crate::DeferMut) trait.
139/// 4. Through the _unsafe_ [Deferred::from_raw_mut] method.
140/// 5. Through the _extremely unsafe_ [`defer_mut`](macro@defer_mut) macro (not recommended).
141impl<'a, T: ?Sized> Deferred<&'a mut T> {
142 /// Construct a new deferred mutable reference from an existing mutable reference.
143 /// ```
144 /// use deferred_reference::Deferred;
145 /// let mut x = [1, 2, 3];
146 /// let mut deferred = Deferred::new_mut(&mut x);
147 /// assert_eq!(&mut 2, &mut deferred[1]);
148 /// ```
149 pub fn new_mut(reference: &'a mut T) -> Self {
150 // SAFETY: an actual reference upholds the same guarantees as [Deferred], to this is safe.
151 unsafe {
152 Self::from_raw_mut(reference)
153 }
154 }
155 /// Construct a new deferred mutable reference to an instance of `T`.
156 ///
157 /// # Safety
158 /// The caller must uphold the invariant of [Deferred]. Most importantly this means that the pointer must be
159 /// derefenceable and may not contain any part of memory which is left uninitialized. Referencing
160 /// uninitialized memory of any type is always instant undefined behavior (see the nomicon at
161 /// <https://doc.rust-lang.org/nomicon/uninitialized.html> for more details on this fact).
162 /// On top of that, the caller must ensure that the pointer remains valid for as long
163 /// as the returned `Deferred` exists and that no references to the instance exist when the [Deferred]
164 /// is constructed. If the `Deferred` refers to a shared memory (mapped) region which may be modified somehow
165 /// (e.g. by other threads or processes), then it is also the caller's reponsibility never to call
166 /// the safe methods [`<Deferred as Deref>::deref`](core::ops::Deref::deref) or
167 /// [`<Deferred as DerefMut>::deref_mut`](core::ops::DerefMut::deref_mut). This would alias the entire memory
168 /// region and is only safe when there are no other writers and readers, respectively.
169 ///
170 /// # Caveat
171 /// The lifetime for the returned `Deferred` is inferred from its usage. To prevent accidental misuse,
172 /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, such as
173 /// by providing a helper function taking the lifetime of a host value, or by explicit annotation.
174 ///
175 /// ```
176 /// use deferred_reference::Deferred;
177 /// /// SAFETY: `Buffer` may only be implemented on valid smart-pointers which don't own
178 /// /// SAFETY: the memory. The smart pointer must also point to fully initialized memory.
179 /// pub unsafe trait Buffer {
180 /// fn as_ptr(&self) -> *mut u8;
181 /// fn len(&self) -> usize;
182 /// }
183 /// /// The lifetime of the returned [Deferred] is bound to the lifetime of the
184 /// /// mutable borrow of smart pointer `T` through the explicit lifetime 'a.
185 /// fn defer_mut<'a, T>(buffer: &'a mut T) -> Deferred<&'a mut [u8]>
186 /// where
187 /// T: Buffer
188 /// {
189 /// let slice_ptr = core::ptr::slice_from_raw_parts_mut(buffer.as_ptr(), buffer.len());
190 /// // SAFETY: this is safe because `Deferred` occupies the only mutable reference
191 /// // SAFETY: to the smart pointer `T` for the duration of lifetime 'a, which means
192 /// // SAFETY: no other callers can safely obtain a mutable reference at the same time.
193 /// unsafe { Deferred::from_raw_mut(slice_ptr) }
194 /// }
195 /// ```
196 /// The documentation of [DeferMut](crate::DeferMut) contains some additional examples of how to properly call
197 /// [Deferred::from_raw_mut].
198 pub unsafe fn from_raw_mut(ptr: *mut T) -> Deferred<&'a mut T> {
199 Self {
200 ptr: NonNull::new_unchecked(ptr as *mut T),
201 }
202 }
203}
204
205/// # Methods available on all deferred references
206impl<T> Deferred<T>
207where
208 T: Reference,
209{
210 /// Obtains an immutable pointer to where the deferred reference points.
211 /// This pointer can be a thin pointer if `T` is sized or a fat pointer
212 /// otherwise.
213 pub fn as_ptr(&self) -> *const T::Target {
214 self.ptr.as_ptr() as *const _
215 }
216
217 /// Unsizes the deferred reference. This method is experimental.
218 ///
219 /// # Example
220 /// ```
221 /// use deferred_reference::{Defer, DeferMut, Deferred};
222 /// use core::cell::UnsafeCell;
223 /// let mut buffer = UnsafeCell::new([0u8; 1024]);
224 /// let deferred_array /* : Deferred<&[u8; 1024]> */ = buffer.defer();
225 /// let deferred_slice: Deferred<&[u8]> = deferred_array.unsize(); // needs an explicit type
226 /// let deferred_array_mut /* : Deferred<&mut [u8; 1024]> */ = unsafe { buffer.defer_mut() };
227 /// let deferred_slice_mut: Deferred<&mut [u8]> = deferred_array_mut.unsize();
228 /// ```
229 ///
230 /// # Unstable
231 /// This method requires the unstable `Cargo.toml` feature `unstable` or `coerce_unsized` to be enabled.
232 /// This method may become stable once the `coerce_unsized` feature lands in stable Rust, see
233 /// <https://github.com/rust-lang/rust/issues/27732>. For a stable alternative, you may also use
234 /// use the [From]/[Into] traits which are implemented on [Deferred] for converting deferred arrays to
235 /// deferred slices.
236 #[cfg(feature = "coerce_unsized")]
237 pub fn unsize<U>(self) -> Deferred<U>
238 where
239 U: Reference,
240 NonNull<T::Target>: core::ops::CoerceUnsized<NonNull<U::Target>>, // requires #![feature(coerce_unsized)]`
241 {
242 Deferred {
243 ptr: self.ptr,
244 }
245 }
246}
247
248/// # Methods available for all deferred _mutable_ references
249impl<'a, T: ?Sized> Deferred<&'a mut T> {
250 /// Obtains an mutable pointer to where the deferred reference points.
251 /// This pointer can be a thin pointer if `T` is sized or a fat pointer
252 /// otherwise.
253 pub fn as_mut_ptr(&self) -> *mut T {
254 self.ptr.as_ptr()
255 }
256 /// Make a copy of this mutable `Deferred<&'a mut T>`. The copy will have the same lifetime as `'a`.
257 ///
258 /// # Safety
259 /// This method can be very unsafe. Cloning a mutable deferred reference will let you safely dereference it mutably
260 /// afterwards (e.g. through [`<Deferred<&mut T> as DerefMut>::deref_mut`](core::ops::DerefMut::deref_mut)) from several
261 /// distinct places simultaneously and this could lead to aliased mutable references which is then instant undefined behavior.
262 /// That is why this function is marked as unsafe. Cloning a `Deferred<&mut T>` is not undefined behavior, because this is a
263 /// smart pointer and not an actual live reference. Be very careful not to accidentally create mutable aliased references through
264 /// dereferencing any `Deferred<&mut T>` after calling [`Deferred::clone_unchecked`](Deferred::clone_unchecked) on it!!!
265 /// Calling [`<Deferred as Clone>::clone`](Clone::clone) on immutable deferred references (i.e. `Deferred<&T>`) is entirely safe
266 /// (and all `Deferred<&T>` also implement the [Copy] trait).
267 pub unsafe fn clone_unchecked(&self) -> Self {
268 // SAFETY: calling `from_raw_parts_mut` is safe because the invariant of [Deferred] is respected.
269 // SAFETY: still this method is unsafe by itself, see the Safety notes.
270 Deferred::from_raw_mut(self.as_mut_ptr())
271 }
272 /// Convert this deferred mutable reference into a deferred immutable reference.
273 ///
274 /// # Example
275 /// ```
276 /// use deferred_reference::{DeferMut, Deferred};
277 /// use core::cell::UnsafeCell;
278 /// let buffer = UnsafeCell::new([0u8; 1024]);
279 /// // SAFETY: this is safe, because this is the only deferred reference we create:
280 /// let deferred_mut: Deferred<&mut [u8; 1024]> = unsafe { buffer.defer_mut() };
281 /// // which we then convert into a deferred immutable reference:
282 /// let deferred: Deferred<&[u8; 1024]> = deferred_mut.into_ref();
283 /// ```
284 pub fn into_ref(self) -> Deferred<&'a T> {
285 self.into()
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use core::cell::UnsafeCell;
292 use crate::{Defer, DeferMut, Deferred};
293
294 #[test]
295 fn new() {
296 let mut buffer = [0u8; 1024];
297 let mut deferred = Deferred::from(&mut buffer);
298 //assert_eq!(0, buffer[0]); // cannot borrow `buffer[_]` as immutable because it is also borrowed as mutable
299 assert_eq!(0, deferred[0]);
300 assert_eq!(&mut 0, &mut deferred[0]);
301 let mut deferred2 = unsafe { deferred.clone_unchecked() };
302 let tmp1: &mut [u8] = &mut deferred[10..20];
303 // let tmp2 = &mut deferred2[30..40];
304 tmp1[0] = 42; // UB because `tmp2` creates a new &mut reference
305 // tmp2[0] = 42;
306 // assert_eq!(&mut tmp1[0], &mut tmp2[0]);
307 deferred2[0] = 42;
308 assert_eq!(42, deferred[0]);
309 assert_eq!(42, buffer[0]);
310 }
311
312 #[test]
313 fn mut_ref_invalidation() {
314 let buffer = UnsafeCell::new([0u8; 1024]);
315 let mut deferred = unsafe { buffer.defer_mut() };
316 let mut deferred2 = unsafe { deferred.clone_unchecked() };
317 deferred[10] = 1; // not UB, because mutable reference is temporary
318 deferred2[30] = 1; // not UB, because new mutable reference is created
319 let _tmp1 = &mut deferred[10..20];
320 let tmp2 = &mut deferred2[30..40];
321 // tmp1[0] = 42; // UB because `tmp2` creates a new &mut reference
322 tmp2[0] = 42;
323 // assert_eq!(&mut tmp1[0], &mut tmp2[0]); // UB
324 }
325
326 /// Tests whether [Deferred] can be casted to pointers of other types without UB
327 #[test]
328 fn cast_to_ptr() {
329 let mut buffer = UnsafeCell::new([0u8; 1024]);
330 buffer.get_mut()[0] = 1;
331 {
332 let deferred = buffer.defer();
333 let ptr = unsafe { *(core::ptr::addr_of!(deferred) as *const *const [u8; 1024]) };
334 assert_eq!(*deferred, unsafe { *ptr });
335 }
336 {
337 let deferred = unsafe { buffer.defer_mut() };
338 let ptr = unsafe { *(core::ptr::addr_of!(deferred) as *const *mut [u8; 1024]) };
339 assert_eq!(*deferred, unsafe { *ptr });
340 }
341 {
342 let mut deferred = unsafe { buffer.defer_mut() };
343 let ptr = unsafe { *(core::ptr::addr_of_mut!(deferred) as *mut *mut [u8; 1024]) };
344 assert_eq!(*deferred, unsafe { *ptr });
345 }
346 }
347
348 /// Tests that niche size optimization works.
349 #[test]
350 fn size_of() {
351 assert_eq!(core::mem::size_of::<Deferred<&[u8]>>(), core::mem::size_of::<Option<Deferred<&[u8]>>>())
352 }
353
354 /// Tests that pointers point to the same address.
355 #[test]
356 fn as_ptr() {
357 let buffer = UnsafeCell::new([0u8; 1024]);
358 let deferred = buffer.defer();
359 assert_eq!(deferred.as_ptr() as usize, buffer.get() as usize);
360 }
361
362 /// Tests that mutable pointers point to the same address.
363 #[test]
364 fn as_mut_ptr() {
365 let buffer = UnsafeCell::new([0u8; 1024]);
366 let deferred = unsafe { buffer.defer_mut() };
367 assert_eq!(deferred.as_mut_ptr() as usize, buffer.get() as usize);
368 }
369
370
371}