From fb9ce0297682a0c54fe374800c2a41cc666d9580 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 12 Feb 2025 16:59:13 +0100 Subject: [PATCH 1/6] Limit formatting width and precision to 16 bits. --- compiler/rustc_ast/src/format.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 11 +++++ compiler/rustc_ast_lowering/src/format.rs | 2 +- compiler/rustc_parse_format/src/lib.rs | 18 ++++---- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/fmt/float.rs | 12 ++--- library/core/src/fmt/mod.rs | 51 ++++++++++++---------- library/core/src/fmt/rt.rs | 13 ++++-- library/core/src/time.rs | 3 +- library/coretests/tests/num/flt2dec/mod.rs | 2 +- 10 files changed, 69 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index b93846c1fe6f3..b611ddea1d9f1 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -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), } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index acf35b75e4df3..0f175ea615f6e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2152,6 +2152,17 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(sp, hir::ExprKind::Lit(lit)) } + pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> 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::U16), + ), + }); + self.expr(sp, hir::ExprKind::Lit(lit)) + } + pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) }); self.expr(sp, hir::ExprKind::Lit(lit)) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 07b94dbc2aebd..faa47274f96ce 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -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)) => { diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 287bd8678da25..5b8a2fe52d3f5 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -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. @@ -564,7 +564,7 @@ impl<'a> Parser<'a> { /// consuming a macro argument, `None` if it's the case. fn position(&mut self) -> Option> { 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) => { @@ -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(); @@ -821,15 +821,15 @@ impl<'a> Parser<'a> { word } - fn integer(&mut self) -> Option { - let mut cur: usize = 0; + fn integer(&mut self) -> Option { + 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; } @@ -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), ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9e7f5047eb30c..8b701de34545c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1016,6 +1016,7 @@ symbols! { from_residual, from_size_align_unchecked, from_str_method, + from_u16, from_usize, from_yeet, fs_create_dir, diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 3f10158193d76..4a43c12be9aaa 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -29,7 +29,7 @@ fn float_to_decimal_common_exact( fmt: &mut Formatter<'_>, num: &T, sign: flt2dec::Sign, - precision: usize, + precision: u16, ) -> Result where T: flt2dec::DecodableFloat, @@ -40,7 +40,7 @@ where flt2dec::strategy::grisu::format_exact, *num, sign, - precision, + precision.into(), &mut buf, &mut parts, ); @@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest( fmt: &mut Formatter<'_>, num: &T, sign: flt2dec::Sign, - precision: usize, + precision: u16, ) -> Result where T: flt2dec::DecodableFloat, @@ -68,7 +68,7 @@ where flt2dec::strategy::grisu::format_shortest, *num, sign, - precision, + precision.into(), &mut buf, &mut parts, ); @@ -101,7 +101,7 @@ fn float_to_exponential_common_exact( fmt: &mut Formatter<'_>, num: &T, sign: flt2dec::Sign, - precision: usize, + precision: u16, upper: bool, ) -> Result where @@ -113,7 +113,7 @@ where flt2dec::strategy::grisu::format_exact, *num, sign, - precision, + precision.into(), upper, &mut buf, &mut parts, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 3f60bb067d6e6..e0dc632df7051 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -294,8 +294,8 @@ pub struct FormattingOptions { flags: u32, fill: char, align: Option, - width: Option, - precision: Option, + width: Option, + precision: Option, } impl FormattingOptions { @@ -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) -> &mut Self { + pub fn width(&mut self, width: Option) -> &mut Self { self.width = width; self } @@ -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) -> &mut Self { + pub fn precision(&mut self, precision: Option) -> &mut Self { self.precision = precision; self } @@ -455,12 +455,12 @@ impl FormattingOptions { } /// Returns the current width. #[unstable(feature = "formatting_options", issue = "118117")] - pub const fn get_width(&self) -> Option { + pub const fn get_width(&self) -> Option { self.width } /// Returns the current precision. #[unstable(feature = "formatting_options", issue = "118117")] - pub const fn get_precision(&self) -> Option { + pub const fn get_precision(&self) -> Option { self.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 fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { +unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { 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() } } } } @@ -1516,11 +1519,11 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option #[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 } } @@ -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) } @@ -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; @@ -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) @@ -1702,14 +1705,14 @@ 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()) @@ -1717,11 +1720,11 @@ impl<'a> Formatter<'a> { // 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 { @@ -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 { let align = self.align().unwrap_or(default); @@ -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)?; @@ -2021,7 +2024,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option { - self.options.width + self.options.width.map(|x| x as usize) } /// Returns the optionally specified precision for numeric types. @@ -2052,7 +2055,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option { - self.options.precision + self.options.precision.map(|x| x as usize) } /// 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); 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); diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 85d089a079082..cb908adc1cbaf 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -47,7 +47,11 @@ pub enum Alignment { #[derive(Copy, Clone)] pub enum Count { /// Specified with a literal number, stores the value + #[cfg(bootstrap)] Is(usize), + /// Specified with a literal number, stores the value + #[cfg(not(bootstrap))] + Is(u16), /// Specified using `$` and `*` syntaxes, stores the index into `args` Param(usize), /// Not specified @@ -74,7 +78,7 @@ enum ArgumentType<'a> { formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result, _lifetime: PhantomData<&'a ()>, }, - Count(usize), + Count(u16), } /// This struct represents a generic "argument" which is taken by format_args!(). @@ -151,7 +155,10 @@ impl Argument<'_> { } #[inline] 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. @@ -181,7 +188,7 @@ impl Argument<'_> { } #[inline] - pub(super) const fn as_usize(&self) -> Option { + pub(super) const fn as_u16(&self) -> Option { match self.ty { ArgumentType::Count(count) => Some(count), ArgumentType::Placeholder { .. } => None, diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 8b211b442eab6..37b5c1076fa2a 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -1377,7 +1377,8 @@ impl fmt::Debug for Duration { } else { // We need to add padding. Use the `Formatter::padding` helper function. 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)?; post_padding.write(f) } diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs index 6041923117c2a..6e74cc91c5b27 100644 --- a/library/coretests/tests/num/flt2dec/mod.rs +++ b/library/coretests/tests/num/flt2dec/mod.rs @@ -577,7 +577,7 @@ where } // 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(mut f_: F) From 4374d5461e9a4041dcbd7413c79fced0bec333fc Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 12 Feb 2025 17:33:05 +0100 Subject: [PATCH 2/6] Update tests. --- library/coretests/tests/num/flt2dec/mod.rs | 28 +-- ...nential_common.GVN.32bit.panic-abort.diff} | 45 ++++- ...ential_common.GVN.32bit.panic-unwind.diff} | 45 ++++- ...onential_common.GVN.64bit.panic-abort.diff | 180 ++++++++++++++++++ ...nential_common.GVN.64bit.panic-unwind.diff | 180 ++++++++++++++++++ tests/mir-opt/funky_arms.rs | 1 + 6 files changed, 459 insertions(+), 20 deletions(-) rename tests/mir-opt/{funky_arms.float_to_exponential_common.GVN.panic-abort.diff => funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff} (73%) rename tests/mir-opt/{funky_arms.float_to_exponential_common.GVN.panic-unwind.diff => funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff} (73%) create mode 100644 tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff create mode 100644 tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs index 6e74cc91c5b27..c64bb0a30720a 100644 --- a/library/coretests/tests/num/flt2dec/mod.rs +++ b/library/coretests/tests/num/flt2dec/mod.rs @@ -914,22 +914,22 @@ where ); // very large output - assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", "")); - assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", "")); - assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{: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, 50000, false), format!("1.{:0>49999}e1", "")); + assert_eq!(to_string(f, 1.0e0, Minus, 50000, false), format!("1.{:0>49999}e0", "")); assert_eq!( - to_string(f, 1.0e-1, Minus, 80000, false), + to_string(f, 1.0e-1, Minus, 50000, false), format!( - "1.000000000000000055511151231257827021181583404541015625{:0>79945}\ + "1.000000000000000055511151231257827021181583404541015625{:0>49945}\ e-1", "" ) ); assert_eq!( - to_string(f, 1.0e-20, Minus, 80000, false), + to_string(f, 1.0e-20, Minus, 50000, false), format!( "9.999999999999999451532714542095716517295037027873924471077157760\ - 66783064379706047475337982177734375{:0>79901}e-21", + 66783064379706047475337982177734375{:0>49901}e-21", "" ) ); @@ -1150,18 +1150,18 @@ where ); // very large output - assert_eq!(to_string(f, 0.0, Minus, 80000), format!("0.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e1, Minus, 80000), format!("10.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e0, Minus, 80000), format!("1.{:0>80000}", "")); + assert_eq!(to_string(f, 0.0, Minus, 50000), format!("0.{:0>50000}", "")); + assert_eq!(to_string(f, 1.0e1, Minus, 50000), format!("10.{:0>50000}", "")); + assert_eq!(to_string(f, 1.0e0, Minus, 50000), format!("1.{:0>50000}", "")); assert_eq!( - to_string(f, 1.0e-1, Minus, 80000), - format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "") + to_string(f, 1.0e-1, Minus, 50000), + format!("0.1000000000000000055511151231257827021181583404541015625{:0>49945}", "") ); assert_eq!( - to_string(f, 1.0e-20, Minus, 80000), + to_string(f, 1.0e-20, Minus, 50000), format!( "0.0000000000000000000099999999999999994515327145420957165172950370\ - 2787392447107715776066783064379706047475337982177734375{:0>79881}", + 2787392447107715776066783064379706047475337982177734375{:0>49881}", "" ) ); diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff similarity index 73% rename from tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff rename to tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff index a1be927e1c04a..45fc7365d8d6c 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff @@ -29,6 +29,16 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { + let mut _22: std::option::Option; + scope 6 (inlined Option::::map::::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: { StorageLive(_6); - _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); - _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; + StorageLive(_24); + StorageLive(_22); + _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); + StorageLive(_23); + _23 = discriminant(_22); + switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; } bb4: { @@ -135,7 +148,33 @@ } 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::::None; + goto -> bb9; + } + + bb12: { + _24 = move ((_22 as Some).0: u16); + StorageLive(_25); + _25 = copy _24 as usize (IntToInt); + _6 = Option::::Some(move _25); + StorageDead(_25); + goto -> bb9; + } + } + + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff similarity index 73% rename from tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff rename to tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff index 87ab71feb2faa..578d2c2194b0e 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff @@ -29,6 +29,16 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { + let mut _22: std::option::Option; + scope 6 (inlined Option::::map::::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: { StorageLive(_6); - _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); - _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; + StorageLive(_24); + StorageLive(_22); + _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); + StorageLive(_23); + _23 = discriminant(_22); + switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; } bb4: { @@ -135,7 +148,33 @@ } 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::::None; + goto -> bb9; + } + + bb12: { + _24 = move ((_22 as Some).0: u16); + StorageLive(_25); + _25 = copy _24 as usize (IntToInt); + _6 = Option::::Some(move _25); + StorageDead(_25); + goto -> bb9; + } + } + + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff new file mode 100644 index 0000000000000..5f0f7d6cc74fb --- /dev/null +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff @@ -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; + 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; + scope 6 (inlined Option::::map::::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); + 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::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable]; ++ _0 = float_to_exponential_common_exact::(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::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable]; ++ _0 = float_to_exponential_common_shortest::(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::::None; + goto -> bb9; + } + + bb12: { + _24 = move ((_22 as Some).0: u16); + StorageLive(_25); + _25 = copy _24 as usize (IntToInt); + _6 = Option::::Some(move _25); + StorageDead(_25); + goto -> bb9; + } + } + + ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ + } + diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff new file mode 100644 index 0000000000000..10cc46a8b8285 --- /dev/null +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff @@ -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; + 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; + scope 6 (inlined Option::::map::::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); + 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::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue]; ++ _0 = float_to_exponential_common_exact::(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::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue]; ++ _0 = float_to_exponential_common_shortest::(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::::None; + goto -> bb9; + } + + bb12: { + _24 = move ((_22 as Some).0: u16); + StorageLive(_25); + _25 = copy _24 as usize (IntToInt); + _6 = Option::::Some(move _25); + StorageDead(_25); + goto -> bb9; + } + } + + ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ + } + diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs index fc3691049eb4a..403a22ebed320 100644 --- a/tests/mir-opt/funky_arms.rs +++ b/tests/mir-opt/funky_arms.rs @@ -1,5 +1,6 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// EMIT_MIR_FOR_EACH_BIT_WIDTH #![feature(flt2dec)] From ce512c2e4d0dc72f0b7cd17896c2c4e4ea8acfe5 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 12 Feb 2025 18:17:28 +0100 Subject: [PATCH 3/6] Fix rust-analyzer for 16-bit fmt width and precision. --- src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 28c824fd31d73..24badc52f25ac 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -137,7 +137,7 @@ pub enum FormatAlignment { #[derive(Clone, Debug, PartialEq, Eq)] pub enum FormatCount { /// `{:5}` or `{:.5}` - Literal(usize), + Literal(u16), /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc. Argument(FormatArgPosition), } From 7677567e54285312c133b135821409f8cf3fa636 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Feb 2025 12:49:20 +0100 Subject: [PATCH 4/6] Remove unnecessary semicolon. --- library/core/src/fmt/rt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index cb908adc1cbaf..a45875ba57c34 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -157,7 +157,7 @@ impl Argument<'_> { pub const fn from_usize(x: &usize) -> Argument<'_> { if *x > u16::MAX as usize { panic!("Formatting argument out of range"); - }; + } Argument { ty: ArgumentType::Count(*x as u16) } } From 2647cf17e75346ed50042a1ebe28aa3137a5544e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Feb 2025 12:49:28 +0100 Subject: [PATCH 5/6] Add #[track_caller] to from_usize. --- library/core/src/fmt/rt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index a45875ba57c34..080fc6ddfc9b8 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -154,6 +154,7 @@ impl Argument<'_> { Self::new(x, UpperExp::fmt) } #[inline] + #[track_caller] pub const fn from_usize(x: &usize) -> Argument<'_> { if *x > u16::MAX as usize { panic!("Formatting argument out of range"); From 2ce0205735afce776f402eb96f85759906959473 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 10 Mar 2025 13:57:23 +0100 Subject: [PATCH 6/6] Share implementation of expr_u{16,32,size}. --- compiler/rustc_ast_lowering/src/expr.rs | 29 +++++++------------------ 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0f175ea615f6e..5bb6704dde45a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2130,37 +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> { - let lit = self.arena.alloc(hir::Lit { - span: sp, - node: ast::LitKind::Int( - u128::from(value).into(), - ast::LitIntType::Unsigned(ast::UintTy::U16), - ), - }); - self.expr(sp, hir::ExprKind::Lit(lit)) + self.expr_uint(sp, ast::UintTy::U16, value as u128) } pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {