unbounded/lib.rs
1//! **Unsound and unsafe**! For edutainment purposes only.
2#![no_std]
3#![deny(unsafe_op_in_unsafe_fn)]
4
5/// Unbinds the lifetime in a [reference][REF] (`&T` or `&mut T`). This
6/// disconnects the input lifetime from the output lifetime, so use of the
7/// output reference will no longer cause input reference to be kept "live" (as
8/// defined in [RFC 2094: non-lexical lifetimes][NLL]). The output reference is
9/// given an [unbounded lifetime][UBL], so the borrow checker is free to coerce
10/// it to whatever is expected.
11///
12/// The output lifetime may still be implicitly bound by any references within
13/// the referenced type `T`. You may need to unbind these as well, or replace
14/// them with `'static`.
15///
16/// [REF]: https://doc.rust-lang.org/std/primitive.reference.html
17/// [NLL]: https://rust-lang.github.io/rfcs/2094-nll.html
18/// [UBL]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html
19///
20/// # Safety
21///
22/// This is **unsound and unsafe**, even though it is marked as a safe function!
23/// Invoking this functions risks incurring the wrath of the optimizer. Rust
24/// references are not pointers. For edutainment purposes only.
25///
26/// # Examples
27///
28/// Here we create two (aliasing) unbounded mutable references at once, and then
29/// continue to use them even after the original value is dropped (and its true
30/// lifetime has ended).
31///
32/// ```
33/// let mut x = 0;
34///
35/// let mut_1 = ::unbounded::reference(&mut x);
36/// let mut_2 = ::unbounded::reference(&mut x);
37///
38/// drop(x);
39///
40/// *mut_1 = 1;
41/// *mut_2 = 2;
42///
43/// assert_eq!(*mut_1, *mut_2, "I hope LLVM is in a good mood!");
44/// ```
45#[inline(always)]
46pub fn reference<'original, 'unbounded, Ref: Reference<'original, 'unbounded>>(
47 reference: Ref,
48) -> Ref::Unbounded {
49 unsafe { reference.unbounded() }
50}
51
52/// Used by [`reference`][self::reference] to abstract over `&T` and `&mut T`
53///
54/// # Safety
55///
56/// _This section intentionally left blank._
57pub unsafe trait Reference<'original, 'unbounded> {
58 type Unbounded;
59
60 /// # Safety
61 ///
62 /// _This section intentionally left blank._
63 unsafe fn unbounded(self) -> Self::Unbounded;
64}
65
66unsafe impl<'original, 'unbounded, T: 'unbounded> Reference<'original, 'unbounded>
67 for &'original T
68{
69 type Unbounded = &'unbounded T;
70
71 #[inline(always)]
72 unsafe fn unbounded(self) -> Self::Unbounded {
73 unsafe { ::core::mem::transmute(self) }
74 }
75}
76
77unsafe impl<'original, 'unbounded, T: 'unbounded> Reference<'original, 'unbounded>
78 for &'original mut T
79{
80 type Unbounded = &'unbounded mut T;
81
82 #[inline(always)]
83 unsafe fn unbounded(self) -> Self::Unbounded {
84 unsafe { ::core::mem::transmute(self) }
85 }
86}