assert_impl/lib.rs
1//! Macro for static assert that types implement a trait or not.
2//!
3//! Note: this macro can only be used inside function body due to
4//! restriction of Rust.
5//!
6//! # Example
7//!
8//! Assuming you have the following definitions:
9//! ```
10//! struct C;
11//! struct Java;
12//! struct JavaScript;
13//! struct Python;
14//! struct Rust;
15//!
16//! trait StaticTyping {}
17//! impl StaticTyping for C {}
18//! impl StaticTyping for Java {}
19//! impl StaticTyping for Rust {}
20//! ```
21//!
22//! This should build:
23//! ```
24//! # #[macro_use] extern crate assert_impl;
25//! # struct C;
26//! # struct Java;
27//! # struct JavaScript;
28//! # struct Python;
29//! # struct Rust;
30//! # trait StaticTyping {}
31//! # impl StaticTyping for C {}
32//! # impl StaticTyping for Java {}
33//! # impl StaticTyping for Rust {}
34//! assert_impl!(StaticTyping: C, Java, Rust);
35//! assert_impl!(StaticTyping: C, Java, Rust, );
36//! assert_impl!(!StaticTyping: JavaScript, Python);
37//! assert_impl!(!StaticTyping: JavaScript, Python, );
38//! ```
39//!
40//! But these should fail to build:
41//! ```compile_fail
42//! # #[macro_use] extern crate assert_impl;
43//! # struct C;
44//! # struct Java;
45//! # struct JavaScript;
46//! # struct Python;
47//! # struct Rust;
48//! # trait StaticTyping {}
49//! # impl StaticTyping for C {}
50//! # impl StaticTyping for Java {}
51//! # impl StaticTyping for Rust {}
52//! assert_impl!(StaticTyping: JavaScript);
53//! ```
54//!
55//! ```compile_fail
56//! # #[macro_use] extern crate assert_impl;
57//! # struct C;
58//! # struct Java;
59//! # struct JavaScript;
60//! # struct Python;
61//! # struct Rust;
62//! # trait StaticTyping {}
63//! # impl StaticTyping for C {}
64//! # impl StaticTyping for Java {}
65//! # impl StaticTyping for Rust {}
66//! assert_impl!(!StaticTyping: Rust);
67//! ```
68
69#[macro_export]
70macro_rules! assert_impl {
71 ($trait:path: $($ty:ty),+) => {{
72 struct Helper<T>(T);
73 trait AssertImpl { fn assert() {} }
74 impl<T: $trait> AssertImpl for Helper<T> {}
75 $(
76 Helper::<$ty>::assert();
77 )+
78 }};
79 (!$trait:path: $($ty:ty),+) => {{
80 struct Helper<T>(T);
81 trait AssertImpl { fn assert() {} }
82 impl<T: $trait> AssertImpl for Helper<T> {}
83 trait AssertNotImpl { fn assert() {} }
84 $(
85 impl AssertNotImpl for Helper<$ty> {}
86 Helper::<$ty>::assert();
87 )+
88 }};
89 ($trait:path: $($ty:ty,)+) => (assert_impl!($trait: $($ty),+));
90 (!$trait:path: $($ty:ty,)+) => (assert_impl!(!$trait: $($ty),+));
91}