Skip to content

Commit cf79eec

Browse files
committed
Auto merge of rust-lang#106824 - m-ou-se:format-args-flatten, r=oli-obk
Flatten/inline format_args!() and (string and int) literal arguments into format_args!() Implements rust-lang#78356 Gated behind `-Zflatten-format-args=yes`. Part of rust-lang#99012 This change inlines string literals, integer literals and nested format_args!() into format_args!() during ast lowering, making all of the following pairs result in equivalent hir: ```rust println!("Hello, {}!", "World"); println!("Hello, World!"); ``` ```rust println!("[info] {}", format_args!("error")); println!("[info] error"); ``` ```rust println!("[{}] {}", status, format_args!("error: {}", msg)); println!("[{}] error: {}", status, msg); ``` ```rust println!("{} + {} = {}", 1, 2, 1 + 2); println!("1 + 2 = {}", 1 + 2); ``` And so on. This is useful for macros. E.g. a `log::info!()` macro could just pass the tokens from the user directly into a `format_args!()` that gets efficiently flattened/inlined into a `format_args!("info: {}")`. It also means that `dbg!(x)` will have its file, line, and expression name inlined: ```rust eprintln!("[{}:{}] {} = {:#?}", file!(), line!(), stringify!(x), x); // before eprintln!("[example.rs:1] x = {:#?}", x); // after ``` Which can be nice in some cases, but also means a lot more unique static strings than before if dbg!() is used a lot.
2 parents 7392f8f + 5da3837 commit cf79eec

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

core/src/fmt/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,31 @@ enum FlagV1 {
392392
}
393393

394394
impl<'a> Arguments<'a> {
395+
#[doc(hidden)]
396+
#[inline]
397+
#[unstable(feature = "fmt_internals", issue = "none")]
398+
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
399+
pub const fn new_const(pieces: &'a [&'static str]) -> Self {
400+
if pieces.len() > 1 {
401+
panic!("invalid args");
402+
}
403+
Arguments { pieces, fmt: None, args: &[] }
404+
}
405+
395406
/// When using the format_args!() macro, this function is used to generate the
396407
/// Arguments structure.
408+
#[cfg(not(bootstrap))]
409+
#[doc(hidden)]
410+
#[inline]
411+
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
412+
pub fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
413+
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
414+
panic!("invalid args");
415+
}
416+
Arguments { pieces, fmt: None, args }
417+
}
418+
419+
#[cfg(bootstrap)]
397420
#[doc(hidden)]
398421
#[inline]
399422
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -417,8 +440,7 @@ impl<'a> Arguments<'a> {
417440
#[doc(hidden)]
418441
#[inline]
419442
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
420-
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
421-
pub const fn new_v1_formatted(
443+
pub fn new_v1_formatted(
422444
pieces: &'a [&'static str],
423445
args: &'a [ArgumentV1<'a>],
424446
fmt: &'a [rt::v1::Argument],

core/src/panicking.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub const fn panic(expr: &'static str) -> ! {
111111
// truncation and padding (even though none is used here). Using
112112
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
113113
// output binary, saving up to a few kilobytes.
114-
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
114+
panic_fmt(fmt::Arguments::new_const(&[expr]));
115115
}
116116

117117
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
@@ -120,7 +120,7 @@ pub const fn panic(expr: &'static str) -> ! {
120120
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
121121
#[rustc_nounwind]
122122
pub fn panic_nounwind(expr: &'static str) -> ! {
123-
panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
123+
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
124124
}
125125

126126
#[inline]

core/tests/fmt/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ fn test_pointer_formats_data_pointer() {
2222
#[test]
2323
fn test_estimated_capacity() {
2424
assert_eq!(format_args!("").estimated_capacity(), 0);
25-
assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
25+
assert_eq!(format_args!("{}", {""}).estimated_capacity(), 0);
2626
assert_eq!(format_args!("Hello").estimated_capacity(), 5);
27-
assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
28-
assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
29-
assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
27+
assert_eq!(format_args!("Hello, {}!", {""}).estimated_capacity(), 16);
28+
assert_eq!(format_args!("{}, hello!", {"World"}).estimated_capacity(), 0);
29+
assert_eq!(format_args!("{}. 16-bytes piece", {"World"}).estimated_capacity(), 32);
3030
}
3131

3232
#[test]

0 commit comments

Comments
 (0)