Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enable flatten-format-args by default. #109999

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: std::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: Marked as 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 added I-compiler-nominated The issue / PR has been 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: Marked as 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
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 oli-obk removed the I-compiler-nominated The issue / PR has been nominated for discussion during a compiler team meeting. label Apr 20, 2023
@oli-obk
Copy link
Contributor

oli-obk commented Apr 20, 2023

@bors r+

@bors
Copy link
Contributor

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
Contributor

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
Contributor

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
Contributor

bors commented Apr 20, 2023

⌛ Testing commit 2cd5ce0 with merge d19b64f...

@bors
Copy link
Contributor

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
12 checks passed
@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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-fmt Area: std::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.

None yet