Skip to content

Conversation

@thomasqueirozb
Copy link

@thomasqueirozb thomasqueirozb commented Jan 26, 2026

Summary

Fix rustfmt giving up on formatting when multi-line strings exceed max_width.

rustfmt would refuse to format code containing multi-line string literals that exceed max_width. The problem occurred because filtered_str_fits() in src/utils.rs would reject valid formatting attempts when string content (which cannot be shortened) exceeded width limits.

Added test fixtures for both issues:

  • tests/source/issue-6769.rs / tests/target/issue-6769.rs - byte string literals in array tuples
  • tests/source/issue-6778.rs / tests/target/issue-6778.rs - multi-line strings in struct fields

References


Note that reverting commit fa5b1e4 "breaks" a bunch of fixtures for the better, allowing formatting of rust code even after very long strings.

Example:

Mismatch at tests/source/string_punctuation.rs:5:
         "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\
          Likethisssssssssssss"
     );
-    format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b);
+    format!(
+        "{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",
+        x, y, z, a, b
+    );

and

Mismatch at tests/source/issue-2179/one.rs:27:
         } else {
             for package in &opts.package {
                 if let None = ws.members().find(|x| x.name() == package) {
-                    warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package);
+                    warn!(
+                        "cargo - couldn't find member package `{}` specified in `analyze_package` configuration",
+                        package
+                    );
                 }
             }
         }

It does, however, break tests/source/issue-1210/c.rs in a not so desirable way:

Mismatch at tests/source/issue-1210/c.rs:1:
 // rustfmt-format_strings: true
 // rustfmt-max_width: 50

-const foo: String =
-    "trailing_spaces!!
+const foo: String = "trailing_spaces!!
                 keep them! Amet neque. Praesent \
-     rhoncus eros non velit.";
+                     rhoncus eros non velit.";

I'd encourage someone to take a look at this and follow up if possible.


Note: This PR was generated with assistance from an LLM (Claude). While I'm happy to address minor feedback, I may not have bandwidth to drive major revisions or extensive back-and-forth due to time constraints. If this approach looks promising but needs significant changes, feel free to take over the branch or use this as a starting point. I mainly wanted to get a potential fix out there since these issues were affecting my workflow but since the issue was actually fixed I thought it was worth sharing these changes.

@rustbot rustbot added the S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author. label Jan 26, 2026
@thomasqueirozb thomasqueirozb marked this pull request as ready for review January 26, 2026 20:00
@rustbot rustbot added S-waiting-on-review Status: awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author. labels Jan 26, 2026
@ytmimi
Copy link
Contributor

ytmimi commented Jan 26, 2026

Just ran the Diff-Check, and its already started finding breaking formatting changes. There's no way we can move forward with the PR as is.

@ytmimi
Copy link
Contributor

ytmimi commented Jan 26, 2026

These changes would need to be style_edition gated, but even then I'm not sure if the formatting changes that they introduce are worth it.

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: awaiting review from the assignee but also interested parties. labels Jan 26, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 26, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@thomasqueirozb
Copy link
Author

thomasqueirozb commented Jan 26, 2026

This is unfortunate. All checks passed locally so I assumed this was fine but I wasn't aware of diff-check. Thanks for looking into this. I think I'll close this PR then, but someone can probably use this as a starting point.

@rustbot rustbot removed the S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author. label Jan 26, 2026
@thomasqueirozb
Copy link
Author

thomasqueirozb commented Jan 27, 2026

@ytmimi just took a closer look at that check and it looks like most changes are not due to rustfmt working on those lines where it previously wasn't.
Example:

2026-01-26T21:37:12.231227Z ERROR check_diff: Diff found in 'mdBook' when formatting mdBook/tests/testsuite/markdown.rs
--- original
+++ modified
@@ -8,13 +8,15 @@
 // Checks custom header id and classes.
 #[test]
 fn custom_header_attributes() {
-    BookTest::from_dir("markdown/custom_header_attributes")
-        .check_main_file("book/custom_header_attributes.html", str![[r##"
+    BookTest::from_dir("markdown/custom_header_attributes").check_main_file(
+        "book/custom_header_attributes.html",
+        str![[r##"
 <h1 id="attrs"><a class="header" href="#attrs">Heading Attributes</a></h1>
 <h2 class="class1 class2" id="heading-with-classes"><a class="header" href="#heading-with-classes">Heading with classes</a></h2>
 <h2 id="both" class="class1 class2"><a class="header" href="#both">Heading with id and classes</a></h2>
 <h2 myattr="" otherattr="value" id="myh3" class="myclass1 myclass2"><a class="header" href="#myh3">Heading with attribute</a></h2>
-"##]]);
+"##]],
+    );
 }

If you run rustfmt on the current code block it'd format it correctly (how the + lines show it) IF you make the <h1>/<h2> strings shorter.

The only change I'd think is maybe undesirable is this one (and even then I'm not sure if this is a case of "rustfmt now works when previously it gave up").

2026-01-26T21:46:34.084616Z ERROR check_diff: Diff found in 'rust' when formatting rust/compiler/rustc_errors/src/tests.rs
--- original
+++ modified
@@ -31,11 +31,13 @@

 #[test]
 fn wellformed_fluent() {
-    let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
+    let translator = make_translator(
+        "mir_build_borrow_of_moved_value = borrow of moved value

What do you think?


Update I found the source code for the last one:

#[test]
fn wellformed_fluent() {
    let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
    .label = value moved into `{$name}` here
    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
    .value_borrowed_label = value borrowed here after move
    .suggestion = borrow this binding in the pattern to avoid moving the value");
}

If you remove some chars from the 3rd line ( .occurs_because_label = move...) to make it in total 100 chars or less rustfmt will format it like so:

#[test]
fn wellformed_fluent() {
    let translator = make_translator(
        "mir_build_borrow_of_moved_value = borrow of moved value
    .label = value moved into `{$name}` here
    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement 
    .value_borrowed_label = value borrowed here after move
    .suggestion = borrow this binding in the pattern to avoid moving the value",
    );
}

(I removed everything after implement to make it 100 chars total)

Therefore this is indeed a case of "rustfmt now works when previously it gave up".

I don't think this should be style_edition gated since the behavior is the same, it's just properly working now

@rustbot rustbot added the S-waiting-on-review Status: awaiting review from the assignee but also interested parties. label Jan 27, 2026
@ytmimi
Copy link
Contributor

ytmimi commented Jan 27, 2026

I haven't re-reviewed the change but as I mentioned in my earlier comment these changes would need to be style_edition gated before we could consider merging the PR. I'd also want to review the diff more carefully to see what changes are getting produced.

@thomasqueirozb
Copy link
Author

thomasqueirozb commented Jan 27, 2026

these changes would need to be style_edition gated

would that be the case even if this is a bug fix and is just restoring expected rustfmt behavior? I think I can add a gate if that's the case

@ytmimi
Copy link
Contributor

ytmimi commented Jan 28, 2026

Yes, there's a strong stability guarantee so these have to be gated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: rustfmt silently breaks on this sample rustfmt gives up if second part of multiline string is >= 100 chars long

3 participants