make it difficult to accidently leak supertraits in sealed traits
This commit is contained in:
parent
7695b680e3
commit
414e63a6dc
|
@ -357,7 +357,7 @@ fn fmt_dec_helper<F: FmtDecHelper>(
|
||||||
*r = b'0' + frac.take_frac_digit();
|
*r = b'0' + frac.take_frac_digit();
|
||||||
}
|
}
|
||||||
// check for rounding up
|
// check for rounding up
|
||||||
let round_up = match frac.cmp(&F::MSB) {
|
let round_up = match frac.traits().cmp(&F::MSB.traits()) {
|
||||||
Ordering::Less => false,
|
Ordering::Less => false,
|
||||||
Ordering::Greater => true,
|
Ordering::Greater => true,
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
|
|
|
@ -49,7 +49,7 @@ use half::f16;
|
||||||
/// [`u64`]: https://doc.rust-lang.org/nightly/std/primitive.u64.html
|
/// [`u64`]: https://doc.rust-lang.org/nightly/std/primitive.u64.html
|
||||||
/// [`u8`]: https://doc.rust-lang.org/nightly/std/primitive.u8.html
|
/// [`u8`]: https://doc.rust-lang.org/nightly/std/primitive.u8.html
|
||||||
/// [`usize`]: https://doc.rust-lang.org/nightly/std/primitive.usize.html
|
/// [`usize`]: https://doc.rust-lang.org/nightly/std/primitive.usize.html
|
||||||
pub trait Int: SealedInt {}
|
pub trait Int: Copy + SealedInt {}
|
||||||
|
|
||||||
/// This trait is implemented for the primitive floating-point types,
|
/// This trait is implemented for the primitive floating-point types,
|
||||||
/// and for [`f16`] if the [`f16` feature] is enabled.
|
/// and for [`f16`] if the [`f16` feature] is enabled.
|
||||||
|
@ -62,7 +62,7 @@ pub trait Int: SealedInt {}
|
||||||
/// [`f32`]: https://doc.rust-lang.org/nightly/std/primitive.f32.html
|
/// [`f32`]: https://doc.rust-lang.org/nightly/std/primitive.f32.html
|
||||||
/// [`f64`]: https://doc.rust-lang.org/nightly/std/primitive.f64.html
|
/// [`f64`]: https://doc.rust-lang.org/nightly/std/primitive.f64.html
|
||||||
/// [`f16` feature]: ../index.html#optional-features
|
/// [`f16` feature]: ../index.html#optional-features
|
||||||
pub trait Float: SealedFloat {}
|
pub trait Float: Copy + SealedFloat {}
|
||||||
|
|
||||||
/// This trait is implemented for all the fixed-point types.
|
/// This trait is implemented for all the fixed-point types.
|
||||||
///
|
///
|
||||||
|
@ -81,7 +81,7 @@ pub trait Float: SealedFloat {}
|
||||||
/// [`FixedU32`]: ../struct.FixedU32.html
|
/// [`FixedU32`]: ../struct.FixedU32.html
|
||||||
/// [`FixedU64`]: ../struct.FixedU64.html
|
/// [`FixedU64`]: ../struct.FixedU64.html
|
||||||
/// [`FixedU8`]: ../struct.FixedU8.html
|
/// [`FixedU8`]: ../struct.FixedU8.html
|
||||||
pub trait Fixed: SealedFixed {}
|
pub trait Fixed: Copy + SealedFixed {}
|
||||||
|
|
||||||
impl Int for i8 {}
|
impl Int for i8 {}
|
||||||
impl Int for i16 {}
|
impl Int for i16 {}
|
||||||
|
|
|
@ -31,9 +31,10 @@ pub enum Widest {
|
||||||
Negative(i128),
|
Negative(i128),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
|
pub trait SealedFixed: Copy {
|
||||||
type FracNBits: Unsigned;
|
type FracNBits: Unsigned;
|
||||||
type SBits: SealedInt;
|
type SBits: SealedInt;
|
||||||
|
type Traits: Copy + Debug + Default + Into<Self> + Display + Eq + Hash + Ord;
|
||||||
|
|
||||||
const FRAC_NBITS: u32 = Self::FracNBits::U32;
|
const FRAC_NBITS: u32 = Self::FracNBits::U32;
|
||||||
const INT_NBITS: u32 = Self::SBits::NBITS - Self::FRAC_NBITS;
|
const INT_NBITS: u32 = Self::SBits::NBITS - Self::FRAC_NBITS;
|
||||||
|
@ -47,10 +48,12 @@ pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
|
||||||
// 0 for no int bits
|
// 0 for no int bits
|
||||||
const INT_LSB: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
|
const INT_LSB: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
|
||||||
|
|
||||||
|
fn traits(self) -> Self::Traits;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_fixed<F: Fixed>(val: F) -> Self {
|
fn from_fixed<F: Fixed>(val: F) -> Self {
|
||||||
let (wrapped, overflow) = SealedFixed::overflowing_from_fixed(val);
|
let (wrapped, overflow) = SealedFixed::overflowing_from_fixed(val);
|
||||||
debug_assert!(!overflow, "{} overflows", val);
|
debug_assert!(!overflow, "{} overflows", val.traits());
|
||||||
let _ = overflow;
|
let _ = overflow;
|
||||||
wrapped
|
wrapped
|
||||||
}
|
}
|
||||||
|
@ -98,6 +101,12 @@ macro_rules! sealed_fixed {
|
||||||
{
|
{
|
||||||
type FracNBits = Frac;
|
type FracNBits = Frac;
|
||||||
type SBits = $Bits;
|
type SBits = $Bits;
|
||||||
|
type Traits = $Fixed<Frac>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn traits(self) -> Self::Traits {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn saturating_from_fixed<F: Fixed>(val: F) -> Self {
|
fn saturating_from_fixed<F: Fixed>(val: F) -> Self {
|
||||||
|
@ -202,7 +211,7 @@ macro_rules! sealed_fixed {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn overflowing_from_float<F: SealedFloat>(val: F) -> (Self, bool) {
|
fn overflowing_from_float<F: SealedFloat>(val: F) -> (Self, bool) {
|
||||||
if !val.is_finite() {
|
if !val.is_finite() {
|
||||||
panic!("{} is not finite", val);
|
panic!("{} is not finite", val.traits());
|
||||||
}
|
}
|
||||||
let (value, _, mut overflow) =
|
let (value, _, mut overflow) =
|
||||||
val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||||
|
|
|
@ -21,8 +21,9 @@ use core::{
|
||||||
#[cfg(feature = "f16")]
|
#[cfg(feature = "f16")]
|
||||||
use half::f16;
|
use half::f16;
|
||||||
|
|
||||||
pub trait SealedFloat: Copy + Debug + Display {
|
pub trait SealedFloat: Copy {
|
||||||
type Bits: SealedInt;
|
type Bits: SealedInt;
|
||||||
|
type Traits: Copy + Debug + Display;
|
||||||
|
|
||||||
const PREC: u32;
|
const PREC: u32;
|
||||||
const EXP_BIAS: i32 = (1 << (Self::Bits::NBITS - Self::PREC - 1)) - 1;
|
const EXP_BIAS: i32 = (1 << (Self::Bits::NBITS - Self::PREC - 1)) - 1;
|
||||||
|
@ -32,6 +33,8 @@ pub trait SealedFloat: Copy + Debug + Display {
|
||||||
const EXP_MASK: Self::Bits;
|
const EXP_MASK: Self::Bits;
|
||||||
const MANT_MASK: Self::Bits;
|
const MANT_MASK: Self::Bits;
|
||||||
|
|
||||||
|
fn traits(self) -> Self::Traits;
|
||||||
|
|
||||||
fn zero(neg: bool) -> Self;
|
fn zero(neg: bool) -> Self;
|
||||||
fn infinity(neg: bool) -> Self;
|
fn infinity(neg: bool) -> Self;
|
||||||
fn is_nan(self) -> bool;
|
fn is_nan(self) -> bool;
|
||||||
|
@ -46,7 +49,7 @@ pub trait SealedFloat: Copy + Debug + Display {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_fixed<F: Fixed>(self) -> F {
|
fn to_fixed<F: Fixed>(self) -> F {
|
||||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||||
debug_assert!(!overflow, "{} overflows", self);
|
debug_assert!(!overflow, "{} overflows", self.traits());
|
||||||
let _ = overflow;
|
let _ = overflow;
|
||||||
wrapped
|
wrapped
|
||||||
}
|
}
|
||||||
|
@ -83,12 +86,18 @@ macro_rules! sealed_float {
|
||||||
($Float:ident($Bits:ty, $IBits:ty, $prec:expr)) => {
|
($Float:ident($Bits:ty, $IBits:ty, $prec:expr)) => {
|
||||||
impl SealedFloat for $Float {
|
impl SealedFloat for $Float {
|
||||||
type Bits = $Bits;
|
type Bits = $Bits;
|
||||||
|
type Traits = $Float;
|
||||||
|
|
||||||
const PREC: u32 = $prec;
|
const PREC: u32 = $prec;
|
||||||
const SIGN_MASK: Self::Bits = Self::Bits::MSB;
|
const SIGN_MASK: Self::Bits = Self::Bits::MSB;
|
||||||
const EXP_MASK: Self::Bits = Self::SIGN_MASK - (1 << (Self::PREC - 1));
|
const EXP_MASK: Self::Bits = Self::SIGN_MASK - (1 << (Self::PREC - 1));
|
||||||
const MANT_MASK: Self::Bits = (1 << (Self::PREC - 1)) - 1;
|
const MANT_MASK: Self::Bits = (1 << (Self::PREC - 1)) - 1;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn traits(self) -> Self::Traits {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero(neg: bool) -> $Float {
|
fn zero(neg: bool) -> $Float {
|
||||||
Self::from_bits(if neg { Self::SIGN_MASK } else { 0 })
|
Self::from_bits(if neg { Self::SIGN_MASK } else { 0 })
|
||||||
|
|
|
@ -24,21 +24,24 @@ use core::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait SealedInt: Copy + Ord + Debug + Display {
|
pub trait SealedInt: Copy {
|
||||||
type NBits: Unsigned;
|
type NBits: Unsigned;
|
||||||
type IsSigned: Bit;
|
type IsSigned: Bit;
|
||||||
type Unsigned: SealedInt;
|
type Unsigned: SealedInt;
|
||||||
type ReprFixed: Fixed;
|
type ReprFixed: Fixed;
|
||||||
|
type Traits: Copy + Ord + Debug + Display;
|
||||||
|
|
||||||
const NBITS: u32 = Self::NBits::U32;
|
const NBITS: u32 = Self::NBits::U32;
|
||||||
const IS_SIGNED: bool = Self::IsSigned::BOOL;
|
const IS_SIGNED: bool = Self::IsSigned::BOOL;
|
||||||
const MSB: Self;
|
const MSB: Self;
|
||||||
const ZERO: Self;
|
const ZERO: Self;
|
||||||
|
|
||||||
|
fn traits(self) -> Self::Traits;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_fixed<F: Fixed>(val: F) -> Self {
|
fn from_fixed<F: Fixed>(val: F) -> Self {
|
||||||
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
||||||
debug_assert!(!overflow, "{} overflows", val);
|
debug_assert!(!overflow, "{} overflows", val.traits());
|
||||||
let _ = overflow;
|
let _ = overflow;
|
||||||
wrapped
|
wrapped
|
||||||
}
|
}
|
||||||
|
@ -60,7 +63,7 @@ pub trait SealedInt: Copy + Ord + Debug + Display {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_fixed<F: Fixed>(self) -> F {
|
fn to_fixed<F: Fixed>(self) -> F {
|
||||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||||
debug_assert!(!overflow, "{} overflows", self);
|
debug_assert!(!overflow, "{} overflows", self.traits());
|
||||||
let _ = overflow;
|
let _ = overflow;
|
||||||
wrapped
|
wrapped
|
||||||
}
|
}
|
||||||
|
@ -109,10 +112,16 @@ macro_rules! sealed_int {
|
||||||
type IsSigned = $IsSigned;
|
type IsSigned = $IsSigned;
|
||||||
type Unsigned = $Unsigned;
|
type Unsigned = $Unsigned;
|
||||||
type ReprFixed = $ReprFixed<U0>;
|
type ReprFixed = $ReprFixed<U0>;
|
||||||
|
type Traits = $Int;
|
||||||
|
|
||||||
const MSB: $Int = 1 << (Self::NBITS - 1);
|
const MSB: $Int = 1 << (Self::NBITS - 1);
|
||||||
const ZERO: $Int = 0;
|
const ZERO: $Int = 0;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn traits(self) -> Self::Traits {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn min_value() -> $Int {
|
fn min_value() -> $Int {
|
||||||
$Int::min_value()
|
$Int::min_value()
|
||||||
|
|
|
@ -135,28 +135,28 @@ impl<F: Fixed> Copy for Wrapping<F> {}
|
||||||
impl<F: Fixed> Default for Wrapping<F> {
|
impl<F: Fixed> Default for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Wrapping<F> {
|
fn default() -> Wrapping<F> {
|
||||||
Wrapping(F::default())
|
Wrapping(F::Traits::default().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fixed> Hash for Wrapping<F> {
|
impl<F: Fixed> Hash for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
(self.0).hash(state);
|
self.0.traits().hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fixed> Debug for Wrapping<F> {
|
impl<F: Fixed> Debug for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
||||||
<F as Debug>::fmt(&self.0, f)
|
<F::Traits as Debug>::fmt(&self.0.traits(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fixed> Display for Wrapping<F> {
|
impl<F: Fixed> Display for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
||||||
<F as Display>::fmt(&self.0, f)
|
<F::Traits as Display>::fmt(&self.0.traits(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,35 +171,35 @@ impl<F: Fixed> Eq for Wrapping<F> {}
|
||||||
impl<F: Fixed> PartialEq<Wrapping<F>> for Wrapping<F> {
|
impl<F: Fixed> PartialEq<Wrapping<F>> for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &Wrapping<F>) -> bool {
|
fn eq(&self, other: &Wrapping<F>) -> bool {
|
||||||
(self.0).eq(&other.0)
|
self.0.traits().eq(&other.0.traits())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<F: Fixed> Ord for Wrapping<F> {
|
impl<F: Fixed> Ord for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &Wrapping<F>) -> Ordering {
|
fn cmp(&self, other: &Wrapping<F>) -> Ordering {
|
||||||
(self.0).cmp(&other.0)
|
self.0.traits().cmp(&other.0.traits())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<F: Fixed> PartialOrd<Wrapping<F>> for Wrapping<F> {
|
impl<F: Fixed> PartialOrd<Wrapping<F>> for Wrapping<F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Wrapping<F>) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Wrapping<F>) -> Option<Ordering> {
|
||||||
(self.0).partial_cmp(&other.0)
|
self.0.traits().partial_cmp(&other.0.traits())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lt(&self, other: &Wrapping<F>) -> bool {
|
fn lt(&self, other: &Wrapping<F>) -> bool {
|
||||||
(self.0).lt(&other.0)
|
self.0.traits().lt(&other.0.traits())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn le(&self, other: &Wrapping<F>) -> bool {
|
fn le(&self, other: &Wrapping<F>) -> bool {
|
||||||
(self.0).le(&other.0)
|
self.0.traits().le(&other.0.traits())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gt(&self, other: &Wrapping<F>) -> bool {
|
fn gt(&self, other: &Wrapping<F>) -> bool {
|
||||||
(self.0).gt(&other.0)
|
self.0.traits().gt(&other.0.traits())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ge(&self, other: &Wrapping<F>) -> bool {
|
fn ge(&self, other: &Wrapping<F>) -> bool {
|
||||||
(self.0).ge(&other.0)
|
self.0.traits().ge(&other.0.traits())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue