Add OneConst and ZeroConst traits
Conditional probing in build script Force enable with crate feature "associated_consts" Update README Add test const_identities
This commit is contained in:
parent
4ab251b0a2
commit
b9c4311fea
|
@ -22,3 +22,4 @@ features = ["std"]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
i128 = []
|
i128 = []
|
||||||
|
associated_consts = []
|
||||||
|
|
|
@ -42,6 +42,10 @@ Implementations for `i128` and `u128` are only available with Rust 1.26 and
|
||||||
later. The build script automatically detects this, but you can make it
|
later. The build script automatically detects this, but you can make it
|
||||||
mandatory by enabling the `i128` crate feature.
|
mandatory by enabling the `i128` crate feature.
|
||||||
|
|
||||||
|
Similarly, additional traits making use of associated constants are available
|
||||||
|
with Rust 1.22 and later. Again, the build script automatically detects this,
|
||||||
|
but you can make it mandatory by enabling the `associated_consts` crate feature.
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
Release notes are available in [RELEASES.md](RELEASES.md).
|
Release notes are available in [RELEASES.md](RELEASES.md).
|
||||||
|
|
10
build.rs
10
build.rs
|
@ -8,6 +8,16 @@ fn main() {
|
||||||
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
|
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
|
||||||
panic!("i128 support was not detected!");
|
panic!("i128 support was not detected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if probe("fn main() {
|
||||||
|
struct TestDrop(); impl Drop for TestDrop { fn drop(&mut self) {} }
|
||||||
|
trait TestConst { const TEST: Self; }
|
||||||
|
impl TestConst for TestDrop { const TEST: TestDrop = TestDrop(); }
|
||||||
|
}") {
|
||||||
|
println!("cargo:rustc-cfg=has_associated_consts");
|
||||||
|
} else if env::var_os("CARGO_FEATURE_ASSOCIATED_CONSTS").is_some() {
|
||||||
|
panic!("associated constant support was not detected!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if a code snippet can be compiled
|
/// Test if a code snippet can be compiled
|
||||||
|
|
|
@ -29,6 +29,18 @@ pub trait Zero: Sized + Add<Self, Output = Self> {
|
||||||
fn is_zero(&self) -> bool;
|
fn is_zero(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Supplimentary trait for [`Zero`](trait.Zero.html) types which can be
|
||||||
|
/// expressed as compile-time constants.
|
||||||
|
///
|
||||||
|
/// This is implemented for all primitive types, and should be implemented
|
||||||
|
/// wherever possible. Implementors must ensure that `ZeroConst::ZERO` is
|
||||||
|
/// the same value produced by [`Zero::zero()`](trait.Zero.html#tymethod.zero).
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
pub trait ZeroConst: Zero {
|
||||||
|
/// Additive identity: see [`Zero::zero()`](trait.Zero.html#tymethod.zero).
|
||||||
|
const ZERO: Self;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! zero_impl {
|
macro_rules! zero_impl {
|
||||||
($t:ty, $v:expr) => {
|
($t:ty, $v:expr) => {
|
||||||
impl Zero for $t {
|
impl Zero for $t {
|
||||||
|
@ -44,24 +56,38 @@ macro_rules! zero_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_impl!(usize, 0);
|
#[cfg(has_associated_consts)]
|
||||||
zero_impl!(u8, 0);
|
macro_rules! zero_const_impl {
|
||||||
zero_impl!(u16, 0);
|
($t:ty, $v:expr) => {
|
||||||
zero_impl!(u32, 0);
|
zero_impl!($t, $v);
|
||||||
zero_impl!(u64, 0);
|
impl ZeroConst for $t {
|
||||||
#[cfg(has_i128)]
|
const ZERO: $t = $v;
|
||||||
zero_impl!(u128, 0);
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[cfg(not(has_associated_consts))]
|
||||||
|
macro_rules! zero_const_impl {
|
||||||
|
($t:ty, $v:expr) => { zero_impl!($t, $v); };
|
||||||
|
}
|
||||||
|
|
||||||
zero_impl!(isize, 0);
|
zero_const_impl!(usize, 0);
|
||||||
zero_impl!(i8, 0);
|
zero_const_impl!(u8, 0);
|
||||||
zero_impl!(i16, 0);
|
zero_const_impl!(u16, 0);
|
||||||
zero_impl!(i32, 0);
|
zero_const_impl!(u32, 0);
|
||||||
zero_impl!(i64, 0);
|
zero_const_impl!(u64, 0);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
zero_impl!(i128, 0);
|
zero_const_impl!(u128, 0);
|
||||||
|
|
||||||
zero_impl!(f32, 0.0);
|
zero_const_impl!(isize, 0);
|
||||||
zero_impl!(f64, 0.0);
|
zero_const_impl!(i8, 0);
|
||||||
|
zero_const_impl!(i16, 0);
|
||||||
|
zero_const_impl!(i32, 0);
|
||||||
|
zero_const_impl!(i64, 0);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
zero_const_impl!(i128, 0);
|
||||||
|
|
||||||
|
zero_const_impl!(f32, 0.0);
|
||||||
|
zero_const_impl!(f64, 0.0);
|
||||||
|
|
||||||
impl<T: Zero> Zero for Wrapping<T>
|
impl<T: Zero> Zero for Wrapping<T>
|
||||||
where
|
where
|
||||||
|
@ -80,6 +106,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
impl<T: ZeroConst> ZeroConst for Wrapping<T>
|
||||||
|
where
|
||||||
|
Wrapping<T>: Zero,
|
||||||
|
{
|
||||||
|
const ZERO: Self = Wrapping(T::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
/// Defines a multiplicative identity element for `Self`.
|
/// Defines a multiplicative identity element for `Self`.
|
||||||
///
|
///
|
||||||
/// # Laws
|
/// # Laws
|
||||||
|
@ -118,6 +152,18 @@ pub trait One: Sized + Mul<Self, Output = Self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Supplimentary trait for [`One`](trait.One.html) types which can be
|
||||||
|
/// expressed as compile-time constants.
|
||||||
|
///
|
||||||
|
/// This is implemented for all primitive types, and should be implemented
|
||||||
|
/// wherever possible. Implementors must ensure that `OneConst::ONE` is
|
||||||
|
/// the same value produced by [`One::one()`](trait.One.html#tymethod.one).
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
pub trait OneConst: One {
|
||||||
|
/// Multiplicative identity: see [`One::one`](trait.One.html#tymethod.one).
|
||||||
|
const ONE: Self;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! one_impl {
|
macro_rules! one_impl {
|
||||||
($t:ty, $v:expr) => {
|
($t:ty, $v:expr) => {
|
||||||
impl One for $t {
|
impl One for $t {
|
||||||
|
@ -133,24 +179,39 @@ macro_rules! one_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
one_impl!(usize, 1);
|
#[cfg(has_associated_consts)]
|
||||||
one_impl!(u8, 1);
|
macro_rules! one_const_impl {
|
||||||
one_impl!(u16, 1);
|
($t:ty, $v:expr) => {
|
||||||
one_impl!(u32, 1);
|
one_impl!($t, $v);
|
||||||
one_impl!(u64, 1);
|
impl OneConst for $t {
|
||||||
#[cfg(has_i128)]
|
const ONE: $t = $v;
|
||||||
one_impl!(u128, 1);
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[cfg(not(has_associated_consts))]
|
||||||
|
macro_rules! one_const_impl {
|
||||||
|
($t:ty, $v:expr) => { one_impl!($t, $v); };
|
||||||
|
}
|
||||||
|
|
||||||
one_impl!(isize, 1);
|
|
||||||
one_impl!(i8, 1);
|
|
||||||
one_impl!(i16, 1);
|
|
||||||
one_impl!(i32, 1);
|
|
||||||
one_impl!(i64, 1);
|
|
||||||
#[cfg(has_i128)]
|
|
||||||
one_impl!(i128, 1);
|
|
||||||
|
|
||||||
one_impl!(f32, 1.0);
|
one_const_impl!(usize, 1);
|
||||||
one_impl!(f64, 1.0);
|
one_const_impl!(u8, 1);
|
||||||
|
one_const_impl!(u16, 1);
|
||||||
|
one_const_impl!(u32, 1);
|
||||||
|
one_const_impl!(u64, 1);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
one_const_impl!(u128, 1);
|
||||||
|
|
||||||
|
one_const_impl!(isize, 1);
|
||||||
|
one_const_impl!(i8, 1);
|
||||||
|
one_const_impl!(i16, 1);
|
||||||
|
one_const_impl!(i32, 1);
|
||||||
|
one_const_impl!(i64, 1);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
one_const_impl!(i128, 1);
|
||||||
|
|
||||||
|
one_const_impl!(f32, 1.0);
|
||||||
|
one_const_impl!(f64, 1.0);
|
||||||
|
|
||||||
impl<T: One> One for Wrapping<T>
|
impl<T: One> One for Wrapping<T>
|
||||||
where
|
where
|
||||||
|
@ -165,6 +226,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
impl<T: OneConst> OneConst for Wrapping<T>
|
||||||
|
where
|
||||||
|
Wrapping<T>: One,
|
||||||
|
{
|
||||||
|
const ONE: Self = Wrapping(T::ONE);
|
||||||
|
}
|
||||||
|
|
||||||
// Some helper functions provided for backwards compatibility.
|
// Some helper functions provided for backwards compatibility.
|
||||||
|
|
||||||
/// Returns the additive identity, `0`.
|
/// Returns the additive identity, `0`.
|
||||||
|
@ -179,6 +248,23 @@ pub fn one<T: One>() -> T {
|
||||||
One::one()
|
One::one()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
fn const_identies() {
|
||||||
|
macro_rules! test_zero_one {
|
||||||
|
($zero:expr, $one:expr; $($t:ty),+) => {
|
||||||
|
$(
|
||||||
|
assert_eq!(<$t as ZeroConst>::ZERO, $zero);
|
||||||
|
assert_eq!(<$t as ZeroConst>::ZERO, <$t as Zero>::zero());
|
||||||
|
assert_eq!(<$t as OneConst>::ONE, $one);
|
||||||
|
assert_eq!(<$t as OneConst>::ONE, <$t as One>::one());
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_zero_one!(0, 1; isize, i8, i16, i32, i64, usize, u8, u16, u32, u64);
|
||||||
|
test_zero_one!(0.0, 1.0; f32, f64);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrapping_identities() {
|
fn wrapping_identities() {
|
||||||
macro_rules! test_wrapping_identities {
|
macro_rules! test_wrapping_identities {
|
||||||
|
|
|
@ -32,6 +32,8 @@ pub use float::FloatConst;
|
||||||
// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
||||||
pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
|
pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
|
||||||
pub use identities::{one, zero, One, Zero};
|
pub use identities::{one, zero, One, Zero};
|
||||||
|
#[cfg(has_associated_consts)]
|
||||||
|
pub use identities::{OneConst, ZeroConst};
|
||||||
pub use int::PrimInt;
|
pub use int::PrimInt;
|
||||||
pub use ops::checked::{
|
pub use ops::checked::{
|
||||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
|
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
|
||||||
|
|
Loading…
Reference in New Issue