Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatting guidelines #2436

Closed
wants to merge 2 commits into
base: master
from

Conversation

@nrc
Copy link
Member

nrc commented May 10, 2018

This RFC defines an official Rust style guide. The style is a specification for the default behaviour of Rustfmt, is required for official Rust projects (including the compiler and standard libraries), and is recommended for all Rust projects. The style guide in this RFC only covers the formatting of code, it does not have any recommendations about how to write idiomatic or high quality Rust code.

Edit: Rendered RFC, and Style Guide Readme

@nrc nrc added the T-dev-tools label May 10, 2018

@nrc nrc self-assigned this May 10, 2018

@nrc nrc referenced this pull request May 10, 2018

Closed

Tools news #35

@steveklabnik

This comment was marked as resolved.

@varkor
Copy link
Member

varkor left a comment

Overall, this looks like a very sensible, well-thought out proposal (unsurprisingly, considering how long it's been maturing). Personally, I think the styles proposed here are almost all readable and aesthetically-pleasing.

My one real reservation is the omission of .-aligning chained method calls / field accesses. (I also prefer trailing |, but then, I know it's impossible to make everyone happy about everything.)

Really nice work!

}
```

If a struct variant is *short* (TODO link to definition), it may be formatted on

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

There's still a TODO here.

}
```

Prefer using a unit struct to an empty struct (these only exist to simplify code

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Perhaps it'd be helpful if this point was clarified like below (i.e. that "unit struct" refers to struct Foo; and not, e.g., struct Foo();).

```rust
pub trait IndexRanges:
Index<Range<usize>, Output=Self>
+ Index<RangeTo<usize>, Output=Self>

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Is there a reason this format is preferred over trailing +, like in comma-separated lists, for consistency?

This comment has been minimized.

@Centril

Centril May 11, 2018

Contributor

Personally I would have formatted it as follows had I had the choice, it would read like the spine of a list:

pub trait IndexRanges:
    + Index<Range<usize>, Output=Self>
    + Index<RangeTo<usize>, Output=Self>
    + Index<RangeFrom<usize>, Output=Self>
    + Index<RangeFull, Output=Self>
{
    ...
}

I do find that a + at the end makes it harder to scan structure.

This comment has been minimized.

@joshtriplett

joshtriplett May 11, 2018

Member

We're pretty consistent, throughout the document, of putting binary operators (or things that work like binary operators) at the starts of continuation lines.

#### Option - `where_single_line`
`where_single_line` is `false` by default. If `true`, then a where clause with
exactly one component may be formatted on a single line if the rest of the

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

What's the rationale for only permitting this for a single component? As long as it fits within a single line, it seems like multiple parameters would still be readable.

This comment has been minimized.

@nrc

nrc Jul 30, 2018

Author Member

Where clauses get complicated quickly and can be very confusing even if they fit on one line. Furthermore, we reasoned that if a where clause is simple enough to justify being on one line, then it can nearly always be represented as bounds on generic arguments, rather than a where clause.

before:

```rust
pub type Foo: Bar;

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Nit: indentation.


## Names

* Types shall be `PascalCase`,

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

It was decided to use UpperCamelCase rather than PascalCase.


Avoid line-breaking in the signature if possible. If a line break is required in
a non-inherent impl, break immediately before `for`, block indent the concrete type
and put the opening brace on it's own line:

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Typo: "its".

Do not put any spaces around the `.`.

```rust
x.foo().bar().baz(x, y, z);

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

I feel the wrapping style:

variable.foo()
        .bar()
        .baz(x, y, z);

should at least be mentioned (if not considered). This is quite prevalent in the Rust codebase and personally, I think it's easier to read than a single level of indentation (where possible). Has there been previous discussion about this?

This comment has been minimized.

@Centril

Centril May 11, 2018

Contributor

Another style is:

variable
    .foo()
    .bar()
    .baz(x, y, z);

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

@Centril: this is mentioned lower down (I probably should have commented further down).

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Ah, this point is mentioned in the (unlinked) guiding principles document. Smaller diffs should be generally preferred, but I wonder whether this particular point comes at the cost of readability.

Note there is block indent due to the chain and the function call in the above
example.

Prefer formatting the whole chain in mulit-line style and each element on one

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

Typo: "multi-line".

clause, then you must use the above form:

```rust
a_very_long_pattern

This comment has been minimized.

@varkor

varkor May 11, 2018

Member

This is very much bike-shedding (sorry!), but I much prefer aligning the patterns (including the first), rather than the bars. Is there a good reason not to go for trailing |?

This comment has been minimized.

@joshtriplett

joshtriplett May 11, 2018

Member

We're pretty consistent, throughout the document, of putting binary operators (or things that work like binary operators) at the starts of continuation lines.


```rust
let pattern: Type =
expr;

This comment has been minimized.

@Centril

Centril May 11, 2018

Contributor

I find this style hard to read; it obscures structure for me; I'd personally write this as (if it is long...):

let pattern
  : Type
  = expr;

This comment has been minimized.

@repax

repax May 11, 2018

I think the guideline as currently stated is more consistent. There's a stronger cohesion between pattern and Type from there being no space before the colon.
That motivates having pattern: Type on the same line.

This comment has been minimized.

@Centril

Centril May 11, 2018

Contributor

@repax My point was mostly about pattern and = ; moving and aligning the = with the end of let becomes easier to scan imo; but I suppose it might not fit with the overall style.


#### Doc comments

Prefer line comments (`///`) to block comments (`//* ... */`).

This comment has been minimized.

@scottmcm

scottmcm May 11, 2018

Member

I'm not sure how "prefer" can fit with "required for official Rust projects". Is it a violation of the rules if someone writes a doc-comment with //*?

This comment has been minimized.

@steveklabnik

steveklabnik May 14, 2018

Member

This is phrasing to straddle the difference between what the Rust project requires, and what we think should be imposed on other comments. Inside the compiler/stdlib, and as far as I know, in all official projects, we require ///. However, while discussing making this a requirement, we decided to relax the wording to "prefer" over "require", as it felt like a bit of an over-reach to mandate this to everyone, and rustfmt basically doesn't touch comments already, so it woudn't even be enforced.

In other words, it's MUST for the Rust project, but SHOULD everywhere else.

```rust
fn foo() {
let x = ...;

This comment has been minimized.

@jethrogb

jethrogb May 11, 2018

Contributor

Are the four spaces on this line intentional or not? And if they are intentional, are they normative or not?

This comment has been minimized.

@joshtriplett

joshtriplett May 11, 2018

Member

That looks like a bug to me.


If a struct variant is *short* (TODO link to definition), it may be formatted on
one line. In this case, do not use a trailing comma for the field list, but do
put spaces around braces:

This comment has been minimized.

@scottmcm

scottmcm May 11, 2018

Member

nitpick: I read "spaces around braces" as Error {err: u32} ,; perhaps inside braces instead?

This comment has been minimized.

@Phrohdoh

Phrohdoh May 11, 2018

Shouldn't we specify both around and inside the braces?

Error { err: u32 }

This comment has been minimized.

@rpjohnst

rpjohnst May 11, 2018

Or, "spaces around each individual brace." :P

# Guiding principles and rationale

When deciding on style guidelines, the style team tried to be guided by the
following principles (in rough priority order):

This comment has been minimized.

@scottmcm

scottmcm May 11, 2018

Member

This is a great file, but doesn't seemed to be linked from anywhere. Maybe reference it in the readme?

declarations; if imports and modules are separated, then they should be ordered
alphabetically. When sorting, `self` and `super` must come before any other
names. Module declarations should not be moved if they are annotated with
`#[macro_export]`, since that may be semantics changing.

This comment has been minimized.

@petrochenkov

petrochenkov May 11, 2018

Contributor

macro_export -> macro_use


This RFC defines an official Rust style guide. The style is a specification for the default behaviour of [Rustfmt](https://github.com/rust-lang-nursery/rustfmt), is required for official Rust projects (including the compiler and standard libraries), and is recommended for all Rust projects. The style guide in this RFC only covers the formatting of code, it does not have any recommendations about how to write idiomatic or high quality Rust code.

The formatting guidelines in the style guide have been decided on in the [formatting RFC process](https://github.com/rust-lang/rfcs/blob/master/text/1607-style-rfcs.md) by the style team. The guidelines were [extensively debated](https://github.com/rust-lang-nursery/fmt-rfcs/issues?utf8=%E2%9C%93&q=is%3Aissue) and this RFC is the result of that consensus process. I would like to discourage re-opening debate on the guidelines themselves here. Please limit discussion to the presentation and application of the guide, omissions from the guide, and issues which were missed in the formatting RFC process.

This comment has been minimized.

@scottmcm

scottmcm May 11, 2018

Member

I agree that re-debating is likely unhelpful, but it would be nice if more of the reasonings for the choices made it into the guide, or were easier to find from the relevant sections.

Maybe put more things into "overarching guidelines", and then include reasoning for any places were it's better do things differently? Some things that largely seem true, or were often repeated:

  • keywords should have spaces around them
  • put a space after {/before } (unless they end/start the line)
  • no space before a semicolon
  • single-line lists have separators; multi-line lists have terminators
// This comment goes up to the ................................. 80 char margin.
{
// This comment is .............................................. 80 chars wide.

This comment has been minimized.

@nnethercote

nnethercote May 11, 2018

I can see the rationale, but this suggestion seems very hard to enforce, esp. in combination with "a mechanical formatter should not change comments except to move them within a file".

This comment has been minimized.

@pachi

pachi May 11, 2018

Maybe the comment means "a mechanical formatter should not change comments except to move them within a line"?

}
```

If a struct variant is *short* (TODO link to definition), it may be formatted on

This comment has been minimized.

@Phrohdoh

Phrohdoh May 11, 2018

s/struct/enum

This comment has been minimized.

@Phrohdoh

Phrohdoh May 11, 2018

Nevermind this actually. I see what is being said here.

@alexreg

This comment has been minimized.

Copy link

alexreg commented May 11, 2018

The link to the actual style guide in the Markdown file is broken.

Prefer to put a comment on its own line. Where a comment follows code, there
should be a single space before it. Where a block comment is inline, there
should be surrounding whitespace as if it were an identifier or keyword. There
should be no trailing whitespace after a comment. Examples:

This comment has been minimized.

@claui

claui May 12, 2018

By trailing whitespace, do you mean whitespace that trails a line comment? Or are you referring to any excessive whitespace immediately after a comment, e. g. 2+ chars after a one-line block comment?

To which of the following cases would your rule apply?

Line comment

// This comment has trailing whitespace.       
                                        ^^^^^^^

Between block comment and closing sigil

pub fn foo(/* This is the foo implementation. */ x: T) {...}
pub fn bar(/* Like foo but with bar.          */ y: T) {...}
                                    ^^^^^^^^^

After the closing sigil

pub fn foo(/* This is the foo implementation. */ x: T) {...}
pub fn bar(/* Like foo but with bar. */          y: T) {...}
                                        ^^^^^^^^^

This comment has been minimized.

@steveklabnik

steveklabnik May 14, 2018

Member

@claui given that the guide also says to prefer // to /*, I don't believe /* and stuff like this was taken into consideration; it's only talking about the line comment style.

that said, in general, we tend not to align things anyway, so it'd be

pub fn foo(/* This is the foo implementation. */ x: T) {...}
pub fn bar(/* Like foo but with bar. */ y: T) {...}

AFAIK.

This comment has been minimized.

@claui

claui May 14, 2018

it's only talking about the line comment style.

I see. Would it make sense to discourage the same thing for newlines in multi-line block comments?

“There should be no trailing whitespace after a line comment. Similarly, no line in a multi-line block comment should have trailing whitespace.”

foo => bar,
a_very_long_patten | another_pattern if an_expression() => {
no_room_for_this_expression()
}

This comment has been minimized.

@brendanzab

brendanzab May 12, 2018

Member

The mixing of comma/vs-no comma for match arms always felt kind of inconsistent and annoying to manage as code evolves, so I've been setting match_block_trailing_comma = true. Was there any reasoning around going with match_block_trailing_comma = false as the default?

This comment has been minimized.

@brendanzab

brendanzab May 13, 2018

Member

Oh, I see - seems to have been brought up way back in the match formatting RFC:

Will we still have the option of configuring this in the future?

This comment has been minimized.

@nrc

nrc Jul 30, 2018

Author Member

Probably yes, that seems to be a popular option.


Humans comprehend information through pattern matching. By ensuring that all
Rust code has similar formatting, less mental effort is required to comprehend a
new project, lowering the bar to entry for new developers.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

Minor nitpick: the phrase is "barrier to entry"


Use spaces, not tabs. Each level of indentation must be four spaces. The maximum
width for a line is 100 characters. A tool should be configurable for all three
of these variables.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

Might I suggest converting this from a paragraph to a list?

  • Use spaces, not tabs.
  • Each level of indentation must be four spaces.
  • The maximum width for a line is 100 characters.
  • A tool should be configurable for all three of these variables.
Put each attribute on its own line, indented to the indentation of its item.
In the case of inner attributes (`#!`), indent it to the inner indentation (the
indentation of the item + 1). Prefer outer attributes, where possible.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

There are too many "indentations" in this paragraph, imo.

complexity of an item (for example, that all components must be simple names,
not more complex sub-expressions). For more discussion on suitable heuristics,
see the discussion on [this issue](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47).

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

Perhaps remove the second "discussion" in this sentence?

For more discussion on suitable heuristics, see this issue.

the `name` and `version` keys in that order at the top of that section,
followed by the remaining keys other than `description` in alphabetical order,
followed by the `description` at the end of that section.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

An example would go a long way here, to prevent any ambiguity.


* it is either
- used in expression position (not statement position)
- is an unsafe block in statement position

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

I'm not sure these need to be a sub-list. I think it would read more clearly to remove the "is is either" bullet and pull the following two - lines back and make them * instead.

by `move`), but put a space between the second `|` and the expression of the
closure. Between the `|`s, you should use function definition syntax, however,
elide types where possible.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

  • If at the beginning of a line, do not put a space before the closure's opening |.
  • If the closure is preceded by move, put a single space between move and the opening |.
  • If the closure precedes an expression, put a single space between the closing | and the expression.
  • Between the |s, use function definition syntax.
  • Omit types where possible.
a return type, when there are statements, there are comments in the body, or the
body expression spans multiple lines and is a control-flow expression. If using
braces, follow the rules above for blocks. Examples:

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

If possible, omit enclosing {}. However, there are a few circumstances under which {} should be used:

  • When you have a return type.
  • When there are statements.
  • When there are comments in the body.
  • When the body expression spans multiple lines and is a control-flow expression.

If using braces, follow the rules above for blocks. Examples:

```

Functional record update syntax is treated like a field, but it must never have
a trailing comma. There should be no space after `..`.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

"Additionally, there should be no space after ..."


Use a single-line form where possible. There should not be spaces around the
parentheses. Where a single-line form is not possible, each element of the tuple
should be on it's own block-indented line and there should be a trailing comma.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

Should be its and not it's

### Chains of fields and method calls

A chain is a sequence of field accesses and/or method calls. A chain may also
include the try operator. E.g., `a.b.c().d` or `foo?.bar().baz?`.

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

Proposed change:

include the try operator ?. For example:


Prefer formatting on one line if possible, and the chain is *small*. If
formatting on multiple lines, each field access or method call in the chain
should be on it's own line with the line-break before the `.` and after any `?`.

This comment has been minimized.

@yoshizzle
Prefer formatting on one line if possible, and the chain is *small*. If
formatting on multiple lines, each field access or method call in the chain
should be on it's own line with the line-break before the `.` and after any `?`.
Each line should be block-indented. E.g.,

This comment has been minimized.

@yoshizzle

yoshizzle May 14, 2018

perhaps add a colon after indented and remove E.g.,

@varkor

This comment has been minimized.

Copy link
Member

varkor commented May 18, 2018

Would this be the right place to specify formatting guidelines for macro syntax (e.g. list-like macros should accept trailing commas)?

@nrc

This comment has been minimized.

Copy link
Member Author

nrc commented Jul 30, 2018

Would this be the right place to specify formatting guidelines for macro syntax (e.g. list-like macros should accept trailing commas)?

Macro syntax is mostly out of scope here. Rustfmt mostly avoids formatting macro definitions and some macro uses and I expect that we'll revisit both the specification and implementation of macro formatting in the future.

nrc added a commit to rust-dev-tools/fmt-rfcs that referenced this pull request Jul 30, 2018

@nrc

This comment has been minimized.

Copy link
Member Author

nrc commented Jul 30, 2018

@rfcbot fcp merge

The RFC is updated with most of the feedback here. Thanks everyone!

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Jul 30, 2018

Team member @nrc has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@killercup

This comment has been minimized.

Copy link
Member

killercup commented Aug 28, 2018

@rfcbot reviewed

@japaric

This comment has been minimized.

Copy link
Member

japaric commented Aug 28, 2018

@rfcbot reviewed

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Oct 9, 2018

🔔 This is now entering its final comment period, as per the review above. 🔔

@fitzgen

This comment has been minimized.

Copy link
Member

fitzgen commented Oct 9, 2018

@rfcbot reviewed

nrc added some commits May 5, 2018

Formatting guidelines
This RFC defines an official Rust style guide. The style is a specification for the default behaviour of [Rustfmt](https://github.com/rust-lang-nursery/rustfmt), is required for official Rust projects (including the compiler and standard libraries), and is recommended for all Rust projects. The style guide in this RFC only covers the formatting of code, it does not have any recommendations about how to write idiomatic or high quality Rust code.

@nrc nrc force-pushed the nrc:style-guide branch from c2dfcad to 9bb238e Oct 15, 2018

@@ -118,7 +117,7 @@ fn main() {
### Closures

Don't put any extra spaces before the first `|` (unless the closure is prefixed
by `move`), but put a space between the second `|` and the expression of the
by `move`); put a space between the second `|` and the expression of the

This comment has been minimized.

@liigo

liigo Oct 15, 2018

Contributor
let x = |a| a; // a space before |
test( |a| a ); // a space before |

which one is extra space?

This comment has been minimized.

@joshtriplett

joshtriplett Oct 15, 2018

Member

The latter. The former is covered by always putting spaces around =.

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Oct 19, 2018

The final comment period, with a disposition to merge, as per the review above, is now complete.

@nrc

This comment has been minimized.

Copy link
Member Author

nrc commented Oct 22, 2018

Merged in 3efb02f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.