#7113·rustfmt

Closure parameter wrapping appears to ignore block-prefix width

Author: ATOMLuboverCreated Sep 11, 2026Updated Sep 15, 2026
LabelsC-bugA-closuresSO-max_widthA-blocksA-async-blocksA-gen-blocks

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):

rust
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:

rust
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:

toml
max_width = 80
use_small_heuristics = "Max"
style_edition = "2027"

Command:

bash
rustfmt +nightly --edition 2024 --config-path rustfmt.toml < repro.rs

The language edition is 2024; the formatting style edition is 2027.

Reproduction Steps

  1. Save the input above as repro.rs in a temporary directory.
  2. Save the configuration above as rustfmt.toml in the same directory.
  3. Run the command above from that directory.
  4. 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.