# Properly formatted \`cargo fix\` code

**URL:** <https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539>\
**Category:** cargo\
**Created:** [March 11, 2025, 7:35pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539 "2025-03-11T19:35:51Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [March 11, 2025, 7:35pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/1 "2025-03-11T19:35:51Z")

</div>

Being spoiled by my editor running `rustfmt`, I frequently find that when I run `cargo fix` or `cargo clippy --fix`, I forget that I need to manually run `cargo fmt` afterwards. Sometimes I don't notice until CI complains.

@kpreid brought up the idea of `cargo fix` concluding with a call to `cargo fmt` in [Automatic `cargo fmt` after `cargo fix` · Issue #12608 · rust-lang/cargo · GitHub](https://github.com/rust-lang/cargo/issues/12608).

As a Cargo team, there are different opinions on whether we should do something about this but we at wanted to get further input on the idea and the potential ways of moving this forward.

The most basic solution is for `cargo fix` to print a note reminding people that the applied changes don't conform to a style guide and a call to `cargo fmt` may be warranted.

The next step up from that is a way for users to opt-in to `cargo fmt` integration. Initially, this would mean that whenever `cargo fix` or `cargo clippy --fix` change source, Cargo runs `rustfmt` with the appropriate edition set. This could even be done in-memory, avoiding a write/read/write between operations. Later as `cargo fmt` gains `Cargo.toml` formatting support, this could extend to `cargo add`, etc.

Do others feel this is a problem to be solved?

What would the opt-in look like? To match my editor, I would prefer user config. Its rare that that causes me problems at least. However, maybe its a repo setting (maybe config) or a project setting (manifest)?

How cautious should we be with formatting? `cargo fix` is already cautious in what code it touches. Even with the opt-in, there might be a question of whether we should format unformatted code, like `cargo fix` not fixing uncommitted changes. We could `cargo fmt --check` the file first and require `--allow-dirty` to move forward. If we could tell rustfmt the byte ranges of the code we changed and it could do the minimal format for that, that could also help.

What other commands would benefit from check integration? While we could have different enforcement points built-in to cargo, I feel like an error would be too disruptive to development. We could do these as warnings though.

What problems may we run into with rustfmt config? One I've run into with my editor is when nightly rustfmt features are used and I have to format with a different toolchain than I do development with.

CC @calebcartwright

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [March 11, 2025, 8:53pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/2 "2025-03-11T20:53:04Z")

</div>

Isn’t the no-brainer/minimalist and presumably straightforward approach something like “if a file was fully cargo-fmt formatted before _then_ the file should be formatted after _else_ behave like currently”? Could there be any downsides to this approach?

* * *

This could be _combined_ with warning that fires if the file in question was _not_ found to be correctly formatted yet.

Further opt-in or settings aren’t really required IMO anyway. In cases where people would _want_ the file completely `cargo fmt`-formatted, but it hasn’t been in a well-`cargo fmt`-ed, I don’t see any benefit in prompting the user to “please `cargo fmt` first” if they could just as well run `cargo fmt` _afterwards_ and be done already, with the same end result.

Maybe the suggestion could even include the command that would format _just the files_ in question – would have been my next sentence, but looking into this some more, is it _really_ true that stable `rustfmt` does _not_ support single-file formatting (i.e. _without_ other files reachable via `mod foo;`) yet!?

* * *

A mode to “always run `cargo fmt`, too” seems unnecessary as well, because `cargo fix` isn’t supposed to _replace_ `cargo fmt` anyway, right? So all proper users would _also_ be using `cargo fmt` manually, anyway, (or equivalent functionality through their IDE).

> **Thinking of possible downsides anyway…**
>
> …the only remaining somewhat unsupported use-case is when users want to e.g. use stable `cargo fix` in a project where nightly `rustfmt` is used and configured in a place that the `cargo fix`-invoked `rustfmt` would pick up, that motivates simply also emitting the same warning that the resulting changes might not be ideally formatter; perhaps with an added `help` or `note` that describes the failure case.
> 
> The only false behavior would be in the rare case where
> 
> - `rustfmt` (or alternative Rust formatting infrastructure) that the user _actually_ uses is configured somewhere else – or a different stable version – but happens to consider the file in question well-formatted before the fix, too, as does the actual tool the user uses
> - then after the fix, formats it into a state that no longer matches the formatting tooling that user actually uses
> - so there was no warning, but the result wasn’t the “desired” formatted result the user would have wanted
> 
> Though this is not worse than the status quo, anyway.
> 
> * * *
> 
> Aaaand I’m noticing a second possible case of misbehavior:
> 
> - `rustfmt` sometimes “gives up” on sections of code leaving them untouched as a result
> - this means that if the fix happens in such a section, the result could be not-properly-formatted (needing to be looked at by the user) but `rustfmt` behavior itself gives no indication of this happening
> - this means that if the `cargo fix` change happens to _remove_ the issue that `rustfmt` got stuck on, then subsequent formatting of the file can affect a larger section of code, in principle
> - this means that if the `cargo fix` change happens to _introduce_ a code pattern that `rustfmt` “gives up” on, the result could be not-properly-formatted without warning
> 
> Only the second case would be an actual possible regression; but I also think this is rarely all that problematic because `rustfmt` “giving up” is often well-restricted to small sections of code anyway.
> 
> Ideally, `rustfmt` should have a mode where it simply _tells_ use the set of ranges of file positions that it “gave up on” and if the `cargo fix` diffs overlap with those, a warning could be generated.
> 
> Probably, the behavior should still be the same “for each file separately: if a per-file `cargo fmt --check` operation blessed the file’s previous state, then run a per-file formatting after the fix”. The main case the warning addresses is where the fix applies to an non-formattable section, and thus manual review by the user is might be required for a good-looking result.
> 
> I do think all of this can be left as a future possibility though.
> 
> Just like a range-based mode can be a future possibility. (Looks like `rustfmt` already has unstable functionality for formatting ranges within a file; so in the future with this, it might be possible to transition the per-file based logic to a per-diff based logic, but maybe that should wait for the relevant `rustfmt` feature to be stabilized.)\[1\]
> 
> _Edit:_ Another example I’m just thinking of is `rustfmt::skip` on a code section; though that would probably have all the same implications & relevant mechanisms… Realistically, the only reason why we would want to warn here is “hey, you should look at this code, it might not be formatted do your desires”, but realistically reviewing of `cargo fix` changes “look good” is the user’s job anyway, and the main concern that we’re instead solving is to avoid cases where the result _does_ look like (and _is_) perfectly valid and well-formatted code, but happens not to be `cargo fmt`’s _exact_ choice of formatting. This main concern does not apply with `rustfmt::skip` sections or sections rustfmt “gives up” on.
> 
> * * *
> 
> A last concern is that that _occasionally_ `rustfmt` itself can break code. In theory there could be a case where `cargo fix` would change code _correctly_ and only subsequent formatting breaks it. It’s usually the opposite, i.e. `cargo fix` seems more likely to break code itself in the first place, and there’s already counter measures in place that check vcs so that no state is lost unless the user opts in to it. This should be rare and the user still has the compiler warning anyway, so between [case 1:] a slightly incorrect suggestion from `cargo check` where `cargo fix` breaks your code, and this new case [case 2:] of the suggestion from `cargo fix` being 100% correct and only the conditional automatic subsequent formatting making the code slightly wrong… the UX should be quite similar. They can always try acting on the warning manually; and might not even notice the difference between these cases.

* * *

1. I think even in this range-based approach as a future added functionality, it would _ **necessarily be a fallback** _ to full-file approaches. Because it isn’t trivial to find the right ranges IMO! It could always happen that ranges being too short means that `rustfmt` doesn’t format the whole file properly, which would be unacceptable if the _initial_ state of the whole file was “completely formatted”.

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [March 11, 2025, 9:12pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/3 "2025-03-11T21:12:58Z")

</div>

Arguing against myself a bit, here’s a recent reason why I would want a file _not_ to be formatted by `cargo fix`: The 2024 edition migration has drop order “fixes” where the right choice is often to revert the fix (because the drop order doesn’t actually matter). It was easier to understand what happened, and revert them with `git checkout -p`, because only the beginning and ending changed, without also reindenting (and potentially rewrapping) the code in the middle of the block. For that, I would have appreciated a `cargo fix --no-fmt` option.

I have not thought of any specific opinions on how _enabling_ automatic formatting should work, though. @steffahn’s “format if was formatted” is elegant but feels like the sort of DWIM thing that could easily turn out troublesome.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [March 11, 2025, 9:27pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/4 "2025-03-11T21:27:30Z")

</div>

> [@kpreid](#):
>
> The 2024 edition migration has drop order “fixes” where the right choice is often to revert the fix (because the drop order doesn’t actually matter). It was easier to understand what happened, and revert them with `git checkout -p`, because only the beginning and ending changed, without also reindenting (and potentially rewrapping) the code in the middle of the block

1. Try the migration on nightly and if still is doing matches when you don't need it, open an issue! That diagnostic has been improving
2. I think a `cargo fix --interactive` would also make a big difference in that case. I'd like to see it have "accept / reject all for lint X" to help with problems like the edition migration until the diagnostic is improved (or in case it can't be further improved)

Granted, that does illustrate a broader point that diffs for `cargo fix` are small as-is which makes it harder to look back on.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [March 11, 2025, 9:33pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/5 "2025-03-11T21:33:28Z")

</div>

I’d agree that offering a way of turning off the “format if was formatted” behavior _(and instead doing no formatting at all)_ definitely seems appropriate. In my opinion, that’s the only configuration necessary though. It can also be useful _as a setting_, not just a command line argument; e.g. running the additional formatting checks might be unwanted extra work/computation for users that don’t use `rustfmt` anyway; and disabling the behavior would presumably also turn off all those new warnings regarding formatting. Those warnings could presumably also _mention_ the existence of such a setting, anyway!

The question on whether this setting is a case of on-by-default +opt-out, or off-by-default +opt-in I’m not even 100% sure. But as I argue in my previous comment, I don’t _really_ see much value in offering any “always format” option.

* * *

Exploring a ranges-based approach\[1\] I’ve already touched on in the `<details>` of my previous answer could perhaps be worthwhile thing as an argument in favor of making this feature on-by-default; because it can make it much more useful on projects that don’t maintain a global `rustfmt`-compatible style.

* * *

For `cargo fix --edition` _specifically_, [usage of `cargo fmt` is already part of the official guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html), so it might be a reasonable idea to consider making the `--edition` flag _imply_ some `--no-fmt` flag in a world where this formatting feature is otherwise opt-out.\[2\]

* * *

Totally unrelated, but another thing I’m wondering now: what does `#[rustfmt::skip]` on a `mod foo;` do? On a file-by-file based approach, wouldn’t be wanting to format _more_ files than what a full-project `cargo fmt` does…

* * *

1. perhaps using existing unstable functionality `rustfmt` already has, or aiming for stabilization, or at least stabilization-for-internal-use [i.e. a guarantee that this _kind_ of functionality won’t go away completely] 

2. I can also imagine reasonable arguments against making such an exception to the opt-out rules; I’m just saying that it’s something to consider.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [March 12, 2025, 4:23am UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/6 "2025-03-12T04:23:26Z")

</div>

I am of the opinion that `cargo fix` should've always included `cargo fmt`. To me, "fix" includes "fix formatting", especially since vast majority of machine - applicable fixes are purely stylistic.

But then we have non-trivial fixes like migrating editions. And I would postulate that it would make a lot of sense to separate applying those into a different subcomand altogether.

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [March 12, 2025, 7:34am UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/7 "2025-03-12T07:34:13Z")

</div>

Well, people definitely wouldn't want `cargo fix` to mess up their formatting if they don't use `rustfmt` in the first place.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [March 12, 2025, 10:08am UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/8 "2025-03-12T10:08:08Z")

</div>

I use `git diff` to review the changes from `cargo fix`/`cargo clippy --fix`. I wouldn't want anything else formatted other than the cargo-fixed lines/items, because the diff would be diluted by unrelated formatting changes, and that would add extra work to the code review.

`rustfmt` can be counter-productive for reviewing code diffs, because if a 1-line change ends up crossing some threshold, it can cause the entire block of code to be reformatted, making it look big in the diff and obscure what has been actually changed.

In my experience changes from `cargo fix` are generally formatted well enough. Clippy's added `#[must_use]` stands out as one change that doesn't follow the usual formatting style, but that could be fixed in the lint itself.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [March 12, 2025, 12:48pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/9 "2025-03-12T12:48:17Z")

</div>

Sorry, if I was unclear, I meant to advocate for having applying formatting be the default, with `cargo fix --no-format` opt-out.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 3, 2026, 12:48pm UTC](https://internals.rust-lang.org/t/properly-formatted-cargo-fix-code/22539/10 "2026-09-03T12:48:28Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
