Hi, I'm fairly new to rust, trying to get used to new concepts.
I tried to write a macro that can check if a given value is equal to one of the literals.
It would be rather a simple task using position, but I wanted seamless support for Option.
Say, I'd like to write the following code,
let x = None
let ls = vec![Some(1), None, Some(2), Some(3)]
assert!(ls.iter().position(|&y| y == x).is_none())
without having to write Some
so many times.
This is the closest I could get, yet fails.
macro_rules! oneof {
($x :expr ;; $y:expr) => (lifting_eq!($x, $y));
($x :expr ;; $y:expr, $($z :expr),+) => ( lifting_eq!($x, $y) || oneof!($x ;; $($z),*) );
}
macro_rules! lifting_eq { ($a :expr, $b :expr) => ({
use std::convert::TryInto;
let a :Result<Option<_>,_> = $a.try_into();
let b :Result<Option<_>,_> = $b.try_into();
a == b
})}
fn main() {
let c :Option<u32> = None;
assert!(!oneof!(4u32 ;; 1u32, 2u32, 3u32));
assert!( oneof!(1u32 ;; 1u32, 2u32, 3u32));
assert!(!oneof!(1u32 ;; None, 2u32, 3u32));
//assert!( oneof!(None ;; None, 2u32, 3u32));
//assert!( oneof!(c ;; None, 2u32, 3u32));
}
The last two lines of main
do not compile with the error cannot infer type
for a
in lifting_eq
macro invocation.
error[E0282]: type annotations needed
--> ps.rs:45:12
|
45 | let a :Result<Option<_>,_> = $a.try_into();
| ^^^^^^^^^^^^^^^^^^^ cannot infer type
...
57 | assert!( oneof!(c;; 1u32, None, 3u32));
| ---------------------------- in this macro invocation
|
= note: this error originates in the macro `lifting_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
Is there a way to work around this error? or any other suggestion to implement it?