user11165129
user11165129

Reputation:

Macro match arm pattern "no rules expected the token `if`"

So i have this macro thats used to match Box<dyn error::Error> against multiple error types

#[macro_export]
macro_rules! dynmatch {
    ($e:expr, $(type $ty:ty {$(arm $pat:pat => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
        $(
            if let Some(e) = $e.downcast_ref::<$ty>() {
                match e {
                    $(
                        $pat => {$result}
                    )*
                    _ => $any
                }
            } else
        )*
        {$end}
    );
}

It was working fine until i tried adding match gaurds. when i try using "if" statements in the pattern it gives me the error no rules expected the token 'if'

let _i = match example(2) {
    Ok(i) => i,
    Err(e) => {
        dynmatch!(e,                                                            
            type ExampleError1 {                                                
                arm ExampleError1::ThisError(2) => panic!("it was 2!"),  
                _ => panic!("{}",e)                                             
            },
            type ExampleError2 {
                arm ExampleError2::ThatError(8) => panic!("it was 8!"),
                arm ExampleError2::ThatError(9..=11) => 10,
                _ => panic!("{}",e)
            }, 
            type std::io::Error {                                               
                arm i if i.kind() == std::io::ErrorKind::NotFound => panic!("not found"), //ERROR no rules expected the token `if`
                _ => panic!("{}", e)
            },
            _ => panic!("{}",e)                                                 
        )
    }
};

Is there any way to use match guards in my pattern matching without getting token errors?

Upvotes: 0

Views: 135

Answers (1)

user11165129
user11165129

Reputation:

and of course, even though i spent like an hour looking for a solution, right after i post this question i find an answer.

the correct macro looks like:

#[macro_export]
macro_rules! dynmatch {
    ($e:expr, $(type $ty:ty {$(arm $( $pattern:pat )|+ $( if $guard: expr )? => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
        $(
            if let Some(e) = $e.downcast_ref::<$ty>() {
                match e {
                    $(
                        $( $pattern )|+ $( if $guard )? => {$result}
                    )*
                    _ => $any
                }
            } else
        )*
        {$end}
    );
}

credit to the rust matches! source lines 244-251

Upvotes: 2

Related Questions