Skip to content

fix: strip trailing whitespace on codegenned new lines#4639

Merged
aws-sdk-rust-ci merged 2 commits intosmithy-lang:mainfrom
jlizen:fix/trailing-whitespace
May 1, 2026
Merged

fix: strip trailing whitespace on codegenned new lines#4639
aws-sdk-rust-ci merged 2 commits intosmithy-lang:mainfrom
jlizen:fix/trailing-whitespace

Conversation

@jlizen
Copy link
Copy Markdown
Member

@jlizen jlizen commented May 1, 2026

Motivation and Context

Part of the solution for #4634

Generated Rust server code contains whitespace-only lines that cause cargo fmt to fail with error[internal]: left behind trailing whitespace. This reproduces on the stock smithy-rust-quickstart template with no modifications.

Description

Smithy's AbstractCodeWriter prepends the current indentation to every line it writes, including blank lines. When codegen templates produce empty lines (via join("\n") separators between writables, or empty string interpolations like $boxIt/$boxErr), the writer turns them into whitespace-only lines.

This change strips trailing whitespace (spaces and tabs before a newline) from all lines in RustWriter.toString() using a single regex replace. Blank lines are preserved; only the invisible indentation on them is removed. This is a global fix that catches all current and future instances rather than patching individual templates.

The alternative would be to patch each template that produces blank lines (the join("\n") separator in SmithyValidationExceptionDecorator, the $boxIt/$boxErr interpolations in UnconstrainedUnionGenerator, etc.). That approach is fragile since any new template could reintroduce the problem. The toString() approach is a single chokepoint that all generated output passes through.

The performance cost is negligible: the regex ([ \t]+\n) is pre-compiled as a companion object val, and it runs a simple character class scan with no backtracking. toString() is called once per output file during flushWriters() (plus once per inline module writer). In the codegen-server-test suite (~2500 generated .rs files, ~18MB total), this adds no measurable overhead compared to the model traversal, template rendering, and cargo fmt invocation that dominate the build.

This is a partial fix: it eliminates all trailing whitespace produced by codegen, which resolves the whitespace-only blank lines described in the issue. However, both reproducers in the issue also generate pub(crate) tuple structs with long type paths (e.g. constrained map/collection wrappers), and rustfmt itself reintroduces trailing whitespace when wrapping those fields. That means cargo fmt will still fail on a freshly generated workspace for models that produce these types. That is an upstream rustfmt bug (rust-lang/rustfmt#6880). The codegen pipeline already catches and logs cargo fmt failures, so those cases are non-blocking.

Testing

Added a regression test in RustWriterTest that reproduces both patterns from the issue (join separator blank lines and empty string interpolation blank lines inside indented blocks) and asserts no trailing whitespace in the output. Full codegen-core test suite passes.

Verified end-to-end with a clean codegen-server-test:assemble build (~2500 generated .rs files). All codegen-produced trailing whitespace is eliminated. The only remaining trailing whitespace in generated files comes from rustfmt reintroducing it on pub(crate) tuple struct fields (the upstream bug).

Benchmarked codegen-server-test:clean assemble over 10 runs each: 25.2s +/- 0.6s with the fix vs 24.9s +/- 0.7s without. Within noise, no measurable performance impact.

Checklist

  • For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "client," "server," or both in the applies_to key.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@jlizen jlizen requested review from a team as code owners May 1, 2026 16:41
@jlizen jlizen changed the title Fix/trailing whitespace fix: strip trailing whitespace on codegenned new lines May 1, 2026
@jlizen jlizen enabled auto-merge May 1, 2026 17:01
@jlizen
Copy link
Copy Markdown
Member Author

jlizen commented May 1, 2026

Here's the fix for the rustfmt-side-bug, though it will take time to release even if merged: rust-lang/rustfmt#6881

@jlizen
Copy link
Copy Markdown
Member Author

jlizen commented May 1, 2026

The semver checks failure is expected:

That is an expected behavior the semver check running the old aws-sdk-rust test (asserts 40s) against our fix (produces 38s). @ysaito1001 approved overriding it. Safe to override on your CI too.

@jlizen jlizen disabled auto-merge May 1, 2026 18:22
@jlizen jlizen enabled auto-merge May 1, 2026 18:22
@aws-sdk-rust-ci aws-sdk-rust-ci disabled auto-merge May 1, 2026 18:25
@aws-sdk-rust-ci aws-sdk-rust-ci merged commit a0d46cd into smithy-lang:main May 1, 2026
44 of 47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants