From 06c0ee035cb12a9d3ed1a32e8fde80c04922417f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 14 Dec 2023 11:55:13 -0700 Subject: [PATCH] Add `ZeroConstant` and `OneConstant` traits Adds traits which are alternatives to the more dynamic `Zero`/`One` traits which are useful for stack-allocated types where it's possible to define constant values for zero/one. `ZeroConstant` bounds on `Zero` as a supertrait, and `OneConstant` on `One`, allowing them to be used as drop-in replacements. When a type also impls `PartialEq`, then `ZeroConstant` also provides a blanket impl of `Zero`, and likewise for `OneConstant`/`One`, making it simple for stack-allocated integers to impl these traits as an alternative to `Zero`/`One` while still remaining fully compatible. The internal impls of `Zero`/`One` on the numeric primitive types have been changed to use these traits, which should be a fully backwards-compatible change. --- src/identities.rs | 66 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index 2486cb19..046c28db 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -28,17 +28,32 @@ pub trait Zero: Sized + Add { fn is_zero(&self) -> bool; } +/// Defines an associated constant representing the additive identity element +/// for `Self`. +/// +/// Types which impl both this trait and [`PartialEq`] will receive a blanket +/// impl of the [`Zero`] trait. +pub trait ZeroConstant: Zero { + /// The additive identity element of `Self`, `0`. + const ZERO: Self; +} + +impl Zero for T { + #[inline(always)] + fn zero() -> T { + Self::ZERO + } + + #[inline(always)] + fn is_zero(&self) -> bool { + self == &Self::ZERO + } +} + macro_rules! zero_impl { ($t:ty, $v:expr) => { - impl Zero for $t { - #[inline] - fn zero() -> $t { - $v - } - #[inline] - fn is_zero(&self) -> bool { - *self == $v - } + impl ZeroConstant for $t { + const ZERO: Self = $v; } }; } @@ -115,17 +130,32 @@ pub trait One: Sized + Mul { } } +/// Defines an associated constant representing the multiplicative identity +/// element for `Self`. +/// +/// Types which impl both this trait and [`PartialEq`] will receive a blanket +/// impl of the [`One`] trait. +pub trait OneConstant: One { + /// The multiplicative identity element of `Self`, `1`. + const ONE: Self; +} + +impl One for T { + #[inline(always)] + fn one() -> T { + Self::ONE + } + + #[inline(always)] + fn is_one(&self) -> bool { + self == &Self::ONE + } +} + macro_rules! one_impl { ($t:ty, $v:expr) => { - impl One for $t { - #[inline] - fn one() -> $t { - $v - } - #[inline] - fn is_one(&self) -> bool { - *self == $v - } + impl OneConstant for $t { + const ONE: Self = $v; } }; }