deferred_reference/defer_mut.rs
1use core::cell::UnsafeCell;
2
3use super::{Defer, Deferred};
4
5/// An unsafe macro to create a deferred mutable reference (i.e. a [`Deferred<&mut T>`](Deferred)) to a place,
6/// without creating an intermediate reference. See the documentation at [Deferred] explaining the
7/// [constructors for deferred mutable references](Deferred#constructors-for-deferred-mutable-references)
8/// for safer alternatives.
9///
10/// Use of this macro is not recommended, because it's a lot more unsafe than obtaining a `Deferred<&mut T>` through
11/// a type that implements the [DeferMut] trait. Use [`DeferMut::defer_mut`](DeferMut::defer_mut) or
12/// [`Deferred::from(&mut T)`](From::from) for a safer alternative instead.
13///
14/// The only use case for this macro is when you can't create a reference to a place and also can't use [UnsafeCell]
15/// to achieve interior mutability. However, this is a rare case and requires advanced knowledge of unsafe Rust.
16///
17/// # Example
18/// ```
19/// #[macro_use]
20/// extern crate deferred_reference;
21/// use deferred_reference::Deferred;
22/// fn main() {
23/// let mut buffer = [0u8; 1024];
24/// let deferred: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
25/// assert_eq!(buffer[0], deferred[0]);
26/// // works also for references to arrays:
27/// let deferred: Deferred<&mut [u8; 1024]> = unsafe { defer_mut!(buffer) };
28/// assert_eq!(buffer[0], deferred[0]);
29/// }
30/// ```
31///
32/// # Safety
33/// This macro is very unsafe and should only be used if there is no other safe way to obtain a deferred mutable reference.
34/// See the [DeferMut] trait for the preferred way to create an deferred mutable reference. When using this
35/// macro, the caller must uphold the following guarantees:
36/// * When dereferencing the [Deferred], the Rust alias rules must be upheld at all times. E.g. don't create mutable and
37/// immutable references to the same place (these may not partially overlap either).
38/// * The place must be properly aligned and initialized.
39/// * The caller must ensure that the invariant of the returned [Deferred] is upheld.
40/// * The place must not be moved or dropped for as long as the returned [Deferred] is in use.
41/// * No explicit references to the place may be created as long as the [Deferred] is in use. This will invalidate the [Deferred].
42/// * Any other instances of [Deferred] that point to the same location, must be reborrowed from the original deferred mutable reference.
43/// This is possible using [Deferred::clone_unchecked] and [Deferred::into_ref]. Any other deferred references will becomed invalidated
44/// as soon as the deferred mutable reference is dereferenced (unless its target contents are inside an [UnsafeCell]).
45///
46/// Here is an example that will trigger undefined behavior, in order to illustrate how unsafe this macro is:
47/// ```no_run
48/// #[macro_use]
49/// extern crate deferred_reference;
50/// fn main() {
51/// let mut buffer = [0u8; 1024];
52/// let deferred = unsafe { defer_mut!(buffer) };
53/// buffer[0] = 42; // implicitly creates a temporary mutable reference to all of `buffer`
54/// // `deferred` is now invalidated !!!
55/// // therefore dereferencing `deferred` is undefined behavior, even though
56/// // the lifetimes of the immutable and mutable references don't overlap:
57/// assert_eq!(buffer[0], deferred[0]); // undefined behavior!!!
58/// }
59/// ```
60///
61/// # Caveat
62/// The lifetime for the returned [Deferred] is inferred from its usage. To prevent accidental misuse,
63/// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, such as
64/// by providing a helper function taking the lifetime of a host value, or by explicit annotation.
65/// However, this can get very complicated and very unsafe real fast, see the [`defer`](macro@defer#caveat)
66/// macro for an example of how to do this without creating an intermediate reference.
67///
68/// # How can this be safely used together with the `defer!` macro?
69/// As mentioned above under section "[*Safety*](#safety)", dereferencing a `Deferred<&mut T>` will invalidate any other [Deferred] instances
70/// which are not re-borrowed, even the ones created by the [`defer`](macro@defer) macro (`Deferred<&T>` instances returned by the
71/// [`defer`](macro@defer) macro do not constitute as re-borrows). This means that the [`defer`](macro@defer) macro is only safe to use
72/// together with the [`defer_mut`](macro@defer_mut) macro if you take special care to always call [`defer!`](macro@defer) again to refresh
73/// its pointer, after a mutable reference has been given out through dereferencing the `Deferred<&mut T>.` For example, this is definately
74/// __considered undefined behavior__:
75/// ```no_run
76/// #[macro_use]
77/// extern crate deferred_reference;
78/// use deferred_reference::Deferred;
79/// fn main() {
80/// let mut buffer = [0u8; 1024];
81/// // SAFETY: what we are about to do is very unsafe!
82/// let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
83/// let deferred: Deferred<&[u8]> = unsafe { defer!(buffer) };
84/// assert_eq!(0, deferred_mut[0]);
85/// assert_eq!(0, deferred[0]); // so far so good, no UB yet...
86/// deferred_mut[0] = 42; // this implicity creates a mutable reference to `buffer`
87/// // `deferred` is now invalidated!
88/// assert_eq!(42, deferred_mut[0]); // this is not yet UB...
89/// assert_eq!(42, deferred[0]); // this is UB!
90/// }
91/// ```
92/// The undefined behavior can be side-stepped if the deferred mutable reference is re-borrowed, like so:
93/// ```
94/// #[macro_use]
95/// extern crate deferred_reference;
96/// use deferred_reference::Deferred;
97/// fn main() {
98/// let mut buffer = [0u8; 1024];
99/// // SAFETY: this is safe because we reborrow `deferred_mut` and
100/// // SAFETY: we don't create any overlapping references.
101/// let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
102/// let deferred: Deferred<&[u8]> = unsafe { deferred_mut.clone_unchecked().into_ref() };
103/// assert_eq!(0, deferred_mut[0]);
104/// assert_eq!(0, deferred[0]);
105/// deferred_mut[0] = 42; // this implicity creates a mutable reference to `buffer`
106/// assert_eq!(42, deferred_mut[0]);
107/// assert_eq!(42, deferred[0]); // but this is not UB thanks the re-borrow
108/// }
109/// ```
110/// If the calls to the [`defer`](macro@defer) macro are timed well, then it is possible to combine
111/// the two macros without running into undefined behavior:
112/// ```
113/// #[macro_use]
114/// extern crate deferred_reference;
115/// use deferred_reference::Deferred;
116/// fn main() {
117/// let mut buffer = [0u8; 1024];
118/// // SAFETY: this is safe, because we create new deferred references after
119/// // SAFETY: dereferencing `deferred_mut` into an actual mutable reference.
120/// let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
121/// let mut deferred: Deferred<&[u8]> = unsafe { defer!(buffer) };
122/// assert_eq!(0, deferred_mut[0]);
123/// assert_eq!(0, deferred[0]);
124/// deferred_mut[0] = 42; // this implicity creates a temporary mutable reference to `buffer`
125/// // `deferred` is now invalidated! we refresh it again:
126/// deferred = unsafe { defer!(buffer) };
127/// assert_eq!(42, deferred_mut[0]);
128/// // this is not UB, because the mutable reference did not overlap
129/// // with the re-creation of `deferred`:
130/// assert_eq!(42, deferred[0]);
131/// }
132/// ```
133/// The previous 3 examples consist of very unsafe Rust and should not be attempted unless there
134/// exists a specific reason why this is needed and the implementor has intricate knowledge
135/// about raw pointer management in Rust. In all other cases, using the [DeferMut::defer_mut]
136/// is the much better alternative to the [`defer_mut`](macro@defer_mut) macro.
137#[macro_export]
138macro_rules! defer_mut {
139 ($place:expr) => {
140 $crate::Deferred::from_raw_mut(core::ptr::addr_of_mut!($place))
141 };
142}
143
144/// The [DeferMut] trait offers easy access to deferred mutable references
145/// to types that implement [DeferMut]. This trait is already implemented on all types `T: ?Sized` for
146/// [`UnsafeCell<T>`](core::cell::UnsafeCell) out-of-the-box and this should be sufficient for most purposes,
147/// but it is also possible to implement the [Defer] and [DeferMut] traits for your own types, please see
148/// the documentation of this trait on how to do this safely.
149///
150/// # Safety
151/// This trait may only be implemented for:
152/// 1. All types that support interior mutability. Concretely, this means that
153/// for types that have interior mutability, the type must contain an [UnsafeCell] or one of
154/// of its derivatives, such as those in the Rust standard library like `RefCell`, `RwLock` or `Mutex`.
155/// 2. Other smart-pointers which do not "own" their data. Smart-pointers which contain a
156/// mutable pointer `*mut T` don't need to wrap the mutable pointer in an [UnsafeCell], because
157/// dereferencing a mutable pointer does not constitute interior mutability.
158///
159/// Additionally, all types that implement [DeferMut] must uphold the following invariants:
160/// * The type must also implement the [Defer] trait.
161/// * The deferred reference that the [DeferMut::defer_mut] method returns, must point to the same location
162/// as the [Deferred] returned by [Defer::defer].
163/// * Both the [Defer] and [DeferMut] trait implementations may not create any references
164/// to the location where the returned [Deferred] points, nor may the location
165/// be accessed in any way (e.g. dereferencing). Taking an immutable shared reference to a wrapping [UnsafeCell]
166/// is okay, but creating a reference to the contents of the [UnsafeCell] is not! Creating a
167/// mutable reference to the wrapping [UnsafeCell] is also not okay, because [UnsafeCell] only protects
168/// shared references to a place that may be mutated, it does not weaken the rules for mutable references,
169/// which say that a mutable reference must be exclusive in order to stay clear of undefined behavior.
170///
171/// # Example
172/// Here is an example for how to implement this trait for custom smart pointers.
173/// ```
174/// use deferred_reference::{Defer, DeferMut, Deferred};
175/// /// `MemoryMappedBuffer` is a simplified representation of a memory mapped slice of bytes.
176/// /// Proper implementations would also contain a `MemoryMappedBuffer::new` constructor
177/// /// which sets up the owned memory map and `MemoryMappedBuffer` should also implement
178/// /// the `Drop` trait to properly clean up the memory map when `MemoryMappedBuffer`
179/// /// goes out of scope.
180/// pub struct MemoryMappedBuffer {
181/// ptr: *mut u8,
182/// length: usize,
183/// }
184/// impl Defer for MemoryMappedBuffer {
185/// type Target = [u8];
186/// fn defer(&self) -> Deferred<&[u8]> {
187/// let slice_ptr = core::ptr::slice_from_raw_parts(self.ptr as *const u8, self.length);
188/// // SAFETY: this is safe because the Deferred occupies a shared reference to the
189/// // SAFETY: smart pointer `MemoryMappedBuffer` for the duration of lifetime of &self,
190/// // SAFETY: which means no other callers can safely obtain a mutable reference
191/// // SAFETY: the MemoryMappedBuffer instance.
192/// unsafe { Deferred::from_raw(slice_ptr) }
193/// }
194/// }
195/// // SAFETY: this is safe, because the invariant of `Deferred` is upheld.
196/// // SAFETY: this is only safe if the memory mapped region is properly aligned and initialized
197/// // SAFETY: and `ptr` is non-null and not dangling (i.e. it must point to a valid memory region).
198/// unsafe impl DeferMut for MemoryMappedBuffer {
199/// unsafe fn defer_mut(&self) -> Deferred<&mut [u8]> {
200/// let slice_mut_ptr = core::ptr::slice_from_raw_parts_mut(self.ptr, self.length);
201/// Deferred::from_raw_mut(slice_mut_ptr)
202/// }
203/// }
204/// ```
205/// If you want to build your own custom smart pointer that also owns the backing memory,
206/// then you can use `Vec`, `Box` and `UnsafeCell` to do so through interior mutability like this:
207/// ```
208/// use deferred_reference::{Defer, DeferMut, Deferred};
209/// use core::ops::{Deref, DerefMut};
210/// use core::cell::UnsafeCell;
211/// pub struct MyBuffer {
212/// memory: Box<UnsafeCell<[u8]>>,
213/// }
214/// impl MyBuffer {
215/// fn new(capacity: usize) -> Self {
216/// let mut vector = Vec::with_capacity(capacity);
217/// // we have to initialize the full vector, otherwise it is undefined behavior
218/// // when we give out references to the backing slice of bytes.
219/// vector.resize(capacity, 0u8);
220/// let boxed_slice: Box<[u8]> = vector.into_boxed_slice();
221/// // SAFETY: UnsafeCell is #[repr(transparent)] so this is safe.
222/// let memory: Box<UnsafeCell<[u8]>> = unsafe { core::mem::transmute(boxed_slice) };
223/// Self { memory }
224/// }
225/// }
226/// // we only need to implement Deref, because the Defer and DeferMut
227/// // traits are already implemented for UnsafeCell<[u8]>.
228/// impl Deref for MyBuffer {
229/// type Target = UnsafeCell<[u8]>;
230/// fn deref(&self) -> &Self::Target {
231/// self.memory.deref()
232/// }
233/// }
234/// // we also implement DerefMut just to illustrate the invalidation of
235/// // Deferred when taking out a mutable borrow. this is optional.
236/// impl DerefMut for MyBuffer {
237/// fn deref_mut(&mut self) -> &mut Self::Target {
238/// self.memory.deref_mut()
239/// }
240/// }
241/// fn main() {
242/// let mut my_buffer = MyBuffer::new(1024 * 100); // 100kb buffer
243/// // SAFETY: this is safe, because there exist no references to the slice.
244/// let deferred_mut: Deferred<&mut [u8]> = unsafe { my_buffer.defer_mut() };
245/// // the next line implicitly calls Deref::deref() on `my_buffer`.
246/// // this is also okay, because the slice sits inside an UnsafeCell.
247/// let deferred: Deferred<&[u8]> = my_buffer.defer();
248/// // the next statement is also safe, because by taking out a `&mut self` on MyBuffer
249/// // the deferred references are invalidated due to their lifetimes.
250/// // this implicitly calls DerefMut::deref_mut() and then UnsafeCell::get_mut():
251/// let mut_ref: &mut [u8] = my_buffer.get_mut();
252/// // with the next statement uncommmented, the above statement will error:
253/// // "cannot borrow `my_buffer` as mutable because it is also borrowed as immutable"
254/// //let mut_ref2: &mut [u8] = deferred_mut.deref_mut(); // uncomment for error
255/// }
256/// ```
257pub unsafe trait DeferMut: Defer {
258 /// Obtain a deferred mutable reference to [Defer::Target].
259 ///
260 /// # Example
261 /// ```
262 /// use deferred_reference::{Defer, DeferMut};
263 /// use core::cell::UnsafeCell;
264 /// let buffer = UnsafeCell::new([0u8; 1024]);
265 /// // calling defer() or defer_mut() immutably borrows `buffer` for as long
266 /// // as the returned `Deferred` is in use.
267 /// let deferred = buffer.defer();
268 /// // SAFETY: this is safe, because we promise not to create an overlapping mutable reference
269 /// let mut deferred_mut = unsafe { buffer.defer_mut() };
270 /// // both `deferred` and `deferred_mut` can be safely immutably dereferenced simultaneously:
271 /// assert_eq!(&deferred[0], &deferred_mut[0]);
272 /// // we can mutate the `buffer` through `deferred_mut` as any other array.
273 /// // this implicity creates a temporary mutable reference into the array inside `buffer`.
274 /// // even though an immutable reference to `buffer` exists, this is okay because
275 /// // the inner array sits inside an `UnsafeCell` which allows interior mutability:
276 /// deferred_mut[0] = 42;
277 /// // and observe the change through `deferred`:
278 /// assert_eq!(deferred[0], 42);
279 /// // all this time, both deferred references are alive, but because
280 /// // these are not actual references, this doesn't violate the Rust borrow
281 /// // rules and this is not undefined behavior. The lifetimes of the mutable
282 /// // and immutable references derived from the Deferred do not overlap,
283 /// // so the Rust borrow rules are respected all this time.
284 /// assert_eq!(&deferred[0], &deferred_mut[0]);
285 /// // this also works for multiple deferred mutable references!
286 /// // SAFETY: this is safe, because we promise not to create overlapping references
287 /// let mut deferred_mut2 = unsafe { buffer.defer_mut() };
288 /// // we can mutate the buffer through 2 distinct deferred mutable references
289 /// // (as long as we don't do this at the same time!)
290 /// deferred_mut[0] += 1;
291 /// deferred_mut2[0] += 1;
292 /// assert_eq!(44, deferred[0]);
293 /// assert_eq!(deferred_mut[0], deferred_mut2[0]);
294 /// // because `Deferred` implements the `Index` and `IndexMut` trait, it is possible
295 /// // to create two references that overlap in lifetime, but are disjoint in index:
296 /// assert_eq!(&mut deferred_mut[1], &mut deferred_mut2[2]); // indices are disjoint, so no UB
297 /// ```
298 ///
299 /// # Safety
300 /// This method is unsafe, because it is possible to call it more than once. This is in contrast
301 /// to the regular Rust borrowing rules, where it is only allowed to have one mutable borrow at
302 /// a time. [Deferred] instances are not actual references and this is why this is not considered
303 /// undefined behavior. However, the absence of instant undefined behavior does not make this
304 /// method safe. [Deferred] also implements the [DerefMut](core::ops::DerefMut) trait, which lets
305 /// anyone call `<Deferred as DerefMut>::deref_mut(&mut self)` on the [Deferred] and this creates
306 /// an actual mutable reference from safe code. Hence, this method must be marked as unsafe,
307 /// otherwise it could lead to unsoundness when creating multiple mutable references from safe code.
308 /// The caller must take special care not to create any references (mutable or immutable) that
309 /// may overlap with the actual mutable reference created from the returned [`Deferred<&mut T>`](Deferred).
310 /// Note that overlap means a reference to the same region during the same lifetime. If two
311 /// [Deferred] both create a reference to the same region, but with disjoint lifetimes, then
312 /// this is safe.
313 unsafe fn defer_mut(&self) -> Deferred<&mut Self::Target>;
314}
315
316unsafe impl<T: ?Sized> DeferMut for UnsafeCell<T> {
317 unsafe fn defer_mut(&self) -> Deferred<&mut T> {
318 Deferred::from_raw_mut(self.get())
319 }
320}
321
322unsafe impl<T: ?Sized> DeferMut for Deferred<&mut T> {
323 unsafe fn defer_mut(&self) -> Deferred<&mut Self::Target> {
324 Deferred::from_raw_mut(self.as_mut_ptr())
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use crate::{Defer, DeferMut};
331 use core::cell::UnsafeCell;
332
333 /// this test is identical to the example doctest of [DeferMut],
334 /// but it is repeated here because Miri does not support doctests yet.
335 #[test]
336 fn doc_test() {
337 let buffer = UnsafeCell::new([0u8; 1024]);
338 // calling defer() or defer_mut() immutably borrows `buffer` for as long
339 // as the returned `Deferred` is in use.
340 let deferred = buffer.defer();
341 // SAFETY: this is safe, because we promise not to create overlapping references
342 let mut deferred_mut = unsafe { buffer.defer_mut() };
343 // both `deferred` and `deferred_mut` can be safely immutably dereferenced:
344 assert_eq!(&deferred[0], &deferred_mut[0]);
345 // we can mutate the `buffer` through `deferred_mut` as any other array.
346 // this implicity creates a temporary mutable reference into the array inside `buffer`.
347 // even though an immutable reference to `buffer` exists, this is okay because
348 // the inner array sits inside an `UnsafeCell` which allows interior mutability:
349 deferred_mut[0] = 42;
350 // and observe the change through `deferred`:
351 assert_eq!(deferred[0], 42);
352 // all this time, both deferred references are alive, but because
353 // these are not actual references, this doesn't violate the Rust borrow
354 // rules and this is not undefined behavior. The lifetimes of the mutable
355 // and immutable references derived from the Deferred do not overlap,
356 // so the Rust borrow rules are respected all this time.
357 assert_eq!(&deferred[0], &deferred_mut[0]);
358 // this also works for multiple deferred mutable references!
359 // SAFETY: this is safe, because we promise not to create overlapping references
360 let mut deferred_mut2 = unsafe { buffer.defer_mut() };
361 // we can mutate the buffer through 2 distinct deferred mutable references
362 // (as long as we don't do this at the same time!)
363 deferred_mut[0] += 1;
364 deferred_mut2[0] += 1;
365 assert_eq!(44, deferred[0]);
366 assert_eq!(deferred_mut[0], deferred_mut2[0]);
367 // however, the following is not okay, because this would create two overlapping
368 // mutable references and this is undefined behavior (hence the use of `unsafe` above):
369 //assert_eq!(&mut deferred_mut[0], &mut deferred_mut2[0]);
370 // because `Deferred` implements the `Index` and `IndexMut` trait, it is possible
371 // to create two references that overlap in lifetime, but are disjoint in index:
372 assert_eq!(&mut deferred_mut[1], &mut deferred_mut2[2]); // indices are disjoint, so no UB
373 }
374
375 mod defer_mut_macro {
376 use crate::{defer, Deferred};
377 #[test]
378 fn call_macro() {
379 let mut buffer = [1u8; 1024];
380 let mut deferred = unsafe { defer_mut!(buffer) };
381 assert_eq!(buffer[0], deferred[0]);
382 deferred[0] = 2;
383 assert_eq!(2, buffer[0]);
384 }
385 // /// this triggers UB in miri, because deferred gets invalidated
386 // #[test]
387 // fn example_ub() {
388 // let mut buffer = [2u8; 1024];
389 // let deferred = unsafe { defer_mut!(buffer) };
390 // // this is undefined behavior:
391 // buffer[0] = 42; // because this implicitly creates a temporary mutable reference
392 // assert_eq!(buffer[0], deferred[0]);
393 // }
394
395 #[test]
396 fn assert_no_reference_created() {
397 let mut buffer = [3u8; 1024];
398 let mut deferred = unsafe { defer_mut!(buffer) };
399 assert_eq!(&3, &buffer[0]); // this implicitly creates a temporary immutable reference to all of `buffer`
400 // this is undefined behavior:
401 //buffer[0] = 42; // because this implicitly creates a temporary mutable reference to all of `buffer`, which invalidates `deferred`
402 // but this is not undefined behavior:
403 deferred[0] = 42; // because the mutable pointer to `buffer` inside `deferred` is re-borrowed
404 assert_eq!(buffer[0], deferred[0]);
405 assert_eq!(42, buffer[0]);
406 }
407
408 /// extra test to ensure the doctest above doesn't cause UB (miri doesn't work on doctests yet)
409 #[test]
410 fn doc_test() {
411 let mut buffer = [0u8; 1024];
412 let deferred: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
413 assert_eq!(buffer[0], deferred[0]);
414 // works also for references to arrays:
415 let deferred: Deferred<&mut [u8; 1024]> = unsafe { defer_mut!(buffer) };
416 assert_eq!(buffer[0], deferred[0]);
417 }
418
419 /// canary test to see if mutable references reborrowed from Deferred invalidate other Deferred.
420 /// (so far miri doesn't complain here yet)
421 #[test]
422 fn overlapping_deferreds() {
423 let mut buffer = [3u8; 1024];
424 let mut deferred1 = unsafe { defer_mut!(buffer) };
425 let mut deferred2 = unsafe { defer_mut!(buffer) };
426 assert_eq!(&mut 3, &mut deferred1[0]);
427 assert_eq!(&mut 3, &mut deferred2[0]);
428 assert_eq!(&mut 3, &mut deferred1[0]);
429 deferred1[0] = 42;
430 deferred2[1] = 42;
431 assert_eq!(&mut 42, &mut deferred2[0]);
432 assert_eq!(&mut 42, &mut deferred1[0]);
433 assert_eq!(&mut 42, &mut deferred2[0]);
434 assert_eq!(&deferred1[..], &deferred2[..]);
435 }
436
437 #[test]
438 fn mixing_defer_and_defer_mut() {
439 let mut buffer = [0u8; 1024];
440 let deferred: Deferred<&[u8]> = unsafe { crate::defer!(buffer) };
441 assert_eq!(0, deferred[0]);
442 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
443 assert_eq!(0, deferred[0]); // deferred is still valid
444 deferred_mut[0] = 42;
445 assert_eq!(42, deferred_mut[0]);
446 // the previous line created a mutable reference, so we need to re-obtain Deferred<&[u8]>
447 let deferred: Deferred<&[u8]> = unsafe { crate::defer!(buffer) }; // omitting this line is UB!
448 assert_eq!(42, deferred[0]);
449 assert_eq!(42, deferred_mut[0]);
450 }
451 #[test]
452 fn mixing_defer_and_defer_mut2() {
453 let mut buffer = [0u8; 1024];
454 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
455 assert_eq!(0, deferred_mut[0]);
456 let deferred: Deferred<&[u8]> = unsafe { crate::defer!(buffer) };
457 assert_eq!(0, deferred[0]);
458 deferred_mut[0] = 42;
459 assert_eq!(42, deferred_mut[0]);
460 // the previous line created a mutable reference, so we need to re-obtain Deferred<&[u8]>
461 let deferred: Deferred<&[u8]> = unsafe { crate::defer!(buffer) }; // omitting this line is UB!
462 assert_eq!(42, deferred[0]);
463 assert_eq!(42, deferred_mut[0]);
464 }
465 #[test]
466 fn mixing_defer_and_defer_mut3() {
467 let mut buffer = [0u8; 1024];
468 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
469 assert_eq!(0, deferred_mut[0]);
470 // here we create a deferred immutable reference which reborrows the pointer:
471 let deferred: Deferred<&[u8]> = unsafe { deferred_mut.clone_unchecked().into() };
472 assert_eq!(0, deferred[0]);
473 deferred_mut[0] = 42;
474 assert_eq!(42, deferred[0]); // NOT UB! thanks to the reborrow
475 assert_eq!(42, deferred_mut[0]);
476 }
477
478 #[test]
479 fn doctest_defer1() {
480 let mut buffer = [0u8; 1024];
481 // SAFETY: what we are about to do is very unsafe!
482 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
483 let deferred: Deferred<&[u8]> = unsafe { defer!(buffer) };
484 assert_eq!(0, deferred_mut[0]);
485 assert_eq!(0, deferred[0]); // so far so good, no UB yet...
486 deferred_mut[0] = 42; // this implicity creates a mutable reference to `buffer`
487 // `deferred` is now invalidated!
488 assert_eq!(42, deferred_mut[0]);
489 //assert_eq!(42, deferred[0]); // this is UB!
490 }
491 #[test]
492 fn doctest_defer2() {
493 let mut buffer = [0u8; 1024];
494 // SAFETY: this is safe because we reborrow `deferred_mut` and
495 // SAFETY: we don't create any overlapping references.
496 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
497 let deferred: Deferred<&[u8]> = unsafe { deferred_mut.clone_unchecked().into_ref() };
498 assert_eq!(0, deferred_mut[0]);
499 assert_eq!(0, deferred[0]);
500 deferred_mut[0] = 42; // this implicity creates a mutable reference to `buffer`
501 assert_eq!(42, deferred_mut[0]);
502 assert_eq!(42, deferred[0]); // but this is not UB thanks the re-borrow
503 }
504 #[test]
505 fn doctest_defer3() {
506 let mut buffer = [0u8; 1024];
507 // SAFETY: this is safe, because we create new deferred references after
508 // SAFETY: dereferencing `deferred_mut` into an actual mutable reference.
509 let mut deferred_mut: Deferred<&mut [u8]> = unsafe { defer_mut!(buffer) };
510 let mut deferred: Deferred<&[u8]> = unsafe { defer!(buffer) };
511 assert_eq!(0, deferred_mut[0]);
512 assert_eq!(0, deferred[0]); // so far so good, no UB yet...
513 deferred_mut[0] = 42; // this implicity creates a temporary mutable reference to `buffer`
514 // `deferred` is now invalidated! we refresh it again:
515 deferred = unsafe { defer!(buffer) };
516 assert_eq!(42, deferred_mut[0]);
517 // this is not UB, because the mutable reference did not overlap
518 // with the re-creation of `deferred`:
519 assert_eq!(42, deferred[0]);
520 }
521 }
522}