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 {}