has_impl/
lib.rs

1/*!
2This crate provides `has_impl!(type: Trait)` macro to check if `Trait` is implemented for `type`
3at complie time
4
5```rust
6use has_impl::*;
7
8trait Foo {}
9
10impl Foo for i32 {}
11
12fn main() {
13	assert_eq!(has_impl!(i32: Foo), true);
14}
15```
16*/
17
18#![no_std]
19
20#[macro_export]
21macro_rules! has_impl {
22	($ty:ty: $tr:path) => {
23		{
24			struct Test<T: ?Sized>(core::marker::PhantomData<T>);
25
26			#[allow(dead_code)]
27			impl<T: ?Sized + $tr> Test<T> {
28				const HAS_IMPL: bool = true;
29			}
30
31			trait Fallback {
32				const HAS_IMPL: bool = false;
33			}
34
35			impl<T: ?Sized> Fallback for T {}
36
37			Test::<$ty>::HAS_IMPL
38		}
39	};
40}
41
42#[cfg(test)]
43mod tests {
44	trait Foo {}
45
46	impl Foo for i32 {}
47
48	trait Bar {}
49
50	#[test]
51	fn basic() {
52		assert_eq!(has_impl!(i32: Foo), true);
53		assert_eq!(has_impl!(i32: Bar), false);
54	}
55
56	mod path {
57		pub(crate) trait Trait1 {}
58
59		pub(crate) trait Trait2 {}
60	}
61
62	impl path::Trait1 for i32 {}
63
64	#[test]
65	fn with_path() {
66		assert_eq!(has_impl!(i32: path::Trait1), true);
67		assert_eq!(has_impl!(i32: path::Trait2), false);
68	}
69}