From afdff944d00410b0ea43a106f156472011f1e30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=99=CF=89=CE=AC=CE=BD=CE=BD=CE=B7=CF=82=20=CE=9D=CE=B9?= =?UTF-8?q?=CE=BA=CE=BF=CE=BB=CE=B1=CE=90=CE=B4=CE=B7=CF=82?= Date: Sun, 25 Sep 2022 20:27:10 +0300 Subject: [PATCH 1/2] =?UTF-8?q?1)=20Implemented=20all=20FIXMEs:=20=20=20?= =?UTF-8?q?=20=20=E2=86=92=20Trait=20now=20contains=20associated=20constan?= =?UTF-8?q?ts=20rather=20than=20non-`const`=20functions.=20=20=20=20=20?= =?UTF-8?q?=E2=86=92=20`LowerBounded`=20and=20`UpperBounded`=20are=20now?= =?UTF-8?q?=20supertraits=20of=20`Bounded`,=20not=20subtraits.=202)=20Expa?= =?UTF-8?q?nded=20implementations=20to=20also=20cover=20`NonZero`=20data-t?= =?UTF-8?q?ypes.=203)=20Made=20the=20code=20DRYer,=20with=20regards=20to?= =?UTF-8?q?=20the=20implementation=20of=20`bounded=5Fimpl!`.=204)=20Added?= =?UTF-8?q?=20a=20couple=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bounds.rs | 161 +++++++++++++++++++++++++++----------------------- tests/cast.rs | 16 ++--- 2 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/bounds.rs b/src/bounds.rs index acc990ea..e1c1e633 100644 --- a/src/bounds.rs +++ b/src/bounds.rs @@ -1,83 +1,98 @@ -use core::num::Wrapping; +use core::num::*; use core::{f32, f64}; use core::{i128, i16, i32, i64, i8, isize}; use core::{u128, u16, u32, u64, u8, usize}; -/// Numbers which have upper and lower bounds -pub trait Bounded { - // FIXME (#5527): These should be associated constants - /// Returns the smallest finite number this type can represent - fn min_value() -> Self; - /// Returns the largest finite number this type can represent - fn max_value() -> Self; -} - /// Numbers which have lower bounds pub trait LowerBounded { - /// Returns the smallest finite number this type can represent - fn min_value() -> Self; -} - -// FIXME: With a major version bump, this should be a supertrait instead -impl LowerBounded for T { - fn min_value() -> T { - Bounded::min_value() - } + /// The smallest finite number this type can represent. + const MIN: Self; } /// Numbers which have upper bounds pub trait UpperBounded { - /// Returns the largest finite number this type can represent - fn max_value() -> Self; + /// The largest finite number this type can represent. + const MAX: Self; } -// FIXME: With a major version bump, this should be a supertrait instead -impl UpperBounded for T { - fn max_value() -> T { - Bounded::max_value() - } +/// Numbers which have upper and lower bounds +pub trait Bounded: UpperBounded + LowerBounded + Sized { + const MIN: Self = ::MIN; + const MAX: Self = ::MAX; } macro_rules! bounded_impl { - ($t:ty, $min:expr, $max:expr) => { - impl Bounded for $t { - #[inline] - fn min_value() -> $t { - $min - } - - #[inline] - fn max_value() -> $t { - $max - } + ($t:ty) => { + + impl LowerBounded for $t { + const MIN: $t = <$t>::MIN; + } + + impl UpperBounded for $t { + const MAX: $t = <$t>::MAX; } }; } -bounded_impl!(usize, usize::MIN, usize::MAX); -bounded_impl!(u8, u8::MIN, u8::MAX); -bounded_impl!(u16, u16::MIN, u16::MAX); -bounded_impl!(u32, u32::MIN, u32::MAX); -bounded_impl!(u64, u64::MIN, u64::MAX); -bounded_impl!(u128, u128::MIN, u128::MAX); - -bounded_impl!(isize, isize::MIN, isize::MAX); -bounded_impl!(i8, i8::MIN, i8::MAX); -bounded_impl!(i16, i16::MIN, i16::MAX); -bounded_impl!(i32, i32::MIN, i32::MAX); -bounded_impl!(i64, i64::MIN, i64::MAX); -bounded_impl!(i128, i128::MIN, i128::MAX); - -impl Bounded for Wrapping { - fn min_value() -> Self { - Wrapping(T::min_value()) - } - fn max_value() -> Self { - Wrapping(T::max_value()) - } +macro_rules! bounded_impl_nonzero { + ($NonZero:ty, $PossiblyZero:ty) => { + + impl LowerBounded for $NonZero { + const MIN: $NonZero = unsafe { + if <$PossiblyZero>::MIN == 0 as $PossiblyZero { + Self::new_unchecked(1 as $PossiblyZero) + } else { + Self::new_unchecked(<$PossiblyZero>::MIN) + } + }; + } + + impl UpperBounded for $NonZero { + const MAX: $NonZero = unsafe { Self::new_unchecked(<$PossiblyZero>::MAX) }; + } + }; } -bounded_impl!(f32, f32::MIN, f32::MAX); +bounded_impl!(u8); +bounded_impl!(u16); +bounded_impl!(u32); +bounded_impl!(u64); +bounded_impl!(u128); +bounded_impl!(usize); + +bounded_impl!(i8); +bounded_impl!(i16); +bounded_impl!(i32); +bounded_impl!(i64); +bounded_impl!(i128); +bounded_impl!(isize); + +bounded_impl_nonzero!(NonZeroU8, u8); +bounded_impl_nonzero!(NonZeroU16, u16); +bounded_impl_nonzero!(NonZeroU32, u32); +bounded_impl_nonzero!(NonZeroU64, u64); +bounded_impl_nonzero!(NonZeroU128, u128); +bounded_impl_nonzero!(NonZeroUsize, usize); + +bounded_impl_nonzero!(NonZeroI8, i8); +bounded_impl_nonzero!(NonZeroI16, i16); +bounded_impl_nonzero!(NonZeroI32, i32); +bounded_impl_nonzero!(NonZeroI64, i64); +bounded_impl_nonzero!(NonZeroI128, i128); +bounded_impl_nonzero!(NonZeroIsize, isize); + +impl LowerBounded for Wrapping { + const MIN: Wrapping = Wrapping(T::MIN); +} + +impl UpperBounded for Wrapping { + const MAX: Wrapping = Wrapping(T::MAX); +} + +impl Bounded for T {} + +bounded_impl!(f32); +bounded_impl!(f64); macro_rules! for_each_tuple_ { ( $m:ident !! ) => ( @@ -96,29 +111,27 @@ macro_rules! for_each_tuple { macro_rules! bounded_tuple { ( $($name:ident)* ) => ( - impl<$($name: Bounded,)*> Bounded for ($($name,)*) { - #[inline] - fn min_value() -> Self { - ($($name::min_value(),)*) - } - #[inline] - fn max_value() -> Self { - ($($name::max_value(),)*) - } + impl<$($name: LowerBounded,)*> LowerBounded for ($($name,)*) { + const MIN: Self = ($($name::MIN,)*); + } + + impl<$($name: UpperBounded,)*> UpperBounded for ($($name,)*) { + const MAX: Self = ($($name::MAX,)*); } ); } for_each_tuple!(bounded_tuple); -bounded_impl!(f64, f64::MIN, f64::MAX); #[test] fn wrapping_bounded() { macro_rules! test_wrapping_bounded { ($($t:ty)+) => { $( - assert_eq!( as Bounded>::min_value().0, <$t>::min_value()); - assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); + assert_eq!( as Bounded>::MIN.0, <$t>::MIN); + assert_eq!( as Bounded>::MAX.0, <$t>::MAX); + assert_eq!( as Bounded>::MIN.0 - 1, <$t>::MAX); + assert_eq!( as Bounded>::MAX.0 + 1, <$t>::MIN); )+ }; } @@ -131,8 +144,10 @@ fn wrapping_bounded_i128() { macro_rules! test_wrapping_bounded { ($($t:ty)+) => { $( - assert_eq!( as Bounded>::min_value().0, <$t>::min_value()); - assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); + assert_eq!( as Bounded>::MIN.0, <$t>::MIN); + assert_eq!( as Bounded>::MAX.0, <$t>::MAX); + assert_eq!( as Bounded>::MIN.0 - 1, <$t>::MAX); + assert_eq!( as Bounded>::MAX.0 + 1, <$t>::MIN); )+ }; } diff --git a/tests/cast.rs b/tests/cast.rs index 21094f6b..602618ae 100644 --- a/tests/cast.rs +++ b/tests/cast.rs @@ -327,10 +327,10 @@ fn newtype_from_primitive() { macro_rules! assert_eq_from { ($( $from:ident )+) => {$( - assert_eq!(T::$from(Bounded::min_value()).map(New), - New::::$from(Bounded::min_value())); - assert_eq!(T::$from(Bounded::max_value()).map(New), - New::::$from(Bounded::max_value())); + assert_eq!(T::$from(Bounded::MIN).map(New), + New::::$from(Bounded::MIN)); + assert_eq!(T::$from(Bounded::MAX).map(New), + New::::$from(Bounded::MAX)); )+} } @@ -365,10 +365,10 @@ fn newtype_to_primitive() { macro_rules! assert_eq_to { ($( $to:ident )+) => {$( - assert_eq!(T::$to(&Bounded::min_value()), - New::::$to(&New(Bounded::min_value()))); - assert_eq!(T::$to(&Bounded::max_value()), - New::::$to(&New(Bounded::max_value()))); + assert_eq!(T::$to(&Bounded::MIN), + New::::$to(&New(Bounded::MIN))); + assert_eq!(T::$to(&Bounded::MAX), + New::::$to(&New(Bounded::MAX))); )+} } From 6d6dd4d875b1cd0a24a0211ae6f4d8ebfedc650f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=99=CF=89=CE=AC=CE=BD=CE=BD=CE=B7=CF=82=20=CE=9D=CE=B9?= =?UTF-8?q?=CE=BA=CE=BF=CE=BB=CE=B1=CE=90=CE=B4=CE=B7=CF=82?= Date: Sun, 25 Sep 2022 20:42:11 +0300 Subject: [PATCH 2/2] Clarified new tests so they also work in debug mode. --- src/bounds.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bounds.rs b/src/bounds.rs index e1c1e633..61174f86 100644 --- a/src/bounds.rs +++ b/src/bounds.rs @@ -130,8 +130,8 @@ fn wrapping_bounded() { $( assert_eq!( as Bounded>::MIN.0, <$t>::MIN); assert_eq!( as Bounded>::MAX.0, <$t>::MAX); - assert_eq!( as Bounded>::MIN.0 - 1, <$t>::MAX); - assert_eq!( as Bounded>::MAX.0 + 1, <$t>::MIN); + assert_eq!( as Bounded>::MIN.0.wrapping_sub(1), <$t>::MAX); + assert_eq!( as Bounded>::MAX.0.wrapping_add(1), <$t>::MIN); )+ }; } @@ -146,8 +146,8 @@ fn wrapping_bounded_i128() { $( assert_eq!( as Bounded>::MIN.0, <$t>::MIN); assert_eq!( as Bounded>::MAX.0, <$t>::MAX); - assert_eq!( as Bounded>::MIN.0 - 1, <$t>::MAX); - assert_eq!( as Bounded>::MAX.0 + 1, <$t>::MIN); + assert_eq!( as Bounded>::MIN.0.wrapping_sub(1), <$t>::MAX); + assert_eq!( as Bounded>::MAX.0.wrapping_add(1), <$t>::MIN); )+ }; }