Auto merge of #136932 - m-ou-se:fmt-width-precision-u16, r=scottmcm
Reduce formatting `width` and `precision` to 16 bits This is part of https://github.com/rust-lang/rust/issues/99012 This is reduces the `width` and `precision` fields in format strings to 16 bits. They are currently full `usize`s, but it's a bit nonsensical that we need to support the case where someone wants to pad their value to eighteen quintillion spaces and/or have eighteen quintillion digits of precision. By reducing these fields to 16 bit, we can reduce `FormattingOptions` to 64 bits (see https://github.com/rust-lang/rust/pull/136974) and improve the in memory representation of `format_args!()`. (See additional context below.) This also fixes a bug where the width or precision is silently truncated when cross-compiling to a target with a smaller `usize`. By reducing the width and precision fields to the minimum guaranteed size of `usize`, 16 bits, this bug is eliminated. This is a breaking change, but affects almost no existing code. --- Details of this change: There are three ways to set a width or precision today: 1. Directly a formatting string, e.g. `println!("{a:1234}")` 2. Indirectly in a formatting string, e.g. `println!("{a:width$}", width=1234)` 3. Through the unstable `FormattingOptions::width` method. This PR: - Adds a compiler error for 1. (`println!("{a:9999999}")` no longer compiles and gives a clear error.) - Adds a runtime check for 2. (`println!("{a:width$}, width=9999999)` will panic.) - Changes the signatures of the (unstable) `FormattingOptions::[get_]width` methods to use a `u16` instead. --- Additional context for improving `FormattingOptions` and `fmt::Arguments`: All the formatting flags and options are currently: - The `+` flag (1 bit) - The `-` flag (1 bit) - The `#` flag (1 bit) - The `0` flag (1 bit) - The `x?` flag (1 bit) - The `X?` flag (1 bit) - The alignment (2 bits) - The fill character (21 bits) - Whether a width is specified (1 bit) - Whether a precision is specified (1 bit) - If used, the width (a full usize) - If used, the precision (a full usize) Everything except the last two can simply fit in a `u32` (those add up to 31 bits in total). If we can accept a max width and precision of u16::MAX, we can make a `FormattingOptions` that is exactly 64 bits in size; the same size as a thin reference on most platforms. If, additionally, we also limit the number of formatting arguments, we can also reduce the size of `fmt::Arguments` (that is, of a `format_args!()` expression).
This commit is contained in:
commit
374ce1f909
16 changed files with 530 additions and 80 deletions
|
@ -266,7 +266,7 @@ pub enum FormatAlignment {
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||||
pub enum FormatCount {
|
pub enum FormatCount {
|
||||||
/// `{:5}` or `{:.5}`
|
/// `{:5}` or `{:.5}`
|
||||||
Literal(usize),
|
Literal(u16),
|
||||||
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
||||||
Argument(FormatArgPosition),
|
Argument(FormatArgPosition),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2130,26 +2130,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
|
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 {
|
let lit = self.arena.alloc(hir::Lit {
|
||||||
span: sp,
|
span: sp,
|
||||||
node: ast::LitKind::Int(
|
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ty)),
|
||||||
(value as u128).into(),
|
|
||||||
ast::LitIntType::Unsigned(ast::UintTy::Usize),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
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> {
|
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
|
||||||
let lit = self.arena.alloc(hir::Lit {
|
self.expr_uint(sp, ast::UintTy::U32, value as u128)
|
||||||
span: sp,
|
}
|
||||||
node: ast::LitKind::Int(
|
|
||||||
u128::from(value).into(),
|
pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
|
||||||
ast::LitIntType::Unsigned(ast::UintTy::U32),
|
self.expr_uint(sp, ast::UintTy::U16, value as u128)
|
||||||
),
|
|
||||||
});
|
|
||||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
|
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
|
||||||
|
|
|
@ -292,7 +292,7 @@ fn make_count<'hir>(
|
||||||
hir::LangItem::FormatCount,
|
hir::LangItem::FormatCount,
|
||||||
sym::Is,
|
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)
|
ctx.expr_call_mut(sp, count_is, value)
|
||||||
}
|
}
|
||||||
Some(FormatCount::Argument(arg)) => {
|
Some(FormatCount::Argument(arg)) => {
|
||||||
|
|
|
@ -190,7 +190,7 @@ pub enum DebugHex {
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Count<'a> {
|
pub enum Count<'a> {
|
||||||
/// The count is specified explicitly.
|
/// The count is specified explicitly.
|
||||||
CountIs(usize),
|
CountIs(u16),
|
||||||
/// The count is specified by the argument with the given name.
|
/// The count is specified by the argument with the given name.
|
||||||
CountIsName(&'a str, InnerSpan),
|
CountIsName(&'a str, InnerSpan),
|
||||||
/// The count is specified by the argument at the given index.
|
/// The count is specified by the argument at the given index.
|
||||||
|
@ -565,7 +565,7 @@ impl<'a> Parser<'a> {
|
||||||
/// consuming a macro argument, `None` if it's the case.
|
/// consuming a macro argument, `None` if it's the case.
|
||||||
fn position(&mut self) -> Option<Position<'a>> {
|
fn position(&mut self) -> Option<Position<'a>> {
|
||||||
if let Some(i) = self.integer() {
|
if let Some(i) = self.integer() {
|
||||||
Some(ArgumentIs(i))
|
Some(ArgumentIs(i.into()))
|
||||||
} else {
|
} else {
|
||||||
match self.cur.peek() {
|
match self.cur.peek() {
|
||||||
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
|
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
|
||||||
|
@ -771,7 +771,7 @@ impl<'a> Parser<'a> {
|
||||||
/// width.
|
/// width.
|
||||||
fn count(&mut self, start: usize) -> Count<'a> {
|
fn count(&mut self, start: usize) -> Count<'a> {
|
||||||
if let Some(i) = self.integer() {
|
if let Some(i) = self.integer() {
|
||||||
if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
|
if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) }
|
||||||
} else {
|
} else {
|
||||||
let tmp = self.cur.clone();
|
let tmp = self.cur.clone();
|
||||||
let word = self.word();
|
let word = self.word();
|
||||||
|
@ -822,15 +822,15 @@ impl<'a> Parser<'a> {
|
||||||
word
|
word
|
||||||
}
|
}
|
||||||
|
|
||||||
fn integer(&mut self) -> Option<usize> {
|
fn integer(&mut self) -> Option<u16> {
|
||||||
let mut cur: usize = 0;
|
let mut cur: u16 = 0;
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let mut overflow = false;
|
let mut overflow = false;
|
||||||
let start = self.current_pos();
|
let start = self.current_pos();
|
||||||
while let Some(&(_, c)) = self.cur.peek() {
|
while let Some(&(_, c)) = self.cur.peek() {
|
||||||
if let Some(i) = c.to_digit(10) {
|
if let Some(i) = c.to_digit(10) {
|
||||||
let (tmp, mul_overflow) = cur.overflowing_mul(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 {
|
if mul_overflow || add_overflow {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
}
|
}
|
||||||
|
@ -847,11 +847,11 @@ impl<'a> Parser<'a> {
|
||||||
let overflowed_int = &self.input[start..end];
|
let overflowed_int = &self.input[start..end];
|
||||||
self.err(
|
self.err(
|
||||||
format!(
|
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,
|
overflowed_int,
|
||||||
usize::MAX
|
u16::MAX
|
||||||
),
|
),
|
||||||
"integer out of range for `usize`",
|
"integer out of range for `u16`",
|
||||||
self.span(start, end),
|
self.span(start, end),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1016,6 +1016,7 @@ symbols! {
|
||||||
from_residual,
|
from_residual,
|
||||||
from_size_align_unchecked,
|
from_size_align_unchecked,
|
||||||
from_str_method,
|
from_str_method,
|
||||||
|
from_u16,
|
||||||
from_usize,
|
from_usize,
|
||||||
from_yeet,
|
from_yeet,
|
||||||
fs_create_dir,
|
fs_create_dir,
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn float_to_decimal_common_exact<T>(
|
||||||
fmt: &mut Formatter<'_>,
|
fmt: &mut Formatter<'_>,
|
||||||
num: &T,
|
num: &T,
|
||||||
sign: flt2dec::Sign,
|
sign: flt2dec::Sign,
|
||||||
precision: usize,
|
precision: u16,
|
||||||
) -> Result
|
) -> Result
|
||||||
where
|
where
|
||||||
T: flt2dec::DecodableFloat,
|
T: flt2dec::DecodableFloat,
|
||||||
|
@ -40,7 +40,7 @@ where
|
||||||
flt2dec::strategy::grisu::format_exact,
|
flt2dec::strategy::grisu::format_exact,
|
||||||
*num,
|
*num,
|
||||||
sign,
|
sign,
|
||||||
precision,
|
precision.into(),
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&mut parts,
|
&mut parts,
|
||||||
);
|
);
|
||||||
|
@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest<T>(
|
||||||
fmt: &mut Formatter<'_>,
|
fmt: &mut Formatter<'_>,
|
||||||
num: &T,
|
num: &T,
|
||||||
sign: flt2dec::Sign,
|
sign: flt2dec::Sign,
|
||||||
precision: usize,
|
precision: u16,
|
||||||
) -> Result
|
) -> Result
|
||||||
where
|
where
|
||||||
T: flt2dec::DecodableFloat,
|
T: flt2dec::DecodableFloat,
|
||||||
|
@ -68,7 +68,7 @@ where
|
||||||
flt2dec::strategy::grisu::format_shortest,
|
flt2dec::strategy::grisu::format_shortest,
|
||||||
*num,
|
*num,
|
||||||
sign,
|
sign,
|
||||||
precision,
|
precision.into(),
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&mut parts,
|
&mut parts,
|
||||||
);
|
);
|
||||||
|
@ -101,7 +101,7 @@ fn float_to_exponential_common_exact<T>(
|
||||||
fmt: &mut Formatter<'_>,
|
fmt: &mut Formatter<'_>,
|
||||||
num: &T,
|
num: &T,
|
||||||
sign: flt2dec::Sign,
|
sign: flt2dec::Sign,
|
||||||
precision: usize,
|
precision: u16,
|
||||||
upper: bool,
|
upper: bool,
|
||||||
) -> Result
|
) -> Result
|
||||||
where
|
where
|
||||||
|
@ -113,7 +113,7 @@ where
|
||||||
flt2dec::strategy::grisu::format_exact,
|
flt2dec::strategy::grisu::format_exact,
|
||||||
*num,
|
*num,
|
||||||
sign,
|
sign,
|
||||||
precision,
|
precision.into(),
|
||||||
upper,
|
upper,
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&mut parts,
|
&mut parts,
|
||||||
|
|
|
@ -294,8 +294,8 @@ pub struct FormattingOptions {
|
||||||
flags: u32,
|
flags: u32,
|
||||||
fill: char,
|
fill: char,
|
||||||
align: Option<Alignment>,
|
align: Option<Alignment>,
|
||||||
width: Option<usize>,
|
width: Option<u16>,
|
||||||
precision: Option<usize>,
|
precision: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormattingOptions {
|
impl FormattingOptions {
|
||||||
|
@ -389,7 +389,7 @@ impl FormattingOptions {
|
||||||
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
|
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
|
||||||
/// will be used to take up the required space.
|
/// will be used to take up the required space.
|
||||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
#[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.width = width;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -403,7 +403,7 @@ impl FormattingOptions {
|
||||||
/// - For floating-point types, this indicates how many digits after the
|
/// - For floating-point types, this indicates how many digits after the
|
||||||
/// decimal point should be printed.
|
/// decimal point should be printed.
|
||||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
#[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.precision = precision;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -455,12 +455,12 @@ impl FormattingOptions {
|
||||||
}
|
}
|
||||||
/// Returns the current width.
|
/// Returns the current width.
|
||||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||||
pub const fn get_width(&self) -> Option<usize> {
|
pub const fn get_width(&self) -> Option<u16> {
|
||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
/// Returns the current precision.
|
/// Returns the current precision.
|
||||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||||
pub const fn get_precision(&self) -> Option<usize> {
|
pub const fn get_precision(&self) -> Option<u16> {
|
||||||
self.precision
|
self.precision
|
||||||
}
|
}
|
||||||
/// Returns the current precision.
|
/// Returns the current precision.
|
||||||
|
@ -1499,15 +1499,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
|
||||||
unsafe { value.fmt(fmt) }
|
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 {
|
match *cnt {
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
rt::Count::Is(n) => Some(n as u16),
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
rt::Count::Is(n) => Some(n),
|
rt::Count::Is(n) => Some(n),
|
||||||
rt::Count::Implied => None,
|
rt::Count::Implied => None,
|
||||||
rt::Count::Param(i) => {
|
rt::Count::Param(i) => {
|
||||||
debug_assert!(i < args.len());
|
debug_assert!(i < args.len());
|
||||||
// SAFETY: cnt and args come from the same Arguments,
|
// SAFETY: cnt and args come from the same Arguments,
|
||||||
// which guarantees this index is always within bounds.
|
// which guarantees this index is always within bounds.
|
||||||
unsafe { args.get_unchecked(i).as_usize() }
|
unsafe { args.get_unchecked(i).as_u16() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"]
|
#[must_use = "don't forget to write the post padding"]
|
||||||
pub(crate) struct PostPadding {
|
pub(crate) struct PostPadding {
|
||||||
fill: char,
|
fill: char,
|
||||||
padding: usize,
|
padding: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PostPadding {
|
impl PostPadding {
|
||||||
fn new(fill: char, padding: usize) -> PostPadding {
|
fn new(fill: char, padding: u16) -> PostPadding {
|
||||||
PostPadding { fill, padding }
|
PostPadding { fill, padding }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1634,7 +1637,7 @@ impl<'a> Formatter<'a> {
|
||||||
}
|
}
|
||||||
// Check if we're over the minimum width, if so then we can also
|
// Check if we're over the minimum width, if so then we can also
|
||||||
// just write the bytes.
|
// just write the bytes.
|
||||||
Some(min) if width >= min => {
|
Some(min) if width >= usize::from(min) => {
|
||||||
write_prefix(self, sign, prefix)?;
|
write_prefix(self, sign, prefix)?;
|
||||||
self.buf.write_str(buf)
|
self.buf.write_str(buf)
|
||||||
}
|
}
|
||||||
|
@ -1645,7 +1648,7 @@ impl<'a> Formatter<'a> {
|
||||||
let old_align =
|
let old_align =
|
||||||
crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
|
crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
|
||||||
write_prefix(self, sign, prefix)?;
|
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)?;
|
self.buf.write_str(buf)?;
|
||||||
post_padding.write(self)?;
|
post_padding.write(self)?;
|
||||||
self.options.fill = old_fill;
|
self.options.fill = old_fill;
|
||||||
|
@ -1654,7 +1657,7 @@ impl<'a> Formatter<'a> {
|
||||||
}
|
}
|
||||||
// Otherwise, the sign and prefix goes after the padding
|
// Otherwise, the sign and prefix goes after the padding
|
||||||
Some(min) => {
|
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)?;
|
write_prefix(self, sign, prefix)?;
|
||||||
self.buf.write_str(buf)?;
|
self.buf.write_str(buf)?;
|
||||||
post_padding.write(self)
|
post_padding.write(self)
|
||||||
|
@ -1702,14 +1705,14 @@ impl<'a> Formatter<'a> {
|
||||||
// string being formatted.
|
// string being formatted.
|
||||||
let (s, char_count) = if let Some(max_char_count) = self.options.precision {
|
let (s, char_count) = if let Some(max_char_count) = self.options.precision {
|
||||||
let mut iter = s.char_indices();
|
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,
|
Ok(()) => 0,
|
||||||
Err(remaining) => remaining.get(),
|
Err(remaining) => remaining.get(),
|
||||||
};
|
};
|
||||||
// SAFETY: The offset of `.char_indices()` is guaranteed to be
|
// SAFETY: The offset of `.char_indices()` is guaranteed to be
|
||||||
// in-bounds and between character boundaries.
|
// in-bounds and between character boundaries.
|
||||||
let truncated = unsafe { s.get_unchecked(..iter.offset()) };
|
let truncated = unsafe { s.get_unchecked(..iter.offset()) };
|
||||||
(truncated, max_char_count - remaining)
|
(truncated, usize::from(max_char_count) - remaining)
|
||||||
} else {
|
} else {
|
||||||
// Use the optimized char counting algorithm for the full string.
|
// Use the optimized char counting algorithm for the full string.
|
||||||
(s, s.chars().count())
|
(s, s.chars().count())
|
||||||
|
@ -1717,11 +1720,11 @@ impl<'a> Formatter<'a> {
|
||||||
|
|
||||||
// The `width` field is more of a minimum width parameter at this point.
|
// The `width` field is more of a minimum width parameter at this point.
|
||||||
if let Some(width) = self.options.width
|
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
|
// If we're under the minimum width, then fill up the minimum width
|
||||||
// with the specified string + some alignment.
|
// 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)?;
|
self.buf.write_str(s)?;
|
||||||
post_padding.write(self)
|
post_padding.write(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1737,7 +1740,7 @@ impl<'a> Formatter<'a> {
|
||||||
/// thing that is being padded.
|
/// thing that is being padded.
|
||||||
pub(crate) fn padding(
|
pub(crate) fn padding(
|
||||||
&mut self,
|
&mut self,
|
||||||
padding: usize,
|
padding: u16,
|
||||||
default: Alignment,
|
default: Alignment,
|
||||||
) -> result::Result<PostPadding, Error> {
|
) -> result::Result<PostPadding, Error> {
|
||||||
let align = self.align().unwrap_or(default);
|
let align = self.align().unwrap_or(default);
|
||||||
|
@ -1777,19 +1780,19 @@ impl<'a> Formatter<'a> {
|
||||||
|
|
||||||
// remove the sign from the formatted parts
|
// remove the sign from the formatted parts
|
||||||
formatted.sign = "";
|
formatted.sign = "";
|
||||||
width = width.saturating_sub(sign.len());
|
width = width.saturating_sub(sign.len() as u16);
|
||||||
self.options.fill = '0';
|
self.options.fill = '0';
|
||||||
self.options.align = Some(Alignment::Right);
|
self.options.align = Some(Alignment::Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remaining parts go through the ordinary padding process.
|
// remaining parts go through the ordinary padding process.
|
||||||
let len = formatted.len();
|
let len = formatted.len();
|
||||||
let ret = if width <= len {
|
let ret = if usize::from(width) <= len {
|
||||||
// no padding
|
// no padding
|
||||||
// SAFETY: Per the precondition.
|
// SAFETY: Per the precondition.
|
||||||
unsafe { self.write_formatted_parts(&formatted) }
|
unsafe { self.write_formatted_parts(&formatted) }
|
||||||
} else {
|
} 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.
|
// SAFETY: Per the precondition.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.write_formatted_parts(&formatted)?;
|
self.write_formatted_parts(&formatted)?;
|
||||||
|
@ -2021,7 +2024,7 @@ impl<'a> Formatter<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn width(&self) -> Option<usize> {
|
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.
|
/// Returns the optionally specified precision for numeric types.
|
||||||
|
@ -2052,7 +2055,7 @@ impl<'a> Formatter<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn precision(&self) -> Option<usize> {
|
pub fn precision(&self) -> Option<usize> {
|
||||||
self.options.precision
|
self.options.precision.map(|x| x as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if the `+` flag was specified.
|
/// Determines if the `+` flag was specified.
|
||||||
|
@ -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);
|
f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
|
||||||
|
|
||||||
if f.options.width.is_none() {
|
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);
|
f.options.flags |= 1 << (rt::Flag::Alternate as u32);
|
||||||
|
|
|
@ -47,7 +47,11 @@ pub enum Alignment {
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Count {
|
pub enum Count {
|
||||||
/// Specified with a literal number, stores the value
|
/// Specified with a literal number, stores the value
|
||||||
|
#[cfg(bootstrap)]
|
||||||
Is(usize),
|
Is(usize),
|
||||||
|
/// Specified with a literal number, stores the value
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
Is(u16),
|
||||||
/// Specified using `$` and `*` syntaxes, stores the index into `args`
|
/// Specified using `$` and `*` syntaxes, stores the index into `args`
|
||||||
Param(usize),
|
Param(usize),
|
||||||
/// Not specified
|
/// Not specified
|
||||||
|
@ -74,7 +78,7 @@ enum ArgumentType<'a> {
|
||||||
formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
|
formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
|
||||||
_lifetime: PhantomData<&'a ()>,
|
_lifetime: PhantomData<&'a ()>,
|
||||||
},
|
},
|
||||||
Count(usize),
|
Count(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct represents a generic "argument" which is taken by format_args!().
|
/// This struct represents a generic "argument" which is taken by format_args!().
|
||||||
|
@ -150,8 +154,12 @@ impl Argument<'_> {
|
||||||
Self::new(x, UpperExp::fmt)
|
Self::new(x, UpperExp::fmt)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
pub const fn from_usize(x: &usize) -> Argument<'_> {
|
pub const fn from_usize(x: &usize) -> Argument<'_> {
|
||||||
Argument { ty: ArgumentType::Count(*x) }
|
if *x > u16::MAX as usize {
|
||||||
|
panic!("Formatting argument out of range");
|
||||||
|
}
|
||||||
|
Argument { ty: ArgumentType::Count(*x as u16) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format this placeholder argument.
|
/// Format this placeholder argument.
|
||||||
|
@ -181,7 +189,7 @@ impl Argument<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) const fn as_usize(&self) -> Option<usize> {
|
pub(super) const fn as_u16(&self) -> Option<u16> {
|
||||||
match self.ty {
|
match self.ty {
|
||||||
ArgumentType::Count(count) => Some(count),
|
ArgumentType::Count(count) => Some(count),
|
||||||
ArgumentType::Placeholder { .. } => None,
|
ArgumentType::Placeholder { .. } => None,
|
||||||
|
|
|
@ -1377,7 +1377,8 @@ impl fmt::Debug for Duration {
|
||||||
} else {
|
} else {
|
||||||
// We need to add padding. Use the `Formatter::padding` helper function.
|
// We need to add padding. Use the `Formatter::padding` helper function.
|
||||||
let default_align = fmt::Alignment::Left;
|
let default_align = fmt::Alignment::Left;
|
||||||
let post_padding = f.padding(requested_w - actual_w, default_align)?;
|
let post_padding =
|
||||||
|
f.padding((requested_w - actual_w) as u16, default_align)?;
|
||||||
emit_without_padding(f)?;
|
emit_without_padding(f)?;
|
||||||
post_padding.write(f)
|
post_padding.write(f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,7 +577,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// very large output
|
// very large output
|
||||||
assert_eq!(to_string(f, 1.1, Minus, 80000), format!("1.1{:0>79999}", ""));
|
assert_eq!(to_string(f, 1.1, Minus, 50000), format!("1.1{:0>49999}", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_shortest_exp_str_test<F>(mut f_: F)
|
pub fn to_shortest_exp_str_test<F>(mut f_: F)
|
||||||
|
@ -914,22 +914,22 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
// very large output
|
// very large output
|
||||||
assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", ""));
|
assert_eq!(to_string(f, 0.0, Minus, 50000, false), format!("0.{:0>49999}e0", ""));
|
||||||
assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", ""));
|
assert_eq!(to_string(f, 1.0e1, Minus, 50000, false), format!("1.{:0>49999}e1", ""));
|
||||||
assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", ""));
|
assert_eq!(to_string(f, 1.0e0, Minus, 50000, false), format!("1.{:0>49999}e0", ""));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_string(f, 1.0e-1, Minus, 80000, false),
|
to_string(f, 1.0e-1, Minus, 50000, false),
|
||||||
format!(
|
format!(
|
||||||
"1.000000000000000055511151231257827021181583404541015625{:0>79945}\
|
"1.000000000000000055511151231257827021181583404541015625{:0>49945}\
|
||||||
e-1",
|
e-1",
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_string(f, 1.0e-20, Minus, 80000, false),
|
to_string(f, 1.0e-20, Minus, 50000, false),
|
||||||
format!(
|
format!(
|
||||||
"9.999999999999999451532714542095716517295037027873924471077157760\
|
"9.999999999999999451532714542095716517295037027873924471077157760\
|
||||||
66783064379706047475337982177734375{:0>79901}e-21",
|
66783064379706047475337982177734375{:0>49901}e-21",
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -1150,18 +1150,18 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
// very large output
|
// very large output
|
||||||
assert_eq!(to_string(f, 0.0, Minus, 80000), format!("0.{:0>80000}", ""));
|
assert_eq!(to_string(f, 0.0, Minus, 50000), format!("0.{:0>50000}", ""));
|
||||||
assert_eq!(to_string(f, 1.0e1, Minus, 80000), format!("10.{:0>80000}", ""));
|
assert_eq!(to_string(f, 1.0e1, Minus, 50000), format!("10.{:0>50000}", ""));
|
||||||
assert_eq!(to_string(f, 1.0e0, Minus, 80000), format!("1.{:0>80000}", ""));
|
assert_eq!(to_string(f, 1.0e0, Minus, 50000), format!("1.{:0>50000}", ""));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_string(f, 1.0e-1, Minus, 80000),
|
to_string(f, 1.0e-1, Minus, 50000),
|
||||||
format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "")
|
format!("0.1000000000000000055511151231257827021181583404541015625{:0>49945}", "")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_string(f, 1.0e-20, Minus, 80000),
|
to_string(f, 1.0e-20, Minus, 50000),
|
||||||
format!(
|
format!(
|
||||||
"0.0000000000000000000099999999999999994515327145420957165172950370\
|
"0.0000000000000000000099999999999999994515327145420957165172950370\
|
||||||
2787392447107715776066783064379706047475337982177734375{:0>79881}",
|
2787392447107715776066783064379706047475337982177734375{:0>49881}",
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -137,7 +137,7 @@ pub enum FormatAlignment {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum FormatCount {
|
pub enum FormatCount {
|
||||||
/// `{:5}` or `{:.5}`
|
/// `{:5}` or `{:.5}`
|
||||||
Literal(usize),
|
Literal(u16),
|
||||||
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
||||||
Argument(FormatArgPosition),
|
Argument(FormatArgPosition),
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,16 @@
|
||||||
debug precision => _8;
|
debug precision => _8;
|
||||||
let _8: usize;
|
let _8: usize;
|
||||||
scope 5 (inlined Formatter::<'_>::precision) {
|
scope 5 (inlined Formatter::<'_>::precision) {
|
||||||
|
let mut _22: std::option::Option<u16>;
|
||||||
|
scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
|
||||||
|
let mut _23: isize;
|
||||||
|
let _24: u16;
|
||||||
|
let mut _25: usize;
|
||||||
|
scope 7 {
|
||||||
|
scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +75,12 @@
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
|
StorageLive(_24);
|
||||||
_7 = discriminant(_6);
|
StorageLive(_22);
|
||||||
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
|
_22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = discriminant(_22);
|
||||||
|
switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
@ -135,7 +148,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
|
StorageDead(_24);
|
||||||
|
_7 = discriminant(_6);
|
||||||
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb10: {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb11: {
|
||||||
|
_6 = const Option::<usize>::None;
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb12: {
|
||||||
|
_24 = move ((_22 as Some).0: u16);
|
||||||
|
StorageLive(_25);
|
||||||
|
_25 = copy _24 as usize (IntToInt);
|
||||||
|
_6 = Option::<usize>::Some(move _25);
|
||||||
|
StorageDead(_25);
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALLOC0 (size: 8, align: 4) {
|
||||||
|
00 00 00 00 __ __ __ __ │ ....░░░░
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,16 @@
|
||||||
debug precision => _8;
|
debug precision => _8;
|
||||||
let _8: usize;
|
let _8: usize;
|
||||||
scope 5 (inlined Formatter::<'_>::precision) {
|
scope 5 (inlined Formatter::<'_>::precision) {
|
||||||
|
let mut _22: std::option::Option<u16>;
|
||||||
|
scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
|
||||||
|
let mut _23: isize;
|
||||||
|
let _24: u16;
|
||||||
|
let mut _25: usize;
|
||||||
|
scope 7 {
|
||||||
|
scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +75,12 @@
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
|
StorageLive(_24);
|
||||||
_7 = discriminant(_6);
|
StorageLive(_22);
|
||||||
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
|
_22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = discriminant(_22);
|
||||||
|
switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
@ -135,7 +148,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
|
StorageDead(_24);
|
||||||
|
_7 = discriminant(_6);
|
||||||
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb10: {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb11: {
|
||||||
|
_6 = const Option::<usize>::None;
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb12: {
|
||||||
|
_24 = move ((_22 as Some).0: u16);
|
||||||
|
StorageLive(_25);
|
||||||
|
_25 = copy _24 as usize (IntToInt);
|
||||||
|
_6 = Option::<usize>::Some(move _25);
|
||||||
|
StorageDead(_25);
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALLOC0 (size: 8, align: 4) {
|
||||||
|
00 00 00 00 __ __ __ __ │ ....░░░░
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
- // MIR for `float_to_exponential_common` before GVN
|
||||||
|
+ // MIR for `float_to_exponential_common` after GVN
|
||||||
|
|
||||||
|
fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
|
||||||
|
debug fmt => _1;
|
||||||
|
debug num => _2;
|
||||||
|
debug upper => _3;
|
||||||
|
let mut _0: std::result::Result<(), std::fmt::Error>;
|
||||||
|
let _4: bool;
|
||||||
|
let mut _6: std::option::Option<usize>;
|
||||||
|
let mut _7: isize;
|
||||||
|
let mut _9: &mut std::fmt::Formatter<'_>;
|
||||||
|
let mut _10: &T;
|
||||||
|
let mut _11: core::num::flt2dec::Sign;
|
||||||
|
let mut _12: u32;
|
||||||
|
let mut _13: u32;
|
||||||
|
let mut _14: usize;
|
||||||
|
let mut _15: bool;
|
||||||
|
let mut _16: &mut std::fmt::Formatter<'_>;
|
||||||
|
let mut _17: &T;
|
||||||
|
let mut _18: core::num::flt2dec::Sign;
|
||||||
|
let mut _19: bool;
|
||||||
|
scope 1 {
|
||||||
|
debug force_sign => _4;
|
||||||
|
let _5: core::num::flt2dec::Sign;
|
||||||
|
scope 2 {
|
||||||
|
debug sign => _5;
|
||||||
|
scope 3 {
|
||||||
|
debug precision => _8;
|
||||||
|
let _8: usize;
|
||||||
|
scope 5 (inlined Formatter::<'_>::precision) {
|
||||||
|
let mut _22: std::option::Option<u16>;
|
||||||
|
scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
|
||||||
|
let mut _23: isize;
|
||||||
|
let _24: u16;
|
||||||
|
let mut _25: usize;
|
||||||
|
scope 7 {
|
||||||
|
scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope 4 (inlined Formatter::<'_>::sign_plus) {
|
||||||
|
let mut _20: u32;
|
||||||
|
let mut _21: u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_20);
|
||||||
|
StorageLive(_21);
|
||||||
|
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
|
||||||
|
_20 = BitAnd(move _21, const 1_u32);
|
||||||
|
StorageDead(_21);
|
||||||
|
_4 = Ne(move _20, const 0_u32);
|
||||||
|
StorageDead(_20);
|
||||||
|
StorageLive(_5);
|
||||||
|
switchInt(copy _4) -> [0: bb2, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
- _5 = MinusPlus;
|
||||||
|
+ _5 = const MinusPlus;
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
- _5 = core::num::flt2dec::Sign::Minus;
|
||||||
|
+ _5 = const core::num::flt2dec::Sign::Minus;
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_24);
|
||||||
|
StorageLive(_22);
|
||||||
|
_22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = discriminant(_22);
|
||||||
|
switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
- StorageLive(_8);
|
||||||
|
+ nop;
|
||||||
|
_8 = copy ((_6 as Some).0: usize);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = copy _1;
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = copy _2;
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = copy _5;
|
||||||
|
StorageLive(_12);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = copy _8;
|
||||||
|
- _13 = move _14 as u32 (IntToInt);
|
||||||
|
+ _13 = copy _8 as u32 (IntToInt);
|
||||||
|
StorageDead(_14);
|
||||||
|
_12 = Add(move _13, const 1_u32);
|
||||||
|
StorageDead(_13);
|
||||||
|
StorageLive(_15);
|
||||||
|
_15 = copy _3;
|
||||||
|
- _0 = float_to_exponential_common_exact::<T>(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable];
|
||||||
|
+ _0 = float_to_exponential_common_exact::<T>(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageDead(_12);
|
||||||
|
StorageDead(_11);
|
||||||
|
StorageDead(_10);
|
||||||
|
StorageDead(_9);
|
||||||
|
- StorageDead(_8);
|
||||||
|
+ nop;
|
||||||
|
goto -> bb8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageLive(_16);
|
||||||
|
_16 = copy _1;
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = copy _2;
|
||||||
|
StorageLive(_18);
|
||||||
|
_18 = copy _5;
|
||||||
|
StorageLive(_19);
|
||||||
|
_19 = copy _3;
|
||||||
|
- _0 = float_to_exponential_common_shortest::<T>(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable];
|
||||||
|
+ _0 = float_to_exponential_common_shortest::<T>(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_19);
|
||||||
|
StorageDead(_18);
|
||||||
|
StorageDead(_17);
|
||||||
|
StorageDead(_16);
|
||||||
|
goto -> bb8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb8: {
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageDead(_4);
|
||||||
|
StorageDead(_6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb9: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
|
StorageDead(_24);
|
||||||
|
_7 = discriminant(_6);
|
||||||
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb10: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb11: {
|
||||||
|
_6 = const Option::<usize>::None;
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb12: {
|
||||||
|
_24 = move ((_22 as Some).0: u16);
|
||||||
|
StorageLive(_25);
|
||||||
|
_25 = copy _24 as usize (IntToInt);
|
||||||
|
_6 = Option::<usize>::Some(move _25);
|
||||||
|
StorageDead(_25);
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALLOC0 (size: 16, align: 8) {
|
||||||
|
00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
- // MIR for `float_to_exponential_common` before GVN
|
||||||
|
+ // MIR for `float_to_exponential_common` after GVN
|
||||||
|
|
||||||
|
fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
|
||||||
|
debug fmt => _1;
|
||||||
|
debug num => _2;
|
||||||
|
debug upper => _3;
|
||||||
|
let mut _0: std::result::Result<(), std::fmt::Error>;
|
||||||
|
let _4: bool;
|
||||||
|
let mut _6: std::option::Option<usize>;
|
||||||
|
let mut _7: isize;
|
||||||
|
let mut _9: &mut std::fmt::Formatter<'_>;
|
||||||
|
let mut _10: &T;
|
||||||
|
let mut _11: core::num::flt2dec::Sign;
|
||||||
|
let mut _12: u32;
|
||||||
|
let mut _13: u32;
|
||||||
|
let mut _14: usize;
|
||||||
|
let mut _15: bool;
|
||||||
|
let mut _16: &mut std::fmt::Formatter<'_>;
|
||||||
|
let mut _17: &T;
|
||||||
|
let mut _18: core::num::flt2dec::Sign;
|
||||||
|
let mut _19: bool;
|
||||||
|
scope 1 {
|
||||||
|
debug force_sign => _4;
|
||||||
|
let _5: core::num::flt2dec::Sign;
|
||||||
|
scope 2 {
|
||||||
|
debug sign => _5;
|
||||||
|
scope 3 {
|
||||||
|
debug precision => _8;
|
||||||
|
let _8: usize;
|
||||||
|
scope 5 (inlined Formatter::<'_>::precision) {
|
||||||
|
let mut _22: std::option::Option<u16>;
|
||||||
|
scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
|
||||||
|
let mut _23: isize;
|
||||||
|
let _24: u16;
|
||||||
|
let mut _25: usize;
|
||||||
|
scope 7 {
|
||||||
|
scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope 4 (inlined Formatter::<'_>::sign_plus) {
|
||||||
|
let mut _20: u32;
|
||||||
|
let mut _21: u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_20);
|
||||||
|
StorageLive(_21);
|
||||||
|
_21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
|
||||||
|
_20 = BitAnd(move _21, const 1_u32);
|
||||||
|
StorageDead(_21);
|
||||||
|
_4 = Ne(move _20, const 0_u32);
|
||||||
|
StorageDead(_20);
|
||||||
|
StorageLive(_5);
|
||||||
|
switchInt(copy _4) -> [0: bb2, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
- _5 = MinusPlus;
|
||||||
|
+ _5 = const MinusPlus;
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
- _5 = core::num::flt2dec::Sign::Minus;
|
||||||
|
+ _5 = const core::num::flt2dec::Sign::Minus;
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_24);
|
||||||
|
StorageLive(_22);
|
||||||
|
_22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = discriminant(_22);
|
||||||
|
switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
- StorageLive(_8);
|
||||||
|
+ nop;
|
||||||
|
_8 = copy ((_6 as Some).0: usize);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = copy _1;
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = copy _2;
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = copy _5;
|
||||||
|
StorageLive(_12);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = copy _8;
|
||||||
|
- _13 = move _14 as u32 (IntToInt);
|
||||||
|
+ _13 = copy _8 as u32 (IntToInt);
|
||||||
|
StorageDead(_14);
|
||||||
|
_12 = Add(move _13, const 1_u32);
|
||||||
|
StorageDead(_13);
|
||||||
|
StorageLive(_15);
|
||||||
|
_15 = copy _3;
|
||||||
|
- _0 = float_to_exponential_common_exact::<T>(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue];
|
||||||
|
+ _0 = float_to_exponential_common_exact::<T>(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageDead(_12);
|
||||||
|
StorageDead(_11);
|
||||||
|
StorageDead(_10);
|
||||||
|
StorageDead(_9);
|
||||||
|
- StorageDead(_8);
|
||||||
|
+ nop;
|
||||||
|
goto -> bb8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageLive(_16);
|
||||||
|
_16 = copy _1;
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = copy _2;
|
||||||
|
StorageLive(_18);
|
||||||
|
_18 = copy _5;
|
||||||
|
StorageLive(_19);
|
||||||
|
_19 = copy _3;
|
||||||
|
- _0 = float_to_exponential_common_shortest::<T>(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue];
|
||||||
|
+ _0 = float_to_exponential_common_shortest::<T>(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_19);
|
||||||
|
StorageDead(_18);
|
||||||
|
StorageDead(_17);
|
||||||
|
StorageDead(_16);
|
||||||
|
goto -> bb8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb8: {
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageDead(_4);
|
||||||
|
StorageDead(_6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb9: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
|
StorageDead(_24);
|
||||||
|
_7 = discriminant(_6);
|
||||||
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb10: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb11: {
|
||||||
|
_6 = const Option::<usize>::None;
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb12: {
|
||||||
|
_24 = move ((_22 as Some).0: u16);
|
||||||
|
StorageLive(_25);
|
||||||
|
_25 = copy _24 as usize (IntToInt);
|
||||||
|
_6 = Option::<usize>::Some(move _25);
|
||||||
|
StorageDead(_25);
|
||||||
|
goto -> bb9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALLOC0 (size: 16, align: 8) {
|
||||||
|
00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// skip-filecheck
|
// skip-filecheck
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||||
|
|
||||||
#![feature(flt2dec)]
|
#![feature(flt2dec)]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue