eq_type/
lib.rs

1//! A crate that allows declaring an equality bound on two types and coercing between them.
2//!
3//! # Examples
4//!
5//! ```
6//! # use eq_type::Is;
7//! #
8//! pub trait ResultExt<T, E>: Sized + Is<Result<T, E>> {
9//!     /// Given any `E` and `EI` that implement `Into<ER>`, converts from Result<Result<T, EI>, E> to Result<T, ER>.
10//!     fn flatten_into<TI, EI, ER>(self) -> Result<TI, ER>
11//!     where
12//!         T: Is<Result<TI, EI>>,
13//!         E: Into<ER>,
14//!         EI: Into<ER>,
15//!     {
16//!         self.coerce().map_err(|e| e.into()).and_then(|x| x.coerce().map_err(|e| e.into()))
17//!     }
18//! }
19//! #
20//! # fn main() { }
21//! ```
22
23mod private {
24    pub trait Sealed {}
25}
26
27pub trait Is<Rhs: ?Sized>: private::Sealed {
28    fn coerce(self) -> Rhs
29    where
30        Self: Sized,
31        Rhs: Sized;
32
33    fn rcoerce(rhs: Rhs) -> Self
34    where
35        Self: Sized,
36        Rhs: Sized;
37}
38
39impl<T: ?Sized> private::Sealed for T {}
40
41impl<T: ?Sized> Is<T> for T {
42    #[inline(always)]
43    fn coerce(self) -> T
44    where
45        T: Sized,
46    {
47        self
48    }
49
50    #[inline(always)]
51    fn rcoerce(t: T) -> T
52    where
53        T: Sized,
54    {
55        t
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::Is;
62
63    fn forward<T, U>(t: T) -> U
64    where
65        T: Is<U>,
66    {
67        t.coerce()
68    }
69
70    fn backward<T, U>(u: U) -> T
71    where
72        U: Is<T>,
73    {
74        u.coerce()
75    }
76
77    #[test]
78    fn test() {
79        let mut x = 4;
80        x = forward(x);
81        x = backward(x);
82        x = backward(forward(x));
83        x = forward(backward(x));
84        assert_eq!(x, 4);
85    }
86}