type_factory/
lib.rs

1//! Generates unique values of opaque types.
2//!
3//! # Purpose
4//!
5//! <code>impl [Unique]</code> types are guaranteed to be unique. They cannot be
6//! copied or cloned and are suitable for use as brand types.
7//!
8//! The [`toast-cell`](https://crates.io/crates/toast-cell) crate utilizes this
9//! property.
10//!
11//! # Similar crates
12//!
13//! [`generativity`](https://crates.io/crates/generativity) provides a macro to
14//! generate unique invariant lifetimes. It does not require dependent code to
15//! reside within a closure.
16//!
17//! # Minimum supported Rust version
18//!
19//! The MSRV is currently 1.56.
20//!
21//! This may change between minor releases.
22//!
23//! # License
24//!
25//! This crate is licensed under the
26//! [Blue Oak Model License 1.0.0](https://blueoakcouncil.org/license/1.0.0).
27
28// Attributes
29#![cfg_attr(not(any(doc, test)), no_std)]
30// Lints
31#![warn(missing_docs)]
32
33use core::{
34	fmt::{self, Debug, Formatter},
35	marker::PhantomData,
36};
37
38#[cfg(any(doctest, test))]
39mod tests;
40
41mod sealed {
42	pub trait Sealed {}
43}
44use sealed::Sealed;
45
46/// The initial unique type.
47///
48/// Construct an instance of this type within a scope using [`with`].
49///
50/// See [`Unique`] for more details.
51pub struct Initial<'scope>(PhantomData<fn(&'scope ()) -> &'scope ()>);
52
53impl<'scope> Sealed for Initial<'scope> {}
54
55impl<'scope> Debug for Initial<'scope> {
56	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57		f.write_str("impl Unique")
58	}
59}
60
61/// A unique type.
62///
63/// The [`Initial`] unique type for a scope may be constructed using [`with`].
64///
65/// Further unique types may be obtained via [`split`].
66///
67/// # Invariant
68///
69/// `Unique` has one invariant: more than one instance of an `impl Unique` type
70/// must *not* exist within a scope.
71///
72/// The crate is designed in such a way that this may never be violated in safe
73/// code.
74///
75/// # Guarantees
76///
77/// As `impl Unique` types are opaque, they have a few properties that are not
78/// possible to expose.
79///
80/// ## Types are zero-sized
81///
82/// All `impl Unique` types are zero-sized.
83///
84/// ## Types do nothing on drop
85///
86/// All `impl Unique` types can be [forgotten] without worry as they lack an
87/// implementation of [`Drop`].
88///
89/// [forgotten]: std::mem::forget
90///
91/// # Safeguards
92///
93/// A number of safeguards are in place to prevent `Unique` from potential
94/// misuse. The following is a list of these including examples of what could go
95/// wrong if they were *not* in place.
96///
97/// ## The trait is not object-safe
98///
99/// `dyn Unique` trait objects are forbidden from existence for a reason. See
100/// the following example:
101///
102/// ```compile_fail,E0038
103/// # use type_factory::{split, with, Unique};
104/// fn assert_type_eq<T>(_: T, _: T) {}
105///
106/// with(|initial| {
107///     let (a, b) = split(initial);
108///     let a: Box<dyn Unique> = Box::new(a);
109///     let b: Box<dyn Unique> = Box::new(b);
110///     // In this hypothetical world, unique types aren't so unique.
111///     assert_type_eq(a, b);
112/// });
113/// ```
114///
115/// If `Unique` were object-safe, trait objects of it could be arbitrarily
116/// created. As they would implement `Unique` while being the same type, the
117/// trait's invariant would be violated.
118///
119/// ## The trait is sealed
120///
121/// `Unique` cannot be implemented for external types because it is [sealed].
122/// See the following example:
123///
124/// ```compile_fail,E0277
125/// # use type_factory::Unique;
126/// fn assert_type_eq<T>(_: T, _: T) {}
127///
128/// #[derive(Debug)]
129/// struct MyUnique;
130///
131/// impl Unique for MyUnique {}
132///
133/// let a = MyUnique;
134/// let b = MyUnique;
135/// // The invariant is trivially violated once again.
136/// assert_type_eq(a, b);
137/// ```
138///
139/// If the trait were not sealed, its invariant could easily be violated.
140///
141/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
142///
143/// ## Values are tied to a scoped invariant lifetime
144///
145/// [`with`] and [`split`] both have very particular function signatures:
146///
147/// ```
148/// # use type_factory::{Initial, Unique};
149/// fn with<R, F>(scope: F) -> R
150/// where
151///     F: for<'scope> FnOnce(Initial<'scope>) -> R,
152/// # { type_factory::with(scope) }
153/// { /* ... */ }
154///
155/// fn split<'scope, T>(unique: T) -> (impl 'scope + Unique, impl 'scope + Unique)
156/// where
157///     T: 'scope + Unique,
158/// # { type_factory::split(unique) }
159/// { /* ... */ }
160/// ```
161///
162/// `'scope` can be thought of as the "scope" of the closure passed to [`with`].
163/// No type bound by it can escape (or be returned from) the closure.
164///
165/// ```compile_fail
166/// # use type_factory::{split, with};
167/// with(|initial| {
168///     // error: lifetime may not live long enough
169///     split(initial)
170/// });
171/// ```
172///
173/// Furthermore, the lifetime is [invariant][variance] in order to guarantee
174/// that `impl Unique` types are truly unique. If the lifetime were absent, such
175/// types would be `'static`, allowing them to be [downcast] between each other
176/// since they would all share the same [`TypeId`]. Consider the following
177/// example:
178///
179/// ```
180/// # use std::any::Any;
181/// # use type_factory::Unique;
182/// // Because all `impl Unique` values are backed by the same concrete type,
183/// // they share a `TypeId`. This allows them to be downcast between each other
184/// // thanks to `Box<dyn Any>`'s `downcast` methods.
185/// fn unify<T, U>(x: T, y: U) -> Option<(T, T)>
186/// where
187///     T: 'static + Unique,
188///     U: 'static + Unique,
189/// {
190///     let y: Box<dyn Any> = Box::new(y);
191///     match y.downcast::<T>() {
192///        Ok(y) => Some((x, *y)),
193///        Err(_) => None,
194///     }
195/// }
196/// ```
197///
198/// Thankfully, this is forbidden from occurring since, due to the design of the
199/// crate, it is impossible to create an `impl Unique` type that is `'static`.
200///
201/// [variance]: https://doc.rust-lang.org/reference/subtyping.html
202/// [downcast]: std::any
203/// [`TypeId`]: std::any::TypeId
204///
205/// ## Values cannot be duplicated
206///
207/// No type that implements `Unique` also implements [`Copy`] or [`Clone`] as to
208/// forbid its instance from being trivially duplicated.
209#[must_use = "unique types do nothing unless used"]
210pub trait Unique: Sealed + Sized + Debug {}
211
212impl<'scope> Unique for Initial<'scope> {}
213
214/// Uses a unique type in a scope.
215///
216/// # Example
217///
218/// ```
219/// # use type_factory::{split, with};
220/// with(|initial/*: Initial<'_> */| {
221///     let (a, b) = split(initial);
222///     let (b, c) = split(b);
223///     // `a`, `b`, and `c` are each of a distinct `impl '_ + Unique` type.
224/// });
225/// ```
226pub fn with<R, F>(scope: F) -> R
227where
228	F: for<'scope> FnOnce(Initial<'scope>) -> R,
229{
230	scope(Initial(PhantomData))
231}
232
233/// Splits a unique type in two.
234///
235/// # Example
236///
237/// ```
238/// # use type_factory::{split, with};
239/// with(|initial| {
240///     // Split in two.
241///     let (a, b) = split(initial);
242///
243///     // ...
244/// });
245/// ```
246pub fn split<'scope, T>(
247	#[allow(unused_variables)] unique: T,
248) -> (impl 'scope + Unique, impl 'scope + Unique)
249where
250	T: 'scope + Unique,
251{
252	(Initial(PhantomData), Initial(PhantomData))
253}