Skip to content

fix: prevent newlines around quotes in macro invocations - #7157

Open
penguinawesome1 wants to merge 4 commits into
rust-lang:mainfrom
penguinawesome1:macro-string-indent
Open

penguinawesome1 wants to merge 4 commits into
rust-lang:mainfrom
penguinawesome1:macro-string-indent

Conversation

@penguinawesome1

@penguinawesome1 penguinawesome1 commented Oct 4, 2026 •

Copy link
Copy Markdown

Fixes formatting for string literals that contain a newline in macro invocations.

Closes #5029

  • I did not use an LLM to create a change in this PR.
  • I used an LLM to create a change in this PR, and I have explained below how it was used.
    Used to review Rust syntax and for a sanity check (reminded me to use as_str instead of to_string).

@rustbot rustbot added the S-waiting-on-review Status: awaiting review from the assignee but also interested parties. label Oct 4, 2026
Comment thread src/macros.rs Outdated
Comment on lines +303 to +315
// Handle special case where there is one argument,
// a string literal containing a newline.
if let [MacroArg::Expr(expr)] = arg_vec.as_slice() {
if let ast::ExprKind::Lit(lit) = expr.kind {
if lit.kind == LitKind::Str && lit.symbol.as_str().contains("\n") {
let rw = format!("{}(\"{}\")", macro_name, lit.symbol);
return match position {
MacroPosition::Item => Ok(format!("{};", rw)),
_ => Ok(rw),
};
}
}
}

@jieyouxu jieyouxu Oct 4, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remark: this feels very special-cased and somewhat strange to me. I agree the existing formatting doesn't seem great, but I'm not convinced special-casing here makes sense either.

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the special case in macros.rs seems out of place.
I was trying to figure out where function macros and normal functions diverged, since they both call rewrite in overflow.rs.

I figured out that it's due to this code here:

rustfmt/src/overflow.rs

Lines 485 to 489 in ff02051

let combine_arg_with_callee = self.items.len() == 1
&& self.items[0].is_expr()
&& !self.items[0].has_attrs()
&& self.ident.len() < self.context.config.tab_spaces();
let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, &self.items);

Interestingly, the only reason foo and foo! are different is because the exclamation point is included in the identifier length. When tab spaces are 4, foo is shorter than 4, so only it was eligible for overflow. This means my solution shouldn't exclusively target macros, but should affect functions too.

Instead of modifying that, I just made it so literals can sometimes overflow (when a single argument contains a newline in edition 2027).

@ytmimi ytmimi added the A-style-edition-2027 Area: style edition 2027 label Oct 4, 2026
@rustbot

This comment has been minimized.

Comment thread src/expr.rs
Comment on lines +1596 to +1601
ast::ExprKind::Lit(lit) => {
context.config.style_edition() >= StyleEdition::Edition2027
&& args_len == 1
&& lit.kind == LitKind::Str
&& lit.symbol.as_str().contains('\n')
}

@ytmimi ytmimi Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also check that the first line of the string literal fits within max_width?

Can you add some test cases where the first line of the string literal is at exactly the max_width after reformatting and then max_width + 1.

View changes since the review

@penguinawesome1 penguinawesome1 Oct 17, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the test cases, and the formatter moves the string to a new line once the line reaches max_width - 1.
Is this intentional, or possibly a known issue? To my understanding, it should only do that once the line exceeds max_width.

@ytmimi ytmimi 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 Oct 17, 2026
@rustbot

rustbot commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@penguinawesome1

Copy link
Copy Markdown
Author

@rustbot ready

@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 Oct 17, 2026

This branch has not been deployed

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

Labels

A-style-edition-2027 Area: style edition 2027 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.

Inconsistent formatting between functions and function-like macros

4 participants