diff --git a/prdoc/pr_6411.prdoc b/prdoc/pr_6411.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..3d8c2219e90ed0668b388f1c0fbf6eb9a6075d5b --- /dev/null +++ b/prdoc/pr_6411.prdoc @@ -0,0 +1,10 @@ +title: "Support more types in TypeWithDefault" + +doc: + - audience: Runtime Dev + description: | + This PR supports more integer types to be used with `TypeWithDefault` and makes `TypeWithDefault<u8/u16/u32, ..>: BaseArithmetic` satisfied + +crates: + - name: sp-runtime + bump: patch diff --git a/substrate/primitives/runtime/src/type_with_default.rs b/substrate/primitives/runtime/src/type_with_default.rs index 1465393640dc103347f8687d3272402570a1903d..5790e3ab6bf68a2380943f66d98ae48793777508 100644 --- a/substrate/primitives/runtime/src/type_with_default.rs +++ b/substrate/primitives/runtime/src/type_with_default.rs @@ -91,24 +91,6 @@ impl<T, D: Get<T>> Default for TypeWithDefault<T, D> { } } -impl<T: From<u16>, D: Get<T>> From<u16> for TypeWithDefault<T, D> { - fn from(value: u16) -> Self { - Self::new(value.into()) - } -} - -impl<T: From<u32>, D: Get<T>> From<u32> for TypeWithDefault<T, D> { - fn from(value: u32) -> Self { - Self::new(value.into()) - } -} - -impl<T: From<u64>, D: Get<T>> From<u64> for TypeWithDefault<T, D> { - fn from(value: u64) -> Self { - Self::new(value.into()) - } -} - impl<T: CheckedNeg, D: Get<T>> CheckedNeg for TypeWithDefault<T, D> { fn checked_neg(&self) -> Option<Self> { self.0.checked_neg().map(Self::new) @@ -205,24 +187,45 @@ impl<T: AddAssign, D: Get<T>> AddAssign for TypeWithDefault<T, D> { } } -impl<T: From<u8>, D: Get<T>> From<u8> for TypeWithDefault<T, D> { - fn from(value: u8) -> Self { - Self::new(value.into()) - } -} - impl<T: Display, D: Get<T>> Display for TypeWithDefault<T, D> { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "{}", self.0) } } -impl<T: TryFrom<u128>, D: Get<T>> TryFrom<u128> for TypeWithDefault<T, D> { - type Error = <T as TryFrom<u128>>::Error; - fn try_from(n: u128) -> Result<TypeWithDefault<T, D>, Self::Error> { - T::try_from(n).map(Self::new) - } -} +macro_rules! impl_from { + ($for_type:ty $(, $from_type:ty)*) => { + $( + impl<D: Get<$for_type>> From<$from_type> for TypeWithDefault<$for_type, D> { + fn from(value: $from_type) -> Self { + Self::new(value.into()) + } + } + )* + } +} +impl_from!(u128, u128, u64, u32, u16, u8); +impl_from!(u64, u64, u32, u16, u8); +impl_from!(u32, u32, u16, u8); +impl_from!(u16, u16, u8); +impl_from!(u8, u8); + +macro_rules! impl_try_from { + ($for_type:ty $(, $try_from_type:ty)*) => { + $( + impl<D: Get<$for_type>> TryFrom<$try_from_type> for TypeWithDefault<$for_type, D> { + type Error = <$for_type as TryFrom<$try_from_type>>::Error; + fn try_from(n: $try_from_type) -> Result<TypeWithDefault<$for_type, D>, Self::Error> { + <$for_type as TryFrom<$try_from_type>>::try_from(n).map(Self::new) + } + } + )* + } +} +impl_try_from!(u8, u16, u32, u64, u128); +impl_try_from!(u16, u32, u64, u128); +impl_try_from!(u32, u64, u128); +impl_try_from!(u64, u128); impl<T: TryFrom<usize>, D: Get<T>> TryFrom<usize> for TypeWithDefault<T, D> { type Error = <T as TryFrom<usize>>::Error; @@ -504,3 +507,63 @@ impl<T: HasCompact, D: Get<T>> CompactAs for TypeWithDefault<T, D> { Ok(Self::new(val)) } } + +#[cfg(test)] +mod tests { + use super::TypeWithDefault; + use sp_arithmetic::traits::{AtLeast16Bit, AtLeast32Bit, AtLeast8Bit}; + use sp_core::Get; + + #[test] + #[allow(dead_code)] + fn test_type_with_default_impl_base_arithmetic() { + trait WrapAtLeast8Bit: AtLeast8Bit {} + trait WrapAtLeast16Bit: AtLeast16Bit {} + trait WrapAtLeast32Bit: AtLeast32Bit {} + + struct Getu8; + impl Get<u8> for Getu8 { + fn get() -> u8 { + 0 + } + } + type U8WithDefault = TypeWithDefault<u8, Getu8>; + impl WrapAtLeast8Bit for U8WithDefault {} + + struct Getu16; + impl Get<u16> for Getu16 { + fn get() -> u16 { + 0 + } + } + type U16WithDefault = TypeWithDefault<u16, Getu16>; + impl WrapAtLeast16Bit for U16WithDefault {} + + struct Getu32; + impl Get<u32> for Getu32 { + fn get() -> u32 { + 0 + } + } + type U32WithDefault = TypeWithDefault<u32, Getu32>; + impl WrapAtLeast32Bit for U32WithDefault {} + + struct Getu64; + impl Get<u64> for Getu64 { + fn get() -> u64 { + 0 + } + } + type U64WithDefault = TypeWithDefault<u64, Getu64>; + impl WrapAtLeast32Bit for U64WithDefault {} + + struct Getu128; + impl Get<u128> for Getu128 { + fn get() -> u128 { + 0 + } + } + type U128WithDefault = TypeWithDefault<u128, Getu128>; + impl WrapAtLeast32Bit for U128WithDefault {} + } +}