Auto merge of #228 - rust-num:fix/num-macros, r=cuviper
Fix `num-macros` `FromPrimitive` implementation Current solution follow syntax proposed in rust-lang/rfcs#1681. Tracking issue rust-lang/rust#35900 Close #227 Code broken after change: - [ ] https://github.com/kdar/gameboy-rs - [ ] https://github.com/lemonrock/mbedtls - [ ] https://github.com/timorantalaiho/kelaa - [ ] https://github.com/dylanede/cef-rs - [ ] https://github.com/klutzy/aheui-llvm - [ ] https://github.com/pcwalton/rust-media - [ ] https://github.com/PistonDevelopers/hematite_server
This commit is contained in:
commit
019c136b8c
|
@ -5,6 +5,7 @@ set -ex
|
|||
cargo bench --verbose
|
||||
|
||||
cargo test --verbose --manifest-path=macros/Cargo.toml
|
||||
cargo test --verbose --manifest-path=derive/Cargo.toml
|
||||
|
||||
# Build test for the serde feature
|
||||
cargo build --verbose --features "serde"
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
description = "Numeric syntax extensions"
|
||||
documentation = "http://rust-num.github.io/num"
|
||||
homepage = "https://github.com/rust-num/num"
|
||||
keywords = ["mathematics", "numerics"]
|
||||
license = "MIT/Apache-2.0"
|
||||
name = "num-derive"
|
||||
repository = "https://github.com/rust-num/num"
|
||||
version = "0.1.33"
|
||||
|
||||
[dependencies]
|
||||
quote = "0.1.3"
|
||||
syn = "0.7.0"
|
||||
|
||||
[dev-dependencies]
|
||||
compiletest_rs = "0.2.2"
|
||||
|
||||
[dev-dependencies.num]
|
||||
path = ".."
|
||||
version = "0.1"
|
||||
|
||||
[lib]
|
||||
crate-type = ["rustc-macro"]
|
||||
name = "num_derive"
|
||||
rustc-macro = true
|
||||
test = false
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rustc-macro"]
|
||||
#![feature(rustc_macro, rustc_macro_lib)]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate rustc_macro;
|
||||
|
||||
use rustc_macro::TokenStream;
|
||||
|
||||
use syn::Body::Enum;
|
||||
use syn::VariantData::Unit;
|
||||
|
||||
#[rustc_macro_derive(FromPrimitive)]
|
||||
pub fn from_primitive(input: TokenStream) -> TokenStream {
|
||||
let source = input.to_string();
|
||||
|
||||
let ast = syn::parse_macro_input(&source).unwrap();
|
||||
let name = &ast.ident;
|
||||
|
||||
let variants = match ast.body {
|
||||
Enum(ref variants) => variants,
|
||||
_ => {
|
||||
panic!("`FromPrimitive` can be applied only to the enums, {} is not an enum",
|
||||
name)
|
||||
}
|
||||
};
|
||||
|
||||
let mut idx = 0;
|
||||
let variants: Vec<_> = variants.iter()
|
||||
.map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
match variant.data {
|
||||
Unit => (),
|
||||
_ => {
|
||||
panic!("`FromPrimitive` can be applied only to unitary enums, {}::{} is either struct or tuple", name, ident)
|
||||
},
|
||||
}
|
||||
if let Some(val) = variant.discriminant {
|
||||
idx = val.value;
|
||||
}
|
||||
let tt = quote!(#idx => Some(#name::#ident));
|
||||
idx += 1;
|
||||
tt
|
||||
})
|
||||
.collect();
|
||||
|
||||
let res = quote! {
|
||||
#ast
|
||||
|
||||
impl ::num::traits::FromPrimitive for #name {
|
||||
fn from_i64(n: i64) -> Option<Self> {
|
||||
Self::from_u64(n as u64)
|
||||
}
|
||||
|
||||
fn from_u64(n: u64) -> Option<Self> {
|
||||
match n {
|
||||
#(variants,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
res.to_string().parse().unwrap()
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR
|
||||
struct Color {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR
|
||||
enum Color {
|
||||
Rgb(u8, u8, u8),
|
||||
Hsv(u8, u8, u8),
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,25 @@
|
|||
extern crate compiletest_rs as compiletest;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::env::var;
|
||||
|
||||
fn run_mode(mode: &'static str) {
|
||||
let mut config = compiletest::default_config();
|
||||
|
||||
let cfg_mode = mode.parse().ok().expect("Invalid mode");
|
||||
|
||||
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
|
||||
if let Ok(name) = var::<&str>("TESTNAME") {
|
||||
let s : String = name.to_owned();
|
||||
config.filter = Some(s)
|
||||
}
|
||||
config.mode = cfg_mode;
|
||||
config.src_base = PathBuf::from(format!("tests/{}", mode));
|
||||
|
||||
compiletest::run_tests(&config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_test() {
|
||||
run_mode("compile-fail");
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
#[derive(Debug, PartialEq, FromPrimitive)]
|
||||
enum Color {}
|
||||
|
||||
#[test]
|
||||
fn test_empty_enum() {
|
||||
let v: [Option<Color>; 1] = [num::FromPrimitive::from_u64(0)];
|
||||
|
||||
assert_eq!(v, [None]);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
#[derive(Debug, PartialEq, FromPrimitive)]
|
||||
enum Color {
|
||||
Red,
|
||||
Blue,
|
||||
Green,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_primitive_for_trivial_case() {
|
||||
let v: [Option<Color>; 4] = [num::FromPrimitive::from_u64(0),
|
||||
num::FromPrimitive::from_u64(1),
|
||||
num::FromPrimitive::from_u64(2),
|
||||
num::FromPrimitive::from_u64(3)];
|
||||
|
||||
assert_eq!(v,
|
||||
[Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
#[derive(Debug, PartialEq, FromPrimitive)]
|
||||
enum Color {
|
||||
Red,
|
||||
Blue = 5,
|
||||
Green,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_primitive_for_enum_with_custom_value() {
|
||||
let v: [Option<Color>; 4] = [num::FromPrimitive::from_u64(0),
|
||||
num::FromPrimitive::from_u64(5),
|
||||
num::FromPrimitive::from_u64(6),
|
||||
num::FromPrimitive::from_u64(3)];
|
||||
|
||||
assert_eq!(v,
|
||||
[Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]);
|
||||
}
|
Loading…
Reference in New Issue