auto merge of #9250 : erickt/rust/num, r=erickt
This PR solves one of the pain points with c-style enums. Simplifies writing a fn to convert from an int/uint to an enum. It does this through a `#[deriving(FromPrimitive)]` syntax extension. Before this is committed though, we need to discuss if `ToPrimitive`/`FromPrimitive` has the right design (cc #4819). I've changed all the `.to_int()` and `from_int()` style functions to return `Option<int>` so we can handle partial functions. For this PR though only enums and `extra::num::bigint::*` take advantage of returning None for unrepresentable values. In the long run it'd be better if `i64.to_i8()` returned `None` if the value was too large, but I'll save this for a future PR. Closes #3868.
This commit is contained in:
commit
2733b189ac
25 changed files with 1632 additions and 394 deletions
34
src/test/compile-fail/deriving-primitive.rs
Normal file
34
src/test/compile-fail/deriving-primitive.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
use std::num::FromPrimitive;
|
||||
use std::int;
|
||||
|
||||
#[deriving(FromPrimitive)]
|
||||
struct A { x: int }
|
||||
//~^^ ERROR `FromPrimitive` cannot be derived for structs
|
||||
//~^^^ ERROR `FromPrimitive` cannot be derived for structs
|
||||
|
||||
#[deriving(FromPrimitive)]
|
||||
struct B(int);
|
||||
//~^^ ERROR `FromPrimitive` cannot be derived for structs
|
||||
//~^^^ ERROR `FromPrimitive` cannot be derived for structs
|
||||
|
||||
#[deriving(FromPrimitive)]
|
||||
enum C { Foo(int), Bar(uint) }
|
||||
//~^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
|
||||
//~^^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
|
||||
|
||||
#[deriving(FromPrimitive)]
|
||||
enum D { Baz { x: int } }
|
||||
//~^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
|
||||
//~^^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
|
||||
|
||||
pub fn main() {}
|
||||
37
src/test/run-pass/deriving-primitive.rs
Normal file
37
src/test/run-pass/deriving-primitive.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
use std::num::FromPrimitive;
|
||||
use std::int;
|
||||
|
||||
#[deriving(Eq, FromPrimitive)]
|
||||
enum A {
|
||||
Foo = int::max_value,
|
||||
Bar = 1,
|
||||
Baz = 3,
|
||||
Qux,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: Option<A> = FromPrimitive::from_int(int::max_value);
|
||||
assert_eq!(x, Some(Foo));
|
||||
|
||||
let x: Option<A> = FromPrimitive::from_int(1);
|
||||
assert_eq!(x, Some(Bar));
|
||||
|
||||
let x: Option<A> = FromPrimitive::from_int(3);
|
||||
assert_eq!(x, Some(Baz));
|
||||
|
||||
let x: Option<A> = FromPrimitive::from_int(4);
|
||||
assert_eq!(x, Some(Qux));
|
||||
|
||||
let x: Option<A> = FromPrimitive::from_int(5);
|
||||
assert_eq!(x, None);
|
||||
}
|
||||
|
|
@ -36,6 +36,6 @@ pub fn main() {
|
|||
|
||||
// floats
|
||||
// num
|
||||
assert_eq!(10f32.to_int(), 10);
|
||||
assert_eq!(10f64.to_int(), 10);
|
||||
assert_eq!(10f32.to_int().unwrap(), 10);
|
||||
assert_eq!(10f64.to_int().unwrap(), 10);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pub trait NumExt: Num + NumCast + Eq + Ord {}
|
|||
|
||||
pub trait FloatExt: NumExt + ApproxEq<Self> {}
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > NumCast::from(1) }
|
||||
fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > NumCast::from(1) }
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
|
||||
fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ trait Num {
|
|||
pub trait NumExt: Num + NumCast { }
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool {
|
||||
n.gt(&NumCast::from(1))
|
||||
n.gt(&NumCast::from(1).unwrap())
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::num::NumCast;
|
|||
pub trait NumExt: Num + NumCast + Ord { }
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool {
|
||||
*n > NumCast::from(1)
|
||||
*n > NumCast::from(1).unwrap()
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub trait NumExt: Eq + Ord + Num + NumCast {}
|
|||
impl NumExt for f32 {}
|
||||
|
||||
fn num_eq_one<T:NumExt>(n: T) {
|
||||
println!("{}", n == NumCast::from(1))
|
||||
println!("{}", n == NumCast::from(1).unwrap())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl NumExt for f32 {}
|
|||
impl NumExt for int {}
|
||||
|
||||
fn num_eq_one<T:NumExt>() -> T {
|
||||
NumCast::from(1)
|
||||
NumCast::from(1).unwrap()
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue