Completing rustfmt and the Rust style guidelines

You know what bothers me most about JavaScript? There’s too many coding style guides that i know of. I mean - not ‘strong personal preferences’ of a couple of people, but heavyweights. Google, Mozilla, the man himself, and lately npm, the largest library repository. Whatever coding style guide you choose, the moment you need to fork + patch some project you are in trouble. No editor on this planet automatically picks up the underlying conventions, so we all need to fiddle around with spaces, line length, naming conventions, … How tiring is this!?! We, the Rust community, have better things to do.

I hope that Rust, the project, offers an automatic formatting tool a la gofmt. I’m not a big fan of Go per se, but one and only one formatting tool producing one and only one style is uberformidable. No twisting based on personal sensitivities, project settings, corporate identities, …

Thanks you followed me so far. I hope you could read this post easily. I tried to follow the english style guide as close as possible, because i want you to understand my ideas. Personally, i prefer a much better style, that is far superior to plain english, and fasterToTypeOn MY keyboardbecosofallthechrstht arnt reqd bt yknow readng is hadd. It’s also far more artistic, nay?

Search for ‘rust lang logo’ using your favourite search engine: all the same. Easily recognizable. Beautiful, aye?

There are a variety of reasons to want to tweak the default Rust style, such as to fit in with an existing code base, for technical considerations with one's development environment, or even strong personal preference. That's why I think it is very important to have a rustfmt with a default Rust style, but which allows individual guidelines to be tweaked as necessary via a per-project configuration file. That way, I can make the small tweaks I need for my environment, but still use rustfmt to enforce the standard guidelines to the extent possible. Without the possibility for customization, I would be forced to forgo using rustfmt altogether.

Having a standardized rustfmt configuration file would allow just that. Checkouts of the code would include the per-project format settings, and Rust-aware editors could read that to automatically configure themselves appropriately for that project without the user having to mess with their editor's global settings. Even without editor awareness, it would also make it easy for the contributor to use rustfmt to format their contributions to the project's style before check-in.

2 Likes

There is only one coding style that I like (for user code), it works on all programming languages, and is as simple as it gets, since it has just one single rule:

  1. Do as the standard library does.

It is based on the following claim:

Everybody needs to know and use the coding style of the standard library anyways.

This makes it as easy as possible for anybody to read, use, and contribute back to your library.

So in my opinion:

  • the main developers of the rust standard library should write down the coding style of the rust standard library (I encourage this to happen in the open but I will put up with whatever they decide), and
  • the standard rustfmt tool (and crates.io) should enforce this style without mercy.

There seems to be a misconception about the main advantage of rustfmt (gofmt, clang-format, ...). It is not reformatting your code automatically, that is a mean to an end. The main advantage of rustfmt is not having to speak* about coding styles, ever. By allowing two (or N) styles, the value of rustfmt as a tool significantly drops, as its main advantage is lost.

[*] update: speak/think/discuss/argue/...!

2 Likes

Exactly.

Maybe this is a bit esoteric, but in my opinion it boils down to a psychological phenomenon. It’s part of our human nature to conform, to be part of a swarm, to copy. But we also want to be special (where no man has gone before) and to craft things the way we personally think it is the right thing to do.

The Rust community could have both, if code format means conformance, and code content receives all the good brain power energy. That, in itself, would make it very different from other languages :wink:

2 Likes

My desire is not to have a completely different coding style, it is simply to make a couple of tweaks for my environment. It would still have the advantage you mention, as the vast majority of people would just use the defaults, and those with specific needs could make the required tweaks while still deferring the vast majority of style decisions to the community standards. Without this support for customization, people in such situations wouldn’t be able to use rustfmt at all, most likely leading to code that is inconsistent in other ways as well.

The most important thing for me is to have style be consistent within a project. A strong secondary goal is to be consistent with the community to the extent possible given the constraints of the project. A rustfmt without customization would defeat both those goals in my case, as I wouldn’t be able to use the tool at all. While I would still try to meet them manually, my code would not be nearly as consistent as it would be if I could use rustfmt.

I disagree that adding customization would result in significant brain power being expended on style considerations, as developers will be able to take the defaults, possibly make a few tweaks for their environment (most people won’t need to make any), and get on with coding. Not being able to use rustfmt, however, would waste quite a bit of brainpower forcing the developer to try to remember and manually enforce local and community style guidelines.

are there already that many incompatible style preferences in the rust community? I mean I’ve seen some crazy stuff on stackoverflow, but that was mainly people from other languages enforcing their other-language-style to rust.

IIRC rustfmt already keeps your format if it adheres to the style, even if it would choose a different format if it wouldn’t adhere to the style.

One example is if you always put function arguments on their own line, even if it’s only a few args that would fit into one line. Rustfmt doesn’t “fix” this, because it’s already correct.

Care to elaborate more about which things need to be tweaked for different environments? The ones you mention above:

There are a variety of reasons to want to tweak the default Rust style, such as to fit in with an existing code base, for technical considerations with one's development environment, or even strong personal preference.

are really weak arguments. The first two are not a problem if there is only one style since code automatically fits (there is only one style) and there is nothing to tweak on IDEs since rust modes for all of them support this single style. And if they don't (e.g. notepad....) it doesn't matter, since you can always run rustfmt to automatically reformat the code, or have cargo automatically run it for you.

The last reason is even weaker, since everybody has a difference personal reference, and agreeing on one is the whole point of rustfmt.

Anybody who has worked on projects using different styles can adapt from one style to another. I'm pretty sure there are things about the chosen style that I won't like. I will fight for 80 characters per line as hard as I can, but if I loose I'll have to accept it anyways. This is what compromises are all about.

It has been said before, but here is my viewpoint: For my own projects, I’d like the style to be most readable to me, especially in a more syntactically complex language like Rust.

If I have a tool to keep that consistency, I’ll use it. If the tool insists on putting things in a style that I find harder to read, I won’t run it.

That’s why I’m personally in favor of per-project settings, defaulting to the style guide unless changed.

1 Like

I also support per-project settings with a standard set of defaults.

Being as strict as gofmt has many downsides, including:

  1. If a formatter is too strict, it’s more likely to divide people on whether they use it at all rather than creating a uniform style.
  2. Cannot improve the formatter in a backwards-compatible way: with per-project settings you can maintain a system-wide up-to-date version of the formatter, and just not update the settings file for projects whose formatting you don’t want to change.
  3. Some settings are more than just a personal preference - they may actually affect the usability of some editors. For example: spaces vs tabs, 80 chars per line limit, import style, etc.

Being flexible has only one downside: everyone uses a similar formatting style rather than an identical formatting style. Since we’re not machines, that shouldn’t be a big deal :stuck_out_tongue:

1 Like

To quote myself from an old rant on the subreddit:

I've often got an editor on the same screen as a browser for reference, and the editor gets about 80 columns. More than that, and the browser's damn near useless.

More than that, though, I strongly feel that if you're going to have a line length limit, it should be chosen based on technical grounds, to ensure code is (99+% of the time) going to fit on screen. That puts it in the 72-79 range (depending on whether you want to account for line numbers in a terminal editor or not).

As it stands, if code is hard-wrapped at 100, you can't make the editor window narrower without ending up either needing to scroll horizontally, or with jagged soft-wrapped lines, both of which ruin readability. As someone who has had to mark programming assignments that were hard-wrapped at 100, then printed out at 80: this will give you one hell of a headache really damn fast.

You also, obviously, can't make the window wider since it won't do anything, though that's less of a problem.

To give you an idea of what this is like, here's what the Rust documentation looks like next to a 100-column editor on my monitor. The editor and Firefox are taking up the entire width of the screen.

Extremism breeds extremism: you try to force 100 column hard wrapping on me, and I'll just stop using rustfmt altogether.

1 Like

Line length is a good example. While 100 is great for many environments, sometimes there are limitations that make it less than ideal (such as if you often need to view your code in an 80-column terminal, for instance), and it would be nice to have the flexibility to change that setting. (I find that 90 characters works best for my common development machines, so that's what I use for personal projects).

Having a per-project configuration means I can set my desired maximum line-length for reformatting, and contributors can easily make sure they are matching my style.

You may not consider having a very strong preference for a given line-length or indentation style to be a good reason for using a slightly altered style, but I'm sure the ones with those preferences would disagree with you. Making rustfmt inflexible will cause some people to avoid it altogether, no matter how strong or weak anyone else thinks their reasons are.

1 Like

@phaylon wrote:

If I have a tool to keep that consistency, I'll use it. If the tool insists on putting things in a style that I find harder to read, I won't run it.

Then fight to make the default rustfmt standard nice to read for you. In particular, don't fight about everything, fight about what really is important to you (what would make rustfmt completely unusable in your situation).

@Diggsey wrote:

  1. If a formatter is too strict, it's more likely to divide people on whether they use it at all rather than creating a uniform style.

I think this is not an argument against having a single style, but rather about how to enforce it (Python enforces some style via indentation at the interpreter level).

I doubt this is a problem tho. Everybody uses gofmt and basic Python style. In which language with a single default style did this division happen?

  1. Cannot improve the formatter in a backwards-compatible way: with per-project settings you can maintain a system-wide up-to-date version of the formatter, and just not update the settings file for projects whose formatting you don't want to change.

First, note that having a setting files won't be enough to ensure that formatting doesn't change, since a bugfix can change the resulting formatting even in this case.

The best solution I've seen is what clang and clang-format do: sync the release of rustc with that of rustfmt. New language features require a new rustfmt version anyways. The only difference is that the commit message when upgrading a project to a new version of rustc would look like "upgraded rustc to version X, upgraded project version to Y, reformatted" instead.

Bugs in the formatting tool are a real issue. It took clang-format one year of full time development to reach a point where new features and bug fixes have minimal impact on the resulting format. Rust is simpler than C++, so hopefully this will happen faster. The solution here is to not start enforcing rustfmt until it has stabilized and making it opt-in till then.

Some settings are more than just a personal preference - they may actually affect the usability of some editors. For example: spaces vs tabs, 80 chars per line limit, import style, etc

This is not an argument against a single stye, but about the details of that style. There are combinations of these settings that work on all editors, all environments, ... (spaces, 80 char limit, ....). In particular, there are already a lot of tools designed for the minimum common denominator. By trying to go above that we make rust unusable in those environments. For example, there was a reddit post about the Calendar example in Rust. A solution to this problem was posted on github: Calendar formatter in Rust (translated from D solution) · GitHub

I find it insane that I have to scroll to the right here on a 27`` monitor because github does not support lines this long (1k characters?): Calendar formatter in Rust (translated from D solution) · GitHub

rustfmt should make sure that you can always read and edit your rust code everywhere, so if the proposed style doesn't allow you to do that, argue against it.

@rkjnsn wrote:

Line length is a good example. While 100 is great for many environments, sometimes there are limitations that make it less than ideal (such as if you often need to view your code in an 80-column terminal, for instance), and it would be nice to have the flexibility to change that setting. (I find that 90 characters works best for my common development machines, so that's what I use for personal projects).

This is not an argument against having a single style line, but about a particular detail of that style line. If you are against 100 character limit, argue against it. If you are in favour of 90 character limit, argue for it. I will argue that 80 character limit works for everybody (see the gist above for an example of tools not coping with a given character limit).

To all three of you:

Seriously, if every single project I've been in was able to agree on style, we can agree on a single style for rustfmt too!

Even if this style is not perfect to each one of us, as long as it is usable, we'll be able to live with it. Every developer is able to adapt to different styles on different projects.

Note that Go is very opinionated in general and enforces its opinions on users. Folks who have their own ideas on code style and structure .... generally don't use Go if it's not in line with them. (So gofmt is a smaller part of a larger "problem")

Rust does try to cater to most use cases, so we're a bit different here.

There will be tons more who fight otherwise. Line length was brought up; it's a perfect example. Rust is very prone to going past an 80-line limit, but many more have legitimate reasons for wanting it to stay 80.

IMO keeping it configurable but deciding on a default config that works for the majority is the way to go here. Larger projects with their own special needs can then tweak it if necessary.

1 Like

Note that Go is very opinionated in general and enforces its opinions on users. Folks who have their own ideas on code style and structure .... generally don't use Go if it's not in line with them. (So gofmt is a smaller part of a larger "problem").

It is, and Python is too. At the end of the day in every single project with more than 1 developer a coding style ends up being a compromise anyways. Not every single developer is happy with it, but they all do fine. gofmt removes the problem altogether. As long as you can read and write the code and your tools work with it, it is not really a problem worth investing that much time into.

There will be tons more who fight otherwise. Line length was brought up; it's a perfect example. Rust is very prone to going past an 80-line limit, but many more have legitimate reasons for wanting it to stay 80.

Actually as long as all rust styles have 80 character line limits I would be happy. I basically don't really care about anything else. So it is a very good example indeed. There are solutions to going past an 80 line limit at the style level (like using 2 space indentation instead of 4/8 spaces) and generally at the language level (use try! or option/results methods instead of match).

I have to read others people code, all the time. Sometimes this code is in other projects, and sometimes I have to send fixes to those projects. If every single one of them had a different line length, and in particular line lengths > 100 you are just making it hard for me to read your code and to use git and diff to submit patches.

Larger projects with their own special needs can then tweak it if necessary.

I really want to hear those needs. In the discussion above, others were against to 100 character limit (which makes sense), and one cited "strong personal preference". In particular, for larger projects, "strong personal preference" of a single developer is not really a need.

I think this is not an argument against having a single style, but rather about how to enforce it (Python enforces some style via indentation at the interpreter level).

Python enforces the bare minimum for the interpretter to be able to understand the code - I'd hardly describe it as a strict formatting.

I doubt this is a problem tho. Everybody uses gofmt and basic Python style. In which language with a single default style did this division happen?

There is no strict definition of "basic Python style", ie. it's flexible, exactly as I'm advocating.

While I'm quite happy to conform when working on other projects which already have a set of styles, if I can't use my preferred style on my own personal projects I'm either going to find a way around it, or avoid the language altogether.

First, note that having a setting files won't be enough to ensure that formatting doesn't change, since a bugfix can change the resulting formatting even in this case.

Any bug-fix can be implemented as a change to the default settings file in a completely backwards compatible way, even if that's just incrementing a version in the file (although this allows for much more flexibility than that).

Bugs in the formatting tool are a real issue.

Agreed, but they're less of an issue if the formatting tool is less strict.

This is not an argument against a single stye, but about the details of that style. There are combinations of these settings that work on all editors, all environments, ... (spaces, 80 char limit, ....).

There is no "common denominator" - different environments have different, conflicting requirements which cannot all be satisfied at the same time. Even if you manage to find a common denominator which works in most environments, that's almost certainly not going to be the most aesthetic or ergonomic style in more advanced editors.

rustfmt should make sure that you can always read and edit your rust code everywhere, so if the proposed style doesn't allow you to do that, argue against it.

I have a code editor on my phone that can only display ~30 columns, perhaps we should limit all code to that?

1 Like

There is no strict definition of "basic Python style", ie. it's flexible, exactly as I'm advocating.

Of course there is some form of "basic Python style", that is why I used quotes. The interpreter forbids mixing tabs and spaces in Python 3, relative indentation is significant, ...

I'm either going to find a way around it, or avoid the language altogether.

I think it would be awesome if the only reason one would have not to use Rust in their projects was because its enforced style guide is not perfect. Having said this, maybe the style rustfmt enforces is your preferred style, nothing is set in stone yet.

Any bug-fix can be implemented as a change to the default settings file in a completely backwards compatible way, even if that's just incrementing a version in the file (although this allows for much more flexibility than that).

This is a good point, of course it can, and it is worth discussing this.

For example, clang-format doesn't do this because it is a ton of extra work for almost zero benefit: the largest bugfixes I've seen recently in clang-format cause a reformat of 1LOC every 20kLOC in my projects. Given that one can always check and use a particular revision of clang-format in case one doesn't want to modify the code, cluttering clang-format's code with both revision checks and old broken code is a lot of work, and prevents refactorings and performance improvements.

This might be possible in rustfmt, and maybe one can design it in such a way that these things are not issues.

I don't think so, and I don't think that without a lot of manpower it would be feasible to do it without hindering rustfmt's development significantly. I think it would be awesome if I was proven wrong, since such a design would certainly be extremely interesting.

I have a code editor on my phone that can only display ~30 columns, perhaps we should limit all code to that?

I don't think so, I think we should stick to 80 (or 79) columns for all the arguments that have been repeated ad nauseum, but if this is really important to you, I cannot wait to hear your arguments for advocating this. Of particular interest would be which modern enough phone doesn't offer a 80x24 terminal.

As I said in my post above, a style guide for the standard library should be proposed first. Afterwards we can all "cry" about how this style guide is evil and we don't like it and argue that we need a formatting tool with Y features.

I think it is sad that the only strong argument against "let's try to form a consensus about a single style guide first" is "I don't know what it will be like but I know I will not like it".

My point is that devs with issues with an opinionated tool probably would have avoided Go in the first place.

You may be happy; others may not. Rust is annoying to limit to 80chars. Doable, but very annoying. Especially for code with lots of matching (see: all of libsyntax and plugins which use it)

That's not what I'm proposing. Most people will stick to the default; as with any tool. Most projects already write code in the Rust style, modulo line length. I bet the line length thing is just due to laziness and people will stick to 80 unless they have a strong preference.

I was making a general statement about tools with rigid features generally not working for large projects (eg Servo uses a lot of hacks to get around the lack of the lack of configurability in some aspects of Cargo, though Cargo has gotten many of these features now).

"strong personal preference" of a single dev may not be a need, but it may be if it's for more than a single dev. 80-char limits when you have lots of matching also create hard-to-read code (in particular, reindenting after a change creates a noisy diff, just like how diffs become noisy when you have wrapping). The problem cuts both ways; not everyone here seems to realize that. While I don't see a problem with running rustfmt-80 on Servo, I would never run it on clippy even though I want everything else to be fixed. Clippy is a lint, uses libsyntax, and does TONS of matching. Fixing that rightward drift will lead to really ugly and unreadable blocks.

I'm okay with 80 being the default. But if it's the only option, I won't run it on many of my projects.

The tradeoff here is a slight variation in style vs locking some projects out of the tool entirely.

There is a rough continuum that language projects can be plotted on, with Go toward one end and Perl toward the other, measuring how many choices are made for you by the language/tooling. Rust seems to have a culture that leans toward the Perl end, but in moderation (because there are always trade offs). I don’t think it would be possible for the project to declare a One True Style Guide, we love too much to debate the painting of bikesheds. If rustfmt doesn’t let you config its output, I can’t imagine it seeing widespread adoption.

The direction rustfmt is currently on seems very reasonable. The Rust community will reach a sort of consensus on a standard style guide, which is already mostly completed, but it will not be dogmatic about it, and the tooling will be configurable to deviate from the style guide where appropriate to your personal circumstances. This is a good and achievable middle ground. There will be available a sane and moderate “official style” that projects can adopt to avoid bikeshedding, but if you want to read the code in your personally preferred style, its just a rustfmt away.

EDIT: Also, as far as I am aware, Rust already has a style guide which specifies 4 space tabs and 100 character lines.

I heart you. Really, I used the "tons of matching" example above:

There are solutions to going past an 80 line limit at the style level (like using 2 space indentation instead of 4/8 spaces) and generally at the language level (use try! or option/results methods instead of match).

However I disagree: formatting doesn't solve the tons of matching problem: >100 columns and e.g. 2 space indentation is just a workaround.

Code with tons of matching is hard to write and hard to read: this is a language/library problem. Not a problem rustfmt should solve.

You'd need a configurable rustfmt for that. Which is what I'm advocating.

won't work for libsyntax

This is libsyntax, it's not meant to be a nice API for external use. Rustc contains a lot of nonidiomatic code or APIs because they work well internally. It's too complicated an application to follow all the higher-level style guidelines. I'm pretty sure other large applications may start doing the same. (Of course, rustfmt deals with lower-level style guidelines, not stuff like API design and all)

Having a rigid rustfmt will always be unusable for some folks. You may think you know all the possible problems with a particular style guideline, and how to get around it. I can guarantee that you won't know all of them, and your workarounds won't be generic, however much you try. There will always be strange use cases, and the larger a project gets, the more you see them cropping up.