Skip to content

Commit 47853a6

Browse files
committed
Auto merge of #136974 - m-ou-se:fmt-options-64-bit, r=<try>
Reduce FormattingOptions to 64 bits This reduces FormattingOptions from 6-7 machine words (384 bits on 64-bit platforms, 224 bits on 32-bit platforms) to just 64 bits (a single register on 64-bit platforms). This PR includes #136932, which reduces the width and precision options to 16 bits, to make it all fit. Before: ```rust pub struct FormattingOptions { flags: u32, // only 6 bits used fill: char, align: Option<Alignment>, width: Option<usize>, precision: Option<usize>, } ``` After: ```rust pub struct FormattingOptions { /// Bits: /// - 0: `+` flag [rt::Flag::SignPlus] /// - 1: `-` flag [rt::Flag::SignMinus] /// - 2: `#` flag [rt::Flag::Alternate] /// - 3: `0` flag [rt::Flag::SignAwareZeroPad] /// - 4: `x?` flag [rt::Flag::DebugLowerHex] /// - 5: `X?` flag [rt::Flag::DebugUpperHex] /// - 6-7: Alignment (0: Left, 1: Right, 2: Center, 3: Unknown) /// - 8: Width flag (if set, the width field below is used) /// - 9: Precision flag (if set, the precision field below is used) /// - 10: unused /// - 11-31: fill character (21 bits, a full `char`) flags: u32, /// Width if width flag above is set. Otherwise, always 0. width: u16, /// Precision if precision flag above is set. Otherwise, always 0. precision: u16, } ```
2 parents 54cdc75 + c059377 commit 47853a6

17 files changed

+736
-271
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

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

2154-
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
2155-
let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
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+
});
21562162
self.expr(sp, hir::ExprKind::Lit(lit))
21572163
}
21582164

compiler/rustc_ast_lowering/src/format.rs

+16-15
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)) => {
@@ -361,24 +361,25 @@ fn make_format_spec<'hir>(
361361
zero_pad,
362362
debug_hex,
363363
} = &placeholder.format_options;
364-
let fill = ctx.expr_char(sp, fill.unwrap_or(' '));
365-
let align = ctx.expr_lang_item_type_relative(
366-
sp,
367-
hir::LangItem::FormatAlignment,
368-
match alignment {
369-
Some(FormatAlignment::Left) => sym::Left,
370-
Some(FormatAlignment::Right) => sym::Right,
371-
Some(FormatAlignment::Center) => sym::Center,
372-
None => sym::Unknown,
373-
},
374-
);
375-
// This needs to match `Flag` in library/core/src/fmt/rt.rs.
364+
let fill = fill.unwrap_or(' ');
365+
// These need to match the constants in library/core/src/fmt/rt.rs.
366+
let align = match alignment {
367+
Some(FormatAlignment::Left) => 0,
368+
Some(FormatAlignment::Right) => 1,
369+
Some(FormatAlignment::Center) => 2,
370+
None => 3,
371+
};
372+
// This needs to match the constants in library/core/src/fmt/rt.rs.
376373
let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
377374
| ((sign == Some(FormatSign::Minus)) as u32) << 1
378375
| (alternate as u32) << 2
379376
| (zero_pad as u32) << 3
380377
| ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4
381-
| ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5;
378+
| ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5
379+
| align << 6
380+
| (width.is_some() as u32) << 8
381+
| (precision.is_some() as u32) << 9
382+
| (fill as u32) << 11;
382383
let flags = ctx.expr_u32(sp, flags);
383384
let precision = make_count(ctx, sp, precision, argmap);
384385
let width = make_count(ctx, sp, width, argmap);
@@ -387,7 +388,7 @@ fn make_format_spec<'hir>(
387388
hir::LangItem::FormatPlaceholder,
388389
sym::new,
389390
));
390-
let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]);
391+
let args = ctx.arena.alloc_from_iter([position, flags, precision, width]);
391392
ctx.expr_call_mut(sp, format_placeholder_new, args)
392393
}
393394

compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,6 @@ language_item_table! {
321321
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
322322

323323
// Lang items needed for `format_args!()`.
324-
FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None;
325324
FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
326325
FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
327326
FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None;

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-1
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,6 @@ symbols! {
978978
forbid,
979979
forget,
980980
format,
981-
format_alignment,
982981
format_args,
983982
format_args_capture,
984983
format_args_macro,
@@ -1003,6 +1002,7 @@ symbols! {
10031002
from_residual,
10041003
from_size_align_unchecked,
10051004
from_str_method,
1005+
from_u16,
10061006
from_usize,
10071007
from_yeet,
10081008
fs_create_dir,

library/core/src/fmt/float.rs

+9-9
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
);
@@ -86,7 +86,7 @@ where
8686
true => flt2dec::Sign::MinusPlus,
8787
};
8888

89-
if let Some(precision) = fmt.options.precision {
89+
if let Some(precision) = fmt.options.get_precision() {
9090
float_to_decimal_common_exact(fmt, num, sign, precision)
9191
} else {
9292
let min_precision = 0;
@@ -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,
@@ -162,7 +162,7 @@ where
162162
true => flt2dec::Sign::MinusPlus,
163163
};
164164

165-
if let Some(precision) = fmt.options.precision {
165+
if let Some(precision) = fmt.options.get_precision() {
166166
// 1 integral digit + `precision` fractional digits = `precision + 1` total digits
167167
float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
168168
} else {
@@ -180,7 +180,7 @@ where
180180
true => flt2dec::Sign::MinusPlus,
181181
};
182182

183-
if let Some(precision) = fmt.options.precision {
183+
if let Some(precision) = fmt.options.get_precision() {
184184
// this behavior of {:.PREC?} predates exponential formatting for {:?}
185185
float_to_decimal_common_exact(fmt, num, sign, precision)
186186
} else {

0 commit comments

Comments
 (0)