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:
bors 2013-10-05 14:26:44 -07:00
commit 2733b189ac
25 changed files with 1632 additions and 394 deletions

View 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() {}

View 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);
}

View file

@ -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);
}

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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() {

View file

@ -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() {