generic_container/
kinds.rs

1//! # Container Kind Traits
2//!
3//! Currently, Rust doesn't allow bounds like
4//! `where C: for<T: Send> Container<T> + Clone + Send + Sync`.
5//! The solution is to define an extra trait with whatever you need as the bounds of a GAT
6//! (generic associated type):
7//! ```
8//! use generic_container::FragileMutContainer;
9//! use dupe::Dupe;
10//!
11//! pub trait NeededContainerStuff {
12//!    // Implementors should use `T: ?Sized` when possible. But right now, the only way to create,
13//!    // for example, `Arc<Mutex<[T]>>` is via unsizing coercion from `Arc<Mutex<[T; N]>>`;
14//!    // as such, a `T: ?Sized` bound would be somewhat useless without also requiring the
15//!    // container to support unsizing coercion, which currently requires nightly-only traits.
16//!    type MutableContainer<T: Send>: FragileMutContainer<T> + Dupe + Send + Sync;
17//! }
18//! ```
19//!
20//! If some data needs thread-safe mutability, but you don't want to pay the cost of a lock for
21//! read-only data, you can use multiple GATs:
22//! ```
23//! use generic_container::{FragileMutContainer, Container};
24//! use dupe::Dupe;
25//!
26//! pub trait NeededContainerStuff {
27//!    // E.g.: `Arc<Mutex<T>>`, or something `parking_lot`-based
28//!    type MutableContainer<T: Send>: FragileMutContainer<T> + Dupe + Send + Sync;
29//!    // E.g.: `Arc<T>`
30//!    type ReadOnlyContainer<T: Send + Sync>: Container<T> + Dupe + Send + Sync;
31//! }
32//! ```
33//!
34//! Such a trait is called a "container kind trait" (with implementations being "container kinds",
35//! just as implementations of the container traits are "containers"). Relevant characteristics for
36//! a container kind's container include the eight container traits, `Send + Sync` bounds (possibly
37//! only when `T` is `Send + Sync`, or just `Send`), [`Dupe`], whether the GAT allows `T` to be
38//! unsized, and `Debug` bounds.
39//!
40//! Not every conceivably-useful container kind trait is provided, as there would be
41//! exponentially-many such traits. Note also that creating simple container kind traits that can
42//! be combined into more complicated bounds does *work*, but not well. A container kind should set
43//! the GAT of each container kind trait it implements to the same container type; this *can* be
44//! asserted or required with Rust's type system, but the trait solver doesn't understand it very
45//! well. Such container kind traits would likely not be pleasant to use.
46//!
47//! When the `kinds` feature is enabled, container kinds for common sorts of containers are
48//! provided. They do not use [`Dupe`] bounds, and do not mess with type-equality shenanigans that
49//! confuse the trait solver.
50//!
51//! [`Dupe`]: https://docs.rs/dupe/0.9/dupe/trait.Dupe.html
52
53use crate::container_traits::{
54    Container, FragileContainer, FragileMutContainer, MutContainer, TryMutContainer,
55};
56
57
58// ================================
59//  Container Kind Traits
60// ================================
61
62/// A [container kind trait](self) based on how a type `T` acts as a container for itself.
63///
64/// Has strictly tighter requirements than [`FragileTLike`].
65pub trait TLike {
66    /// A `T`-like container type
67    type Container<T>: MutContainer<T>;
68}
69
70/// A [container kind trait](self) based on how a type `T` acts as a container for itself.
71///
72/// `T`, however, is not a [fragile](crate#fragility-potential-panics-or-deadlocks) container;
73/// this kind trait loosens that requirement.
74pub trait FragileTLike {
75    /// A `T`-like container type, but permitted to be
76    /// [fragile](crate#fragility-potential-panics-or-deadlocks).
77    type Container<T>: FragileMutContainer<T>;
78}
79
80/// A [container kind trait](self) based on how `Box<T>` acts as a container for `T`.
81///
82/// Has strictly tighter requirements than [`TLike`], [`FragileTLike`], and [`FragileBoxLike`].
83pub trait BoxLike {
84    /// A `Box<T>`-like container type
85    type Container<T: ?Sized>: MutContainer<T>;
86}
87
88/// A [container kind trait](self) based on how `Box<T>` acts as a container for `T`.
89///
90/// `Box<T>`, however, is not a [fragile](crate#fragility-potential-panics-or-deadlocks) container;
91/// this kind trait loosens that requirement.
92///
93/// Has strictly tighter requirements than [`FragileTLike`].
94pub trait FragileBoxLike {
95    /// A `Box<T>`-like container type, but permitted to be
96    /// [fragile](crate#fragility-potential-panics-or-deadlocks).
97    type Container<T: ?Sized>: FragileMutContainer<T>;
98}
99
100/// A [container kind trait](self) based on how `Rc<T>` acts as a container for `T`.
101///
102/// Has strictly tighter requirements than [`FragileRcLike`].
103pub trait RcLike {
104    /// An `Rc<T>`-like container type
105    type Container<T: ?Sized>: Container<T> + Clone;
106}
107
108/// A [container kind trait](self) based on how `Rc<T>` acts as a container for `T`.
109///
110/// `Rc<T>`, however, is not a [fragile](crate#fragility-potential-panics-or-deadlocks) container;
111/// this kind trait loosens that requirement.
112pub trait FragileRcLike {
113    /// An `Rc<T>`-like container type, but permitted to be
114    /// [fragile](crate#fragility-potential-panics-or-deadlocks).
115    type Container<T: ?Sized>: FragileContainer<T> + Clone;
116}
117
118/// A [container kind trait](self) based on how `Rc<RefCell<T>>` acts as a container for `T`.
119///
120/// Has strictly tighter requirements than [`FragileRcLike`].
121pub trait RcRefCellLike {
122    /// An `Rc<RefCell<T>>`-like container type
123    type Container<T: ?Sized>: FragileMutContainer<T> + Clone;
124}
125
126/// A [container kind trait](self) based on how `Arc<T>` acts as a container for `T`.
127///
128/// Has strictly tighter requirements than [`FragileArcLike`].
129pub trait ArcLike {
130    /// An `Arc<T>`-like container type
131    type Container<T: ?Sized + Send + Sync>: Container<T> + Clone + Send + Sync;
132}
133
134/// A [container kind trait](self) based on how `Arc<T>` acts as a container for `T`.
135///
136/// `Arc<T>`, however, is not a [fragile](crate#fragility-potential-panics-or-deadlocks) container;
137/// this kind trait loosens that requirement.
138pub trait FragileArcLike {
139    /// An `Arc<T>`-like container type, but permitted to be
140    /// [fragile](crate#fragility-potential-panics-or-deadlocks).
141    type Container<T: ?Sized + Send + Sync>: FragileContainer<T> + Clone + Send + Sync;
142}
143
144/// A [container kind trait](self) based on how `Arc<RwLock<T>>` acts as a container for `T`.
145///
146/// Has strictly tighter requirements than [`FragileArcLike`].
147/// Similar to [`RcRefCellLike`], but not strictly tighter.
148pub trait ArcRwLockLike {
149    /// An `Arc<RwLock<T>>`-like container type
150    type Container<T: ?Sized + Send + Sync>: FragileMutContainer<T> + Clone + Send + Sync;
151}
152
153/// A [container kind trait](self) based on how `Arc<Mutex<T>>` acts as a container for `T`.
154///
155/// Has strictly tighter requirements than [`ArcRwLockLike`] and [`FragileArcLike`].
156/// Similar to [`RcRefCellLike`], but not strictly tighter.
157pub trait ArcMutexLike {
158    /// An `Arc<Mutex<T>>`-like container type
159    type Container<T: ?Sized + Send>: FragileMutContainer<T> + Clone + Send + Sync;
160}
161
162/// A [container kind trait](self) based on how [`CheckedRcRefCell<T>`] acts as a container for `T`.
163///
164#[cfg_attr(
165    feature = "alloc",
166    doc = "[`CheckedRcRefCell<T>`]: crate::CheckedRcRefCell",
167)]
168#[cfg_attr(
169    not(feature = "alloc"),
170    doc = "[`CheckedRcRefCell<T>`]: \
171    https://docs.rs/generic-container/0/generic_container/struct.CheckedRcRefCell.html",
172)]
173pub trait CheckedRcRefCellLike {
174    /// A [`CheckedRcRefCell<T>`]-like container type
175    ///
176    #[cfg_attr(
177        feature = "alloc",
178        doc = "[`CheckedRcRefCell<T>`]: crate::CheckedRcRefCell",
179    )]
180    #[cfg_attr(
181        not(feature = "alloc"),
182        doc = "[`CheckedRcRefCell<T>`]: \
183        https://docs.rs/generic-container/0/generic_container/struct.CheckedRcRefCell.html",
184    )]
185    type Container<T: ?Sized>: TryMutContainer<T> + Clone;
186}
187
188/// A [container kind trait](self) based on how <code>Arc<[ThreadCheckedMutex]\<T\>></code> acts as
189/// a container for `T`.
190///
191#[cfg_attr(
192    feature = "thread-checked-lock",
193    doc = "[ThreadCheckedMutex]: thread_checked_lock::ThreadCheckedMutex",
194)]
195#[cfg_attr(
196    not(feature = "thread-checked-lock"),
197    doc = "[ThreadCheckedMutex]: \
198    https://docs.rs/thread-checked-lock/0/thread_checked_lock/struct.ThreadCheckedMutex.html",
199)]
200pub trait ArcThreadCheckedMutexLike {
201    /// An <code>Arc<[ThreadCheckedMutex]\<T\>></code>-like container type
202    ///
203    #[cfg_attr(
204        feature = "thread-checked-lock",
205        doc = "[ThreadCheckedMutex]: thread_checked_lock::ThreadCheckedMutex",
206    )]
207    #[cfg_attr(
208        not(feature = "thread-checked-lock"),
209        doc = "[ThreadCheckedMutex]: \
210        https://docs.rs/thread-checked-lock/0/thread_checked_lock/struct.ThreadCheckedMutex.html",
211    )]
212    type Container<T: ?Sized + Send>: TryMutContainer<T> + Clone + Send + Sync;
213}
214
215// ================================
216//  Container Kinds
217// ================================
218
219/// The [container kind](crate::kinds) corresponding to `T` as a container for itself.
220#[cfg_attr(docsrs, doc(cfg(feature = "kinds")))]
221#[derive(Default, Debug, Clone, Copy)]
222pub struct TKind;
223
224impl TLike for TKind {
225    type Container<T> = T;
226}
227
228impl FragileTLike for TKind {
229    type Container<T> = T;
230}
231
232#[cfg(any(feature = "alloc", doc))]
233mod alloc_kinds {
234    use core::cell::RefCell;
235    use alloc::{boxed::Box, rc::Rc, sync::Arc};
236
237    use crate::impls::CheckedRcRefCell;
238    use super::{
239        ArcLike, BoxLike, CheckedRcRefCellLike,
240        FragileArcLike, FragileBoxLike, FragileTLike, FragileRcLike,
241        RcLike, RcRefCellLike, TLike,
242    };
243
244
245    /// The [container kind](crate::kinds) corresponding to `Box<T>` as a container for `T`.
246    #[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "kinds"))))]
247    #[derive(Default, Debug, Clone, Copy)]
248    pub struct BoxKind;
249
250    impl BoxLike for BoxKind {
251        type Container<T: ?Sized> = Box<T>;
252    }
253
254    impl FragileBoxLike for BoxKind {
255        type Container<T: ?Sized> = Box<T>;
256    }
257
258    impl TLike for BoxKind {
259        type Container<T> = Box<T>;
260    }
261
262    impl FragileTLike for BoxKind {
263        type Container<T> = Box<T>;
264    }
265
266    /// The [container kind](crate::kinds) corresponding to `Rc<T>` as a container for `T`.
267    #[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "kinds"))))]
268    #[derive(Default, Debug, Clone, Copy)]
269    pub struct RcKind;
270
271    impl RcLike for RcKind {
272        type Container<T: ?Sized> = Rc<T>;
273    }
274
275    impl FragileRcLike for RcKind {
276        type Container<T: ?Sized> = Rc<T>;
277    }
278
279    /// The [container kind](crate::kinds) corresponding to `Arc<T>` as a container for `T`.
280    #[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "kinds"))))]
281    #[derive(Default, Debug, Clone, Copy)]
282    pub struct ArcKind;
283
284    impl ArcLike for ArcKind {
285        type Container<T: ?Sized + Send + Sync> = Arc<T>;
286    }
287
288    impl FragileArcLike for ArcKind {
289        type Container<T: ?Sized + Send + Sync> = Arc<T>;
290    }
291
292    impl RcLike for ArcKind {
293        type Container<T: ?Sized> = Arc<T>;
294    }
295
296    impl FragileRcLike for ArcKind {
297        type Container<T: ?Sized> = Arc<T>;
298    }
299
300    /// The [container kind](crate::kinds) corresponding to `Rc<RefCell<T>>` as a container for `T`.
301    #[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "kinds"))))]
302    #[derive(Default, Debug, Clone, Copy)]
303    pub struct RcRefCellKind;
304
305    impl RcRefCellLike for RcRefCellKind {
306        type Container<T: ?Sized> = Rc<RefCell<T>>;
307    }
308
309    impl FragileRcLike for RcRefCellKind {
310        type Container<T: ?Sized> = Rc<RefCell<T>>;
311    }
312
313    /// The [container kind](crate::kinds) corresponding to [`CheckedRcRefCell<T>`] as a container
314    /// for `T`.
315    #[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "kinds"))))]
316    #[derive(Default, Debug, Clone, Copy)]
317    pub struct CheckedRcRefCellKind;
318
319    impl CheckedRcRefCellLike for CheckedRcRefCellKind {
320        type Container<T: ?Sized> = CheckedRcRefCell<T>;
321    }
322}
323
324#[cfg(any(feature = "alloc", doc))]
325pub use self::alloc_kinds::{ArcKind, BoxKind, CheckedRcRefCellKind, RcKind, RcRefCellKind};
326
327#[cfg(any(feature = "std", doc))]
328mod std_kinds {
329    use alloc::sync::Arc;
330    use std::sync::{Mutex, RwLock};
331
332    use super::{ArcMutexLike, ArcRwLockLike, FragileArcLike, FragileRcLike, RcRefCellLike};
333
334
335    /// The [container kind](crate::kinds) corresponding to `Arc<RwLock<T>>` as a container for `T`.
336    #[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "kinds"))))]
337    #[derive(Default, Debug, Clone, Copy)]
338    pub struct ArcRwLockKind;
339
340    impl ArcRwLockLike for ArcRwLockKind {
341        type Container<T: ?Sized + Send + Sync> = Arc<RwLock<T>>;
342    }
343
344    impl FragileArcLike for ArcRwLockKind {
345        type Container<T: ?Sized + Send + Sync> = Arc<RwLock<T>>;
346    }
347
348    impl RcRefCellLike for ArcRwLockKind {
349        type Container<T: ?Sized> = Arc<RwLock<T>>;
350    }
351
352    impl FragileRcLike for ArcRwLockKind {
353        type Container<T: ?Sized> = Arc<RwLock<T>>;
354    }
355
356    /// The [container kind](crate::kinds) corresponding to `Arc<Mutex<T>>` as a container for `T`.
357    #[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "kinds"))))]
358    #[derive(Default, Debug, Clone, Copy)]
359    pub struct ArcMutexKind;
360
361    impl ArcMutexLike for ArcMutexKind {
362        type Container<T: ?Sized + Send> = Arc<Mutex<T>>;
363    }
364
365    impl ArcRwLockLike for ArcMutexKind {
366        type Container<T: ?Sized + Send + Sync> = Arc<Mutex<T>>;
367    }
368
369    impl FragileArcLike for ArcMutexKind {
370        type Container<T: ?Sized + Send + Sync> = Arc<Mutex<T>>;
371    }
372
373    impl RcRefCellLike for ArcMutexKind {
374        type Container<T: ?Sized> = Arc<Mutex<T>>;
375    }
376
377    impl FragileRcLike for ArcMutexKind {
378        type Container<T: ?Sized> = Arc<Mutex<T>>;
379    }
380}
381
382#[cfg(any(feature = "std", doc))]
383pub use self::std_kinds::{ArcMutexKind, ArcRwLockKind};
384
385#[cfg(feature = "thread-checked-lock")]
386mod thread_checked_lock_kinds {
387    use alloc::sync::Arc;
388
389    use thread_checked_lock::ThreadCheckedMutex;
390
391    use super::{ArcThreadCheckedMutexLike, CheckedRcRefCellLike};
392
393
394    /// The [container kind](crate::kinds) corresponding to
395    /// <code>[Arc]<[ThreadCheckedMutex]\<T\>></code> as a container for `T`.
396    #[cfg_attr(docsrs, doc(cfg(all(feature = "thread-checked-lock", feature = "kinds"))))]
397    #[derive(Default, Debug, Clone, Copy)]
398    pub struct ArcThreadCheckedMutexKind;
399
400    impl ArcThreadCheckedMutexLike for ArcThreadCheckedMutexKind {
401        type Container<T: ?Sized + Send> = Arc<ThreadCheckedMutex<T>>;
402    }
403
404    impl CheckedRcRefCellLike for ArcThreadCheckedMutexKind {
405        type Container<T: ?Sized> = Arc<ThreadCheckedMutex<T>>;
406    }
407}
408
409#[cfg(feature = "thread-checked-lock")]
410pub use self::thread_checked_lock_kinds::ArcThreadCheckedMutexKind;