trait-bounds 0.1.1

Trait bounds primitives using generic_const_exprs
Documentation
  • Coverage
  • 75%
    9 out of 12 items documented1 out of 9 items with examples
  • Size
  • Source code size: 21.25 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.04 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1m 8s Average build duration of successful builds.
  • all releases: 54s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • funsafemath

trait-bounds

This nightly-only library provides useful primitives for defining trait bounds

eq and ne functions allow to check whether two types are equal in a const context

type_id is similar to core::intrinsics::type_id, but it can be used on PointeeSized types

Assert<true> implements IsTrue

Assert<false> implements IsFalse

Is<T> is implemented for U if and only if U is equal to T

Not<T> is implemented for U if and only if U is not equal to T

The Not trait can be used to define multiple blanket implementations, which is particularly useful with the From<T> trait, as From<T> for T often collides with user-defined blanket impls

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
}
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(())
}