generic_container/
container_traits.rs

1use core::ops::{Deref, DerefMut};
2
3
4// ================================================================
5//  The four `{Fragile|}{Try|}Container` traits
6// ================================================================
7
8/// An abstraction over some container which owns a `T` and can provide immutable references to it,
9/// or be consumed to return the inner `T` (if `T` is [`Sized`]).
10///
11/// This is the base container trait, which places the fewest requirements on implementors.
12///
13/// # Fragility: Potential Panics or Deadlocks
14///
15/// Unless a `FragileTryContainer` is known to also implement [`TryContainer`], it should be treated
16/// as [fragile].
17///
18/// # Errors
19///
20/// The [`into_inner`] and [`try_get_ref`] methods may be able to fail, depending on the container;
21/// a container should clearly document the circumstances in which a `None` or `Err` variant may
22/// be returned.
23///
24/// [`into_inner`]: FragileTryContainer::into_inner
25/// [`try_get_ref`]: FragileTryContainer::try_get_ref
26/// [fragile]: crate#fragility-potential-panics-or-deadlocks
27pub trait FragileTryContainer<T: ?Sized> {
28    /// An immutably borrowed value from the container.
29    ///
30    /// May have a nontrivial `Drop` implementatation, as with the [`Ref`] type corresponding
31    /// to [`RefCell`].
32    ///
33    /// [`Ref`]: std::cell::Ref
34    /// [`RefCell`]: std::cell::RefCell
35    type Ref<'a>:  Deref<Target = T> where Self: 'a;
36    /// An error that might be returned by [`try_get_ref`]. This type should implement
37    /// [`std::error::Error`].
38    ///
39    /// The canonical error to use when [`try_get_ref`] can never return an error
40    /// is [`Infallible`].
41    ///
42    /// [`try_get_ref`]: FragileTryContainer::try_get_ref
43    /// [`Infallible`]: std::convert::Infallible
44    type RefError;
45
46    /// Create a new container that owns the provided `T`.
47    #[must_use]
48    fn new_container(t: T) -> Self where Self: Sized, T: Sized;
49
50    /// Attempt to retrieve the inner `T` from the container.
51    ///
52    /// ### Note for implementors
53    ///
54    /// Given a collection of containers that refer to the same inner `T` (as with several cloned
55    /// `Rc` or `Arc` containers, or the trivial case of a single container like `Box<T>`), if
56    /// `into_inner` is called on each of those containers, then an implementation should return
57    /// `Some(T)` for exactly one of them, unless there is some useful reason for the implementation
58    /// to do otherwise.
59    #[must_use]
60    fn into_inner(self) -> Option<T> where Self: Sized, T: Sized;
61
62    /// Attempt to immutably access the inner `T`.
63    ///
64    /// There are no particular constraints imposed on implementations. In particular, depending on
65    /// the container implementation:
66    /// - the function could be infallible,
67    /// - the function could panic or deadlock (see below),
68    /// - retrying the function in a loop might never succeed.
69    ///
70    /// However, if the container implements [`FragileContainer<T>`], then implementors should
71    /// usually make `try_get_ref` infallible as well, unless there is some useful reason to not
72    /// do so.
73    ///
74    /// # Fragility: Potential Panics or Deadlocks
75    ///
76    /// Unless this [`FragileTryContainer`] is also a [`TryContainer`], implementations are
77    /// permitted to panic or deadlock if this method is called from a thread which already has a
78    /// reference to the inner `T` of this container.
79    ///
80    /// [Read more about fragility.](crate#fragility-potential-panics-or-deadlocks)
81    ///
82    /// # Errors
83    ///
84    /// Errors are implementation-defined, and should be documented by implementors.
85    fn try_get_ref(&self) -> Result<Self::Ref<'_>, Self::RefError>;
86}
87
88/// An abstraction over some container which owns a `T` and can infallibly provide immutable
89/// references to it, or attempt to be consumed to return the inner `T` (if `T` is [`Sized`]).
90///
91/// # Fragility: Potential Panics or Deadlocks
92///
93/// This container should be assumed to be [fragile], unless it is known to implement
94/// [`Container<T>`].
95///
96/// # `None` values
97///
98/// Note that [`into_inner`] is still permitted to return `None`, even though [`get_ref`] does not
99/// fail, and most implementors should make [`try_get_ref`] infallible as well. A container should
100/// clearly document when [`into_inner`] returns `None`.
101///
102/// [`into_inner`]: FragileTryContainer::into_inner
103/// [`try_get_ref`]: FragileTryContainer::try_get_ref
104/// [`get_ref`]: FragileContainer::get_ref
105/// [fragile]: crate#fragility-potential-panics-or-deadlocks
106pub trait FragileContainer<T: ?Sized>: FragileTryContainer<T> {
107    /// Immutably borrow the inner `T`.
108    ///
109    /// # Fragility: Potential Panics or Deadlocks
110    ///
111    /// Unless this [`FragileContainer`] is also a [`Container`], implementations are
112    /// permitted to panic or deadlock if this method is called from a thread which already has a
113    /// reference to the inner `T` of this container.
114    ///
115    /// [Read more about fragility.](crate#fragility-potential-panics-or-deadlocks)
116    #[must_use]
117    fn get_ref(&self) -> Self::Ref<'_>;
118}
119
120/// An abstraction over some container which owns a `T` and can provide immutable references to it,
121/// or be consumed to return the inner `T` (if `T` is [`Sized`]).
122///
123/// # Errors
124///
125/// The [`into_inner`] and [`try_get_ref`] methods may be able to fail, depending on the container;
126/// a container should clearly document the circumstances in which a `None` or `Err` variant may
127/// be returned.
128///
129/// [`into_inner`]: FragileTryContainer::into_inner
130/// [`try_get_ref`]: FragileTryContainer::try_get_ref
131pub trait TryContainer<T: ?Sized>: FragileTryContainer<T> {}
132
133/// An abstraction over some container which owns a `T` and can infallibly provide immutable
134/// references to it, or attempt to be consumed to return the inner `T` (if `T` is [`Sized`]).
135///
136/// # `None` values
137///
138/// Note that [`into_inner`] is still permitted to return `None`, even though [`get_ref`] does not
139/// fail, and most implementors should make [`try_get_ref`] infallible as well. A container should
140/// clearly document when [`into_inner`] returns `None`.
141///
142/// [`into_inner`]: FragileTryContainer::into_inner
143/// [`try_get_ref`]: FragileTryContainer::try_get_ref
144/// [`get_ref`]: FragileContainer::get_ref
145pub trait Container<T: ?Sized>: FragileContainer<T> + TryContainer<T> {}
146
147// ================================================================
148//  The four `{Fragile|}{Try|}MutContainer` traits
149// ================================================================
150
151/// An abstraction over some container which owns a `T` and can provide mutable or immutable
152/// references to it, or be consumed to return the inner `T` (if `T` is [`Sized`]).
153///
154/// This is the base mutable container trait, which places the fewest requirements on container
155/// implementations that can provide mutable access to the inner `T`.
156///
157/// # Fragility: Potential Panics or Deadlocks
158///
159/// Unless a `FragileTryMutContainer` is known to also implement [`TryMutContainer`], it should be
160/// treated as [fragile].
161///
162/// # Errors
163///
164/// The [`into_inner`], [`try_get_ref`], and [`try_get_mut`] methods may be able to fail, depending
165/// on the container; a container should clearly document the circumstances in which a `None` or
166/// `Err` variant may be returned.
167///
168/// [`into_inner`]: FragileTryContainer::into_inner
169/// [`try_get_ref`]: FragileTryContainer::try_get_ref
170/// [`try_get_mut`]: FragileTryMutContainer::try_get_mut
171/// [fragile]: crate#fragility-potential-panics-or-deadlocks
172pub trait FragileTryMutContainer<T: ?Sized>: FragileTryContainer<T> {
173    /// A mutably borrowed value from the container.
174    ///
175    /// May have a nontrivial `Drop` implementatation, as with the [`RefMut`] type corresponding
176    /// to [`RefCell`].
177    ///
178    /// [`RefMut`]: std::cell::RefMut
179    /// [`RefCell`]: std::cell::RefCell
180    type RefMut<'a>:  DerefMut<Target = T> where Self: 'a;
181    /// An error that might be returned by [`try_get_mut`]. This type should implement
182    /// [`std::error::Error`].
183    ///
184    /// The canonical error to use when [`try_get_mut`] can never return an error
185    /// is [`Infallible`].
186    ///
187    /// [`try_get_mut`]: FragileTryMutContainer::try_get_mut
188    /// [`Infallible`]: std::convert::Infallible
189    type RefMutError;
190
191    /// Attempt to mutably access the inner `T`.
192    ///
193    /// There are no particular constraints imposed on implementations. In particular, depending on
194    /// the container implementation:
195    /// - the function could be infallible,
196    /// - the function could panic or deadlock (see below),
197    /// - retrying the function in a loop might never succeed.
198    ///
199    /// However, if the container implements [`FragileMutContainer<T>`], then implementors should
200    /// usually make `try_get_mut` infallible as well, unless there is some useful reason to not
201    /// do so.
202    ///
203    /// # Fragility: Potential Panics or Deadlocks
204    ///
205    /// Unless this [`FragileTryMutContainer`] is also a [`TryMutContainer`], implementations are
206    /// permitted to panic or deadlock if this method is called from a thread which already has a
207    /// reference to the inner `T` of this container.
208    ///
209    /// [Read more about fragility.](crate#fragility-potential-panics-or-deadlocks)
210    ///
211    /// # Errors
212    /// Errors are implementation-defined, and should be documented by implementors.
213    fn try_get_mut(&mut self) -> Result<Self::RefMut<'_>, Self::RefMutError>;
214}
215
216/// An abstraction over some container which owns a `T` and can infallibly provide mutable or
217/// immutable references to it, or attempt to be consumed to return the inner `T`
218/// (if `T` is [`Sized`]).
219///
220/// # Fragility: Potential Panics or Deadlocks
221///
222/// This container should be assumed to be [fragile], unless it is known to implement
223/// [`MutContainer<T>`].
224///
225/// # `None` values
226///
227/// Note that [`into_inner`] is still permitted to return `None`, even though [`get_ref`] and
228/// [`get_mut`] do not fail, and most implementors should make [`try_get_ref`] and [`try_get_mut`]
229/// infallible as well. A container should clearly document when [`into_inner`] returns `None`.
230///
231/// [`into_inner`]: FragileTryContainer::into_inner
232/// [`try_get_ref`]: FragileTryContainer::try_get_ref
233/// [`get_ref`]: FragileContainer::get_ref
234/// [`try_get_mut`]: FragileTryMutContainer::try_get_mut
235/// [`get_mut`]: FragileMutContainer::get_mut
236/// [fragile]: crate#fragility-potential-panics-or-deadlocks
237pub trait FragileMutContainer<T: ?Sized>: FragileTryMutContainer<T> + FragileContainer<T> {
238    /// Mutably borrow the inner `T`.
239    ///
240    /// # Fragility: Potential Panics or Deadlocks
241    ///
242    /// Unless this [`FragileMutContainer`] is also a [`MutContainer`], implementations are
243    /// permitted to panic or deadlock if this method is called from a thread which already has a
244    /// reference to the inner `T` of this container.
245    ///
246    /// [Read more about fragility.](crate#fragility-potential-panics-or-deadlocks)
247    #[must_use]
248    fn get_mut(&mut self) -> Self::RefMut<'_>;
249}
250
251/// An abstraction over some container which owns a `T` and can provide mutable or immutable
252/// references to it, or be consumed to return the inner `T` (if `T` is [`Sized`]).
253///
254/// # Errors
255///
256/// The [`into_inner`], [`try_get_ref`], and [`try_get_mut`] methods may be able to fail, depending
257/// on the container; a container should clearly document the circumstances in which a `None` or
258/// `Err` variant may be returned.
259///
260/// [`into_inner`]: FragileTryContainer::into_inner
261/// [`try_get_ref`]: FragileTryContainer::try_get_ref
262/// [`try_get_mut`]: FragileTryMutContainer::try_get_mut
263pub trait TryMutContainer<T: ?Sized>: FragileTryMutContainer<T> + TryContainer<T> {}
264
265/// An abstraction over some container which owns a `T` and can infallibly provide mutable or
266/// immutable references to it, or attempt to be consumed to return the inner `T`
267/// (if `T` is [`Sized`]).
268///
269/// # `None` values
270///
271/// Note that [`into_inner`] is still permitted to return `None`, even though [`get_ref`] and
272/// [`get_mut`] do not fail, and most implementors should make [`try_get_ref`] and [`try_get_mut`]
273/// infallible as well. A container should clearly document when [`into_inner`] returns `None`.
274///
275/// [`into_inner`]: FragileTryContainer::into_inner
276/// [`try_get_ref`]: FragileTryContainer::try_get_ref
277/// [`get_ref`]: FragileContainer::get_ref
278/// [`try_get_mut`]: FragileTryMutContainer::try_get_mut
279/// [`get_mut`]: FragileMutContainer::get_mut
280pub trait MutContainer<T: ?Sized>: FragileMutContainer<T> + TryMutContainer<T> + Container<T> {}
281
282// ================================================================
283//  The two `*Base*Container` traits intended as aliases
284// ================================================================
285
286/// The trait for containers which places the fewest constraints on implementations.
287///
288/// A user-made trait alias for [`FragileTryContainer`].
289pub trait BaseContainer<T: ?Sized>: FragileTryContainer<T> {}
290
291impl<T: ?Sized, C: ?Sized + FragileTryContainer<T>> BaseContainer<T> for C {}
292
293/// The trait for mutable containers which places the fewest constraints on implementations.
294///
295/// A user-made trait alias for [`FragileTryMutContainer`].
296pub trait BaseMutContainer<T: ?Sized>: FragileTryMutContainer<T> {}
297
298impl<T: ?Sized, C: ?Sized + FragileTryMutContainer<T>> BaseMutContainer<T> for C {}