fp_library/classes/pointer.rs
1//! Independent traits for abstracting over different types of pointers and their capabilities.
2//!
3//! The pointer traits are independent (no supertrait relationships between them):
4//! * [`Pointer`]: Base trait for any heap-allocated pointer (`Box`, `Rc`, `Arc`).
5//! * [`RefCountedPointer`][super::ref_counted_pointer::RefCountedPointer]: Clonable reference-counted pointer (`Rc`, `Arc`).
6//! * [`SendRefCountedPointer`][super::send_ref_counted_pointer::SendRefCountedPointer]: Thread-safe reference-counted pointer (`Arc`).
7//!
8//! Coercion traits wrap closures into `dyn Fn` trait objects:
9//! * [`ToDynFn`][super::to_dyn_fn::ToDynFn]: Coerce to `dyn Fn` behind any pointer (extends `Pointer`).
10//! * [`ToDynCloneFn`][super::to_dyn_clone_fn::ToDynCloneFn]: Coerce to `dyn Fn` behind a clonable pointer (extends `RefCountedPointer`).
11//! * [`ToDynSendFn`][super::to_dyn_send_fn::ToDynSendFn]: Coerce to `dyn Fn + Send + Sync` behind a thread-safe pointer (extends `SendRefCountedPointer`).
12//!
13//! ### Examples
14//!
15//! ```
16//! use fp_library::{
17//! brands::*,
18//! functions::*,
19//! };
20//!
21//! let ptr = pointer_new::<RcBrand, _>(42);
22//! assert_eq!(*ptr, 42);
23//! ```
24
25#[fp_macros::document_module]
26mod inner {
27 use {
28 fp_macros::*,
29 std::ops::Deref,
30 };
31
32 /// Base type class for heap-allocated pointers.
33 ///
34 /// This is the minimal abstraction: any type that can wrap a value and
35 /// dereference to it. Does NOT require Clone - that's added by subtraits.
36 ///
37 /// By explicitly requiring that the type parameter `T` outlives the application lifetime `'a`,
38 /// we provide the compiler with the necessary guarantees to handle trait objects
39 /// (like `dyn Fn`) commonly used in pointer implementations. This resolves potential
40 /// E0310 errors where the compiler cannot otherwise prove that captured variables in
41 /// closures satisfy the required lifetime bounds.
42 pub trait Pointer {
43 /// The pointer type constructor.
44 ///
45 /// For `RcBrand`, this is `Rc<T>`. For `ArcBrand`, this is `Arc<T>`.
46 type Of<'a, T: ?Sized + 'a>: Deref<Target = T> + 'a;
47
48 /// Wraps a sized value in the pointer.
49 #[document_signature]
50 ///
51 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
52 ///
53 #[document_parameters("The value to wrap.")]
54 ///
55 #[document_returns("The value wrapped in the pointer type.")]
56 #[document_examples]
57 ///
58 /// ```
59 /// use fp_library::{
60 /// brands::*,
61 /// classes::*,
62 /// };
63 ///
64 /// let ptr = <RcBrand as Pointer>::new(42);
65 /// assert_eq!(*ptr, 42);
66 /// ```
67 fn new<'a, T: 'a>(value: T) -> Self::Of<'a, T>
68 where
69 Self::Of<'a, T>: Sized;
70 }
71
72 /// Wraps a sized value in the pointer.
73 #[document_signature]
74 ///
75 #[document_type_parameters(
76 "The pointer brand.",
77 "The lifetime of the value.",
78 "The type of the value to wrap."
79 )]
80 ///
81 #[document_parameters("The value to wrap.")]
82 ///
83 #[document_returns("The value wrapped in the pointer type.")]
84 #[document_examples]
85 ///
86 /// ```
87 /// use fp_library::{
88 /// brands::*,
89 /// functions::*,
90 /// };
91 ///
92 /// let ptr = pointer_new::<RcBrand, _>(42);
93 /// assert_eq!(*ptr, 42);
94 /// ```
95 pub fn new<'a, P: Pointer, T: 'a>(value: T) -> P::Of<'a, T>
96 where
97 P::Of<'a, T>: Sized, {
98 P::new(value)
99 }
100}
101
102pub use inner::*;