maybe-impl

Crates.iomaybe-impl
lib.rsmaybe-impl
version0.1.0
sourcesrc
created_at2024-01-10 18:19:01.263606
updated_at2024-01-10 18:19:01.263606
descriptionProvides support to conditionally implement one or more traits
homepage
repositoryhttps://github.com/commonsensesoftware/maybe-impl
max_upload_size
id1095478
size17,500
Chris Martinez (commonsensesoftware)

documentation

README

Maybe Implements   CI Crates.io MIT licensed

Maybe Implements provides Rust procedural macro attributes that can be used to optionally implement traits.

Optional Traits in Action

Technically, the provided attribute always implements the specified traits. It can be combined with the existing cfg_attr attribute to conditionally implement one or more traits. The primary use case for such behavior is optionally implementing Send and Sync.

First, consider that asynchronous behavior is an optional feature in your crate:

[features]
async = ["maybe-impl"]

[dependencies]
maybe-impl = { version = "0.1.0", optional = true }

Consider the crate has the following trait:

#[cfg_attr(feature = "async", maybe_impl::traits(Send,Sync))]
trait Foo {
    fn bar(&self);
}

When the crate is used with the default features, there is no change in behavior. When the async feature is enabled:

cargo add my-crate --features async

The trait is expanded to:

trait Foo: Send + Sync {
    fn bar(&self);
}

Using Generics

If you define a trait with generics that requires Send and/or Sync, specifically, that will require the generic type constraint to match. Trait aliases are currently unstable, however, you can bridge these two concepts with a pseudo trait alias by defining a marker trait with a blanket implementation.

#[cfg(not(feature = "async"))]
trait Bar: Sized {}

#[cfg(not(feature = "async"))]
impl<T> Bar for T {}

#[cfg(feature = "async")]
trait Bar: Sized + Send + Sync {}

#[cfg(feature = "async")]
impl<T: Send + Sync> Bar for T {}

#[cfg_attr(feature = "async", maybe_impl::traits(Send,Sync))]
trait Foo<T: Bar> {
    fn bar(&self, bar: &T);
}

The default, synchronous build remains vanilla, while the asynchronous path expands to the equivalent of:

trait Foo<T: Send + Sync>: Send + Sync {
    fn bar(&self, bar: &T);
}

License

This project is licensed under the MIT license.

Commit count: 0

cargo fmt