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