eq-type.rs/src/lib.rs

126 lines
2.4 KiB
Rust

//! A crate that allows declaring an equality bound on two types and coercing between them.
//!
//! # Examples
#![cfg_attr(feature = "__nightly-sugar", doc = r##"
```
# use eq_type::Is;
#
pub trait ResultExt<T, E>: Sized + Is<Result<T, E>> {
/// Given any `E` and `EI` that implement `Into<ER>`, converts from Result<Result<T, EI>, E> to Result<T, ER>.
fn flatten_into<TI, EI, ER>(self) -> Result<TI, ER>
where
T: Is<Result<TI, EI>>,
E: Into<ER>,
EI: Into<ER>,
{
self.coerce().map_err(|e| e.into()).and_then(|x| x.coerce().map_err(|e| e.into()))
}
}
#
# fn main() { }
```
"##)]
#![cfg_attr(feature = "__nightly-sugar", feature(trait_alias))]
mod private {
pub trait Sealed {}
}
pub trait __Is: private::Sealed {
type Rhs: ?Sized;
fn coerce(self) -> Self::Rhs
where
Self: Sized,
Self::Rhs: Sized;
fn rcoerce(rhs: Self::Rhs) -> Self
where
Self: Sized,
Self::Rhs: Sized;
}
impl<T: ?Sized> private::Sealed for T {}
impl<T: ?Sized> __Is for T {
type Rhs = T;
#[inline(always)]
fn coerce(self) -> T
where
T: Sized,
{
self
}
#[inline(always)]
fn rcoerce(t: T) -> T
where
T: Sized,
{
t
}
}
#[cfg(feature = "__nightly-sugar")]
pub trait Is<Rhs> = __Is<Rhs = Rhs>;
#[cfg(test)]
mod tests {
use super::__Is;
#[cfg(feature = "__nightly-sugar")]
use super::Is;
fn forward<T, U>(t: T) -> U
where
T: __Is<Rhs = U>,
{
t.coerce()
}
fn backward<T, U>(u: U) -> T
where
U: __Is<Rhs = T>,
{
u.coerce()
}
#[cfg(feature = "__nightly-sugar")]
fn forward_sugar<T, U>(t: T) -> U
where
T: Is<U>,
{
t.coerce()
}
#[cfg(feature = "__nightly-sugar")]
fn backward_sugar<T, U>(u: U) -> T
where
U: Is<T>,
{
u.coerce()
}
#[test]
fn test() {
let mut x = 4;
x = forward(x);
x = backward(x);
x = backward(forward(x));
x = forward(backward(x));
assert_eq!(x, 4);
}
#[cfg(feature = "__nightly-sugar")]
#[test]
fn test_sugar() {
let mut x = 4;
x = forward_sugar(x);
x = backward_sugar(x);
x = backward_sugar(forward_sugar(x));
x = forward_sugar(backward_sugar(x));
assert_eq!(x, 4);
}
}