-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Formatting guidelines #2436
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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!
style-guide/items.md
Outdated
} | ||
``` | ||
|
||
If a struct variant is *short* (TODO link to definition), it may be formatted on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's still a TODO
here.
style-guide/items.md
Outdated
} | ||
``` | ||
|
||
Prefer using a unit struct to an empty struct (these only exist to simplify code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this format is preferred over trailing
, like in comma-separated lists, for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
style-guide/items.md
Outdated
before: | ||
|
||
```rust | ||
pub type Foo: Bar; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: indentation.
style-guide/advice.md
Outdated
|
||
## Names | ||
|
||
* Types shall be `PascalCase`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was decided to use UpperCamelCase
rather than PascalCase
.
style-guide/items.md
Outdated
|
||
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "its".
Do not put any spaces around the `.`. | ||
|
||
```rust | ||
x.foo().bar().baz(x, y, z); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another style is:
variable
.foo()
.bar()
.baz(x, y, z);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Centril: this is mentioned lower down (I probably should have commented further down).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
style-guide/expressions.md
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "multi-line".
clause, then you must use the above form: | ||
|
||
```rust | ||
a_very_long_pattern |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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 (`//* ... */`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 //*
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
style-guide/README.md
Outdated
```rust | ||
fn foo() { | ||
let x = ...; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the four spaces on this line intentional or not? And if they are intentional, are they normative or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks like a bug to me.
style-guide/items.md
Outdated
|
||
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: I read "spaces around braces" as Error {err: u32} ,
; perhaps inside braces instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we specify both around and inside the braces?
Error { err: u32 }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great file, but doesn't seemed to be linked from anywhere. Maybe reference it in the readme?
style-guide/items.md
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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=✓&q=is:issue) 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the comment means "a mechanical formatter should not change comments except to move them within a line"?
style-guide/items.md
Outdated
} | ||
``` | ||
|
||
If a struct variant is *short* (TODO link to definition), it may be formatted on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/struct/enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind this actually. I see what is being said here.
The link to the actual style guide in the Markdown file is broken. |
style-guide/README.md
Outdated
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) {...}
^^^^^^^^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably yes, that seems to be a popular option.
style-guide/README.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nitpick: the phrase is "barrier to entry"
style-guide/README.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example would go a long way here, to prevent any ambiguity.
style-guide/expressions.md
Outdated
|
||
* it is either | ||
- used in expression position (not statement position) | ||
- is an unsafe block in statement position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 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 betweenmove
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: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 `..`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Additionally, there should be no space after ..
."
style-guide/expressions.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be its and not it's
style-guide/expressions.md
Outdated
### 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?`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposed change:
include the try operator ?
. For example:
style-guide/expressions.md
Outdated
|
||
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 `?`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its not it's
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., |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps add a colon after indented and remove E.g.,
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. |
@rfcbot fcp merge The RFC is updated with most of the feedback here. Thanks everyone! |
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. |
@rfcbot reviewed |
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@rfcbot reviewed |
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.
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let x = |a| a; // a space before |
test( |a| a ); // a space before |
which one is extra space
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latter. The former is covered by always putting spaces around =
.
The final comment period, with a disposition to merge, as per the review above, is now complete. |
Merged in 3efb02f |
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