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}