Skip to content

The macro_rules treat -1 as not a pattern #42820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
iddm opened this issue Jun 22, 2017 · 2 comments
Closed

The macro_rules treat -1 as not a pattern #42820

iddm opened this issue Jun 22, 2017 · 2 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)

Comments

@iddm
Copy link

iddm commented Jun 22, 2017

I need a enum which is deserialized with serde from number: -1, 0 and 1.
When I try to use enum_number macro from official serde documentation I get this:


error: expected pattern, found `-1`
  --> src/serde_utils.rs:37:32
   |
37 |                             $( $value => Ok($name::$variant), )*
   |                                ^^^^^^

error: aborting due to previous error

The code is very simple:

enum_number!(Change {
    Down = -1,
    None = 0,
    Up = 1,
});
macro_rules! enum_number {
    ($name:ident { $($variant:ident = $value:expr, )* }) => {
        #[allow(missing_docs)]
        #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
        pub enum $name {
            $($variant = $value,)*
        }

        impl serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: serde::Serializer
            {
                // Serialize the enum as a i64.
                serializer.serialize_i64(*self as i64)
            }
        }

        impl<'de> serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where D: serde::Deserializer<'de>
            {
                struct Visitor;

                impl<'de> serde::de::Visitor<'de> for Visitor {
                    type Value = $name;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("signed 64-bit integer")
                    }

                    fn visit_i64<E>(self, value: i64) -> Result<$name, E>
                        where E: serde::de::Error
                    {
                        // Rust does not come with a simple way of converting a
                        // number to an enum, so use a big `match`.
                        match value {
                            $( $value => Ok($name::$variant), )*
                            _ => Err(E::custom(
                                format!("unknown {} value: {}",
                                stringify!($name), value))),
                        }
                    }
                }

                // Deserialize the enum from a i64.
                deserializer.deserialize_i64(Visitor)
            }
        }
    }
}

If I change -1 to a positive number it compiles okay. I think it is a problem.

@iddm iddm changed the title The macro_rules treats -1 as not a pattern The macro_rules treat -1 as not a pattern Jun 22, 2017
@Mark-Simulacrum Mark-Simulacrum added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Jun 23, 2017
@durka
Copy link
Contributor

durka commented Jun 24, 2017

I think I know how to fix this. But LLVM's building, so we'll find out in a few hours :)

@durka
Copy link
Contributor

durka commented Jun 24, 2017

PR incoming.

arielb1 pushed a commit to arielb1/rust that referenced this issue Jun 29, 2017
syntax: allow negative integer literal expression to be interpolated as pattern

Fixes rust-lang#42820.

r? @jseyfried
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
Projects
None yet
Development

No branches or pull requests

3 participants