symbolic_common/
cell.rs

1//! Primitives for dealing with self-referential data.
2//!
3//! The types and traits in this module aim to work around the lack of self-referencial types in
4//! Rust. This can happen when a _dependent_ type -- one that needs to borrow data without holding
5//! on to the owning reference -- needs to be stored alongside its owner. This is inherently not
6//! possible in Rust, since it would require the owner to have a stable memory address, but it is
7//! moved along with the reference.
8//!
9//! This module solves this by introducing the `AsSelf` trait, which can be used to coerce the
10//! lifetime of a dependent object to the lifetime of its owners at the time of the borrow.
11//!
12//! See [`SelfCell`] and [`AsSelf`] for more information.
13//!
14//! [`SelfCell`]: struct.SelfCell.html
15//! [`AsSelf`]: trait.AsSelf.html
16
17// FIXME(swatinem): clippy 1.67 complains about `# Safety` docs for safe fns
18// #![allow(clippy::unnecessary_safety_doc)]
19
20use std::ops::Deref;
21
22pub use stable_deref_trait::StableDeref;
23
24/// Safe downcasting of dependent lifetime bounds on structs.
25///
26/// This trait is similar to `AsRef`, except that it allows to capture the lifetime of the own
27/// instance at the time of the borrow. This allows to force it onto the type's lifetime bounds.
28/// This is particularly useful when the type's lifetime is somehow tied to it's own existence, such
29/// as in self-referential structs. See [`SelfCell`] for an implementation that makes use of this.
30///
31/// # Implementation
32///
33/// While this trait may be implemented for any type, it is only useful for types that specify a
34/// lifetime bound, such as `Cow` or [`ByteView`]. To implement, define `Ref` as the type with all
35/// dependent lifetimes set to `'slf`. Then, simply return `self` in `as_self`.
36///
37/// ```rust
38/// use symbolic_common::AsSelf;
39///
40/// struct Foo<'a>(&'a str);
41///
42/// impl<'slf> AsSelf<'slf> for Foo<'_> {
43///     type Ref = Foo<'slf>;
44///
45///     fn as_self(&'slf self) -> &Self::Ref {
46///         self
47///     }
48/// }
49/// ```
50///
51/// # Interior Mutability
52///
53/// **Note** that if your type uses interior mutability (essentially any type from `std::sync`, but
54/// specifically everything built on top of `UnsafeCell`), this implicit coercion will not work. The
55/// compiler imposes this limitation by declaring any lifetime on such types as invariant, to avoid
56/// interior mutations to write back data with the lowered lifetime.
57///
58/// If you are sure that your type will not borrow and store data of the lower lifetime, then
59/// implement the coercion with an unsafe transmute:
60///
61/// ```rust
62/// use std::cell::UnsafeCell;
63/// use symbolic_common::AsSelf;
64///
65/// struct Foo<'a>(UnsafeCell<&'a str>);
66///
67/// impl<'slf> AsSelf<'slf> for Foo<'_> {
68///     type Ref = Foo<'slf>;
69///
70///     fn as_self(&'slf self) -> &Self::Ref {
71///         unsafe { std::mem::transmute(self) }
72///     }
73/// }
74/// ```
75///
76/// [`SelfCell`]: struct.SelfCell.html
77/// [`ByteView`]: struct.ByteView.html
78pub trait AsSelf<'slf> {
79    /// The `Self` type with `'slf` lifetimes, returned by `as_self`.
80    type Ref: ?Sized;
81
82    /// Returns a reference to `self` with downcasted lifetime.
83    fn as_self(&'slf self) -> &'slf Self::Ref;
84}
85
86impl AsSelf<'_> for u8 {
87    type Ref = u8;
88
89    fn as_self(&self) -> &Self::Ref {
90        self
91    }
92}
93
94impl AsSelf<'_> for str {
95    type Ref = str;
96
97    fn as_self(&self) -> &Self::Ref {
98        self
99    }
100}
101
102impl<'slf, T> AsSelf<'slf> for [T]
103where
104    T: AsSelf<'slf>,
105    T::Ref: Sized,
106{
107    type Ref = [T::Ref];
108
109    fn as_self(&'slf self) -> &'slf Self::Ref {
110        unsafe { &*(self as *const [T] as *const [T::Ref]) }
111    }
112}
113
114impl<'slf, T> AsSelf<'slf> for &'slf T
115where
116    T: AsSelf<'slf> + ?Sized,
117{
118    type Ref = T::Ref;
119
120    fn as_self(&'slf self) -> &'slf Self::Ref {
121        (*self).as_self()
122    }
123}
124
125impl<'slf, T> AsSelf<'slf> for &'slf mut T
126where
127    T: AsSelf<'slf> + ?Sized,
128{
129    type Ref = T::Ref;
130
131    fn as_self(&'slf self) -> &'slf Self::Ref {
132        (**self).as_self()
133    }
134}
135
136impl<'slf, T> AsSelf<'slf> for Vec<T>
137where
138    T: AsSelf<'slf>,
139    T::Ref: Sized,
140{
141    type Ref = [T::Ref];
142
143    fn as_self(&'slf self) -> &'slf Self::Ref {
144        (**self).as_self()
145    }
146}
147
148impl<'slf, T> AsSelf<'slf> for std::rc::Rc<T>
149where
150    T: AsSelf<'slf>,
151{
152    type Ref = T::Ref;
153
154    fn as_self(&'slf self) -> &'slf Self::Ref {
155        (**self).as_self()
156    }
157}
158
159impl<'slf, T> AsSelf<'slf> for std::sync::Arc<T>
160where
161    T: AsSelf<'slf>,
162{
163    type Ref = T::Ref;
164
165    fn as_self(&'slf self) -> &'slf Self::Ref {
166        (**self).as_self()
167    }
168}
169
170/// A container carrying a derived object alongside its owner.
171///
172/// **Warning**: This is an inherently unsafe type that builds on top of [`StableDeref`] and
173/// [`AsSelf`] to establish somewhat safe memory semantics. Always try to avoid self-references by
174/// storing data in an outer scope or avoiding the need alltogether, first.
175///
176/// `SelfCell` stores an owner object that must implement [`StableDeref`]. This guarantees that the
177/// reference pointed to by the dependent object never moves over the lifetime of this object. This
178/// is already implemented for most heap-allocating types, like `Box`, `Rc`, `Arc` or `ByteView`.
179///
180/// Additionally, the dependent object must implement [`AsSelf`]. This guarantees that the borrow's
181/// lifetime and its lifetime bounds never exceed the lifetime of the owner. As such, an object
182/// `Foo<'a>` that borrows data from the owner, will be coerced down to `Foo<'self>` when borrowing.
183/// There are two constructor functions, `new` and `try_new`, each of which are passed a pointer to
184/// the owned data. Dereferencing this pointer is intentionally unsafe, and beware that a borrow of
185/// that pointer **must not** leave the callback.
186///
187/// While it is possible to store derived *references* in a `SelfCell`, too, there are simpler
188/// alternatives, such as `owning_ref::OwningRef`. Consider using such types before using
189/// `SelfCell`.
190///
191/// ## Example
192///
193/// ```rust
194/// use symbolic_common::{AsSelf, SelfCell};
195///
196/// struct Foo<'a>(&'a str);
197///
198/// impl<'slf> AsSelf<'slf> for Foo<'_> {
199///     type Ref = Foo<'slf>;
200///
201///     fn as_self(&'slf self) -> &Self::Ref {
202///         self
203///     }
204/// }
205///
206/// let owner = String::from("hello world");
207/// let cell = SelfCell::new(owner, |s| Foo(unsafe { &*s }));
208/// assert_eq!(cell.get().0, "hello world");
209/// ```
210///
211/// [`StableDeref`]: trait.StableDeref.html
212/// [`AsSelf`]: trait.AsSelf.html
213#[derive(Clone, Debug)]
214pub struct SelfCell<O, D>
215where
216    O: StableDeref,
217{
218    owner: O,
219    derived: D,
220}
221
222impl<'slf, O, T> SelfCell<O, T>
223where
224    O: StableDeref + 'slf,
225    T: AsSelf<'slf>,
226{
227    /// Creates a new `SelfCell`.
228    ///
229    /// # Safety
230    ///
231    /// The callback receives a pointer to the owned data. Dereferencing the pointer is unsafe. Note
232    /// that a borrow to that data can only safely be used to derive the object and **must not**
233    /// leave the callback.
234    ///
235    /// # Example
236    ///
237    /// ```
238    /// use symbolic_common::SelfCell;
239    ///
240    /// let owner = String::from("hello world");
241    /// let cell = SelfCell::new(owner, |s| unsafe { &*s });
242    /// ```
243    #[inline]
244    pub fn new<F>(owner: O, derive: F) -> Self
245    where
246        F: FnOnce(*const <O as Deref>::Target) -> T,
247    {
248        let derived = derive(owner.deref() as *const _);
249        SelfCell { owner, derived }
250    }
251
252    /// Creates a new `SelfCell` which may fail to construct.
253    ///
254    /// # Safety
255    ///
256    /// The callback receives a pointer to the owned data. Dereferencing the pointer is unsafe. Note
257    /// that a borrow to that data can only safely be used to derive the object and **must not**
258    /// leave the callback.
259    ///
260    /// # Example
261    ///
262    /// ```
263    /// use symbolic_common::SelfCell;
264    ///
265    /// fn main() -> Result<(), std::str::Utf8Error> {
266    ///     let owner = Vec::from("hello world");
267    ///     let cell = SelfCell::try_new(owner, |s| unsafe { std::str::from_utf8(&*s) })?;
268    ///     Ok(())
269    /// }
270    /// ```
271    #[inline]
272    pub fn try_new<E, F>(owner: O, derive: F) -> Result<Self, E>
273    where
274        F: FnOnce(*const <O as Deref>::Target) -> Result<T, E>,
275    {
276        let derived = derive(owner.deref() as *const _)?;
277        Ok(SelfCell { owner, derived })
278    }
279
280    /// Unsafely creates a new `SelfCell` from a derived object by moving the owner.
281    ///
282    /// # Safety
283    ///
284    /// This is an inherently unsafe process. The caller must guarantee that the derived object only
285    /// borrows from the owner that is moved into this container and the borrowed reference has a
286    /// stable address. This is useful, when cloning the owner by deriving a sub-object.
287    ///
288    /// # Example
289    ///
290    /// ```rust
291    /// use std::sync::Arc;
292    /// use symbolic_common::{AsSelf, SelfCell};
293    ///
294    /// struct Foo<'a>(&'a str);
295    ///
296    /// impl<'slf> AsSelf<'slf> for Foo<'_> {
297    ///     type Ref = Foo<'slf>;
298    ///
299    ///     fn as_self(&'slf self) -> &Self::Ref {
300    ///         self
301    ///     }
302    /// }
303    ///
304    /// // Create a clonable owner and move it into cell
305    /// let owner = Arc::<str>::from("  hello  ");
306    /// let cell = SelfCell::new(owner, |s| Foo(unsafe { &*s }));
307    ///
308    /// // Create a second derived object and clone the owner
309    /// let trimmed = Foo(cell.get().0.trim());
310    /// let cell2 = unsafe { SelfCell::from_raw(cell.owner().clone(), trimmed) };
311    ///
312    /// // Now, drop the original cell and continue using the clone
313    /// assert_eq!(cell2.get().0, "hello");
314    /// ```
315    #[inline]
316    pub unsafe fn from_raw(owner: O, derived: T) -> Self {
317        SelfCell { owner, derived }
318    }
319
320    /// Returns a reference to the owner of this cell.
321    ///
322    /// # Example
323    ///
324    /// ```
325    /// use symbolic_common::SelfCell;
326    ///
327    /// let owner = String::from("  hello  ");
328    /// let cell = SelfCell::new(owner, |s| unsafe { (*s).trim() });
329    /// assert_eq!(cell.owner(), "  hello  ");
330    /// ```
331    #[inline(always)]
332    pub fn owner(&self) -> &O {
333        &self.owner
334    }
335
336    /// Returns a safe reference to the derived object in this cell.
337    ///
338    /// # Example
339    ///
340    /// ```
341    /// use symbolic_common::SelfCell;
342    ///
343    /// let owner = String::from("  hello  ");
344    /// let cell = SelfCell::new(owner, |s| unsafe { (*s).trim() });
345    /// assert_eq!(cell.get(), "hello");
346    /// ```
347    #[inline(always)]
348    pub fn get(&'slf self) -> &'slf <T as AsSelf<'slf>>::Ref {
349        self.derived.as_self()
350    }
351}
352
353#[cfg(test)]
354mod tests {
355    use super::*;
356    use similar_asserts::assert_eq;
357
358    #[derive(Debug, PartialEq)]
359    struct Foo<'a>(&'a str);
360
361    impl<'a> Foo<'a> {
362        fn parse(s: &'a str) -> Result<Self, std::num::ParseIntError> {
363            s.parse::<usize>()?;
364            Ok(Foo(s))
365        }
366    }
367
368    impl<'slf> AsSelf<'slf> for Foo<'_> {
369        type Ref = Foo<'slf>;
370
371        fn as_self(&'slf self) -> &'slf Self::Ref {
372            self
373        }
374    }
375
376    #[test]
377    fn test_new() {
378        let fooref = SelfCell::new(String::from("hello world"), |s| Foo(unsafe { &*s }));
379        assert_eq!(fooref.get().0, "hello world");
380    }
381
382    #[test]
383    fn test_try_new() {
384        let result = SelfCell::try_new(String::from("42"), |s| Foo::parse(unsafe { &*s }));
385        result.expect("parsing should not fail");
386
387        let result = SelfCell::try_new(String::from("hello world"), |s| Foo::parse(unsafe { &*s }));
388        result.expect_err("parsing should fail");
389    }
390}