1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
use core::cell::UnsafeCell;

use crate::Reference;

use super::Deferred;

/// An unsafe macro to create a deferred immutable reference (i.e. a [`Deferred<&T>`](Deferred)) to a place,
/// without creating an intermediate reference. See the documentation at [Deferred] explaining the
/// [constructors for deferred immutable references](Deferred#constructors-for-deferred-immutable-references)
/// for safe alternatives.
///
/// Use of this macro is not recommended, because it's a lot more unsafe than obtaining a `Deferred<&T>` through
/// a type that implements the [Defer] trait. Use [`Defer::defer`](Defer::defer) or [`Deferred::from(&T)`](From::from)
/// for a safe alternative instead.
///
/// The only use case for this macro is when you can't create a reference to a place and also can't use [UnsafeCell]
/// to achieve interior mutability. However, this is a rare case and requires advanced knowledge of unsafe Rust.
///
/// # Example
/// ```
/// #[macro_use]
/// extern crate deferred_reference;
/// use deferred_reference::Deferred;
/// fn main() {
///     let buffer = [0u8; 1024];
///     // works for deferred references to slices:
///     let deferred: Deferred<&[u8]> =  unsafe { defer!(buffer) };
///     assert_eq!(buffer[0], deferred[0]);
///     // and works also for deferred references to arrays:
///     let deferred: Deferred<&[u8; 1024]> =  unsafe { defer!(buffer) };
///     assert_eq!(buffer[0], deferred[0]);
/// }
/// ```
///
/// # Safety
/// This macro is very unsafe and should only be used if there is no other safe way to obtain a deferred reference.
/// See the [Defer] trait for the preferred way to create an immutable deferred reference. When using this
/// macro, the caller must uphold the following guarantees:
/// * When dereferencing the [Deferred], the Rust alias rules must be upheld at all times. E.g. don't create mutable and
///   immutable references to the same place (these may not partially overlap either).
/// * The place must be properly aligned and initialized.
/// * The caller must ensure that the invariant of the returned [Deferred] is upheld.
/// * The place must not be moved or dropped for as long as the returned [Deferred] is in use.
/// * No mutable references to the place may be created as long as the [Deferred] is in use. This will invalidate the [Deferred].
///
/// Here is an example that will cause undefined behavior to illustrate how unsafe this macro is.
/// The compiler will happilly compile this and not give any warning:
/// ```no_run
/// #[macro_use]
/// extern crate deferred_reference;
/// fn main() {
///     let mut buffer = [0u8; 1024];
///     let deferred = unsafe { defer!(buffer) };
///     buffer[0] = 42; // this implicitly creates a temporary mutable reference to `buffer`
///     // `deferred` is now invalidated 
///     // this is undefined behavior, even though the lifetimes of
///     // the immutable and mutable reference don't overlap:
///     assert_eq!(buffer[0], deferred[0]);
/// }
/// ```
/// This kind of pitfalls are not possible with instances of `Deferred<&T>` obtained through [Defer::defer],
/// because then the Rust compiler can detect these violations due to the bounded lifetime of
/// `Deferred<&T>`. In this case the compiler will warn you before-hand:
/// ```compile_fail
/// use deferred_reference::Defer;
/// use core::cell::UnsafeCell;
/// let mut buffer = UnsafeCell::new([0u8; 1024]);
/// let deferred = buffer.defer(); // note the absence of the unsafe block!
/// // the next line will cause the compilation to fail with the error:
/// // "cannot borrow `buffer` as mutable because it is also borrowed as immutable"
/// buffer.get_mut()[0] = 42;
/// assert_eq!(0, deferred[0]); // assures `deferred` is in use until here
/// ```
///
/// # Caveat
/// The lifetime for the returned [Deferred] is inferred from its usage. To prevent accidental misuse,
/// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, such as
/// by providing a helper function taking the lifetime of a host value, or by explicit annotation.
/// However, this can get very complicated and very unsafe real fast, here is an example of how this
/// could end up looking like (accompanied by the obligatory "*do not try this at home, kids!*"):
/// ```compile_fail
/// #[macro_use]
/// extern crate deferred_reference;
/// use deferred_reference::Deferred;
/// use core::marker::PhantomData;
/// fn shorten_lifetime<'a, 'b: 'a>(a: &'a PhantomData<[u8]>, b: Deferred<&'b [u8]>)
///     -> (&'a PhantomData<[u8]>, Deferred<&'a [u8]>)
/// {
///     // SAFETY: shortening the lifetime of 'b to 'a is always safe
///     unsafe { core::mem::transmute((a, b)) }
/// }
/// fn borrow_mut<'a>(_accountant: &'a mut PhantomData<[u8]>, borrow_mut: &'a mut [u8])
///     -> &'a mut [u8]
/// {
///     borrow_mut
/// }
/// macro_rules! get_deferred {
///     ($accountant:ident, $place:expr) => {
///         shorten_lifetime(&$accountant, defer!($place)).1
///     };
/// }
/// macro_rules! borrow_mut {
///     ($accountant:ident, $place:expr) => {
///         borrow_mut(&mut $accountant, &mut $place)
///     };
/// }
/// fn main() {
///     let mut buffer = [0u8; 1024];
///     // the `accountant` acts as a compile-time semaphore through the Rust borrow rules.
///     let mut accountant = PhantomData::<[u8]>;
///     // SAFETY: we promise to only use the `get_deferred` and `borrow_mut` macros.
///     // SAFETY: this is safe, because we don't take out explicit borrows like
///     // SAFETY: `&mut buffer` which are not tracked by our `accountant`.
///     let deferred: Deferred<&[u8]> = unsafe { get_deferred!(accountant, buffer) };
///     assert_eq!(0, deferred[0]);
///     // the next line will give an error at compile-time:
///     // "cannot borrow `accountant` as mutable because it is also borrowed as immutable"
///     let ref_mut: &mut [u8] = borrow_mut!(accountant, buffer); // mutably borrows
///     assert_eq!(0, deferred[0]); // asserts that `deferred` is in use until here
/// }
/// ```
#[macro_export]
macro_rules! defer {
    ($place:expr) => {
        $crate::Deferred::from_raw(core::ptr::addr_of!($place))
    };
}

/// The [Defer] trait offers easy access to deferred immutable references
/// to types that implement [Defer].
///
/// # Examples
/// ```
/// use deferred_reference::{Defer, Deferred};
/// use core::cell::UnsafeCell;
///
/// // Defer is implemented by default for any `UnsafeCell` holding an array or a slice:
/// let buffer = UnsafeCell::new([0u8; 1024]);
/// let deferred: Deferred<&[u8; 1024]> = buffer.defer();
/// // A deferred reference to an *array* can be unsized to a deferred reference to a *slice*:
/// let deferred_unsized: Deferred<&[u8]> = deferred.into();
/// // Dereferencing will create an actual reference `&[u8]`:
/// assert_eq!(*deferred, *deferred_unsized);
/// assert_eq!(*deferred, &[0u8; 1024][..]);
///
/// // Even though this crate is `#![no_std]`, it works with heap allocated contents as well:
/// let buffer = Box::new(UnsafeCell::new([0u8; 1024]));
/// let deferred /* : Deferred<&[u8; 1024]> */ = buffer.defer(); // omitting the type is okay
/// let deferred_unsized: Deferred<&[u8]> = deferred.into(); // unsize needs explicit type
/// // Dereferencing will create an actual reference `&[u8]`:
/// assert_eq!(*deferred, *deferred_unsized);
/// assert_eq!(*deferred, &[0u8; 1024][..]);
/// ```
///
/// # Why is `Defer` not implemented for all types?
/// The [Defer] trait comes implemented for all [`UnsafeCell<T: ?Sized>`](core::cell::UnsafeCell),
/// but it is not implemented for all types `T: ?Sized` which are not wrapped in an [UnsafeCell].
/// This is by design, because calling the `Defer::defer(&self)` method will take out an immutable reference
/// for as long as the returned [Deferred] is in use. In other words, this is not a deferrred
/// immutable reference, but an actual immutable reference to the underlying type. As long as this
/// immutable reference is in use, it is not allowed to create additional (deferred) mutable references
/// due to the Rust borrowing rules, unless the type is wrapped in an [UnsafeCell], which allows for
/// interior mutability (in fact this is the only way that Rust supports interior mutability).
/// If you don't intend to mutate the underlying type, then there is no use-case for [Defer]
/// and you're better off using an immutable reference `&T` instead of a `Deferred<&T>`.
/// If you do intend to mutate the underlying type, but have a good reason not to use [UnsafeCell],
/// then you may do so using the unsafe [`defer!`](macro@defer) and [`defer_mut!`](macro@defer_mut) macros.
/// However, use of these macros is not recommend and you should probably only use these if you know what you're
/// doing, because the lifetime of the [Deferred] returned by these macros is unbounded and the burden of
/// managing the lifetimes falls on the implementor. Note that there are also
/// [other (safe) ways to construct a deferred immutable reference](Deferred#constructors-for-deferred-immutable-references),
/// see the documentation at [Deferred] for more information on how to do this.
pub trait Defer {
    /// The type that the deferred reference points to.
    type Target: ?Sized;
    /// Obtain a deferred immutable reference to a [Defer::Target].
    fn defer(&self) -> Deferred<&Self::Target>;
}

impl<T: ?Sized> Defer for UnsafeCell<T> {
    type Target = T;
    fn defer(&self) -> Deferred<&T> {
        unsafe {
            Deferred::from_raw(self.get() as *const _)
        }
    }
}

impl<T: Reference> Defer for Deferred<T> {
    type Target = T::Target;

    fn defer(&self) -> Deferred<&Self::Target> {
        // SAFETY: Deferred (i.e. Self) already holds up the invariant, so this is safe.
        // SAFETY: this yields an almost identical Deferred, except it has a shorter lifetime
        // SAFETY: (it takes the lifetime of `&self` instead of from `T`)
        unsafe {
            Deferred::from_raw(self.as_ptr())
        }
    }
}

#[cfg(test)]
mod tests {
    mod defer_macro {
        use core::marker::PhantomData;

        use crate::Deferred;

        #[test]
        fn call_macro() {
            let buffer = [1u8; 1024];
            let deferred = unsafe { defer!(buffer) };
            assert_eq!(buffer[0], deferred[0]);
        }
        // /// this triggers UB in miri, because deferred gets invalidated
        // #[test]
        // fn example_ub() {
        //     let mut buffer = [2u8; 1024];
        //     let deferred = unsafe { defer!(buffer) };
        //     // this is undefined behavior:
        //     buffer[0] = 42; // because this implicitly creates a temporary mutable reference
        //     assert_eq!(buffer[0], deferred[0]);
        // }
        
        // /// this is also not possible, Rust detects the mutable borrow:
        // /// cannot borrow `buffer` as immutable because it is also borrowed as mutable
        // #[test]
        // fn assert_no_reference_created() {
        //     let mut buffer = [2u8; 1024];
        //     let mut_ref = &mut buffer;
        //     // next line errors: cannot borrow `buffer` as immutable because it is also borrowed as mutable
        //     let deferred = unsafe { defer!(buffer) };
        //     assert_eq!(2, mut_ref[0]);
        //     assert_eq!(buffer[0], deferred[0]);
        // }

        fn shorten_lifetime<'a, 'b: 'a>(a: &'a PhantomData<[u8]>, b: Deferred<&'b [u8]>)
            -> (&'a PhantomData<[u8]>, Deferred<&'a [u8]>) {
            // SAFETY: shortening the lifetime of 'b to 'a is always safe
            unsafe { core::mem::transmute((a, b)) }
        }

        fn borrow_mut<'a>(_accountant: &'a mut PhantomData<[u8]>, borrow_mut: &'a mut [u8]) -> &'a mut [u8] {
            borrow_mut
        }

        macro_rules! get_deferred {
            ($accountant:ident, $place:expr) => {
                shorten_lifetime(&$accountant, defer!($place)).1
            };
        }

        macro_rules! borrow_mut {
            ($accountant:ident, $place:expr) => {
                borrow_mut(&mut $accountant, &mut $place)
            };
        }
        #[test]
        fn bounded_lifetime() {
            let mut buffer = [0u8; 1024];
            let mut accountant = PhantomData::<[u8]>;
            let deferred: Deferred<&[u8]> = unsafe { get_deferred!(accountant, buffer) };
            assert_eq!(0, deferred[0]);
            let ref_mut: &mut [u8] = borrow_mut!(accountant, buffer);
            // assert_eq!(0, deferred[0]);
            assert_eq!(0, ref_mut[0]);
        }
    }

    mod defer_trait {
        use alloc::boxed::Box;
        use core::cell::UnsafeCell;
        use crate::{Defer, Deferred};

        #[test]
        fn doctest1() {
            // Defer is implemented by default for any `UnsafeCell` holding an array or a slice:
            let buffer = UnsafeCell::new([0u8; 1024]);
            let deferred: Deferred<&[u8; 1024]> = buffer.defer();
            // A deferred reference to an *array* can be unsized to a deferred reference to a *slice*:
            let deferred_unsized: Deferred<&[u8]> = deferred.into();
            // Dereferencing will create an actual reference `&[u8]`:
            assert_eq!(*deferred, *deferred_unsized);
            assert_eq!(*deferred, &[0u8; 1024][..]);
            
            // Even though this crate is `#![no_std]`, it works with heap allocated contents as well:
            let buffer = Box::new(UnsafeCell::new([0u8; 1024]));
            let deferred /* : Deferred<&[u8; 1024]> */ = buffer.defer(); // omitting the type is okay
            let deferred_unsized: Deferred<&[u8]> = deferred.into(); // unsize needs explicit type
            // Dereferencing will create an actual reference `&[u8]`:
            assert_eq!(*deferred, *deferred_unsized);
            assert_eq!(*deferred, &[0u8; 1024][..]);
        }
    }
}