Skip to main content

type_sets/
lib.rs

1//! `type-sets` implements various compile-time set-operations on tuples.
2//!
3//! # Basic example
4//!
5//! ```rust
6//! # use type_sets::*;
7//! assert::contains::<(i32, i16), i32>();
8//! assert::subset::<(i32,), (i32, i64)>();
9//! assert::superset::<(i32, i16), (i32,)>();
10//! assert::eq::<(i32, i16), (i16, i32)>();
11//! ```
12//!
13//! # Operations
14//! - [`Contains<E>`]: Checks if a set contains a specific member.
15//! - [`Subset<S>`]: Checks if a set is a subset of another set.
16//! - [`Superset<S>`]: Checks if a set is a superset of another set.
17//! - [`SetEqual<R>`]: Checks if two sets are equal.
18//! - [`IsEmpty`]: Checks if a set is empty.
19//! - [`Insert<T, E>`]: Adds a new member to a set.
20//! - [`Union<T, R>`]: Computes the union of two sets.
21//!
22//! See the individual trait documentation for more details on each operation.
23
24use generate_sets::*;
25use std::{any::TypeId, convert::Infallible};
26
27/// Implemented for any set that contains a member `E`.
28///
29/// # Example
30///
31/// ```rust
32/// # use type_sets::*;
33/// assert::contains::<(i32,), i32>();
34/// assert::contains::<(i16, i32), i32>();
35/// assert::contains::<(i32, i16), i32>();
36/// // assert::contains::<(i8, i16), i32>(); // fails to compile
37/// ```
38#[diagnostic::on_unimplemented(
39    message = "`{Self}` does not contain `{E}`",
40    label = "type does not contain this element",
41    note = "a type implements `Contains<E>` when `E` is one of its set members"
42)]
43pub trait Contains<E>: Contains0 {}
44
45#[diagnostic::do_not_recommend]
46impl<E, T: ?Sized> Contains<E> for T where T: Contains1<E> {}
47
48/// Implemented for any set that is a subset of set `S`.
49///
50/// # Example
51///
52/// ```rust
53/// # use type_sets::*;
54/// assert::subset::<(i32,), (i32,)>();
55/// assert::subset::<(i16, i32), (i16, i32)>();
56/// assert::subset::<(i32, i16), (i16, i32)>();
57/// assert::subset::<(i32,), (i32, i16)>();
58/// // assert::subset::<(i8, i16), (i16, i32)>(); // fails to compile
59/// ```
60#[diagnostic::on_unimplemented(
61    message = "`{Self}` is not a subset of `{S}`",
62    label = "this set is not a subset of the required set",
63    note = "every member of the left-hand set must also be present in the right-hand set"
64)]
65pub trait Subset<S: ?Sized> {}
66
67#[diagnostic::do_not_recommend]
68impl<T, R> Subset<R> for T
69where
70    T: AsTypeSet<Set: Subset<R::Set>>,
71    R: AsTypeSet,
72{
73}
74
75/// Implemented for any set that is a superset of set `S`.
76///
77/// # Example
78///
79/// ```rust
80/// # use type_sets::*;
81/// assert::superset::<(i32, i16), (i32,)>();
82/// assert::superset::<(i16, i32), (i32,)>();
83/// assert::superset::<(i32,), (i32,)>();
84/// assert::superset::<(i32, i16), (i16, i32)>();
85/// // assert::superset::<(i8, i16), (i32,)>(); // fails to compile
86/// ```
87#[diagnostic::on_unimplemented(
88    message = "`{Self}` is not a superset of `{S}`",
89    label = "this set does not contain all required members",
90    note = "every member of the right-hand set must also be present in the left-hand set"
91)]
92pub trait Superset<S: ?Sized> {}
93
94#[diagnostic::do_not_recommend]
95impl<S1: ?Sized, S2: ?Sized> Superset<S2> for S1 where S2: Subset<S1> {}
96
97/// The main trait for representing a set of types.
98///
99/// This is implemented for tuples up to 24 elements.
100///
101/// # Examples
102/// - `(A,)`
103/// - `(A, B)`
104/// - `(A, B, C)`
105pub trait AsTypeSet {
106    /// The underlying set type, which is a private marker-trait.
107    type Set: ?Sized;
108}
109
110/// Trait for retrieving the members of a type set as [`TypeId`]s.
111///
112/// # Example
113///
114/// ```rust
115/// # use type_sets::*;
116/// let members = <(i32, i16) as Members>::members();
117///
118/// assert_eq!(members, &[
119///     std::any::TypeId::of::<i32>(),
120///     std::any::TypeId::of::<i16>(),
121/// ]);
122/// ```
123pub trait Members {
124    /// Returns a static slice of [`TypeId`]s representing the members of the set.
125    fn members() -> &'static [TypeId];
126}
127
128impl<T> Members for T
129where
130    T: AsTypeSet<Set: Members>,
131{
132    fn members() -> &'static [TypeId] {
133        <T::Set as Members>::members()
134    }
135}
136
137/// Indicates that two sets are equal, i.e., they contain the same members.
138///
139/// This is the same as `T: Subset<R> + Superset<R>`
140///
141/// # Example
142///
143/// ```rust
144/// # use type_sets::*;
145/// assert::eq::<(i32, i16), (i16, i32)>();
146/// assert::eq::<(i32,), (i32,)>();
147/// // assert::eq::<(i32,), (i16,)>(); // fails to compile
148/// ```
149#[diagnostic::on_unimplemented(
150    message = "`{Self}` and `{R}` do not represent the same set",
151    label = "the sets contain different members",
152    note = "two sets are equal when every member of one is also a member of the other"
153)]
154pub trait SetEqual<R: ?Sized> {}
155
156/// Indicates that a set is empty, i.e., it contains no members.
157///
158/// This is the same as `T: Subset<()>`
159pub trait IsEmpty: Subset<()> {}
160impl<T> IsEmpty for T where T: Subset<()> {}
161
162/// Trait for adding a new member to a type set.
163///
164/// See [`Insert`] for a convenient type alias to add a member to a set.
165pub trait Push {
166    /// The resulting set after adding the new member.
167    type Output<E>;
168}
169
170/// Type alias for adding a new member to a type set.
171///
172/// # Example
173///
174/// ```rust
175/// # use type_sets::*;
176/// assert::eq::<Insert<(i32,), i16>, (i16, i32)>();
177/// ```
178pub type Insert<T, E> = <T as Push>::Output<E>;
179
180// pub trait Shrink {
181//     type Output;
182//     type Popped;
183// }
184
185// pub type Pop<T> = <T as Shrink>::Output;
186// pub type Last<T> = <T as Shrink>::Popped;
187
188#[diagnostic::do_not_recommend]
189impl<T: AsTypeSet, R: AsTypeSet> SetEqual<R> for T where T: Subset<R> + Superset<R> {}
190
191mod generate_sets;
192
193// pub use intersection::*;
194// mod intersection;
195
196pub use union::*;
197mod union;
198
199#[cfg(feature = "assertions")]
200pub mod assert {
201    use super::*;
202
203    /// Asserts that two sets are equal. (Contain the same members.)
204    pub fn eq<T, R>()
205    where
206        T: SetEqual<R>,
207    {
208    }
209
210    /// Asserts that the first set is a superset of the second set.
211    pub fn superset<T, R>()
212    where
213        T: Superset<R>,
214    {
215    }
216
217    /// Asserts that the first set is a subset of the second set.
218    pub fn subset<T, R>()
219    where
220        T: Subset<R>,
221    {
222    }
223
224    /// Asserts that the set contains the specified member.
225    pub fn contains<T, E>()
226    where
227        T: Contains<E>,
228    {
229    }
230
231    /// Asserts that the set is empty (contains no members).
232    pub fn is_empty<T>()
233    where
234        T: IsEmpty,
235    {
236    }
237}