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}