# trait-bounds
This nightly-only library provides useful primitives for defining trait bounds
[`eq`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/fn.eq.html) and [`ne`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/fn.ne.html) functions allow to check whether two types are equal in a `const` context
[`type_id`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/fn.type_id.html) is similar to [`core::intrinsics::type_id`](https://doc.rust-lang.org/nightly/core/intrinsics/fn.type_id.html), but it can be used on [`PointeeSized`](https://doc.rust-lang.org/nightly/core/marker/trait.PointeeSized.html) types
[`Assert<true>`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/struct.Assert.html) implements [`IsTrue`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/trait.IsTrue.html)
[`Assert<false>`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/struct.Assert.html) implements [`IsFalse`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/trait.IsFalse.html)
[`Is<T>`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/trait.Is.html) is implemented for `U` if and only if `U` is equal to `T`
[`Not<T>`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/trait.Not.html) is implemented for `U` if and only if `U` is not equal to `T`
The [`Not`](https://docs.rs/trait-bounds/0.1.0/trait_bounds/trait.Not.html) trait can be used to define multiple blanket implementations, which is particularly useful with the [`From<T>`](https://doc.rust-lang.org/nightly/core/convert/trait.From.html) trait,
as [`From<T> for T`](https://doc.rust-lang.org/nightly/core/convert/trait.From.html#impl-From%3CT%3E-for-T) often collides with user-defined blanket impls
```rust
use trait_bounds::Not;
trait Trait {}
struct A {}
struct B {}
struct C {}
impl Trait for A {}
impl Trait for B {}
impl Trait for C {}
impl From<B> for A {
fn from(value: B) -> Self {
Self {}
}
}
impl<T: Trait + Not<Self> + Not<B>> From<T> for A {
fn from(value: T) -> Self {
Self {}
}
}
fn main() {
let a: A = A {};
let b: B = B {};
let c: C = C {};
let a: A = a.into(); // core's blanket impl From<T> for T
let a: A = b.into(); // specific impl From<B> for A
let a: A = c.into(); // blanket impl From<T: Trait> for A
}
```
```rust
use std::{
error::Error,
fmt::{self, Debug, Display, Formatter},
fs::File,
};
use trait_bounds::Not;
#[derive(Debug)]
struct Somehow {
inner: Box<dyn Error>,
}
impl Display for Somehow {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
// note that it does implement Error, unlike anyhow/eyre error types
impl Error for Somehow {}
// and excluding Self from the trait bound allows to implement a blanket From<E: Error>, even though a blanket impl From<T> for T is defined in the core
impl<E: Error + Not<Self> + 'static> From<E> for Somehow {
fn from(value: E) -> Self {
Self {
inner: Box::new(value),
}
}
}
fn fallible() -> Result<(), Somehow> {
File::open("/nix")?;
Ok(())
}
fn main() -> Result<(), Somehow> {
fallible()?;
Ok(())
}
```