How are you using rustfmt and clippy?

I'm do not contribute to projects that enforce rustfmt formatting. I can't stand rustfmt.

BTW, I love gofmt. It doesn't actually do what everyone assumes it does. gofmt preserves single-line expressions as single-line, and preserves multi-line expressions as multi-line. It just makes existing indentation neater, preserving original style and layout of the code. Rustfmt OTOH is a bulldozer that destroys everything.


I enforce rustfmt and clippy in CI in my projects, both with stock settings. I don't personally find any of Clippy's default lints objectionable enough to turn off globally, but I do disable them locally where relevant. If nothing else, the fact that there's an explicit annotation disabling a specific lint around a function gives people a heads up that there's something interesting to be aware of.


Yes, this is my primary complaint about rustfmt. I don't see it changing any time soon, so I decided to just swallow the pill. AIUI, or at least, from what I remember, rustfmt does this because they wanted a deterministic format that didn't depend on the style of the original code.


I use rustfmt and clippy with the default settings, and I'm pretty happy with them - I definitely prefer rustfmted code over non-rustfmted code, and I've never had any reason to complain about it destroying my formatting.


I use rustfmt with nearly stock settings, main one being:

# Super useful to make imports neat
merge_imports = true # not available on stable yet

Clippy is also with stock settings.

am somewhat addicted to anything that says "this is how you can do better!", and even better, if it can do it for me.


For me, acquiring a taste for rustfmt-style seems worthwhile to 'eliminate broad classes of debate', even if I didn't like some of the style when I first looked. I've resisted the temptation to even read about how to customise.

Years ago, I was that person writing style guides etc. I now prefer this problem to be automated-away; freeing up time for malloc-memcpy-golf (most popular sport in the Rust community).



I'm do not contribute to projects that enforce rustfmt formatting. I can't stand rustfmt.

That seems rather an extreme view. As much as I may have disagreed with the choices made in a project coding standards I have never seen any that were so awful I would refuse to work on it. I love to hear what you find so objectionable about rustfmt.

My take on it is that in this modern web connected world of Free and Open Source software the project team potentially includes any of the 7 billion people on this planet.

As such there is no place for local variants of style standards. We are all working on the same global project!

I'm all for automate and forget as mentioned above. One less thing to think about and harmoney all around.


In regards to the arbitrary "bikeshedded" style rules, I actually like rustfmt's rules. I happen to use spaces, 1TBS, and trailing commas anyway. I run rustfmt on my projects occasionally and selectively accept changes that don't make readability objectively worse.

My extreme position is mainly about enforcement:

  1. Rustfmt lacks common sense (it's a program with simple rules) and does not take hints from the input source. I don't expect projects that insist on rustfmt to accept #[rustfmt::skip] without arguing, so in the end code will be formatted how rustfmt thinks it should be, even when rustfmt is wrong.
  2. It's annoying when a pull request fails in CI due to formatting style.

My beef with rustfmt is not about the tiny choices. I can work with both tabs and spaces, and various indentation styles. But not with messy code. rustfmt blindly makes big formatting changes, like forced line wrapping and unwrapping, which changes the layout of the code, and destroys visual grouping.

For example, lines may have relationships between them:

match n  {
   1 => (1, one,   ichi),
   2 => (2, two,   ni),
   3 => (3, three, san),

and if the lines happen to exceed rustfmt's line limit, it will make a salad out of them:

match n {
   1 => (
   2 => (
   3 => (

And I do have this pattern often, because I work with graphics, where I have to have nearly-identical lines for R/G/B or RGB/RGBA/Gray pixel formats (enum variants aren't types, so I can't completely avoid such repetition with generics).

I can't even configure a longer line length in rustfmt, because then it will unwind my iterator chains (where I pay attention to make each line a logical group of operations) into one long spaghetti line.

Similarly with Future chains I pay attention to the rightwards drift:|| {

but rustfmt will happily double it every time:

   .and_then(|| {

For some larger chains that I wrote (and they're large because otherwise passing data down the chain gets verbose and tedious) running rustfmt is like throwing a grenade in them.


Regarding Future chains: we wanted to build a rule for that, and couldn't come up with a sufficiently consistent or easy-to-manually-apply rule for "that's too complicated to go on one line".

Personally, I would say that if you can come up with a consistent rule for when to do that, I'd love to see it implemented in rustfmt.

A sketch of what we experimented with, to suggest a starting point: "allow function calls and single-token arguments, break if you hit line length or if you encounter a function call with a non-trivial expression argument".

We also put a lot of work into the rule that does things like this, to avoid double-indentation:

foo(|bar| {
    // ...
1 Like

I don't think it's possible to come up with fixed rules that don't fail, which is why I like gofmt's approach of keeping the general structure of the input code, instead of overriding it with rules.

So my rule would be don't change the number of lines. If a construct is in one line, keep it in one line (but tidy up spaces after commas, etc.) If a construct is in multiple lines, make sure the indentation is even, but don't unwrap them.


This could be modal with both rustfmt and clippy, with the default showing new Rustaceans "Rust's preferred style", thus teaching that style. Experienced Rustaceans like @kornel could use the more nuanced mode that he described in his post.

Edit: I meant both rustfmt and clippy, per the thread title.

@kornel @josh Yeah, this is where I discussed that idea: Limit chain length by number of calls as well as width · Issue #2263 · rust-lang/rustfmt · GitHub

I have vim automatically rustfmt my code whenever I save. It's awesome, because no longer is there any debate over code style. Also, I can lazily throw code into the file, then save it and have it look readable automatically. I'm definitely the type to format code manually when I have to, but formatting code by hand is a waste of time when you can have a tool do it for you.

I use Clippy less often.


What about fixed rules that do better than we do today?

Could you give some ideas of the mental heuristics you use?

Would you format, b).baz(|arg| { on one line?

How about, b).baz(|arg| { ?, c+d).baz(|arg| { ?|arg1, arg2| { ?

Arbitrary combinations of the above?

Do some of those change if the expression or expression components get longer?

For example, I'd write:

foo.into_iter().map(|x| {

with .into_iter() on the same line, because it is an inconsequential detail. However, I'd write:

    .map(|x| {


    .map(|x| {

because rev() makes a huge difference for an algorithm, and I want it to stand out. So here my formatting is based on perceived importance of a function and how much visual whitespace it gets, rather than the length of its name.

I'd write:

    top, left,
    width, height,

rather than:


I find this perfectly fine:

Self {
   color: convert_color_name_to_rgb(),
   x, y, w, h,

rather than spread-out in a way that takes up a lot of vertical space without helping readability:

Self {
   color: convert_color_name_to_rgb(),

And the worst case is when there's enough of a line length:

Self { color: convert_color_name_to_rgb(), x, y, w, h }

and it becomes hard to see where the expression for color: ends, and whether x, y, w, h are arguments to the function, or the struct.

With gofmt I can write:

rect   {
    x:x, y:  
  y ,
      w: w, h :h,
      color:    convert_color_name_to_rgb(),

and it'll sort it out to:

    x: x, y: y,
    w: w, h: h,
    color: convert_color_name_to_rgb(),

That's only partially what gofmt does though. Go has plenty of built-in language rules about line breaks and formating (if/else constructs, etc) that prevent any ambiguity.

It's true that gofmt leaves long lines alone if it can, but Go is also syntactically a much, much simpler language and has way fewer challenging situations for the formatter. I'm not very impressed with gofmt just because most things it does are so trivial.

clangfmt in comparison is super impressive. It does some black magic in certain situations, for example with macro formatting.


That said, my biggest annoyance with rustfmt is the handling of match statements.

I often insert extra curly braces to make an expression readable, and rustfmt happily screws me over. I think the heuristic that determines "simple" expressions needs to be tuned down a little.


Porting/reimplementing rustfmt on top of rust-analyzer’s concrete syntax trees has been on my todo list since forever, but I might actually get to that “soon”, after wrapping up nixpkgs-fmt project...

I personally also prefer IntelliJ/gofmt style formatting, which enforces patterns but doesn’t mess with line endings. Though I feel like majority of the community is enjoying rustfmt’s one true style. Perhaps it’s a good idea to try to implement an alternative go-style formatter and then ask for community’s consensus?

By the way, if someone’s super eager to do a go-style formatter for Rust and is ready to sink significant amount of time into it (on the order of three work-weeks?), reach out to me for mentoring instructions. I believe that this is doable without too much research as a nice stand-alone project, but it does require time investment. I am not ready to drive that myself right now, but I’d love to teach anybody about what i’ve learned about formatters recently :slight_smile:


"AIUI, or at least, from what I remember, rustfmt does this because they wanted a deterministic format that didn't depend on the style of the original code."

Well they nailed it didn't they. Repeat. Deterministic.

Like most things in coding, life and family... my personal tastes are not all that important when it comes time to publish (or have a pleasant meal.)

Being predictable and normative certainly is. Works in dating too. It's a brain thing. Formatting should logically be standardized and easily transformed is desired.

Clearly some collaboration to create CLIPPY configuration sets would tie directly to alternative standards and styles and highlight problem areas. Provided anyone cares about Dev Ops and such it could have benifit.

I have done many bizarre explorations related to natural language code, obfuscation and compaction yet am happy to CLIPPY / format comply within reason. Lol. I am a nice guy that way.

Determinism yes. Narcism no. I vote for a community defined default CLIPPY setting. If I ever voted anyway. I find voting offensive... ... ...

I have zero usage of this. Don't you just open the editor (VSC?) and apply your formatting presets?

I found the few useless warnings in VS to be useless within a design feature and might occur dozens of times.

However a contextually valid one might be buried in the pack.

Regarding the (dev cyclical?) warning review you did? That certainly should be or is a best practice. It is in RAD anyway. (Agile, whatever you use really. When isn't code review a best practice?)

To various degrees the alternatives seem either picky, elitist, unreasonable or unwise.

So... I have to ask... which are the worst, MOST annoying lints? Chuckle. Is there a top ten? Regards, Dave H.

There are two points here both of which are important.

First, the issue of two code modalities in the coding role. I would suggest that after forking you want a highly expanded multi-line view.

However someone experienced with a code base wants a densely packed single line view of the function.

This is about reading mechanics and view paging as much as it is coding. This influences style.

Which leaves the second issue.

Kornel is trying to explain that in some domains style isn't style as such. Layout becomes extremely important and contains both design and conceptual understanding important to the domain expert. Coding isn't the issue.

This implies two rule sets at a minimum.

Excuse my own layout. (Posted via Android Clip Stack.)

1 Like