trait_ext/lib.rs
1//! Crate with a helper macro which can create simple extensions over a specific trait
2//! which is automatically implemented for every type which implements the specified trait.
3#![feature(decl_macro)]
4
5/// Specify a trait which automatically is implemented for each type that implements
6/// the super trait.
7///
8/// The quantificator of implementation makes sure you can't provide any other implementation
9/// (without negative reasoning or specialization at least). This forbids reimplementing
10/// methods.
11///
12/// ## Example use
13///
14/// ```rust,norun
15/// trait_ext! {
16/// pub trait SampleExt for std::fmt::Debug {
17/// fn test(&self) -> {
18/// eprintln!("{:?}", self)
19/// }
20/// }
21/// }
22///
23/// fn foo<T: std::fmt::Debug>(value: T) -> () {
24/// value.test(); // is implemented automatically
25/// }
26/// ```
27///
28/// ## Interesting fact
29///
30/// This almost replicates the inherent implementations in Rust. Inherent implementations
31/// by their nature are basically unnamed traits with more specific algorithm on finding
32/// the implementation in the scope.
33///
34/// Each inherent impl block is basically an unnamed trait which is attached to the type
35/// the impl is implemented for.
36///
37/// For instance:
38///
39/// ```rust,norun
40/// struct Foo;
41///
42/// impl Foo { fn first(&self) -> () {} }
43/// impl Foo { fn second(&self) -> () {} }
44/// ```
45///
46/// Is semantically equivalent to:
47///
48/// ```rust,norun
49/// struct Foo;
50/// trait Foo1 { fn first(&self) -> (); }
51/// impl Foo1 for Foo { fn first(&self) -> () {} }
52/// trait Foo2 { fn first(&self) -> (); }
53/// impl Foo2 for Foo { fn second(&self) -> () {} }
54/// ```
55///
56/// This macro is very simple an replicates this inherent impl logic.
57pub macro trait_ext($vis:vis trait $ident:ident for $($ident2:path),+ { $($item:item)* }) {
58 $vis trait $ident: $($ident2)++ { $($item)* }
59 impl<S: $($ident2)++> $ident for S {}
60}