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();
|
||||
}
|
||||
// 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::Greater => true,
|
||||
Ordering::Equal => {
|
||||
|
|
|
@ -49,7 +49,7 @@ use half::f16;
|
|||
/// [`u64`]: https://doc.rust-lang.org/nightly/std/primitive.u64.html
|
||||
/// [`u8`]: https://doc.rust-lang.org/nightly/std/primitive.u8.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,
|
||||
/// 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
|
||||
/// [`f64`]: https://doc.rust-lang.org/nightly/std/primitive.f64.html
|
||||
/// [`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.
|
||||
///
|
||||
|
@ -81,7 +81,7 @@ pub trait Float: SealedFloat {}
|
|||
/// [`FixedU32`]: ../struct.FixedU32.html
|
||||
/// [`FixedU64`]: ../struct.FixedU64.html
|
||||
/// [`FixedU8`]: ../struct.FixedU8.html
|
||||
pub trait Fixed: SealedFixed {}
|
||||
pub trait Fixed: Copy + SealedFixed {}
|
||||
|
||||
impl Int for i8 {}
|
||||
impl Int for i16 {}
|
||||
|
|
|
@ -31,9 +31,10 @@ pub enum Widest {
|
|||
Negative(i128),
|
||||
}
|
||||
|
||||
pub trait SealedFixed: Copy + Debug + Default + Display + Eq + Hash + Ord {
|
||||
pub trait SealedFixed: Copy {
|
||||
type FracNBits: Unsigned;
|
||||
type SBits: SealedInt;
|
||||
type Traits: Copy + Debug + Default + Into<Self> + Display + Eq + Hash + Ord;
|
||||
|
||||
const FRAC_NBITS: u32 = Self::FracNBits::U32;
|
||||
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
|
||||
const INT_LSB: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
|
||||
|
||||
fn traits(self) -> Self::Traits;
|
||||
|
||||
#[inline]
|
||||
fn from_fixed<F: Fixed>(val: F) -> Self {
|
||||
let (wrapped, overflow) = SealedFixed::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
debug_assert!(!overflow, "{} overflows", val.traits());
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
|
@ -98,6 +101,12 @@ macro_rules! sealed_fixed {
|
|||
{
|
||||
type FracNBits = Frac;
|
||||
type SBits = $Bits;
|
||||
type Traits = $Fixed<Frac>;
|
||||
|
||||
#[inline]
|
||||
fn traits(self) -> Self::Traits {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn saturating_from_fixed<F: Fixed>(val: F) -> Self {
|
||||
|
@ -202,7 +211,7 @@ macro_rules! sealed_fixed {
|
|||
#[inline]
|
||||
fn overflowing_from_float<F: SealedFloat>(val: F) -> (Self, bool) {
|
||||
if !val.is_finite() {
|
||||
panic!("{} is not finite", val);
|
||||
panic!("{} is not finite", val.traits());
|
||||
}
|
||||
let (value, _, mut overflow) =
|
||||
val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
|
|
|
@ -21,8 +21,9 @@ use core::{
|
|||
#[cfg(feature = "f16")]
|
||||
use half::f16;
|
||||
|
||||
pub trait SealedFloat: Copy + Debug + Display {
|
||||
pub trait SealedFloat: Copy {
|
||||
type Bits: SealedInt;
|
||||
type Traits: Copy + Debug + Display;
|
||||
|
||||
const PREC: u32;
|
||||
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 MANT_MASK: Self::Bits;
|
||||
|
||||
fn traits(self) -> Self::Traits;
|
||||
|
||||
fn zero(neg: bool) -> Self;
|
||||
fn infinity(neg: bool) -> Self;
|
||||
fn is_nan(self) -> bool;
|
||||
|
@ -46,7 +49,7 @@ pub trait SealedFloat: Copy + Debug + Display {
|
|||
#[inline]
|
||||
fn to_fixed<F: Fixed>(self) -> F {
|
||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
debug_assert!(!overflow, "{} overflows", self.traits());
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
|
@ -83,12 +86,18 @@ macro_rules! sealed_float {
|
|||
($Float:ident($Bits:ty, $IBits:ty, $prec:expr)) => {
|
||||
impl SealedFloat for $Float {
|
||||
type Bits = $Bits;
|
||||
type Traits = $Float;
|
||||
|
||||
const PREC: u32 = $prec;
|
||||
const SIGN_MASK: Self::Bits = Self::Bits::MSB;
|
||||
const EXP_MASK: Self::Bits = Self::SIGN_MASK - (1 << (Self::PREC - 1));
|
||||
const MANT_MASK: Self::Bits = (1 << (Self::PREC - 1)) - 1;
|
||||
|
||||
#[inline]
|
||||
fn traits(self) -> Self::Traits {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn zero(neg: bool) -> $Float {
|
||||
Self::from_bits(if neg { Self::SIGN_MASK } else { 0 })
|
||||
|
|
|
@ -24,21 +24,24 @@ use core::{
|
|||
fmt::{Debug, Display},
|
||||
};
|
||||
|
||||
pub trait SealedInt: Copy + Ord + Debug + Display {
|
||||
pub trait SealedInt: Copy {
|
||||
type NBits: Unsigned;
|
||||
type IsSigned: Bit;
|
||||
type Unsigned: SealedInt;
|
||||
type ReprFixed: Fixed;
|
||||
type Traits: Copy + Ord + Debug + Display;
|
||||
|
||||
const NBITS: u32 = Self::NBits::U32;
|
||||
const IS_SIGNED: bool = Self::IsSigned::BOOL;
|
||||
const MSB: Self;
|
||||
const ZERO: Self;
|
||||
|
||||
fn traits(self) -> Self::Traits;
|
||||
|
||||
#[inline]
|
||||
fn from_fixed<F: Fixed>(val: F) -> Self {
|
||||
let (wrapped, overflow) = Self::overflowing_from_fixed(val);
|
||||
debug_assert!(!overflow, "{} overflows", val);
|
||||
debug_assert!(!overflow, "{} overflows", val.traits());
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
|
@ -60,7 +63,7 @@ pub trait SealedInt: Copy + Ord + Debug + Display {
|
|||
#[inline]
|
||||
fn to_fixed<F: Fixed>(self) -> F {
|
||||
let (wrapped, overflow) = Self::overflowing_to_fixed(self);
|
||||
debug_assert!(!overflow, "{} overflows", self);
|
||||
debug_assert!(!overflow, "{} overflows", self.traits());
|
||||
let _ = overflow;
|
||||
wrapped
|
||||
}
|
||||
|
@ -109,10 +112,16 @@ macro_rules! sealed_int {
|
|||
type IsSigned = $IsSigned;
|
||||
type Unsigned = $Unsigned;
|
||||
type ReprFixed = $ReprFixed<U0>;
|
||||
type Traits = $Int;
|
||||
|
||||
const MSB: $Int = 1 << (Self::NBITS - 1);
|
||||
const ZERO: $Int = 0;
|
||||
|
||||
#[inline]
|
||||
fn traits(self) -> Self::Traits {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_value() -> $Int {
|
||||
$Int::min_value()
|
||||
|
|
|
@ -135,28 +135,28 @@ impl<F: Fixed> Copy for Wrapping<F> {}
|
|||
impl<F: Fixed> Default for Wrapping<F> {
|
||||
#[inline]
|
||||
fn default() -> Wrapping<F> {
|
||||
Wrapping(F::default())
|
||||
Wrapping(F::Traits::default().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Fixed> Hash for Wrapping<F> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(self.0).hash(state);
|
||||
self.0.traits().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Fixed> Debug for Wrapping<F> {
|
||||
#[inline]
|
||||
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> {
|
||||
#[inline]
|
||||
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> {
|
||||
#[inline]
|
||||
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> {
|
||||
#[inline]
|
||||
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> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Wrapping<F>) -> Option<Ordering> {
|
||||
(self.0).partial_cmp(&other.0)
|
||||
self.0.traits().partial_cmp(&other.0.traits())
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &Wrapping<F>) -> bool {
|
||||
(self.0).lt(&other.0)
|
||||
self.0.traits().lt(&other.0.traits())
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &Wrapping<F>) -> bool {
|
||||
(self.0).le(&other.0)
|
||||
self.0.traits().le(&other.0.traits())
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &Wrapping<F>) -> bool {
|
||||
(self.0).gt(&other.0)
|
||||
self.0.traits().gt(&other.0.traits())
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &Wrapping<F>) -> bool {
|
||||
(self.0).ge(&other.0)
|
||||
self.0.traits().ge(&other.0.traits())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue