Skip to main content

flashmap/util/
aliasing.rs

1use std::{
2    borrow::Borrow,
3    fmt::{self, Debug, Display, Formatter},
4    hash::{Hash, Hasher},
5    marker::PhantomData,
6    mem::{self, MaybeUninit},
7    ops::Deref,
8    ptr,
9};
10
11/// Allows for aliasing typically non-aliasable types without undefined behavior or SB violations.
12///
13/// This type is very similar to [`ManuallyDrop`](std::mem::ManuallyDrop) in that the underlying
14/// value will be leaked without manual intervention, but additionally this type allows aliasing
15/// of the inner value through the [`copy`](crate::Alias::copy) method.
16///
17/// # Alias Families
18///
19/// When describing the safety contracts of this type, it is useful to have a notion of "all
20/// aliases that refer to the same data." We'll call that collection of alises an "alias family."
21/// If an alias `b` is created by copying an alias `a` via [`Alias::copy`](crate::Alias::copy),
22/// then `b` is a member of the same alias family as `a`.
23///
24/// # Safety
25///
26/// This type and its associated operations are sound because it wraps the aliased value in
27/// [`MaybeUninit`](std::mem::MaybeUninit), which causes the compiler to no longer assume any
28/// pointers contained within are unique or dereferenceable. Most of the APIs of this type are
29/// `unsafe`, but notably `Alias<T>` has a [`Deref`](std::ops::Deref) implementation for `T` which
30/// is guaranteed to be safe. The only reason this guarantee can be made is because `Alias<T>`
31/// will only ever safely give out shared references to the inner `T`, and all operations which
32/// require mutable access or ownership of the underlying value are unsafe. If you plan to use
33/// this type, please carefully read the safety comments for its associated methods since the
34/// unsafe contracts often ask the caller to assert facts about the program which cannot easily be
35/// verified locally.
36///
37/// # Thread Safety
38///
39/// `Alias<T>` is `Send` if and only if `T: Send + Sync`, and similarly `Alias<T>` is `Sync` if and
40/// only if `T: Send + Sync`. Clearly if `T: !Send`, then `Alias<T>` cannot be `Send`, however if
41/// `Alias<T>` were `Send` when `T: Send + !Sync`, then one could construct an `Alias<Box<T>>`,
42/// copy it, and send it to another thread, and obtain a shared reference to the inner `T`,
43/// violating the fact that `T: !Sync`.
44///
45/// `T` must also be `Send` in order for `Alias<T>` to be `Sync` due to the following scenario:
46/// ```compile_fail
47/// # use flashmap::Alias;
48/// use std::{marker::PhantomData, thread};
49///
50/// struct NotSend(PhantomData<*const ()>);
51/// unsafe impl Sync for NotSend {}
52///
53/// let dont_send = NotSend(PhantomData);
54/// let alias = Alias::new(dont_send);
55/// let alias_ref: &'static Alias<NotSend> = Box::leak(Box::new(alias));
56///
57/// thread::spawn(move || {
58///     let alias_copy = unsafe { Alias::copy(alias_ref) };
59///     let dont_send = unsafe { Alias::into_owned(alias_copy) };
60///     // Ownership of `dont_send` has been safely obtained in another thread.
61/// });
62/// ```
63/// According to the safety contracts of `copy` and `into_owned`, this program is safe. However,
64/// this program should fail to compile since we've transferred ownership of `dont_send` to
65/// another thread. Hence, for `Alias<T>` to be `Sync`, `T` must be `Send`.
66///
67/// # Examples
68///
69/// You can alias mutable references through this type without undefined behavior:
70/// ```
71/// # use flashmap::Alias;
72/// let mut x = 10i32;
73///
74/// // Store a mutable reference to `x` in an alias
75/// let a: Alias<&mut i32> = Alias::new(&mut x);
76/// // Make a copy to alias the underlying pointer
77/// // Safety: the value being aliased (in this case the mutable reference to `x`) is
78/// // not currently being modified.
79/// let b: Alias<&mut i32> = unsafe { Alias::copy(&a) };
80///
81/// // Same value
82/// assert_eq!(**a, **b);
83/// // Same pointer
84/// assert_eq!(*a as *const i32, *b as *const i32);
85///
86/// // Convert an alias back into an owned value
87/// // Safety: no alias in the same alias family as b is accessed beyond this point
88/// let x_mut: &mut i32 = unsafe { Alias::into_owned(b) };
89///
90/// *x_mut += 1;
91/// assert_eq!(x, 11);
92/// ```
93///
94/// Similarly, you can alias boxes and other pointer types to avoid making deep copies. However,
95/// the aliased value will need to be manually dropped.
96/// ```
97/// # use flashmap::Alias;
98/// let mut boks = Alias::new(Box::new(42i32));
99/// // Safety: the value being aliased is not currently being modified
100/// let another_boks = unsafe { Alias::copy(&boks) };
101///
102/// assert_eq!(**boks, **another_boks);
103///
104/// // Safety: no alias in the same alias family as boks is accessed beyond this point
105/// unsafe { Alias::drop(&mut boks); }
106/// ```
107#[repr(transparent)]
108pub struct Alias<T> {
109    value: MaybeUninit<T>,
110    _not_send_sync: PhantomData<*const ()>,
111}
112
113// See the Thread Safety section in the documentation of Alias
114unsafe impl<T> Send for Alias<T> where T: Send + Sync {}
115unsafe impl<T> Sync for Alias<T> where T: Send + Sync {}
116
117impl<T> Alias<T> {
118    /// Takes ownership of the given value and returns an alias of that value. The alias must be
119    /// manually dropped after calling this function, else the inner value will be leaked.
120    ///
121    /// Note that the alias returned is conceptually associated with a new, unique alias family
122    /// in which it is the only member.
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// # use flashmap::Alias;
128    /// let alias = Alias::new(5i32);
129    /// assert_eq!(*alias, 5);
130    /// // Since i32 is Copy there's no need to drop it
131    /// ```
132    #[inline]
133    pub const fn new(val: T) -> Self {
134        Self {
135            value: MaybeUninit::new(val),
136            _not_send_sync: PhantomData,
137        }
138    }
139
140    /// Create a copy of the given alias.
141    ///
142    /// This function performs a shallow copy. So, for example, if you `copy` an
143    /// `Alias<Box<String>>`, then only the 8 bytes (or however many for your architecture)
144    /// constituting the pointer to the `String` will be copied, and the actual data in the string
145    /// will not be copied or read.
146    ///
147    /// The returned alias is conceptually a member of the same alias family as the argument
148    /// provided.
149    ///
150    /// # Safety
151    ///
152    /// The caller must assert that the `T` being aliased is safe to read. An example of when
153    /// this is **not** safe is shown below:
154    ///
155    /// ```no_run
156    /// # use flashmap::Alias;
157    /// use std::{sync::Mutex, thread};
158    ///
159    /// // Mutexes allow for interior mutability, in other words you can modify the value
160    /// // within a mutex through an immutable reference to that mutex
161    /// let aliased_mutex = Alias::new(Mutex::new(0i32));
162    /// // Obtain an immutable reference to the aliased mutex
163    /// let x: &'static Alias<Mutex<_>> = Box::leak(Box::new(aliased_mutex));
164    ///
165    /// thread::spawn(move || {
166    ///     // Modify the value within the mutex in parallel with the execution of the
167    ///     // spawning thread
168    ///     *x.lock().unwrap() = 42;
169    /// });
170    ///
171    /// // !!!!! UNDEFINED BEHAVIOR !!!!!
172    /// // Copying the alias does a shallow copy of the underlying mutex, which includes
173    /// // copying (and thus reading) the integer being modified in this example.
174    /// // This is a concurrent read+write data race.
175    /// let y = unsafe { Alias::copy(x) };
176    /// ```
177    ///
178    /// The reason that copying `x` is unsound here is because the data it points to could be
179    /// concurrently modified by the spawned thread. `Alias` induces no indirection, and neither
180    /// does `Mutex`, so the reference stored in `x` points to the actual bytes of the integer
181    /// being modified, hence when we copy the alias into `y`, we read those bytes while they are
182    /// being modified, causing a data race.
183    ///
184    /// # Examples
185    ///
186    /// Aliasing a `String`:
187    /// ```
188    /// # use flashmap::Alias;
189    /// let mut a = Alias::new("foo".to_owned());
190    /// // Safety: the value `a` is aliasing is not being concurrently modified
191    /// let b = unsafe { Alias::copy(&a) };
192    ///
193    /// // Equivalent values
194    /// assert_eq!(a, b);
195    /// // Same object in memory
196    /// assert_eq!(a.as_ptr(), b.as_ptr());
197    ///
198    /// // Ensure we don't leak memory
199    /// unsafe {
200    ///     // We only need to drop one of the aliases since they both alias the same
201    ///     // location in memory
202    ///     Alias::drop(&mut a);
203    /// }
204    /// ```
205    #[inline]
206    pub unsafe fn copy(other: &Self) -> Self {
207        Self {
208            value: unsafe { ptr::read(&other.value) },
209            _not_send_sync: PhantomData,
210        }
211    }
212
213    /// Converts an alias of a value into an owned value.
214    ///
215    /// # Safety
216    ///
217    /// The caller must assert that no alias within the same alias family as the argument is
218    /// accessed during, or at any point after this function is called. Note that implicitly
219    /// dropping an `Alias<T>` does **not** count as an access since the `Drop` implementation for
220    /// `Alias<T>` is a no-op and does not access the underlying data.
221    ///
222    /// The following example shows an **incorrect** use of `into_owned`, resulting in undefined
223    /// behavior:
224    /// ```no_run
225    /// # use flashmap::Alias;
226    /// let a = Alias::new(Box::new(10i32));
227    /// // Safety: the data aliased by `a` is not currently being modified
228    /// let b = unsafe { Alias::copy(&a) };
229    ///
230    /// // !!!!! UNDEFINED BEHAVIOR !!!!!
231    /// // `b` is in the same alias family as `a`, and `a` is accessed after this
232    /// // function call.
233    /// let boks = unsafe { Alias::into_owned(b) };
234    /// drop(boks);
235    ///
236    /// // Alias guarantees that calling `deref` is always safe, so although the actual
237    /// // operation (use after free) which immediately causes UB occurs here, this is
238    /// // due to the violation of the unsafe contract on `into_owned` above.
239    /// assert_eq!(**a, 10);
240    /// ```
241    ///
242    /// # Examples
243    ///
244    /// ```
245    /// # use flashmap::Alias;
246    /// let a = Alias::new("foo".to_owned());
247    /// // Safety: the data aliased by `a` is not currently being modified
248    /// let b = unsafe { Alias::copy(&a) };
249    ///
250    /// // Safety: `a` is the only other member of `b`'s alias family, and is not accessed
251    /// // after this point
252    /// let string = unsafe { Alias::into_owned(b) };
253    ///
254    /// assert_eq!(string, "foo");
255    ///
256    /// // Calling Drop::drop on an Alias<T> does not count as an access
257    /// drop(a);
258    /// ```
259    #[inline]
260    pub const unsafe fn into_owned(alias: Self) -> T {
261        unsafe { alias.value.assume_init() }
262    }
263
264    /// Drops the aliased value, potentially invalidating all other aliases to that value.
265    ///
266    /// # Safety
267    ///
268    /// This function has the same safety requirements as [`into_owned`](crate::Alias::into_owned).
269    ///
270    /// The following example shows an **incorrect** use of `drop`, resulting in undefined
271    /// behavior:
272    /// ```no_run
273    /// # use flashmap::Alias;
274    /// let a = Alias::new(Box::new(10i32));
275    /// // Safety: the data aliased by `a` is not currently being modified
276    /// let mut b = unsafe { Alias::copy(&a) };
277    ///
278    /// // !!!!! UNDEFINED BEHAVIOR !!!!!
279    /// // `b` is in the same alias family as `a`, and `a` is accessed after this
280    /// // function call.
281    /// unsafe { Alias::drop(&mut b); }
282    ///
283    /// // Alias guarantees that calling `deref` is always safe, so although the actual
284    /// // operation (use after free) which immediately causes UB occurs here, this is
285    /// // due to the violation of the unsafe contract on `drop` above.
286    /// assert_eq!(**a, 10);
287    /// ```
288    ///
289    /// # Examples
290    ///
291    /// ```
292    /// # use flashmap::Alias;
293    /// let a = Alias::new("foo".to_owned());
294    /// // Safety: the data aliased by `a` is not currently being modified
295    /// let mut b = unsafe { Alias::copy(&a) };
296    ///
297    /// // Safety: neither `a` or `b` are accessed after this point
298    /// unsafe { Alias::drop(&mut b) };
299    ///
300    /// // Calling Drop::drop on an Alias<T> does not count as an access
301    /// drop(a);
302    /// ```
303    #[inline]
304    pub unsafe fn drop(alias: &mut Self) {
305        unsafe { alias.value.assume_init_drop() }
306    }
307}
308
309impl<T> Deref for Alias<T> {
310    type Target = T;
311
312    #[inline]
313    fn deref(&self) -> &Self::Target {
314        // Safety: the caller has asserted that this method will never be called after into_owned
315        // or drop by either never calling those methods or abiding to their safety contracts, so
316        // it is safe to give out a shared reference to the underlying value here.
317        unsafe { self.value.assume_init_ref() }
318    }
319}
320
321impl<T: Debug> Debug for Alias<T> {
322    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
323        Debug::fmt(&**self, f)
324    }
325}
326
327impl<T: Display> Display for Alias<T> {
328    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
329        Display::fmt(&**self, f)
330    }
331}
332
333impl<T: PartialEq> PartialEq for Alias<T> {
334    #[inline]
335    fn eq(&self, other: &Self) -> bool {
336        PartialEq::eq(&**self, &**other)
337    }
338}
339
340impl<T: Eq> Eq for Alias<T> {}
341
342impl<T: Hash> Hash for Alias<T> {
343    #[inline]
344    fn hash<H: Hasher>(&self, state: &mut H) {
345        (**self).hash(state)
346    }
347}
348
349// Workaround for orphan rules when implementing Borrow for Alias
350#[repr(transparent)]
351#[derive(PartialEq, Eq, Hash)]
352pub(crate) struct BorrowHelper<T: ?Sized> {
353    pub(crate) value: T,
354}
355
356impl<T: ?Sized> BorrowHelper<T> {
357    #[inline]
358    pub fn new_ref(value: &T) -> &Self {
359        unsafe { mem::transmute(value) }
360    }
361}
362
363impl<T, U: ?Sized> Borrow<BorrowHelper<U>> for Alias<T>
364where
365    T: Borrow<U>,
366{
367    #[inline]
368    fn borrow(&self) -> &BorrowHelper<U> {
369        unsafe { mem::transmute(<T as Borrow<U>>::borrow(&**self)) }
370    }
371}