Skip to main content

type_sets/
lib.rs

1use std::{any::TypeId, convert::Infallible, fmt::Debug, marker::PhantomData};
2
3/// A set of types.
4///
5/// Examples of valid sets include:
6/// - `Set<()>` - an empty set
7/// - `Set<(A, B, C)>` - a set containing types A, B, and C
8pub struct Set<T>(PhantomData<fn() -> T>);
9
10impl<T> TypeSet for Set<T>
11where
12    T: TypeSet,
13{
14    type Set = T::Set;
15
16    fn members() -> &'static [TypeId]
17    where
18        Self: 'static,
19    {
20        T::members()
21    }
22}
23
24impl<T> Debug for Set<T> {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(f, "Set<{}>", std::any::type_name::<T>())
27    }
28}
29
30/// Indicates that a type contains member `E` in its set.
31#[diagnostic::on_unimplemented(
32    message = "`{Self}` does not contain `{E}`",
33    label = "type does not contain this element",
34    note = "a type implements `Contains<E>` when `E` is one of its set members"
35)]
36pub trait Contains<E>: Contains0 {}
37
38#[diagnostic::do_not_recommend]
39impl<E, T: ?Sized> Contains<E> for T where T: Contains1<E> {}
40
41/// Indicates that a type is a subset of set `S`.
42#[diagnostic::on_unimplemented(
43    message = "`{Self}` is not a subset of `{S}`",
44    label = "this set is not a subset of the required set",
45    note = "every member of the left-hand set must also be present in the right-hand set"
46)]
47pub trait SubsetOf<S: ?Sized> {}
48
49#[diagnostic::do_not_recommend]
50impl<T: TypeSet, R: TypeSet> SubsetOf<R> for T where T::Set: SubsetOf<R::Set> {}
51
52/// Indicates that a type is a superset of set `S`.
53#[diagnostic::on_unimplemented(
54    message = "`{Self}` is not a superset of `{S}`",
55    label = "this set does not contain all required members",
56    note = "every member of the right-hand set must also be present in the left-hand set"
57)]
58pub trait SupersetOf<S: ?Sized> {}
59
60#[diagnostic::do_not_recommend]
61impl<S1: ?Sized, S2: ?Sized> SupersetOf<S2> for S1 where S2: SubsetOf<S1> {}
62
63/// The main trait for representing a set of types.
64///
65/// This is implemented for tuples up to 24 elements, and [`Set`]s of tuples.
66pub trait TypeSet {
67    /// The underlying set type, which is a private marker-trait.
68    type Set: ?Sized;
69
70    /// Returns a static slice of [`TypeId`]s representing the members of the set.
71    fn members() -> &'static [TypeId]
72    where
73        Self: 'static;
74}
75
76/// Indicates that two sets are equal, i.e., they contain the same members.
77#[diagnostic::on_unimplemented(
78    message = "`{Self}` and `{R}` do not represent the same set",
79    label = "the sets contain different members",
80    note = "two sets are equal when every member of one is also a member of the other"
81)]
82pub trait SetEqual<R: ?Sized> {}
83
84#[diagnostic::do_not_recommend]
85impl<T: TypeSet, R: TypeSet> SetEqual<R> for T where T: SubsetOf<R> + SupersetOf<R> {}
86
87mod generate_sets;
88use generate_sets::*;
89
90mod set_macro;
91
92impl TypeSet for Infallible {
93    type Set = ();
94
95    fn members() -> &'static [TypeId]
96    where
97        Self: 'static,
98    {
99        &[]
100    }
101}