Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce formatting width and precision to 16 bits #136932

Merged
merged 6 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ pub enum FormatAlignment {
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatCount {
/// `{:5}` or `{:.5}`
Literal(usize),
Literal(u16),
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
Argument(FormatArgPosition),
}
24 changes: 11 additions & 13 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2130,26 +2130,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
}

pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
fn expr_uint(&mut self, sp: Span, ty: ast::UintTy, value: u128) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
node: ast::LitKind::Int(
(value as u128).into(),
ast::LitIntType::Unsigned(ast::UintTy::Usize),
),
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ty)),
});
self.expr(sp, hir::ExprKind::Lit(lit))
}

pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
self.expr_uint(sp, ast::UintTy::Usize, value as u128)
}

pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
node: ast::LitKind::Int(
u128::from(value).into(),
ast::LitIntType::Unsigned(ast::UintTy::U32),
),
});
self.expr(sp, hir::ExprKind::Lit(lit))
self.expr_uint(sp, ast::UintTy::U32, value as u128)
}

pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
self.expr_uint(sp, ast::UintTy::U16, value as u128)
}

pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ fn make_count<'hir>(
hir::LangItem::FormatCount,
sym::Is,
));
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]);
let value = ctx.arena.alloc_from_iter([ctx.expr_u16(sp, *n)]);
ctx.expr_call_mut(sp, count_is, value)
}
Some(FormatCount::Argument(arg)) => {
Expand Down
18 changes: 9 additions & 9 deletions compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ pub enum DebugHex {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Count<'a> {
/// The count is specified explicitly.
CountIs(usize),
CountIs(u16),
/// The count is specified by the argument with the given name.
CountIsName(&'a str, InnerSpan),
/// The count is specified by the argument at the given index.
Expand Down Expand Up @@ -564,7 +564,7 @@ impl<'a> Parser<'a> {
/// consuming a macro argument, `None` if it's the case.
fn position(&mut self) -> Option<Position<'a>> {
if let Some(i) = self.integer() {
Some(ArgumentIs(i))
Some(ArgumentIs(i.into()))
} else {
match self.cur.peek() {
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
Expand Down Expand Up @@ -770,7 +770,7 @@ impl<'a> Parser<'a> {
/// width.
fn count(&mut self, start: usize) -> Count<'a> {
if let Some(i) = self.integer() {
if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) }
} else {
let tmp = self.cur.clone();
let word = self.word();
Expand Down Expand Up @@ -821,15 +821,15 @@ impl<'a> Parser<'a> {
word
}

fn integer(&mut self) -> Option<usize> {
let mut cur: usize = 0;
fn integer(&mut self) -> Option<u16> {
let mut cur: u16 = 0;
let mut found = false;
let mut overflow = false;
let start = self.current_pos();
while let Some(&(_, c)) = self.cur.peek() {
if let Some(i) = c.to_digit(10) {
let (tmp, mul_overflow) = cur.overflowing_mul(10);
let (tmp, add_overflow) = tmp.overflowing_add(i as usize);
let (tmp, add_overflow) = tmp.overflowing_add(i as u16);
if mul_overflow || add_overflow {
overflow = true;
}
Expand All @@ -846,11 +846,11 @@ impl<'a> Parser<'a> {
let overflowed_int = &self.input[start..end];
self.err(
format!(
"integer `{}` does not fit into the type `usize` whose range is `0..={}`",
"integer `{}` does not fit into the type `u16` whose range is `0..={}`",
overflowed_int,
usize::MAX
u16::MAX
),
"integer out of range for `usize`",
"integer out of range for `u16`",
self.span(start, end),
);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@ symbols! {
from_residual,
from_size_align_unchecked,
from_str_method,
from_u16,
from_usize,
from_yeet,
fs_create_dir,
Expand Down
12 changes: 6 additions & 6 deletions library/core/src/fmt/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn float_to_decimal_common_exact<T>(
fmt: &mut Formatter<'_>,
num: &T,
sign: flt2dec::Sign,
precision: usize,
precision: u16,
) -> Result
where
T: flt2dec::DecodableFloat,
Expand All @@ -40,7 +40,7 @@ where
flt2dec::strategy::grisu::format_exact,
*num,
sign,
precision,
precision.into(),
&mut buf,
&mut parts,
);
Expand All @@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest<T>(
fmt: &mut Formatter<'_>,
num: &T,
sign: flt2dec::Sign,
precision: usize,
precision: u16,
) -> Result
where
T: flt2dec::DecodableFloat,
Expand All @@ -68,7 +68,7 @@ where
flt2dec::strategy::grisu::format_shortest,
*num,
sign,
precision,
precision.into(),
&mut buf,
&mut parts,
);
Expand Down Expand Up @@ -101,7 +101,7 @@ fn float_to_exponential_common_exact<T>(
fmt: &mut Formatter<'_>,
num: &T,
sign: flt2dec::Sign,
precision: usize,
precision: u16,
upper: bool,
) -> Result
where
Expand All @@ -113,7 +113,7 @@ where
flt2dec::strategy::grisu::format_exact,
*num,
sign,
precision,
precision.into(),
upper,
&mut buf,
&mut parts,
Expand Down
51 changes: 27 additions & 24 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ pub struct FormattingOptions {
flags: u32,
fill: char,
align: Option<Alignment>,
width: Option<usize>,
precision: Option<usize>,
width: Option<u16>,
precision: Option<u16>,
}

impl FormattingOptions {
Expand Down Expand Up @@ -389,7 +389,7 @@ impl FormattingOptions {
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
/// will be used to take up the required space.
#[unstable(feature = "formatting_options", issue = "118117")]
pub fn width(&mut self, width: Option<usize>) -> &mut Self {
pub fn width(&mut self, width: Option<u16>) -> &mut Self {
self.width = width;
self
}
Expand All @@ -403,7 +403,7 @@ impl FormattingOptions {
/// - For floating-point types, this indicates how many digits after the
/// decimal point should be printed.
#[unstable(feature = "formatting_options", issue = "118117")]
pub fn precision(&mut self, precision: Option<usize>) -> &mut Self {
pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
self.precision = precision;
self
}
Expand Down Expand Up @@ -455,12 +455,12 @@ impl FormattingOptions {
}
/// Returns the current width.
#[unstable(feature = "formatting_options", issue = "118117")]
pub const fn get_width(&self) -> Option<usize> {
pub const fn get_width(&self) -> Option<u16> {
self.width
}
/// Returns the current precision.
#[unstable(feature = "formatting_options", issue = "118117")]
pub const fn get_precision(&self) -> Option<usize> {
pub const fn get_precision(&self) -> Option<u16> {
self.precision
}
/// Returns the current precision.
Expand Down Expand Up @@ -1499,15 +1499,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
unsafe { value.fmt(fmt) }
}

unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
match *cnt {
#[cfg(bootstrap)]
rt::Count::Is(n) => Some(n as u16),
#[cfg(not(bootstrap))]
rt::Count::Is(n) => Some(n),
rt::Count::Implied => None,
rt::Count::Param(i) => {
debug_assert!(i < args.len());
// SAFETY: cnt and args come from the same Arguments,
// which guarantees this index is always within bounds.
unsafe { args.get_unchecked(i).as_usize() }
unsafe { args.get_unchecked(i).as_u16() }
}
}
}
Expand All @@ -1516,11 +1519,11 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize>
#[must_use = "don't forget to write the post padding"]
pub(crate) struct PostPadding {
fill: char,
padding: usize,
padding: u16,
}

impl PostPadding {
fn new(fill: char, padding: usize) -> PostPadding {
fn new(fill: char, padding: u16) -> PostPadding {
PostPadding { fill, padding }
}

Expand Down Expand Up @@ -1634,7 +1637,7 @@ impl<'a> Formatter<'a> {
}
// Check if we're over the minimum width, if so then we can also
// just write the bytes.
Some(min) if width >= min => {
Some(min) if width >= usize::from(min) => {
write_prefix(self, sign, prefix)?;
self.buf.write_str(buf)
}
Expand All @@ -1645,7 +1648,7 @@ impl<'a> Formatter<'a> {
let old_align =
crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
write_prefix(self, sign, prefix)?;
let post_padding = self.padding(min - width, Alignment::Right)?;
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
self.buf.write_str(buf)?;
post_padding.write(self)?;
self.options.fill = old_fill;
Expand All @@ -1654,7 +1657,7 @@ impl<'a> Formatter<'a> {
}
// Otherwise, the sign and prefix goes after the padding
Some(min) => {
let post_padding = self.padding(min - width, Alignment::Right)?;
let post_padding = self.padding(min - width as u16, Alignment::Right)?;
write_prefix(self, sign, prefix)?;
self.buf.write_str(buf)?;
post_padding.write(self)
Expand Down Expand Up @@ -1702,26 +1705,26 @@ impl<'a> Formatter<'a> {
// string being formatted.
let (s, char_count) = if let Some(max_char_count) = self.options.precision {
let mut iter = s.char_indices();
let remaining = match iter.advance_by(max_char_count) {
let remaining = match iter.advance_by(usize::from(max_char_count)) {
Ok(()) => 0,
Err(remaining) => remaining.get(),
};
// SAFETY: The offset of `.char_indices()` is guaranteed to be
// in-bounds and between character boundaries.
let truncated = unsafe { s.get_unchecked(..iter.offset()) };
(truncated, max_char_count - remaining)
(truncated, usize::from(max_char_count) - remaining)
} else {
// Use the optimized char counting algorithm for the full string.
(s, s.chars().count())
};

// The `width` field is more of a minimum width parameter at this point.
if let Some(width) = self.options.width
&& char_count < width
&& char_count < usize::from(width)
{
// If we're under the minimum width, then fill up the minimum width
// with the specified string + some alignment.
let post_padding = self.padding(width - char_count, Alignment::Left)?;
let post_padding = self.padding(width - char_count as u16, Alignment::Left)?;
self.buf.write_str(s)?;
post_padding.write(self)
} else {
Expand All @@ -1737,7 +1740,7 @@ impl<'a> Formatter<'a> {
/// thing that is being padded.
pub(crate) fn padding(
&mut self,
padding: usize,
padding: u16,
default: Alignment,
) -> result::Result<PostPadding, Error> {
let align = self.align().unwrap_or(default);
Expand Down Expand Up @@ -1777,19 +1780,19 @@ impl<'a> Formatter<'a> {

// remove the sign from the formatted parts
formatted.sign = "";
width = width.saturating_sub(sign.len());
width = width.saturating_sub(sign.len() as u16);
self.options.fill = '0';
self.options.align = Some(Alignment::Right);
}

// remaining parts go through the ordinary padding process.
let len = formatted.len();
let ret = if width <= len {
let ret = if usize::from(width) <= len {
// no padding
// SAFETY: Per the precondition.
unsafe { self.write_formatted_parts(&formatted) }
} else {
let post_padding = self.padding(width - len, Alignment::Right)?;
let post_padding = self.padding(width - len as u16, Alignment::Right)?;
// SAFETY: Per the precondition.
unsafe {
self.write_formatted_parts(&formatted)?;
Expand Down Expand Up @@ -2021,7 +2024,7 @@ impl<'a> Formatter<'a> {
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
pub fn width(&self) -> Option<usize> {
self.options.width
self.options.width.map(|x| x as usize)
}

/// Returns the optionally specified precision for numeric types.
Expand Down Expand Up @@ -2052,7 +2055,7 @@ impl<'a> Formatter<'a> {
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
pub fn precision(&self) -> Option<usize> {
self.options.precision
self.options.precision.map(|x| x as usize)
}

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

if f.options.width.is_none() {
f.options.width = Some((usize::BITS / 4) as usize + 2);
f.options.width = Some((usize::BITS / 4) as u16 + 2);
}
}
f.options.flags |= 1 << (rt::Flag::Alternate as u32);
Expand Down
Loading
Loading