#[macro_export(local_inner_macros)]
macro_rules! does_impl {
($ty:ty: $($trait_expr:tt)+) => {
_does_impl!($ty: $($trait_expr)+).value()
};
}
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! _does_impl {
($ty:ty: $($rest:tt)*) => {{
#[allow(unused_imports)]
use $crate::{
_bool::{True, False},
_core::{marker::PhantomData, ops::Deref},
};
trait DoesntImpl {
const DOES_IMPL: False = False;
}
impl<T: ?Sized> DoesntImpl for T {}
*_does_impl!(@boolexpr($ty,) $($rest)*)
}};
(@boolexpr($($args:tt)*) ($($expr:tt)*)) => {
_does_impl!(@boolexpr($($args)*) $($expr)*)
};
(@boolexpr($($args:tt)*) !($($expr:tt)*)) => {
_does_impl!(@boolexpr($($args)*) $($expr)*).not()
};
(@boolexpr($($args:tt)*) ($($left:tt)*) | $($right:tt)*) => {{
let left = _does_impl!(@boolexpr($($args)*) $($left)*);
let right = _does_impl!(@boolexpr($($args)*) $($right)*);
left.or(right)
}};
(@boolexpr($($args:tt)*) ($($left:tt)*) & $($right:tt)*) => {{
let left = _does_impl!(@boolexpr($($args)*) $($left)*);
let right = _does_impl!(@boolexpr($($args)*) $($right)*);
left.and(right)
}};
(@boolexpr($($args:tt)*) !($($left:tt)*) | $($right:tt)*) => {{
_does_impl!(@boolexpr($($args)*) (!($($left)*)) | $($right)*)
}};
(@boolexpr($($args:tt)*) !($($left:tt)*) & $($right:tt)*) => {{
_does_impl!(@boolexpr($($args)*) (!($($left)*)) & $($right)*)
}};
(@boolexpr($($args:tt)*) !$left:ident | $($right:tt)*) => {{
_does_impl!(@boolexpr($($args)*) !($left) | $($right)*)
}};
(@boolexpr($($args:tt)*) !$left:ident & $($right:tt)*) => {{
_does_impl!(@boolexpr($($args)*) !($left) & $($right)*)
}};
(@boolexpr($($args:tt)*) $left:ident | $($right:tt)*) => {
_does_impl!(@boolexpr($($args)*) ($left) | $($right)*)
};
(@boolexpr($($args:tt)*) $left:ident & $($right:tt)*) => {{
_does_impl!(@boolexpr($($args)*) ($left) & $($right)*)
}};
(@boolexpr($($args:tt)*) !$expr:ident) => {
_does_impl!(@boolexpr($($args)*) !($expr))
};
(@boolexpr($($args:tt)*) !$expr:path) => {
_does_impl!(@boolexpr($($args)*) !($expr))
};
(@boolexpr($($args:tt)*) $expr:ident) => {
_does_impl!(@base($($args)*) $expr)
};
(@boolexpr($($args:tt)*) $expr:path) => {
_does_impl!(@base($($args)*) $expr)
};
(@base($ty:ty, $($args:tt)*) $($trait:tt)*) => {{
struct Wrapper<T: ?Sized>(PhantomData<T>);
#[allow(dead_code)]
impl<T: ?Sized + $($trait)*> Wrapper<T> {
const DOES_IMPL: True = True;
}
&<Wrapper<$ty>>::DOES_IMPL
}};
}