# must-implement-trait ![CI Badge](https://github.com/WasabiFan/must-implement-trait/workflows/Rust/badge.svg) An attribute proc-macro which enforces that a type (auto-)implements the specified trait(s). ## Usage Apply the `must_implement_trait` attribute to your struct or enum: ```rust use must_implement_trait::must_implement_trait; #[must_implement_trait(Send)] struct Resources { data: Rc, } #[must_implement_trait(Send, UnwindSafe)] enum ConfigSource { File(String), Database(DatabaseAdapter) } ``` The attribute can take one or many trait names as parameters; it will enforce that all are implemented. ## Motivation Some traits, chiefly `Send` and `Sync`, are [auto traits](https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits). This means that they are automatically implemented by the compiler, and rarely implemented (or un-implemented) by hand. Their implementations are implicit, and non-obvious to the reader without looking at documentation. As a library author, you may want to guarantee to consumers that your exposed interface will carry these traits. It may also be helpful within one's own code to provoke an error near the source of the un-implementation rather than near a consumer which fails to compile due to a trait bound violation. Consider the following example (`examples/async-future-send.rs`): ```rust struct Resources { data: Rc, } struct MyResourceManager {} #[async_trait] impl ResourceManager for MyResourceManager { async fn update_resources(resources: &Resources) { // Some code to update resources... } } ``` We get an error within the `update_resources` function telling us: ``` error: future cannot be sent between threads safely --> examples/async-future-send.rs:21:54 | 21 | async fn update_resources(resources: &Resources) { | ______________________________________________________^ 22 | | // Some code to update resources... 23 | | } | |_____^ future returned by `__update_resources` is not `Send` | = help: within `Resources`, the trait `std::marker::Sync` is not implemented for `std::rc::Rc` ``` By default, `async-trait` requires returned Futures to be `Send`. That is a rather natural choice, since `async` is often used in multi-threaded contexts. In this case, since we used an `Rc` rather than an `Arc`, `Resources` is not Send; we are given an error at the usage site. If `Resources` were in its own crate which is intended to be used in async contexts, the author may not realize they have made a breaking change by introducing an `Rc`. In my experience, if working in a codebase which is async-oriented, it makes sense to ensure that most or all types are `Send + Sync`; it is easy to break downstream code if an auto-implementation changes implicitly. By applying `must_implement_trait`, the error is moved to the type declaration: ``` error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> examples/async-future-send.rs:11:1 | 11 | #[must_implement_trait(Send)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be sent between threads safely | = help: within `Resources`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `Resources` = help: see issue #48214 = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info) ```