Skip to content

Commit 8fec6a9

Browse files
committed
Experiment: Use u16 for fmt width and precision.
1 parent 021fb9c commit 8fec6a9

File tree

10 files changed

+68
-45
lines changed

10 files changed

+68
-45
lines changed

compiler/rustc_ast/src/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ pub enum FormatAlignment {
266266
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
267267
pub enum FormatCount {
268268
/// `{:5}` or `{:.5}`
269-
Literal(usize),
269+
Literal(u16),
270270
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
271271
Argument(FormatArgPosition),
272272
}

compiler/rustc_ast_lowering/src/expr.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
21512151
self.expr(sp, hir::ExprKind::Lit(lit))
21522152
}
21532153

2154+
pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
2155+
let lit = self.arena.alloc(hir::Lit {
2156+
span: sp,
2157+
node: ast::LitKind::Int(
2158+
u128::from(value).into(),
2159+
ast::LitIntType::Unsigned(ast::UintTy::U16),
2160+
),
2161+
});
2162+
self.expr(sp, hir::ExprKind::Lit(lit))
2163+
}
2164+
21542165
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
21552166
let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
21562167
self.expr(sp, hir::ExprKind::Lit(lit))

compiler/rustc_ast_lowering/src/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ fn make_count<'hir>(
292292
hir::LangItem::FormatCount,
293293
sym::Is,
294294
));
295-
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]);
295+
let value = ctx.arena.alloc_from_iter([ctx.expr_u16(sp, *n)]);
296296
ctx.expr_call_mut(sp, count_is, value)
297297
}
298298
Some(FormatCount::Argument(arg)) => {

compiler/rustc_parse_format/src/lib.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub enum DebugHex {
190190
#[derive(Copy, Clone, Debug, PartialEq)]
191191
pub enum Count<'a> {
192192
/// The count is specified explicitly.
193-
CountIs(usize),
193+
CountIs(u16),
194194
/// The count is specified by the argument with the given name.
195195
CountIsName(&'a str, InnerSpan),
196196
/// The count is specified by the argument at the given index.
@@ -565,7 +565,7 @@ impl<'a> Parser<'a> {
565565
/// consuming a macro argument, `None` if it's the case.
566566
fn position(&mut self) -> Option<Position<'a>> {
567567
if let Some(i) = self.integer() {
568-
Some(ArgumentIs(i))
568+
Some(ArgumentIs(i.into()))
569569
} else {
570570
match self.cur.peek() {
571571
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
@@ -771,7 +771,7 @@ impl<'a> Parser<'a> {
771771
/// width.
772772
fn count(&mut self, start: usize) -> Count<'a> {
773773
if let Some(i) = self.integer() {
774-
if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
774+
if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) }
775775
} else {
776776
let tmp = self.cur.clone();
777777
let word = self.word();
@@ -822,15 +822,15 @@ impl<'a> Parser<'a> {
822822
word
823823
}
824824

825-
fn integer(&mut self) -> Option<usize> {
826-
let mut cur: usize = 0;
825+
fn integer(&mut self) -> Option<u16> {
826+
let mut cur: u16 = 0;
827827
let mut found = false;
828828
let mut overflow = false;
829829
let start = self.current_pos();
830830
while let Some(&(_, c)) = self.cur.peek() {
831831
if let Some(i) = c.to_digit(10) {
832832
let (tmp, mul_overflow) = cur.overflowing_mul(10);
833-
let (tmp, add_overflow) = tmp.overflowing_add(i as usize);
833+
let (tmp, add_overflow) = tmp.overflowing_add(i as u16);
834834
if mul_overflow || add_overflow {
835835
overflow = true;
836836
}
@@ -847,11 +847,11 @@ impl<'a> Parser<'a> {
847847
let overflowed_int = &self.input[start..end];
848848
self.err(
849849
format!(
850-
"integer `{}` does not fit into the type `usize` whose range is `0..={}`",
850+
"integer `{}` does not fit into the type `u16` whose range is `0..={}`",
851851
overflowed_int,
852-
usize::MAX
852+
u16::MAX
853853
),
854-
"integer out of range for `usize`",
854+
"integer out of range for `u16`",
855855
self.span(start, end),
856856
);
857857
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ symbols! {
10001000
from_residual,
10011001
from_size_align_unchecked,
10021002
from_str_method,
1003+
from_u16,
10031004
from_usize,
10041005
from_yeet,
10051006
fs_create_dir,

library/core/src/fmt/float.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn float_to_decimal_common_exact<T>(
2929
fmt: &mut Formatter<'_>,
3030
num: &T,
3131
sign: flt2dec::Sign,
32-
precision: usize,
32+
precision: u16,
3333
) -> Result
3434
where
3535
T: flt2dec::DecodableFloat,
@@ -40,7 +40,7 @@ where
4040
flt2dec::strategy::grisu::format_exact,
4141
*num,
4242
sign,
43-
precision,
43+
precision.into(),
4444
&mut buf,
4545
&mut parts,
4646
);
@@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest<T>(
5555
fmt: &mut Formatter<'_>,
5656
num: &T,
5757
sign: flt2dec::Sign,
58-
precision: usize,
58+
precision: u16,
5959
) -> Result
6060
where
6161
T: flt2dec::DecodableFloat,
@@ -68,7 +68,7 @@ where
6868
flt2dec::strategy::grisu::format_shortest,
6969
*num,
7070
sign,
71-
precision,
71+
precision.into(),
7272
&mut buf,
7373
&mut parts,
7474
);
@@ -101,7 +101,7 @@ fn float_to_exponential_common_exact<T>(
101101
fmt: &mut Formatter<'_>,
102102
num: &T,
103103
sign: flt2dec::Sign,
104-
precision: usize,
104+
precision: u16,
105105
upper: bool,
106106
) -> Result
107107
where
@@ -113,7 +113,7 @@ where
113113
flt2dec::strategy::grisu::format_exact,
114114
*num,
115115
sign,
116-
precision,
116+
precision.into(),
117117
upper,
118118
&mut buf,
119119
&mut parts,

library/core/src/fmt/mod.rs

+26-23
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ pub struct FormattingOptions {
294294
flags: u32,
295295
fill: char,
296296
align: Option<Alignment>,
297-
width: Option<usize>,
298-
precision: Option<usize>,
297+
width: Option<u16>,
298+
precision: Option<u16>,
299299
}
300300

301301
impl FormattingOptions {
@@ -389,7 +389,7 @@ impl FormattingOptions {
389389
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
390390
/// will be used to take up the required space.
391391
#[unstable(feature = "formatting_options", issue = "118117")]
392-
pub fn width(&mut self, width: Option<usize>) -> &mut Self {
392+
pub fn width(&mut self, width: Option<u16>) -> &mut Self {
393393
self.width = width;
394394
self
395395
}
@@ -403,7 +403,7 @@ impl FormattingOptions {
403403
/// - For floating-point types, this indicates how many digits after the
404404
/// decimal point should be printed.
405405
#[unstable(feature = "formatting_options", issue = "118117")]
406-
pub fn precision(&mut self, precision: Option<usize>) -> &mut Self {
406+
pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
407407
self.precision = precision;
408408
self
409409
}
@@ -455,12 +455,12 @@ impl FormattingOptions {
455455
}
456456
/// Returns the current width.
457457
#[unstable(feature = "formatting_options", issue = "118117")]
458-
pub const fn get_width(&self) -> Option<usize> {
458+
pub const fn get_width(&self) -> Option<u16> {
459459
self.width
460460
}
461461
/// Returns the current precision.
462462
#[unstable(feature = "formatting_options", issue = "118117")]
463-
pub const fn get_precision(&self) -> Option<usize> {
463+
pub const fn get_precision(&self) -> Option<u16> {
464464
self.precision
465465
}
466466
/// Returns the current precision.
@@ -1499,15 +1499,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
14991499
unsafe { value.fmt(fmt) }
15001500
}
15011501

1502-
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
1502+
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
15031503
match *cnt {
1504+
#[cfg(bootstrap)]
1505+
rt::Count::Is(n) => Some(n as u16),
1506+
#[cfg(not(bootstrap))]
15041507
rt::Count::Is(n) => Some(n),
15051508
rt::Count::Implied => None,
15061509
rt::Count::Param(i) => {
15071510
debug_assert!(i < args.len());
15081511
// SAFETY: cnt and args come from the same Arguments,
15091512
// which guarantees this index is always within bounds.
1510-
unsafe { args.get_unchecked(i).as_usize() }
1513+
unsafe { args.get_unchecked(i).as_u16() }
15111514
}
15121515
}
15131516
}
@@ -1516,11 +1519,11 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize>
15161519
#[must_use = "don't forget to write the post padding"]
15171520
pub(crate) struct PostPadding {
15181521
fill: char,
1519-
padding: usize,
1522+
padding: u16,
15201523
}
15211524

15221525
impl PostPadding {
1523-
fn new(fill: char, padding: usize) -> PostPadding {
1526+
fn new(fill: char, padding: u16) -> PostPadding {
15241527
PostPadding { fill, padding }
15251528
}
15261529

@@ -1634,7 +1637,7 @@ impl<'a> Formatter<'a> {
16341637
}
16351638
// Check if we're over the minimum width, if so then we can also
16361639
// just write the bytes.
1637-
Some(min) if width >= min => {
1640+
Some(min) if width >= usize::from(min) => {
16381641
write_prefix(self, sign, prefix)?;
16391642
self.buf.write_str(buf)
16401643
}
@@ -1645,7 +1648,7 @@ impl<'a> Formatter<'a> {
16451648
let old_align =
16461649
crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
16471650
write_prefix(self, sign, prefix)?;
1648-
let post_padding = self.padding(min - width, Alignment::Right)?;
1651+
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
16491652
self.buf.write_str(buf)?;
16501653
post_padding.write(self)?;
16511654
self.options.fill = old_fill;
@@ -1654,7 +1657,7 @@ impl<'a> Formatter<'a> {
16541657
}
16551658
// Otherwise, the sign and prefix goes after the padding
16561659
Some(min) => {
1657-
let post_padding = self.padding(min - width, Alignment::Right)?;
1660+
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
16581661
write_prefix(self, sign, prefix)?;
16591662
self.buf.write_str(buf)?;
16601663
post_padding.write(self)
@@ -1703,7 +1706,7 @@ impl<'a> Formatter<'a> {
17031706
// If our string is longer that the precision, then we must have
17041707
// truncation. However other flags like `fill`, `width` and `align`
17051708
// must act as always.
1706-
if let Some((i, _)) = s.char_indices().nth(max) {
1709+
if let Some((i, _)) = s.char_indices().nth(usize::from(max)) {
17071710
// LLVM here can't prove that `..i` won't panic `&s[..i]`, but
17081711
// we know that it can't panic. Use `get` + `unwrap_or` to avoid
17091712
// `unsafe` and otherwise don't emit any panic-related code
@@ -1724,14 +1727,14 @@ impl<'a> Formatter<'a> {
17241727
let chars_count = s.chars().count();
17251728
// If we're under the maximum width, check if we're over the minimum
17261729
// width, if so it's as easy as just emitting the string.
1727-
if chars_count >= width {
1730+
if chars_count >= usize::from(width) {
17281731
self.buf.write_str(s)
17291732
}
17301733
// If we're under both the maximum and the minimum width, then fill
17311734
// up the minimum width with the specified string + some alignment.
17321735
else {
17331736
let align = Alignment::Left;
1734-
let post_padding = self.padding(width - chars_count, align)?;
1737+
let post_padding = self.padding(width - chars_count as u16, align)?;
17351738
self.buf.write_str(s)?;
17361739
post_padding.write(self)
17371740
}
@@ -1745,7 +1748,7 @@ impl<'a> Formatter<'a> {
17451748
/// thing that is being padded.
17461749
pub(crate) fn padding(
17471750
&mut self,
1748-
padding: usize,
1751+
padding: u16,
17491752
default: Alignment,
17501753
) -> result::Result<PostPadding, Error> {
17511754
let align = self.align().unwrap_or(default);
@@ -1785,19 +1788,19 @@ impl<'a> Formatter<'a> {
17851788

17861789
// remove the sign from the formatted parts
17871790
formatted.sign = "";
1788-
width = width.saturating_sub(sign.len());
1791+
width = width.saturating_sub(sign.len() as u16);
17891792
self.options.fill = '0';
17901793
self.options.align = Some(Alignment::Right);
17911794
}
17921795

17931796
// remaining parts go through the ordinary padding process.
17941797
let len = formatted.len();
1795-
let ret = if width <= len {
1798+
let ret = if usize::from(width) <= len {
17961799
// no padding
17971800
// SAFETY: Per the precondition.
17981801
unsafe { self.write_formatted_parts(&formatted) }
17991802
} else {
1800-
let post_padding = self.padding(width - len, Alignment::Right)?;
1803+
let post_padding = self.padding(width - len as u16, Alignment::Right)?;
18011804
// SAFETY: Per the precondition.
18021805
unsafe {
18031806
self.write_formatted_parts(&formatted)?;
@@ -2029,7 +2032,7 @@ impl<'a> Formatter<'a> {
20292032
#[must_use]
20302033
#[stable(feature = "fmt_flags", since = "1.5.0")]
20312034
pub fn width(&self) -> Option<usize> {
2032-
self.options.width
2035+
self.options.width.map(|x| x as usize)
20332036
}
20342037

20352038
/// Returns the optionally specified precision for numeric types.
@@ -2060,7 +2063,7 @@ impl<'a> Formatter<'a> {
20602063
#[must_use]
20612064
#[stable(feature = "fmt_flags", since = "1.5.0")]
20622065
pub fn precision(&self) -> Option<usize> {
2063-
self.options.precision
2066+
self.options.precision.map(|x| x as usize)
20642067
}
20652068

20662069
/// Determines if the `+` flag was specified.
@@ -2800,7 +2803,7 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
28002803
f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
28012804

28022805
if f.options.width.is_none() {
2803-
f.options.width = Some((usize::BITS / 4) as usize + 2);
2806+
f.options.width = Some((usize::BITS / 4) as u16 + 2);
28042807
}
28052808
}
28062809
f.options.flags |= 1 << (rt::Flag::Alternate as u32);

library/core/src/fmt/rt.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ pub enum Alignment {
4747
#[derive(Copy, Clone)]
4848
pub enum Count {
4949
/// Specified with a literal number, stores the value
50+
#[cfg(bootstrap)]
5051
Is(usize),
52+
/// Specified with a literal number, stores the value
53+
#[cfg(not(bootstrap))]
54+
Is(u16),
5155
/// Specified using `$` and `*` syntaxes, stores the index into `args`
5256
Param(usize),
5357
/// Not specified
@@ -74,7 +78,7 @@ enum ArgumentType<'a> {
7478
formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
7579
_lifetime: PhantomData<&'a ()>,
7680
},
77-
Count(usize),
81+
Count(u16),
7882
}
7983

8084
/// This struct represents a generic "argument" which is taken by format_args!().
@@ -151,7 +155,10 @@ impl Argument<'_> {
151155
}
152156
#[inline]
153157
pub const fn from_usize(x: &usize) -> Argument<'_> {
154-
Argument { ty: ArgumentType::Count(*x) }
158+
if *x > u16::MAX as usize {
159+
panic!("Formatting argument out of range");
160+
};
161+
Argument { ty: ArgumentType::Count(*x as u16) }
155162
}
156163

157164
/// Format this placeholder argument.
@@ -181,7 +188,7 @@ impl Argument<'_> {
181188
}
182189

183190
#[inline]
184-
pub(super) const fn as_usize(&self) -> Option<usize> {
191+
pub(super) const fn as_u16(&self) -> Option<u16> {
185192
match self.ty {
186193
ArgumentType::Count(count) => Some(count),
187194
ArgumentType::Placeholder { .. } => None,

0 commit comments

Comments
 (0)