Summary
When a tuple struct field has a parenthesized visibility qualifier (pub(crate), pub(super), pub(in path)) and the type is too long to fit on one line with the visibility, rustfmt wraps the type to the next line but leaves a trailing space after the visibility qualifier. It then detects its own trailing whitespace and reports an internal error, but still writes the broken output to disk.
If the type is short enough to fit on one line, rustfmt collapses it successfully. Plain pub and named struct fields are not affected.
I tried to format this code:
struct S(
pub(crate)
std::collections::HashMap<some::module::path::TypeNameA, some::module::path::TypeNameB>,
);
Expected behavior
I expected rustfmt to format the file without introducing trailing whitespace (or leave it unmodified if it cannot).
Actual behavior
rustfmt writes pub(crate) \n (with a trailing space) to disk and reports:
error[internal]: left behind trailing whitespace
--> src/lib.rs:2:2:15
|
2 | pub(crate)
| ^
|
warning: rustfmt has failed to format. See previous 1 errors.
The input file has no trailing whitespace. After cargo fmt, the file on disk contains the trailing space.
The bug requires all three conditions:
| Condition |
Triggers? |
Parenthesized visibility (pub(crate), pub(super), pub(in path)) on tuple struct field, type too long for one line |
yes |
Plain pub on tuple struct field, type too long for one line |
no |
| Parenthesized visibility on named struct field, type too long for one line |
no (collapses successfully) |
| Parenthesized visibility on tuple struct field, type fits on one line |
no (collapses successfully) |
Configuration
No custom configuration. Default rustfmt settings.
Reproduction Steps
- Save the code above to
src/lib.rs in a Cargo project (the input must have no trailing whitespace)
- Run
cargo fmt
- Observe the
error[internal]: left behind trailing whitespace error
- Observe that the file on disk now contains trailing whitespace that was not present before
Meta
rustfmt --version:
rustfmt 1.8.0-stable (ed61e7d7e2 2025-11-07)
Also confirmed on rustfmt 1.9.0-stable (Rust 1.95.0).
Context
Discovered via smithy-rs#4634, where code generation produces tuple structs with pub(crate) fields and long type paths. The codegen pipeline runs cargo fmt on its output, and this bug causes it to fail.
Summary
When a tuple struct field has a parenthesized visibility qualifier (
pub(crate),pub(super),pub(in path)) and the type is too long to fit on one line with the visibility,rustfmtwraps the type to the next line but leaves a trailing space after the visibility qualifier. It then detects its own trailing whitespace and reports an internal error, but still writes the broken output to disk.If the type is short enough to fit on one line,
rustfmtcollapses it successfully. Plainpuband named struct fields are not affected.I tried to format this code:
Expected behavior
I expected
rustfmtto format the file without introducing trailing whitespace (or leave it unmodified if it cannot).Actual behavior
rustfmtwritespub(crate) \n(with a trailing space) to disk and reports:The input file has no trailing whitespace. After
cargo fmt, the file on disk contains the trailing space.The bug requires all three conditions:
pub(crate),pub(super),pub(in path)) on tuple struct field, type too long for one linepubon tuple struct field, type too long for one lineConfiguration
No custom configuration. Default
rustfmtsettings.Reproduction Steps
src/lib.rsin a Cargo project (the input must have no trailing whitespace)cargo fmterror[internal]: left behind trailing whitespaceerrorMeta
rustfmt --version:Also confirmed on
rustfmt 1.9.0-stable(Rust 1.95.0).Context
Discovered via smithy-rs#4634, where code generation produces tuple structs with
pub(crate)fields and long type paths. The codegen pipeline runscargo fmton its output, and this bug causes it to fail.