Closure parameter wrapping appears to ignore block-prefix width
Translation assisted by an LLM.
Summary
The decision to wrap closure parameters appears not to account for the full
width between the closing | and the opening { of the body. Prefixes such as
unsafe, async, and async move can make the line exceed max_width, but
rustfmt still joins the parameters onto that line.
Is this a width-budget bug, or an intentional formatting rule?
I tried to format this standalone example, which compiles with Rust edition 2024 (with warnings):
fn accept<F>(_: F) {}
fn main() {
accept(
move |first_argument_name_long: u64,
second_argument_name_long: u64| unsafe {
let value = 1;
value
},
);
}Expected behavior
Keep the resulting code within max_width = 80, for example by splitting the
closure parameters or using another suitable layout for the closure body.
I am not requesting preservation of arbitrary manual line breaks.
Actual behavior
Rustfmt produces:
fn accept<F>(_: F) {}
fn main() {
accept(
move |first_argument_name_long: u64, second_argument_name_long: u64| unsafe {
let value = 1;
value
},
);
}The closure's first line is 85 columns including indentation, exceeding the configured 80-column limit. Formatting exits successfully without warnings. Splitting the parameters manually results in the same 85-column line again.
Configuration
rustfmt.toml:
max_width = 80
use_small_heuristics = "Max"
style_edition = "2027"Command:
rustfmt +nightly --edition 2024 --config-path rustfmt.toml < repro.rsThe language edition is 2024; the formatting style edition is 2027.
Reproduction Steps
- Save the input above as
repro.rsin a temporary directory. - Save the configuration above as
rustfmt.tomlin the same directory. - Run the command above from that directory.
- Observe that the two parameter lines are joined into an 85-column line.
Meta
Tested nightly version:
rustfmt 1.10.0-nightly (67854e511d 2026-08-15)This is the installed nightly tested, not a claim about the latest nightly.
The same example also reproduces on the following stable version with
style_edition = "2024" and otherwise the same configuration:
rustfmt 1.9.0-stable (59807616e1 2026-04-14)Additional observations
In the same example, changing only the body prefix produces 78 columns for
{, 84 for async {, 89 for async move {, and 85 for unsafe {. All four
keep the parameters on one line. This is not specific to async blocks.
Related issues
Possibly related: #325 (closed), #2063, #6831, #6538 and #6687. Here rustfmt actively joins breakable parameters into an over-width line, rather than preserving unformatted input. Please let me know if an existing issue already covers this case.
Source: rust-lang/rustfmt