tstr/
asserts.rs

1//! Types for asserting properties of type-level strings.
2
3use core::marker::PhantomData;
4
5/// For asserting the (in)equality of two type-level strings.
6///
7/// # Warning
8///
9/// From testing the associated constants from this type,
10/// these assertions might not be evaluated in functions that
11/// aren't reachable by public functions.
12///
13/// # Examples
14///
15/// For examples, you can look at each associated constant below.
16///
17///
18///
19pub struct Assert<A, B>(core::marker::PhantomData<(A, B)>);
20
21#[cfg(feature = "cmp_traits")]
22#[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp_traits")))]
23impl<A, B> Assert<A, B>
24where
25    A: crate::TStrEq<B>,
26{
27    /// Asserts that the `A` and `B` type-level strings compare equal.
28    pub const EQUAL: EqualityProof<A, B> = {
29        ["Expected the type parameters to be equal"][A::NE as usize];
30        EqualityProof(PhantomData)
31    };
32}
33
34#[cfg(feature = "cmp_traits")]
35#[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp_traits")))]
36impl<A, B> Assert<A, B>
37where
38    A: crate::TStrEq<B>,
39{
40    /// Asserts that the `A` and `B` type-level strings compare not equal.
41    ///
42    /// # Example
43    ///
44    /// This uses types from the `for_examples` module,
45    /// which can be seen in the docs with the "for_examples" feature.
46    ///
47    /// ```rust
48    /// use tstr::for_examples::Foo;
49    /// use tstr::{Assert, ts};
50    ///
51    /// use std::ops::Index;
52    ///
53    /// let this = Foo::new(3, 5, "8");
54    ///
55    /// assert_eq!(this.get_two(ts!(bar), ts!(qux), Assert::NOT_EQUAL), (&3, &"8"))
56    ///
57    /// ```
58    ///
59    /// The same method call errors when we try to get two references to the same field.
60    // For some reason it fails to compile with ```rust
61    // but compiles without errors with ```compile_fail (causing a cargo test failure)
62    /// ```ignore
63    /// use tstr::for_examples::Foo;
64    /// use tstr::{Assert, ts};
65    /// use std::ops::Index;
66    ///
67    /// # pub fn main() {
68    ///
69    /// let this = Foo::new(3, 5, "8");
70    ///
71    /// assert_eq!(this.get_two(ts!(bar), ts!(bar), Assert::NOT_EQUAL), (&3, &3))
72    ///
73    /// # }
74    /// ```
75    ///
76    /// Truncated error:
77    /// ```text
78    /// error[E0080]: erroneous constant used
79    ///   --> src/asserts.rs:55:45
80    ///    |
81    /// 11 | assert_eq!(this.get_two(ts!(bar), ts!(bar), Assert::NOT_EQUAL), (&3, &3))
82    ///    |                                             ^^^^^^^^^^^^^^^^^ referenced constant has errors
83    ///
84    /// ```
85    ///
86    pub const NOT_EQUAL: InequalityProof<A, B> = {
87        ["Expected the type parameters to not be equal"][A::EQ as usize];
88        InequalityProof(PhantomData)
89    };
90}
91
92macro_rules! declare_assert_res {
93    (
94        $(#[$meta:meta])*
95        struct $struct:ident<$L:ident, $R:ident>;
96    )=> {
97        $(#[$meta])*
98        pub struct $struct<$L, $R>(PhantomData<($L, $R)>);
99
100        impl<$L, $R> Copy for $struct<$L, $R> {}
101
102        impl<$L, $R> Clone for $struct<$L, $R> {
103            fn clone(&self) -> Self {
104                *self
105            }
106        }
107
108        impl<$L, $R> $struct<$L, $R> {
109            /// Infers the type parameters by passing them as arguments.
110            pub const fn infer(self, _: &$L, _: &$R){}
111        }
112    };
113}
114
115#[cfg(feature = "cmp_traits")]
116declare_assert_res! {
117    /// Value-level proof that the `L` and `R` type-level strings compared equal.
118    ///
119    /// Constructed with [`Àssert::EQUAL`]
120    ///
121    /// [`Àssert::EQUAL`]: ./struct.Assert.html#associatedconstant.EQUAL
122    struct EqualityProof<L,R>;
123}
124
125#[cfg(feature = "cmp_traits")]
126declare_assert_res! {
127    /// Value-level proof that the `L` and `R` type-level strings compared not equal.
128    ///
129    /// Constructed with [`Àssert::NOT_EQUAL`]
130    ///
131    /// [`Àssert::NOT_EQUAL`]: ./struct.Assert.html#associatedconstant.NOT_EQUAL
132    struct InequalityProof<L, R>;
133}