Skip to content

Enable flatten-format-args by default. #109999

New issue

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

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

Already on GitHub? # to your account

Merged
merged 3 commits into from
Apr 21, 2023
Merged

Conversation

m-ou-se
Copy link
Member

@m-ou-se m-ou-se commented Apr 6, 2023

Part of #99012.

This enables the flatten-format-args feature that was added by #106824:

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:

println!("Hello, {}!", "World");
println!("Hello, World!");
println!("[info] {}", format_args!("error"));
println!("[info] error");
println!("[{}] {}", status, format_args!("error: {}", msg));
println!("[{}] error: {}", status, msg);
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:

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.

This is mostly an optimization, except that it will be visible through fmt::Arguments::as_str().

In #106823, there was already a libs-api FCP about the documentation of fmt::Arguments::as_str() to allow it to give Some rather than None depending on optimizations like this. That was just a documentation update though. This PR is the one that actually makes the user visible change:

assert_eq!(format_args!("abc").as_str(), Some("abc")); // Unchanged.
assert_eq!(format_args!("ab{}", "c").as_str(), Some("abc")); // Was `None` before!

@m-ou-se m-ou-se added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-fmt Area: `core::fmt` labels Apr 6, 2023
@m-ou-se m-ou-se self-assigned this Apr 6, 2023
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 6, 2023
@rust-log-analyzer

This comment was marked as outdated.

@m-ou-se m-ou-se added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 6, 2023
@m-ou-se m-ou-se force-pushed the flatten-format-args branch from c551788 to a77d39b Compare April 13, 2023 10:17
@m-ou-se m-ou-se added I-compiler-nominated Nominated for discussion during a compiler team meeting. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Apr 13, 2023
@m-ou-se m-ou-se marked this pull request as ready for review April 13, 2023 10:23
@nbdd0121
Copy link
Contributor

println!("[info] {}", format_args!("error"));
println!("[info] error");

It also means that dbg!(x) will have its file, line, and expression name inlined:

eprintln!("[{}:{}] {} = {:#?}", file!(), line!(), stringify!(x), x); // before
eprintln!("[example.rs:1] x = {:#?}", x); // after

I am a bit worried about these two cases because these are not achievable by proc macros, and thus would make format_args properly part of the language:

  • For flattening format_args, a proc macro wouldn't be able to tell which macro the nested format_args resolve to, but the std one can;
  • For inlining file!(), proc macro would need to rely on proc_macro_expand feature which is not stable.

@rustbot

This comment was marked as resolved.

@m-ou-se
Copy link
Member Author

m-ou-se commented Apr 13, 2023

these are not achievable by proc macros

Note that pin!() and addr_of!() and file!() and include_str!() and env!() and many more macros are also not fully achievable by proc macros. (You can get close, but you can't get the exact path that include_str!(path) is relative to, and you currently can't cause recompilation when a file or environment variable changes without those macros.)

I'm not saying that necessarily means that format_args!() also doesn't need to be procmacroable1. There is definitely value in a macro being 'just a regular macro', but there is no clear cut rule.

For flattening format_args, a proc macro wouldn't be able to tell which macro the nested format_args resolve to, but the std one can;

A proc macro my_format_args!() indeed wouldn't be able to do flattening perfectly correctly in cases like use …::my_format_args as x; x!("{}", x!("a"));, because it can't resolve that x, but it can get pretty close by simply triggering only on exactly my_format_args!, which could be good enough in practice. I imagine in the future, a proc macro could use the proc_macro_expand feature to expand the argument first to implement this properly.

For inlining file!(), proc macro would need to rely on proc_macro_expand feature which is not stable.

It's usually okay for a standard library macro to use something that's not yet stable. The TokenStream::expand_expr() API is a bit controversial for complicated expressions, but it doesn't seem to be controversial for token streams that expand to literals, which covers these cases.

Footnotes

  1. procmacroable /ˌprɔkˈmækroʊəbəl/ a. Implementable as a procedural macro.

@nbdd0121
Copy link
Contributor

I imagine in the future, a proc macro could use the proc_macro_expand feature to expand the argument first to implement this properly.

This is a quite convincing argument, and address my main worry that this would turn format_args into a language feature. I am less worried about expand_expr given that a handful of std macros also exhibit similar properties.

@rust-log-analyzer

This comment has been minimized.

@m-ou-se m-ou-se force-pushed the flatten-format-args branch from 87d942c to 63d8758 Compare April 17, 2023 11:45
@m-ou-se
Copy link
Member Author

m-ou-se commented Apr 18, 2023

r? @oli-obk

@rustbot rustbot assigned oli-obk and unassigned m-ou-se Apr 18, 2023
@m-ou-se m-ou-se removed the S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). label Apr 18, 2023
@oli-obk
Copy link
Contributor

oli-obk commented Apr 20, 2023

@bors r+

@bors
Copy link
Collaborator

bors commented Apr 20, 2023

📌 Commit 2cd5ce0 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 20, 2023
@bors
Copy link
Collaborator

bors commented Apr 20, 2023

⌛ Testing commit 2cd5ce0 with merge 7bcb998f019b911e8852347cce2433683f85e3ee...

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-apple-2 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling rustc_borrowck v0.0.0 (/Users/runner/work/rust/rust/compiler/rustc_borrowck)
[RUSTC-TIMING] rustc_lint test:false 132.987
   Compiling rustc_mir_transform v0.0.0 (/Users/runner/work/rust/rust/compiler/rustc_mir_transform)
[RUSTC-TIMING] rustc_mir_transform test:false 1.338
rustc exited with signal: 11 (SIGSEGV)

Caused by:
Caused by:
  process didn't exit successfully: `/Users/runner/work/rust/rust/build/bootstrap/debug/rustc --crate-name rustc_mir_transform --edition=2021 compiler/rustc_mir_transform/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C debuginfo=0 -Zunstable-options --check-cfg 'values(feature)' --check-cfg 'names()' --check-cfg 'values()' -C metadata=3d4d75e483bcdacb -C extra-filename=-3d4d75e483bcdacb --out-dir /Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps --target x86_64-apple-darwin -L dependency=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps -L dependency=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/release/deps --extern either=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libeither-33babc3eee1e2d05.rmeta --extern itertools=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libitertools-20432216ff4b6372.rmeta --extern rustc_ast=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_ast-3e13f597f7a74f97.rmeta --extern rustc_attr=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_attr-decb608cdf5b9c0f.rmeta --extern rustc_const_eval=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_const_eval-035fa84049b4a093.rmeta --extern rustc_data_structures=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_data_structures-bb24715b6384f523.rmeta --extern rustc_errors=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_errors-e918a2570a7767e7.rmeta --extern rustc_hir=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_hir-81d461fea2aa3e88.rmeta --extern rustc_index=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_index-62e63d6ecd0b6aeb.rmeta --extern rustc_middle=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_middle-12c1c31c607c11bd.rmeta --extern rustc_mir_dataflow=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_mir_dataflow-501de01e02b9c610.rmeta --extern rustc_serialize=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_serialize-b0014741451808d1.rmeta --extern rustc_session=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_session-099b3092369eb7d5.rmeta --extern rustc_span=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_span-55393c4ba860e999.rmeta --extern rustc_target=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_target-5c53f45b50a2fb04.rmeta --extern rustc_trait_selection=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_trait_selection-417eb7264b6673f3.rmeta --extern smallvec=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libsmallvec-ea6ce5fe76ae98c3.rmeta --extern tracing=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libtracing-99fd66853b2d119d.rmeta --cfg=bootstrap --cfg=windows_raw_dylib -Csymbol-mangling-version=v0 -Zunstable-options '--check-cfg=values(bootstrap)' '--check-cfg=values(parallel_compiler)' '--check-cfg=values(no_btreemap_remove_entry)' '--check-cfg=values(crossbeam_loom)' '--check-cfg=values(span_locations)' '--check-cfg=values(rustix_use_libc)' '--check-cfg=values(emulate_second_only_system)' '--check-cfg=values(windows_raw_dylib)' -Zmacro-backtrace -Zosx-rpath-install-name '-Clink-args=-Wl,-rpath,@loader_path/../lib' -Csplit-debuginfo=unpacked -Zunstable-options '-Wrustc::internal' -Cprefer-dynamic -Z binary-dep-depinfo -L native=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/build/psm-cde397fd7aaf5a1d/out` (exit status: 254)
[RUSTC-TIMING] rustc_infer test:false 222.968
[RUSTC-TIMING] rustc_middle test:false 284.437
[RUSTC-TIMING] rustc_middle test:false 284.437
rustc exited with signal: 11 (SIGSEGV)

Caused by:
Caused by:
  process didn't exit successfully: `/Users/runner/work/rust/rust/build/bootstrap/debug/rustc --crate-name rustc_middle --edition=2021 compiler/rustc_middle/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C debuginfo=0 -Zunstable-options --check-cfg 'values(feature, "rustc-rayon", "rustc-rayon-core", "rustc_use_parallel_compiler")' --check-cfg 'names()' --check-cfg 'values()' -C metadata=12c1c31c607c11bd -C extra-filename=-12c1c31c607c11bd --out-dir /Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps --target x86_64-apple-darwin -L dependency=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps -L dependency=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/release/deps --extern bitflags=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libbitflags-406952cbce57dc87.rmeta --extern chalk_ir=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libchalk_ir-4f8c3c883861c8aa.rmeta --extern derive_more=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/release/deps/libderive_more-c1073d14e15c16bd.dylib --extern either=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libeither-33babc3eee1e2d05.rmeta --extern gsgdt=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libgsgdt-6c39f3f7f457f995.rmeta --extern polonius_engine=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libpolonius_engine-e1bdbea55fe599f0.rmeta --extern rustc_apfloat=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_apfloat-e338b34a6de5daef.rmeta --extern rustc_arena=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_arena-4082e1e70fdf48ae.rmeta --extern rustc_ast=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_ast-3e13f597f7a74f97.rmeta --extern rustc_attr=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_attr-decb608cdf5b9c0f.rmeta --extern rustc_data_structures=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_data_structures-bb24715b6384f523.rmeta --extern rustc_error_messages=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_error_messages-5f991e9af942bf23.rmeta --extern rustc_errors=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_errors-e918a2570a7767e7.rmeta --extern rustc_feature=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_feature-95f91683ff729ef6.rmeta --extern rustc_fluent_macro=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/release/deps/librustc_fluent_macro-67da463448ff489e.dylib --extern rustc_graphviz=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_graphviz-256024e6a3a47524.rmeta --extern rustc_hir=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_hir-81d461fea2aa3e88.rmeta --extern rustc_index=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_index-62e63d6ecd0b6aeb.rmeta --extern rustc_macros=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/release/deps/librustc_macros-e7c8b4e580efcf9c.dylib --extern rustc_query_system=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_query_system-40f49266ef5bff5c.rmeta --extern rustc_serialize=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_serialize-b0014741451808d1.rmeta --extern rustc_session=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_session-099b3092369eb7d5.rmeta --extern rustc_span=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_span-55393c4ba860e999.rmeta --extern rustc_target=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_target-5c53f45b50a2fb04.rmeta --extern rustc_type_ir=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/librustc_type_ir-6627579637e5be0d.rmeta --extern smallvec=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libsmallvec-ea6ce5fe76ae98c3.rmeta --extern thin_vec=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libthin_vec-0b56a69de23beef2.rmeta --extern tracing=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/deps/libtracing-99fd66853b2d119d.rmeta --cfg=bootstrap --cfg=windows_raw_dylib -Csymbol-mangling-version=v0 -Zunstable-options '--check-cfg=values(bootstrap)' '--check-cfg=values(parallel_compiler)' '--check-cfg=values(no_btreemap_remove_entry)' '--check-cfg=values(crossbeam_loom)' '--check-cfg=values(span_locations)' '--check-cfg=values(rustix_use_libc)' '--check-cfg=values(emulate_second_only_system)' '--check-cfg=values(windows_raw_dylib)' -Zmacro-backtrace -Zosx-rpath-install-name '-Clink-args=-Wl,-rpath,@loader_path/../lib' -Csplit-debuginfo=unpacked -Zunstable-options '-Wrustc::internal' -Cprefer-dynamic -Z binary-dep-depinfo -L native=/Users/runner/work/rust/rust/build/x86_64-apple-darwin/stage0-rustc/x86_64-apple-darwin/release/build/psm-cde397fd7aaf5a1d/out` (exit status: 254)
[RUSTC-TIMING] rustc_codegen_llvm test:false 203.361
[RUSTC-TIMING] rustc_const_eval test:false 186.158
[RUSTC-TIMING] rustc_hir_analysis test:false 207.989
[RUSTC-TIMING] rustc_trait_selection test:false 250.758

@bors
Copy link
Collaborator

bors commented Apr 20, 2023

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 20, 2023
@m-ou-se
Copy link
Member Author

m-ou-se commented Apr 20, 2023

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 20, 2023
@bors
Copy link
Collaborator

bors commented Apr 20, 2023

⌛ Testing commit 2cd5ce0 with merge d19b64f...

@bors
Copy link
Collaborator

bors commented Apr 21, 2023

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing d19b64f to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 21, 2023
@bors bors merged commit d19b64f into rust-lang:master Apr 21, 2023
@rustbot rustbot added this to the 1.71.0 milestone Apr 21, 2023
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (d19b64f): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.5% [-2.3%, -0.6%] 10
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.5% [-2.3%, -0.6%] 10

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
4.0% [4.0%, 4.0%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.5% [-3.3%, -0.0%] 4
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -0.4% [-3.3%, 4.0%] 5

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.7% [-2.6%, -1.2%] 7
Improvements ✅
(secondary)
-4.0% [-4.0%, -4.0%] 1
All ❌✅ (primary) -1.7% [-2.6%, -1.2%] 7

@avosa
Copy link

avosa commented Apr 30, 2023

Love this!

flip1995 pushed a commit to flip1995/rust that referenced this pull request May 5, 2023
Enable flatten-format-args by default.

Part of rust-lang#99012.

This enables the `flatten-format-args` feature that was added by rust-lang#106824:

> 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.

This is mostly an optimization, except that it will be visible through [`fmt::Arguments::as_str()`](https://doc.rust-lang.org/nightly/std/fmt/struct.Arguments.html#method.as_str).

In rust-lang#106823, there was already a libs-api FCP about the documentation of `fmt::Arguments::as_str()` to allow it to give `Some` rather than `None` depending on optimizations like this. That was just a documentation update though. This PR is the one that actually makes the user visible change:

```rust
assert_eq!(format_args!("abc").as_str(), Some("abc")); // Unchanged.
assert_eq!(format_args!("ab{}", "c").as_str(), Some("abc")); // Was `None` before!
```
@Mark-Simulacrum Mark-Simulacrum added the relnotes Marks issues that should be documented in the release notes of the next release. label Jun 9, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-fmt Area: `core::fmt` merged-by-bors This PR was explicitly merged by bors. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.