exhaust/lib.rs
1#![no_std]
2
3//! This crate provides the [`Exhaust`] trait and derive macro, which allow iterating over
4//! all values of a given type.
5//!
6//! # Package features
7//!
8//! All features are enabled by default.
9//! If you set `default-features = false`, `exhaust` becomes `no_std` compatible.
10//! The `alloc` and `std` features add `Exhaust` implementations for
11//! the corresponding standard library crates.
12
13#![forbid(rust_2018_idioms)]
14#![forbid(unsafe_code)]
15#![warn(unreachable_pub)]
16#![warn(missing_docs)]
17#![warn(missing_debug_implementations)]
18#![warn(
19 clippy::alloc_instead_of_core,
20 clippy::std_instead_of_core,
21 clippy::std_instead_of_alloc
22)]
23#![warn(clippy::cast_lossless)]
24#![warn(clippy::exhaustive_enums)]
25#![warn(clippy::exhaustive_structs)]
26#![warn(clippy::pedantic)]
27
28#[cfg(feature = "alloc")]
29extern crate alloc;
30#[cfg(feature = "std")]
31extern crate std;
32
33/// Allows the derive macro to be used internally.
34extern crate self as exhaust;
35
36// -------------------------------------------------------------------------------------------------
37
38use core::fmt;
39use core::iter::FusedIterator;
40
41// -------------------------------------------------------------------------------------------------
42
43pub(crate) mod patterns;
44
45mod impls;
46
47pub mod iteration;
48
49#[cfg(doctest)]
50pub mod test_compile_fail;
51
52// -------------------------------------------------------------------------------------------------
53
54/// Types that can be exhaustively iterated. That is, an iterator is available which
55/// produces every possible value of this type.
56///
57/// # Properties
58///
59/// Implementations must have the following properties:
60///
61/// * Exhaustiveness: If [`Self: PartialEq`](PartialEq), then for every value `a` of type
62/// `Self`, there is some element `b` of `Self::exhaust()` for which `a == b`,
63/// unless it is the case that `a != a`.
64///
65/// If there is no `PartialEq` implementation, then follow the spirit of this rule anyway.
66///
67/// * No duplicates: if [`Self: PartialEq`](PartialEq), then for any two items `a, b` produced
68/// by the iterator, `a != b`.
69///
70/// If this rule comes into conflict with exhaustiveness, then exhaustiveness takes priority.
71///
72/// * If there is any value `a` of type `Self` for which `a != a`, then [`Exhaust`]
73/// must produce one or more such values (e.g. [`f32::NAN`]).
74///
75/// * The iterator has a finite length.
76///
77/// For example, collections which can contain arbitrary numbers of duplicate elements, like
78/// [`Vec`](alloc::vec::Vec), should not implement [`Exhaust`],
79/// because they cannot have an iterator which is both finite and exhaustive.
80///
81/// * Purity/determinism: every call to `Self::exhaust()`, or [`Clone::clone()`] of a returned
82/// iterator or factory, should produce the same sequence of items.
83///
84/// (If this is not upheld, then derived implementations of [`Exhaust`] on types containing
85/// this type will not behave consistently.)
86///
87/// * `exhaust()` does not panic, nor does the iterator it returns,
88/// except in the event that memory allocation fails.
89///
90/// * All produced values should be valid according to `Self`’s invariants as enforced by its
91/// ordinary constructors. When the above properties refer to “a value of type `Self`”,
92/// they do not include invalid values.
93///
94/// The following further properties are recommended when feasible:
95///
96/// * If `Self: Ord`, then the items are sorted in ascending order.
97///
98/// * The iterator’s length makes it feasible to actually exhaust.
99///
100/// For example, [`u64`] does not implement [`Exhaust`].
101/// This may be infeasible to ensure in compositions; e.g. `[u16; 4]` is even more infeasible
102/// to exhaust than [`u64`].
103///
104/// [`Exhaust`] is not an `unsafe trait`, and as such, no soundness property should rest
105/// on implementations having any of the above properties unless the particular implementation
106/// guarantees them.
107///
108/// # Examples
109///
110/// Using [`derive(Exhaust)`](macro@Exhaust) to implement the trait:
111///
112/// ```
113#[doc = include_str!("example-derive-usage.rs")]
114/// ```
115///
116/// Writing a manual implementation of `Exhaust`:
117///
118/// ```
119/// use exhaust::Exhaust;
120///
121/// #[derive(Clone, Debug)]
122/// struct AsciiLetter(char);
123///
124/// impl Exhaust for AsciiLetter {
125/// type Iter = ExhaustAsciiLetter;
126///
127/// // We could avoid needing to `derive(Clone, Debug)` by using `char` as the factory,
128/// // but if we did that, then `from_factory()` must check its argument for validity.
129/// type Factory = Self;
130///
131/// fn exhaust_factories() -> Self::Iter {
132/// ExhaustAsciiLetter { next: 'A' }
133/// }
134///
135/// fn from_factory(factory: Self::Factory) -> Self {
136/// factory
137/// }
138/// }
139///
140/// #[derive(Clone, Debug)] // All `Exhaust::Iter`s must implement `Clone` and `Debug`.
141/// struct ExhaustAsciiLetter {
142/// next: char
143/// }
144///
145/// impl Iterator for ExhaustAsciiLetter {
146/// type Item = AsciiLetter;
147///
148/// fn next(&mut self) -> Option<Self::Item> {
149/// match self.next {
150/// 'A'..='Y' | 'a'..='z' => {
151/// let item = self.next;
152/// self.next = char::from_u32(self.next as u32 + 1).unwrap();
153/// Some(AsciiLetter(item))
154/// }
155/// 'Z' => {
156/// self.next = 'a';
157/// Some(AsciiLetter('Z'))
158/// }
159/// '{' => None, // ('z' + 1)
160/// _ => unreachable!(),
161/// }
162/// }
163/// }
164/// impl std::iter::FusedIterator for ExhaustAsciiLetter {}
165///
166/// assert_eq!(
167/// AsciiLetter::exhaust().map(|l| l.0).collect::<String>(),
168/// String::from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
169/// );
170/// ```
171///
172/// # Excluded Types
173///
174/// The following primitive or standard library types **do not implement** [`Exhaust`] for
175/// particular reasons:
176///
177/// * References, because there's nowhere to stash the referent.
178/// (This could be changed for small finite types, like `&bool`, but those are the same
179/// sort of types which are unlikely to be used by reference.)
180/// * Pointers, for the same reason as references (and we could generate invalid pointers,
181/// but that would be almost certainly pointless).
182/// * [`u64`], [`i64`], and [`f64`], because they are too large to feasibly exhaust.
183/// * Containers that permit duplicate items, and can therefore be unboundedly large:
184/// * [`alloc::vec::Vec`]
185/// * [`alloc::collections::VecDeque`]
186/// * [`alloc::collections::LinkedList`]
187/// * [`alloc::collections::BinaryHeap`]
188///
189/// * [`core::mem::ManuallyDrop`], because it would be a memory leak.
190/// * [`core::mem::MaybeUninit`], because it is not useful to obtain a `MaybeUninit<T>`
191/// value without knowing whether it is initialized, and if they are to be all
192/// initialized, then `T::exhaust()` is just as good.
193/// * [`core::ops::Range` and `core::ops::RangeInclusive`](core::ops), because it is ambiguous
194/// whether inverted (start > end) ranges should be generated.
195/// * [`std::io::ErrorKind`] and other explicitly non-exhaustive types.
196pub trait Exhaust: Sized {
197 /// Iterator type returned by [`Self::exhaust_factories()`].
198 /// See the trait documentation for what properties this iterator should have.
199 ///
200 /// <div class="warning">
201 ///
202 /// Note: While it is necessary for this type to be exposed, an implementation of
203 /// [`Exhaust`] changing to another iterator type should not be considered a breaking
204 /// change, as long as it still has the same iterator properties (e.g.
205 /// [`ExactSizeIterator`]); it should be treated as an implementation detail.
206 ///
207 /// </div>
208 type Iter: core::iter::FusedIterator<Item = Self::Factory> + Clone + fmt::Debug;
209
210 /// Data which can be used to construct `Self`.
211 ///
212 /// The difference between `Self` and `Self::Factory` is that the `Factory` must
213 /// implement [`Clone`], while `Self` is not required to.
214 /// This is relevant to, and motivated by, the following cases:
215 ///
216 /// * Types which do not implement [`Clone`], or which conditionally implement [`Clone`],
217 /// can still implement [`Exhaust`] by providing a `Factory` type which is not `Self`.
218 /// For example, interior-mutable types often do not implement [`Clone`], or implement it
219 /// so as to make a new handle to existing shared state; those types should choose a
220 /// `Factory` type which represents their initial state only.
221 ///
222 /// * Generic containers of two or more values need to generate all combinations of their
223 /// values.
224 /// The guarantee that the contents’ `Factory` is [`Clone`] allows them to use clones of the
225 /// factories to perform this iteration straightforwardly.
226 /// (It would be theoretically possible to avoid this by cloning the exhausting iterators
227 /// themselves, but much more complex and difficult to implement correctly.)
228 /// For example, `[AtomicBool; 2]` ends up using `[bool; 2]` as its factory, which
229 /// implements [`Clone`] even though [`AtomicBool`](core::sync::atomic::AtomicBool) does not.
230 ///
231 /// * A lot of wrapper types can easily implement [`Exhaust`] by delegating to another
232 /// iterator and merely implementing [`Self::from_factory()`] to add the wrapper.
233 /// This is not more powerful than use of [`Iterator::map()`], but it is often more
234 /// convenient.
235 ///
236 /// Types which implement [`Clone`] and are not generic can use `type Factory = Self;`
237 /// if they wish.
238 ///
239 /// <div class="warning">
240 ///
241 /// Note: While it is necessary for this type to be exposed, an implementation of
242 /// [`Exhaust`] changing to another factory type should not be considered a breaking
243 /// change; it should be treated as an implementation detail, unless otherwise documented.
244 ///
245 /// </div>
246 type Factory: Clone + fmt::Debug;
247
248 /// Returns an iterator over all values of this type.
249 ///
250 /// See the trait documentation for what properties this iterator should have.
251 ///
252 /// This function is equivalent to `Self::exhaust_factories().map(Self::from_factory)`.
253 /// Implementors should not override it.
254 #[must_use]
255 #[mutants::skip]
256 fn exhaust() -> Iter<Self> {
257 Iter::default()
258 }
259
260 /// Returns an iterator over [factories](Self::Factory) for all values of this type.
261 ///
262 /// Implement this function to implement the trait. Call this function when implementing an
263 /// [`Exhaust::Iter`] iterator for a type that contains this type.
264 ///
265 /// See the trait documentation for what properties this iterator should have.
266 #[must_use]
267 fn exhaust_factories() -> Self::Iter;
268
269 /// Construct a concrete value of this type from a [`Self::Factory`] value produced by
270 /// its [`Self::Iter`].
271 ///
272 /// <div class="warning">
273 ///
274 /// Caution: While this function is meant to be used only with values produced by the iterator,
275 /// this cannot be enforced; therefore, make sure it cannot bypass any invariants that
276 /// the type might have.
277 ///
278 /// </div>
279 ///
280 /// # Panics
281 ///
282 /// - This function may panic if given a factory value that is not one of the values
283 /// [`Self::Iter`] is able to produce.
284 /// - This function may panic or abort if memory allocation that is required to construct
285 /// [`Self`] fails.
286 ///
287 /// Implementations should not panic under any other circumstances.
288 #[must_use]
289 fn from_factory(factory: Self::Factory) -> Self;
290}
291
292/// Derive macro generating an impl of the trait [`Exhaust`].
293///
294/// # Applicability
295///
296/// This macro may be applied to `struct`s and `enum`s, but not `union`s.
297/// All fields must have types which themselves implement [`Exhaust`].
298///
299/// <div class="warning">
300///
301/// If your type has invariants enforced through private fields, then do not use this derive macro,
302/// as that would make it possible to obtain instances with any values whatsoever.
303/// There is not currently any way to add constraints.
304///
305/// </div>
306///
307/// # Generated code
308///
309/// The macro generates the following items:
310///
311/// * An implementation of [`Exhaust`] for your type.
312///
313/// * A “factory” struct type for `<Self as Exhaust>::Factory`.
314///
315/// It has no public fields.
316/// It implements [`Clone`] and [`fmt::Debug`].
317/// It is unnameable except through the associated type, `<Self as Exhaust>::Factory`.
318///
319/// * An iterator struct type for `<Self as Exhaust>::Iter`.
320///
321/// It has no public fields.
322/// It implements [`Iterator`], [`FusedIterator`], [`Clone`], and [`fmt::Debug`],
323/// but not [`DoubleEndedIterator`] or [`ExactSizeIterator`].
324/// It does not currently override any of the optional iterator methods such as
325/// [`Iterator::size_hint()`].
326/// It is unnameable except through the associated type, `<Self as Exhaust>::Iter`.
327///
328/// The [`fmt::Debug`] implementations currently print only a placeholder with no details.
329/// This may be changed in future versions.
330///
331/// All of the generated types have names like `Exhaust<your type name><some suffix>`.
332/// Unfortunately, it is *possible* for these names to conflict with your code’s names;
333/// but conflicts will not occur as long as you avoid *using* any items named `ExhaustFoo*`
334/// from within a type named `Foo`.
335/// Items which are merely in the same module do not interfere, because only the code generated
336/// by the `derive(Exhaust)` macro is affected.
337///
338/// # Example
339///
340/// ```
341#[doc = include_str!("example-derive-usage.rs")]
342/// ```
343pub use exhaust_macros::Exhaust;
344
345// -------------------------------------------------------------------------------------------------
346
347/// Iterator over all values of any type that implements [`Exhaust`].
348///
349/// It may be obtained with [`T::exhaust()`](Exhaust::exhaust) or [`Default::default()`].
350pub struct Iter<T: Exhaust>(<T as Exhaust>::Iter);
351
352impl<T: Exhaust> Default for Iter<T> {
353 #[inline]
354 fn default() -> Self {
355 Self(T::exhaust_factories())
356 }
357}
358
359impl<T: Exhaust> Iterator for Iter<T> {
360 type Item = T;
361
362 #[inline]
363 fn next(&mut self) -> Option<Self::Item> {
364 self.0.next().map(T::from_factory)
365 }
366
367 #[inline]
368 fn size_hint(&self) -> (usize, Option<usize>) {
369 self.0.size_hint()
370 }
371
372 fn fold<B, F>(self, init: B, mut f: F) -> B
373 where
374 Self: Sized,
375 F: FnMut(B, Self::Item) -> B,
376 {
377 self.0.fold(init, |state, item_factory| {
378 f(state, T::from_factory(item_factory))
379 })
380 }
381}
382
383impl<T: Exhaust<Iter: DoubleEndedIterator>> DoubleEndedIterator for Iter<T> {
384 fn next_back(&mut self) -> Option<Self::Item> {
385 self.0.next_back().map(T::from_factory)
386 }
387
388 fn rfold<B, F>(self, init: B, mut f: F) -> B
389 where
390 Self: Sized,
391 F: FnMut(B, Self::Item) -> B,
392 {
393 self.0.rfold(init, |state, item_factory| {
394 f(state, T::from_factory(item_factory))
395 })
396 }
397}
398
399impl<T: Exhaust> FusedIterator for Iter<T> {
400 // Note: This is only correct because of the `FusedIterator` bound on `Exhaust::Iter`.
401 // Otherwise we would have to add a `T::Iter: FusedIterator` bound here too.
402}
403
404impl<T: Exhaust<Iter: ExactSizeIterator>> ExactSizeIterator for Iter<T> {}
405
406impl<T: Exhaust> Clone for Iter<T> {
407 #[inline]
408 fn clone(&self) -> Self {
409 Self(self.0.clone())
410 }
411}
412impl<T: Exhaust<Iter: Copy>> Copy for Iter<T> {}
413
414impl<T: Exhaust<Iter: fmt::Debug>> fmt::Debug for Iter<T> {
415 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416 f.debug_tuple("exhaust::Iter").field(&self.0).finish()
417 }
418}