Improved API

This commit is contained in:
Michael Pfaff 2022-08-21 10:43:32 -04:00
parent a7a092cb19
commit 4d9dec9401
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
2 changed files with 73 additions and 28 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "eq-type" name = "eq-type"
version = "0.1.0" version = "0.2.0"
authors = ["Michael <michael@pfaff.dev>"] authors = ["Michael <michael@pfaff.dev>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Allows declaring an equality bound on two types and coercing between them." description = "Allows declaring an equality bound on two types and coercing between them."
@ -9,4 +9,10 @@ homepage = "https://git.pfaff.dev/michael/eq-type.rs"
readme = "README.md" readme = "README.md"
edition = "2021" edition = "2021"
[features]
default = [ "__nightly-sugar" ]
__nightly-sugar = [ ]
nightly = [ "__nightly-sugar" ]
[dependencies] [dependencies]

View File

@ -1,44 +1,51 @@
//! A crate that allows declaring an equality bound on two types and coercing between them. //! A crate that allows declaring an equality bound on two types and coercing between them.
//! //!
//! # Examples //! # Examples
//! #![cfg_attr(feature = "__nightly-sugar", doc = r##"
//! ``` ```
//! # use eq_type::Is; # use eq_type::Is;
//! # #
//! pub trait ResultExt<T, E>: Sized + Is<Result<T, E>> { 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>. /// 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> fn flatten_into<TI, EI, ER>(self) -> Result<TI, ER>
//! where where
//! T: Is<Result<TI, EI>>, T: Is<Result<TI, EI>>,
//! E: Into<ER>, E: Into<ER>,
//! EI: Into<ER>, EI: Into<ER>,
//! { {
//! self.coerce().map_err(|e| e.into()).and_then(|x| x.coerce().map_err(|e| e.into())) self.coerce().map_err(|e| e.into()).and_then(|x| x.coerce().map_err(|e| e.into()))
//! } }
//! } }
//! # #
//! # fn main() { } # fn main() { }
//! ``` ```
"##)]
#![cfg_attr(feature = "__nightly-sugar", feature(trait_alias))]
mod private { mod private {
pub trait Sealed {} pub trait Sealed {}
} }
pub trait Is<Rhs: ?Sized>: private::Sealed { pub trait __Is: private::Sealed {
fn coerce(self) -> Rhs type Rhs: ?Sized;
where
Self: Sized,
Rhs: Sized;
fn rcoerce(rhs: Rhs) -> Self fn coerce(self) -> Self::Rhs
where where
Self: Sized, Self: Sized,
Rhs: 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> private::Sealed for T {}
impl<T: ?Sized> Is<T> for T { impl<T: ?Sized> __Is for T {
type Rhs = T;
#[inline(always)] #[inline(always)]
fn coerce(self) -> T fn coerce(self) -> T
where where
@ -56,18 +63,39 @@ impl<T: ?Sized> Is<T> for T {
} }
} }
#[cfg(feature = "__nightly-sugar")]
pub trait Is<Rhs> = __Is<Rhs = Rhs>;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::__Is;
#[cfg(feature = "__nightly-sugar")]
use super::Is; use super::Is;
fn forward<T, U>(t: T) -> U 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 where
T: Is<U>, T: Is<U>,
{ {
t.coerce() t.coerce()
} }
fn backward<T, U>(u: U) -> T #[cfg(feature = "__nightly-sugar")]
fn backward_sugar<T, U>(u: U) -> T
where where
U: Is<T>, U: Is<T>,
{ {
@ -83,4 +111,15 @@ mod tests {
x = forward(backward(x)); x = forward(backward(x));
assert_eq!(x, 4); 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);
}
} }