rustrust-proc-macros

Inverse `?` operator in Rust (aka return if Some/Ok)


I am building a macro parser with syn and need to check if a ParseStream is one of several keywords. The code currently looks similar to this:

mod kw {
    syn::custom_keyword!(a);
    syn::custom_keyword!(b);
    syn::custom_keyword!(c);
}

enum MyKeywordEnum {
    A(kw::a),
    B(kw::b),
    C(kw::c),
}

impl syn::parse::Parse for MyKeywordEnum {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(if let Ok(ret) = input.parse::<kw::a>() {
            Self::A(ret)
        } else if let Ok(ret) = input.parse::<kw::b>() {
            Self::B(ret)
        } else if let Ok(ret) = input.parse::<kw::c>() {
            Self::C(ret)
        } else {
            abort!(input.span(), "Couldn't parse primitive type"); // Via #[proc_macro_error]
        })
    }
}

Solution

  • As far as I know, there is not. You could create a macro to do this, or you could use the Result combinator functions to make things a little prettier:

    impl syn::parse::Parse for MyKeywordEnum {
        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
            input.parse::<kw::a>().map(Self::A)
                .or_else(|_| input.parse::<kw::b>().map(Self::B))
                .or_else(|_| input.parse::<kw::c>().map(Self::C))
                .or_else(|_| abort!(input.span(), "Couldn't parse primitive type"))
        }
    }