Skip to content

Commit 0291e78

Browse files
committed
fmt::DisplayInt abstraction obsolete with better macro
1 parent 4ad8606 commit 0291e78

File tree

1 file changed

+72
-94
lines changed

1 file changed

+72
-94
lines changed

library/core/src/fmt/num.rs

Lines changed: 72 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,8 @@
33
use crate::fmt::NumBuffer;
44
use crate::mem::MaybeUninit;
55
use crate::num::fmt as numfmt;
6-
use crate::ops::{Div, Rem, Sub};
76
use crate::{fmt, ptr, slice, str};
87

9-
#[doc(hidden)]
10-
trait DisplayInt:
11-
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
12-
{
13-
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
14-
fn to_u32(&self) -> u32;
15-
fn to_u64(&self) -> u64;
16-
fn to_u128(&self) -> u128;
17-
}
18-
19-
macro_rules! impl_int {
20-
($($t:ident)*) => (
21-
$(impl DisplayInt for $t {
22-
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
23-
fn to_u32(&self) -> u32 { *self as u32 }
24-
fn to_u64(&self) -> u64 { *self as u64 }
25-
fn to_u128(&self) -> u128 { *self as u128 }
26-
})*
27-
)
28-
}
29-
30-
impl_int! {
31-
i8 i16 i32 i64 i128 isize
32-
u8 u16 u32 u64 u128 usize
33-
}
34-
358
/// Formatting of integers with a non-decimal radix.
369
macro_rules! radix_integer {
3710
(fmt::$Trait:ident for $Signed:ident and $Unsigned:ident, $prefix:literal, $dig_tab:literal) => {
@@ -146,49 +119,58 @@ unsafe fn slice_buffer_to_str(buf: &[MaybeUninit<u8>], offset: usize) -> &str {
146119
}
147120

148121
macro_rules! impl_Display {
149-
($($signed:ident, $unsigned:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => {
122+
($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
150123

151124
$(
125+
const _: () = {
126+
assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
127+
assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
128+
};
129+
152130
#[stable(feature = "rust1", since = "1.0.0")]
153-
impl fmt::Display for $unsigned {
131+
impl fmt::Display for $Unsigned {
154132
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155133
#[cfg(not(feature = "optimize_for_size"))]
156134
{
157-
const MAX_DEC_N: usize = $unsigned::MAX.ilog10() as usize + 1;
158-
// Buffer decimals for $unsigned with right alignment.
135+
const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
136+
// Buffer decimals for self with right alignment.
159137
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
160138

161139
// SAFETY: `buf` is always big enough to contain all the digits.
162140
unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) }
163141
}
164142
#[cfg(feature = "optimize_for_size")]
165143
{
166-
$gen_name(self.$conv_fn(), true, f)
144+
// Lossless conversion (with as) is asserted at the top of
145+
// this macro.
146+
$fmt_fn(self as $T, true, f)
167147
}
168148
}
169149
}
170150

171151
#[stable(feature = "rust1", since = "1.0.0")]
172-
impl fmt::Display for $signed {
152+
impl fmt::Display for $Signed {
173153
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174154
#[cfg(not(feature = "optimize_for_size"))]
175155
{
176-
const MAX_DEC_N: usize = $unsigned::MAX.ilog10() as usize + 1;
177-
// Buffer decimals for $unsigned with right alignment.
156+
const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
157+
// Buffer decimals for self with right alignment.
178158
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
179159

180160
// SAFETY: `buf` is always big enough to contain all the digits.
181161
unsafe { f.pad_integral(*self >= 0, "", self.unsigned_abs()._fmt(&mut buf)) }
182162
}
183163
#[cfg(feature = "optimize_for_size")]
184164
{
185-
return $gen_name(self.unsigned_abs().$conv_fn(), *self >= 0, f);
165+
// Lossless conversion (with as) is asserted at the top of
166+
// this macro.
167+
return $fmt_fn(self.unsigned_abs() as $T, *self >= 0, f);
186168
}
187169
}
188170
}
189171

190172
#[cfg(not(feature = "optimize_for_size"))]
191-
impl $unsigned {
173+
impl $Unsigned {
192174
#[doc(hidden)]
193175
#[unstable(
194176
feature = "fmt_internals",
@@ -209,7 +191,7 @@ macro_rules! impl_Display {
209191
let mut remain = self;
210192

211193
// Format per four digits from the lookup table.
212-
// Four digits need a 16-bit $unsigned or wider.
194+
// Four digits need a 16-bit $Unsigned or wider.
213195
while size_of::<Self>() > 1 && remain > 999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)") {
214196
// SAFETY: All of the decimals fit in buf due to MAX_DEC_N
215197
// and the while condition ensures at least 4 more decimals.
@@ -268,7 +250,7 @@ macro_rules! impl_Display {
268250
}
269251
}
270252

271-
impl $signed {
253+
impl $Signed {
272254
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
273255
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
274256
///
@@ -278,15 +260,15 @@ macro_rules! impl_Display {
278260
/// #![feature(int_format_into)]
279261
/// use core::fmt::NumBuffer;
280262
///
281-
#[doc = concat!("let n = 0", stringify!($signed), ";")]
263+
#[doc = concat!("let n = 0", stringify!($Signed), ";")]
282264
/// let mut buf = NumBuffer::new();
283265
/// assert_eq!(n.format_into(&mut buf), "0");
284266
///
285-
#[doc = concat!("let n1 = 32", stringify!($signed), ";")]
267+
#[doc = concat!("let n1 = 32", stringify!($Signed), ";")]
286268
/// assert_eq!(n1.format_into(&mut buf), "32");
287269
///
288-
#[doc = concat!("let n2 = ", stringify!($signed::MAX), ";")]
289-
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($signed::MAX), ".to_string());")]
270+
#[doc = concat!("let n2 = ", stringify!($Signed::MAX), ";")]
271+
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Signed::MAX), ".to_string());")]
290272
/// ```
291273
#[unstable(feature = "int_format_into", issue = "138215")]
292274
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
@@ -299,7 +281,9 @@ macro_rules! impl_Display {
299281
}
300282
#[cfg(feature = "optimize_for_size")]
301283
{
302-
offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.unsigned_abs().$conv_fn(), &mut buf.buf);
284+
// Lossless conversion (with as) is asserted at the top of
285+
// this macro.
286+
offset = ${concat(_inner_slow_integer_to_str, $fmt_fn)}(self.unsigned_abs() as $T, &mut buf.buf);
303287
}
304288
// Only difference between signed and unsigned are these 4 lines.
305289
if self < 0 {
@@ -311,7 +295,7 @@ macro_rules! impl_Display {
311295
}
312296
}
313297

314-
impl $unsigned {
298+
impl $Unsigned {
315299
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
316300
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
317301
///
@@ -321,15 +305,15 @@ macro_rules! impl_Display {
321305
/// #![feature(int_format_into)]
322306
/// use core::fmt::NumBuffer;
323307
///
324-
#[doc = concat!("let n = 0", stringify!($unsigned), ";")]
308+
#[doc = concat!("let n = 0", stringify!($Unsigned), ";")]
325309
/// let mut buf = NumBuffer::new();
326310
/// assert_eq!(n.format_into(&mut buf), "0");
327311
///
328-
#[doc = concat!("let n1 = 32", stringify!($unsigned), ";")]
312+
#[doc = concat!("let n1 = 32", stringify!($Unsigned), ";")]
329313
/// assert_eq!(n1.format_into(&mut buf), "32");
330314
///
331-
#[doc = concat!("let n2 = ", stringify!($unsigned::MAX), ";")]
332-
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($unsigned::MAX), ".to_string());")]
315+
#[doc = concat!("let n2 = ", stringify!($Unsigned::MAX), ";")]
316+
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Unsigned::MAX), ".to_string());")]
333317
/// ```
334318
#[unstable(feature = "int_format_into", issue = "138215")]
335319
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
@@ -342,7 +326,9 @@ macro_rules! impl_Display {
342326
}
343327
#[cfg(feature = "optimize_for_size")]
344328
{
345-
offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.$conv_fn(), &mut buf.buf);
329+
// Lossless conversion (with as) is asserted at the top of
330+
// this macro.
331+
offset = ${concat(_inner_slow_integer_to_str, $fmt_fn)}(*self as $T, &mut buf.buf);
346332
}
347333
// SAFETY: Starting from `offset`, all elements of the slice have been set.
348334
unsafe { slice_buffer_to_str(&buf.buf, offset) }
@@ -353,7 +339,7 @@ macro_rules! impl_Display {
353339
)*
354340

355341
#[cfg(feature = "optimize_for_size")]
356-
fn ${concat(_inner_slow_integer_to_str, $gen_name)}(mut n: $u, buf: &mut [MaybeUninit::<u8>]) -> usize {
342+
fn ${concat(_inner_slow_integer_to_str, $fmt_fn)}(mut n: $T, buf: &mut [MaybeUninit::<u8>]) -> usize {
357343
let mut curr = buf.len();
358344

359345
// SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning
@@ -374,11 +360,11 @@ macro_rules! impl_Display {
374360
}
375361

376362
#[cfg(feature = "optimize_for_size")]
377-
fn $gen_name(n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378-
const MAX_DEC_N: usize = $u::MAX.ilog(10) as usize + 1;
363+
fn $fmt_fn(n: $T, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364+
const MAX_DEC_N: usize = $T::MAX.ilog(10) as usize + 1;
379365
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
380366

381-
let offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(n, &mut buf);
367+
let offset = ${concat(_inner_slow_integer_to_str, $fmt_fn)}(n, &mut buf);
382368
// SAFETY: Starting from `offset`, all elements of the slice have been set.
383369
let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
384370
f.pad_integral(is_nonnegative, "", buf_slice)
@@ -387,9 +373,9 @@ macro_rules! impl_Display {
387373
}
388374

389375
macro_rules! impl_Exp {
390-
($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
391-
fn $name(
392-
mut n: $u,
376+
($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
377+
fn $fmt_fn(
378+
mut n: $T,
393379
is_nonnegative: bool,
394380
upper: bool,
395381
f: &mut fmt::Formatter<'_>
@@ -523,32 +509,41 @@ macro_rules! impl_Exp {
523509

524510
$(
525511
#[stable(feature = "integer_exp_format", since = "1.42.0")]
526-
impl fmt::LowerExp for $t {
527-
#[allow(unused_comparisons)]
512+
impl fmt::LowerExp for $Signed {
528513
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529514
let is_nonnegative = *self >= 0;
530515
let n = if is_nonnegative {
531-
self.$conv_fn()
516+
*self as $T
532517
} else {
533-
// convert the negative num to positive by summing 1 to its 2s complement
534-
(!self.$conv_fn()).wrapping_add(1)
518+
self.unsigned_abs() as $T
535519
};
536-
$name(n, is_nonnegative, false, f)
520+
$fmt_fn(n, is_nonnegative, false, f)
521+
}
522+
}
523+
#[stable(feature = "integer_exp_format", since = "1.42.0")]
524+
impl fmt::LowerExp for $Unsigned {
525+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526+
$fmt_fn(*self as $T, true, false, f)
537527
}
538528
})*
529+
539530
$(
540531
#[stable(feature = "integer_exp_format", since = "1.42.0")]
541-
impl fmt::UpperExp for $t {
542-
#[allow(unused_comparisons)]
532+
impl fmt::UpperExp for $Signed {
543533
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
544534
let is_nonnegative = *self >= 0;
545535
let n = if is_nonnegative {
546-
self.$conv_fn()
536+
*self as $T
547537
} else {
548-
// convert the negative num to positive by summing 1 to its 2s complement
549-
(!self.$conv_fn()).wrapping_add(1)
538+
self.unsigned_abs() as $T
550539
};
551-
$name(n, is_nonnegative, true, f)
540+
$fmt_fn(n, is_nonnegative, true, f)
541+
}
542+
}
543+
#[stable(feature = "integer_exp_format", since = "1.42.0")]
544+
impl fmt::UpperExp for $Unsigned {
545+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546+
$fmt_fn(*self as $T, true, true, f)
552547
}
553548
})*
554549
};
@@ -564,37 +559,20 @@ impl_Debug! {
564559
#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
565560
mod imp {
566561
use super::*;
567-
impl_Display!(
568-
i8, u8,
569-
i16, u16,
570-
i32, u32,
571-
i64, u64,
572-
isize, usize,
573-
; as u64 via to_u64 named fmt_u64
574-
);
575-
impl_Exp!(
576-
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
577-
as u64 via to_u64 named exp_u64
578-
);
562+
impl_Display!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into fmt_u64);
563+
impl_Exp!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into exp_u64);
579564
}
580565

581566
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
582567
mod imp {
583568
use super::*;
584-
impl_Display!(
585-
i8, u8,
586-
i16, u16,
587-
i32, u32,
588-
isize, usize,
589-
; as u32 via to_u32 named fmt_u32);
590-
impl_Display!(
591-
i64, u64,
592-
; as u64 via to_u64 named fmt_u64);
593-
594-
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
595-
impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
569+
impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into fmt_u32);
570+
impl_Display!(i64, u64; as u64 into fmt_u64);
571+
572+
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into exp_u32);
573+
impl_Exp!(i64, u64; as u64 into exp_u64);
596574
}
597-
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
575+
impl_Exp!(i128, u128; as u128 into exp_u128);
598576

599577
const U128_MAX_DEC_N: usize = u128::MAX.ilog10() as usize + 1;
600578

0 commit comments

Comments
 (0)