Rollup merge of #113380 - joshtriplett:style-guide-cleanup-must-should-may, r=calebcartwright

style-guide: clean up "must"/"should"/"may"

Avoid using "should" or "may" for required parts of the default style.

The style guide inconsistently used language like "there should be a space" or
"it should be on its own line", or "may be written on a single line", for
things that are required components of the default Rust style. "should" and
especially "may" come across as optional. While the style guide overall now has
a statement at the top that the default style itself is a *recommendation*, the
*definition* of the default style should not be ambiguous about what's part of
the default style.

Rewrite language in the style guide to only use "should" and "may" and similar
for truly optional components of the style (e.g. things a tool cannot or should
not enforce in its default configuration).

In their place, either use "must", or rewrite in imperative style ("put a
space", "start it on the same line"). The latter also substantially reduces the
use of passive voice.

Looking for "should"s also flagged some recommendations the style guide made
for configurability of tools (e.g. a tool "should" have a given configuration
option). I've removed those recommendations, per discussion with the style
team; it's not the domain of the style guide to make such recommendations, only
to define the default Rust style.

In the process of making this change, I also fixed a typo, fixed a text structure
issue, fixed an example that didn't match the Rust style (missing a trailing
comma), and added an additional example for clarity. (Those changes would have
conflicted with this one.) Those changes appear in separate commits.

These are all purely editorial changes, and do not affect the semantic
definition of the Rust style.
This commit is contained in:
Matthias Krüger 2023-07-21 06:52:27 +02:00 committed by GitHub
commit 20ce7f17c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 260 additions and 270 deletions

View File

@ -40,7 +40,6 @@ options.
* Each level of indentation must be four spaces (that is, all indentation
outside of string literals and comments must be a multiple of four).
* The maximum width for a line is 100 characters.
* A tool may choose to make some of these configurable.
#### Block indent
@ -63,7 +62,8 @@ example) and less rightward drift.
### Trailing commas
Lists should have a trailing comma when followed by a newline:
In comma-separated lists of any kind, use a trailing comma when followed by a
newline:
```rust
function_call(
@ -99,8 +99,6 @@ fn bar() {}
fn baz() {}
```
Formatting tools may wish to make the bounds on blank lines configurable.
### [Module-level items](items.md)
### [Statements](statements.md)
### [Expressions](expressions.md)
@ -114,17 +112,17 @@ formatter might skip formatting of comments.
Prefer line comments (`//`) to block comments (`/* ... */`).
When using line comments there should be a single space after the opening sigil.
When using line comments, put a single space after the opening sigil.
When using single-line block comments there should be a single space after the
opening sigil and before the closing sigil. Multi-line block comments should
have a newline after the opening sigil and before the closing sigil.
When using single-line block comments, put a single space after the opening
sigil and before the closing sigil. For multi-line block comments, put a
newline after the opening sigil, and a newline before the closing sigil.
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 or at the end of any line in a
multi-line comment. Examples:
Prefer to put a comment on its own line. Where a comment follows code, put a
single space before it. Where a block comment appears inline, use surrounding
whitespace as if it were an identifier or keyword. Do not include trailing
whitespace after a comment or at the end of any line in a multi-line comment.
Examples:
```rust
// A comment on an item.
@ -173,7 +171,7 @@ Prefer line comments (`///`) to block comments (`/** ... */`).
Prefer outer doc comments (`///` or `/** ... */`), only use inner doc comments
(`//!` and `/*! ... */`) to write module-level or crate-level documentation.
Doc comments should come before attributes.
Put doc comments before attributes.
### Attributes
@ -198,18 +196,20 @@ struct CRepr {
}
```
For attributes with an equal sign, there should be a single space before and
after the `=`, e.g., `#[foo = 42]`.
For attributes with an equal sign, put a single space before and after the `=`,
e.g., `#[foo = 42]`.
There must only be a single `derive` attribute. Note for tool authors: if
combining multiple `derive` attributes into a single attribute, the ordering of
the derived names should be preserved. E.g., `#[derive(bar)] #[derive(foo)]
struct Baz;` should be formatted to `#[derive(bar, foo)] struct Baz;`.
the derived names must generally be preserved for correctness:
`#[derive(Foo)] #[derive(Bar)] struct Baz;` must be formatted to
`#[derive(Foo, Bar)] struct Baz;`.
### *small* items
In many places in this guide we specify that a formatter may format an item
differently if it is *small*, for example struct literals:
In many places in this guide we specify formatting that depends on a code
construct being *small*. For example, single-line vs multi-line struct
literals:
```rust
// Normal formatting
@ -218,7 +218,7 @@ Foo {
f2: another_expression(),
}
// *small* formatting
// "small" formatting
Foo { f1, f2 }
```
@ -231,10 +231,6 @@ 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 [this issue](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47).
Tools should give the user an option to ignore such heuristics and always use
the normal formatting.
## [Non-formatting conventions](advice.md)
## [Cargo.toml conventions](cargo.md)

View File

@ -2,10 +2,13 @@
### Blocks
A block expression should have a newline after the initial `{` and before the
terminal `}`. Any qualifier before the block (e.g., `unsafe`) should always be
on the same line as the opening brace, and separated with a single space. The
contents of the block should be block indented:
A block expression must have a newline after the initial `{` and before the
terminal `}`, unless it qualifies to be written as a single line based on
another style rule.
A keyword before the block (such as `unsafe` or `async`) must be on the same
line as the opening brace, with a single space between the keyword and the
opening brace. Indent the contents of the block.
```rust
fn block_as_stmt() {
@ -40,7 +43,7 @@ fn unsafe_block_as_stmt() {
}
```
If a block has an attribute, it should be on its own line:
If a block has an attribute, put it on its own line before the block:
```rust
fn block_as_stmt() {
@ -54,18 +57,18 @@ fn block_as_stmt() {
}
```
Avoid writing comments on the same line as the braces.
Avoid writing comments on the same lines as either of the braces.
An empty block should be written as `{}`.
Write an empty block as `{}`.
A block may be written on a single line if:
Write a block on a single line if:
* it is either used in expression position (not statement position) or is an
unsafe block in statement position
* contains a single-line expression and no statements
* contains no comments
* it contains a single-line expression and no statements
* it contains no comments
A single line block should have spaces after the opening brace and before the
For a single-line block, put spaces after the opening brace and before the
closing brace.
Examples:
@ -117,9 +120,9 @@ fn main() {
### Closures
Don't put any extra spaces before the first `|` (unless the closure is prefixed
by `move`); 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.
by a keyword such as `move`); put a space between the second `|` and the
expression of the closure. Between the `|`s, use function definition syntax,
but elide types where possible.
Use closures without the enclosing `{}`, if possible. Add the `{}` when you have
a return type, when there are statements, there are comments in the body, or the
@ -155,13 +158,14 @@ move |arg1: i32, arg2: i32| -> i32 {
### Struct literals
If a struct literal is *small* it may be formatted on a single line. If not,
each field should be on it's own, block-indented line. There should be a
trailing comma in the multi-line form only. There should be a space after the
colon only.
If a struct literal is *small*, format it on a single line, and do not use a
trailing comma. If not, split it across multiple lines, with each field on its
own block-indented line, and use a trailing comma.
There should be a space before the opening brace. In the single-line form there
should be spaces after the opening brace and before the closing brace.
For each `field: value` entry, put a space after the colon only.
Put a space before the opening brace. In the single-line form, put spaces after
the opening brace and before the closing brace.
```rust
Foo { field1, field2: 0 }
@ -172,7 +176,7 @@ let f = Foo {
```
Functional record update syntax is treated like a field, but it must never have
a trailing comma. There should be no space after `..`.
a trailing comma. Do not put a space after `..`.
let f = Foo {
field1,
@ -182,9 +186,13 @@ let f = Foo {
### Tuple literals
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 its own block-indented line and there should be a trailing comma.
Use a single-line form where possible. Do not put spaces between the opening
parenthesis and the first element, or between the last element and the closing
parenthesis. Separate elements with a comma followed by a space.
Where a single-line form is not possible, write the tuple across
multiple lines, with each element of the tuple on its own block-indented line,
and use a trailing comma.
```rust
(a, b, c)
@ -198,14 +206,23 @@ let x = (
### Tuple struct literals
There should be no space between the identifier and the opening parenthesis.
Otherwise, follow the rules for tuple literals, e.g., `Foo(a, b)`.
Do not put space between the identifier and the opening parenthesis. Otherwise,
follow the rules for tuple literals:
```rust
Foo(a, b, c)
let x = Foo(
a_long_expr,
another_very_long_expr,
);
```
### Enum literals
Follow the formatting rules for the various struct literals. Prefer using the
name of the enum as a qualifying name, unless the enum is in the prelude. E.g.,
name of the enum as a qualifying name, unless the enum is in the prelude:
```rust
Foo::Bar(a, b)
@ -219,24 +236,29 @@ Ok(an_expr)
### Array literals
For simple array literals, avoid line breaking, no spaces around square
brackets, contents of the array should be separated by commas and spaces. If
using the repeating initialiser, there should be a space after the semicolon
only. Apply the same rules if using the `vec!` or similar macros (always use
square brackets here). Examples:
Write small array literals on a single line. Do not put spaces between the opening
square bracket and the first element, or between the last element and the closing
square bracket. Separate elements with a comma followed by a space.
If using the repeating initializer, put a space after the semicolon
only.
Apply the same rules if using `vec!` or similar array-like macros; always use
square brackets with such macros. Examples:
```rust
fn main() {
[1, 2, 3];
vec![a, b, c, d];
let x = [1, 2, 3];
let y = vec![a, b, c, d];
let a = [42; 10];
}
```
If a line must be broken, prefer breaking only after the `;`, if possible.
Otherwise, follow the rules below for function calls. In any case, the contents
of the initialiser should be block indented and there should be line breaks
after the opening bracket and before the closing bracket:
For arrays that have to be broken across lines, if using the repeating
initializer, break after the `;`, not before. Otherwise, follow the rules below
for function calls. In any case, block-indent the contents of the initializer,
and put line breaks after the opening square bracket and before the closing
square bracket:
```rust
fn main() {
@ -255,11 +277,12 @@ fn main() {
### Array accesses, indexing, and slicing.
No spaces around the square brackets, avoid breaking lines if possible, never
break a line between the target expression and the opening bracket. If the
indexing expression covers multiple lines, then it should be block indented and
there should be newlines after the opening brackets and before the closing
bracket. However, this should be avoided where possible.
Don't put spaces around the square brackets. Avoid breaking lines if possible.
Never break a line between the target expression and the opening square
bracket. If the indexing expression must be broken onto a subsequent line, or
spans multiple lines itself, then block-indent the indexing expression, and put
newlines after the opening square bracket and before the closing square
bracket:
Examples:
@ -291,7 +314,7 @@ if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general,
within expressions, prefer dereferencing to taking references, unless necessary
(e.g. to avoid an unnecessarily expensive operation).
Use parentheses liberally, do not necessarily elide them due to precedence.
Use parentheses liberally; do not necessarily elide them due to precedence.
Tools should not automatically insert or remove parentheses. Do not use spaces
to indicate precedence.
@ -353,10 +376,10 @@ foo(x, y, z)
#### Multi-line calls
If the function call is not *small*, it would otherwise over-run the max width,
or any argument or the callee is multi-line, then the call should be formatted
across multiple lines. In this case, each argument should be on it's own block-
indented line, there should be a newline after the opening parenthesis and
before the closing parenthesis, and there should be a trailing comma. E.g.,
or any argument or the callee is multi-line, then format the call across
multiple lines. In this case, put each argument on its own block-indented line,
break after the opening parenthesis and before the closing parenthesis,
and use a trailing comma:
```rust
a_function_call(
@ -379,17 +402,18 @@ x.foo().bar().baz(x, y, z);
### Macro uses
Macros which can be parsed like other constructs should be formatted like those
If a macro can be parsed like other constructs, format it like those
constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a
function call (ignoring the `!`), therefore it should be formatted following the
rules for function calls.
function call (ignoring the `!`), so format it using the rules for function
calls.
#### Special case macros
Macros which take a format string and where all other arguments are *small* may
be formatted with arguments before and after the format string on a single line
and the format string on its own line, rather than putting each argument on its
own line. For example,
For macros which take a format string, if all other arguments are *small*,
format the arguments before the format string on a single line if they fit, and
format the arguments after the format string on a single line if they fit, with
the format string on its own line. If the arguments are not small or do not
fit, put each on its own line as with a function. For example:
```rust
println!(
@ -416,13 +440,13 @@ let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char;
### 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?`.
A chain is a sequence of field accesses, method calls, and/or uses of the try
operator `?`. E.g., `a.b.c().d` or `foo?.bar().baz?`.
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 its own line with the line-break before the `.` and after any `?`.
Each line should be block-indented. E.g.,
Format the chain on one line if it is "small" and otherwise possible to do so.
If formatting on multiple lines, put each field access or method call in the
chain on its own line, with the line-break before the `.` and after any `?`.
Block-indent each subsequent line:
```rust
let foo = bar
@ -431,13 +455,16 @@ let foo = bar
```
If the length of the last line of the first element plus its indentation is
less than or equal to the indentation of the second line (and there is space),
then combine the first and second lines, e.g.,
less than or equal to the indentation of the second line, then combine the
first and second lines if they fit. Apply this rule recursively.
```rust
x.baz?
.qux()
x.y.z
.qux()
let foo = x
.baz?
.qux();
@ -489,13 +516,13 @@ self.pre_comment.as_ref().map_or(
This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for`
expressions.
The keyword, any initial clauses, and the opening brace of the block should be
on a single line. The usual rules for [block formatting](#blocks) should be
applied to the block.
Put the keyword, any initial clauses, and the opening brace of the block all on
a single line, if they fit. Apply the usual rules for [block
formatting](#blocks) to the block.
If there is an `else` component, then the closing brace, `else`, any following
clause, and the opening brace should all be on the same line. There should be a
single space before and after the `else` keyword. For example:
If there is an `else` component, then put the closing brace, `else`, any
following clause, and the opening brace all on the same line, with a single
space before and after the `else` keyword:
```rust
if ... {
@ -513,10 +540,10 @@ if let ... {
}
```
If the control line needs to be broken, then prefer to break before the `=` in
`* let` expressions and before `in` in a `for` expression; the following line
should be block indented. If the control line is broken for any reason, then the
opening brace should be on its own line and not indented. Examples:
If the control line needs to be broken, prefer to break before the `=` in `*
let` expressions and before `in` in a `for` expression; block-indent the
following line. If the control line is broken for any reason, put the opening
brace on its own line, not indented. Examples:
```rust
while let Some(foo)
@ -539,10 +566,10 @@ if a_long_expression
}
```
Where the initial clause is multi-lined and ends with one or more closing
parentheses, square brackets, or braces, and there is nothing else on that line,
and that line is not indented beyond the indent on the first line of the control
flow expression, then the opening brace of the block should be put on the same
Where the initial clause spans multiple lines and ends with one or more closing
parentheses, square brackets, or braces, and there is nothing else on that
line, and that line is not indented beyond the indent on the first line of the
control flow expression, then put the opening brace of the block on the same
line with a preceding space. For example:
```rust
@ -558,9 +585,9 @@ if !self.config.file_lines().intersects(
#### Single line `if else`
Formatters may place an `if else` or `if let else` on a single line if it occurs
in expression context (i.e., is not a standalone statement), it contains a
single `else` clause, and is *small*. For example:
Put an `if else` or `if let else` on a single line if it occurs in expression
context (i.e., is not a standalone statement), it contains a single `else`
clause, and is *small*:
```rust
let y = if x { 0 } else { 1 };
@ -582,9 +609,9 @@ if x {
### Match
Prefer not to line-break inside the discriminant expression. There must always
be a line break after the opening brace and before the closing brace. The match
arms must be block indented once:
Prefer not to line-break inside the discriminant expression. Always break after
the opening brace and before the closing brace. Block-indent the match arms
once:
```rust
match foo {
@ -598,7 +625,7 @@ let x = match foo.bar.baz() {
Use a trailing comma for a match arm if and only if not using a block.
Never start a match arm pattern with `|`, e.g.,
Never start a match arm pattern with `|`:
```rust
match foo {
@ -608,14 +635,13 @@ match foo {
| a_very_long_pattern
| another_pattern
| yet_another_pattern
| a_forth_pattern => {
| a_fourth_pattern => {
...
}
}
```
Prefer
Prefer:
```rust
match foo {
@ -623,7 +649,7 @@ match foo {
a_very_long_pattern
| another_pattern
| yet_another_pattern
| a_forth_pattern => {
| a_fourth_pattern => {
...
}
}
@ -633,11 +659,11 @@ Avoid splitting the left-hand side (before the `=>`) of a match arm where
possible. If the right-hand side of the match arm is kept on the same line,
never use a block (unless the block is empty).
If the right-hand side consists of multiple statements or has line comments or
the start of the line cannot be fit on the same line as the left-hand side, use
a block.
If the right-hand side consists of multiple statements, or has line comments,
or the start of the line does not fit on the same line as the left-hand side,
use a block.
The body of a block arm should be block indented once.
Block-indent the body of a block arm.
Examples:
@ -662,8 +688,8 @@ match foo {
```
If the body is a single expression with no line comments and not a control flow
expression, then it may be started on the same line as the right-hand side. If
not, then it must be in a block. Example,
expression, start it on the same line as the left-hand side. If not, then it
must be in a block. Example:
```rust
match foo {
@ -687,8 +713,8 @@ match foo {
#### Line-breaking
Where it is possible to use a block form on the right-hand side and avoid
breaking the left-hand side, do that. E.g.
If using a block form on the right-hand side of a match arm makes it possible
to avoid breaking on the left-hand side, do that:
```rust
// Assuming the following line does not fit in the max width
@ -720,7 +746,7 @@ body on a new line:
If required to break the pattern, put each clause of the pattern on its own
line with no additional indent, breaking before the `|`. If there is an `if`
clause, then you must use the above form:
clause, use the above form:
```rust
a_very_long_pattern
@ -740,7 +766,7 @@ clause, then you must use the above form:
```
If the pattern is multi-line, and the last line is less wide than the indent, do
not put the `if` clause on a newline. E.g.,
not put the `if` clause on a new line. E.g.,
```rust
Token::Dimension {
@ -753,8 +779,8 @@ not put the `if` clause on a newline. E.g.,
```
If every clause in a pattern is *small*, but the whole pattern does not fit on
one line, then the pattern may be formatted across multiple lines with as many
clauses per line as possible. Again break before a `|`:
one line, then format the pattern across multiple lines with as many clauses
per line as possible. Again, break before a `|`:
```rust
foo | bar | baz
@ -783,8 +809,8 @@ E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
### Combinable expressions
Where a function call has a single argument, and that argument is formatted
across multiple-lines, the outer call may be formatted as if it were a single-
line call. The same combining behaviour may be applied to any similar
across multiple-lines, format the outer call as if it were a single-line call,
if the result fits. Apply the same combining behaviour to any similar
expressions which have multi-line, block-indented lists of sub-expressions
delimited by parentheses (e.g., macros or tuple struct literals). E.g.,
@ -814,13 +840,12 @@ let arr = [combinable(
)];
```
Such behaviour should extend recursively, however, tools may choose to limit the
depth of nesting.
Apply this behavior recursively.
Only where the multi-line sub-expression is a closure with an explicit block,
this combining behaviour may be used where there are other arguments, as long as
all the arguments and the first line of the closure fit on the first line, the
closure is the last argument, and there is only one closure argument:
For a function with multiple arguments, if the last argument is a multi-line
closure with an explicit block, there are no other closure arguments, and all
the arguments and the first line of the closure fit on the first line, use the
same combining behavior:
```rust
foo(first_arg, x, |param| {
@ -835,16 +860,17 @@ foo(first_arg, x, |param| {
Do not put spaces in ranges, e.g., `0..10`, `x..=y`, `..x.len()`, `foo..`.
When writing a range with both upper and lower bounds, if the line must be
broken, break before the range operator and block indent the second line:
broken within the range, break before the range operator and block indent the
second line:
```rust
a_long_expression
..another_long_expression
```
For the sake of indicating precedence, we recommend that if either bound is a
compound expression, then use parentheses around it, e.g., `..(x + 1)`,
`(x.f)..(x.f.len())`, or `0..(x - 10)`.
For the sake of indicating precedence, if either bound is a compound
expression, use parentheses around it, e.g., `..(x + 1)`, `(x.f)..(x.f.len())`,
or `0..(x - 10)`.
### Hexadecimal literals
@ -852,11 +878,8 @@ compound expression, then use parentheses around it, e.g., `..(x + 1)`,
Hexadecimal literals may use upper- or lower-case letters, but they must not be
mixed within the same literal. Projects should use the same case for all
literals, but we do not make a recommendation for either lower- or upper-case.
Tools should have an option to convert mixed case literals to upper-case, and
may have an option to convert all literals to either lower- or upper-case.
## Patterns
Patterns should be formatted like their corresponding expressions. See the
section on `match` for additional formatting for patterns in match arms.
Format patterns like their corresponding expressions. See the section on
`match` for additional formatting for patterns in match arms.

View File

@ -9,19 +9,17 @@ an item appears at module level or within another item.
alphabetically.
`use` statements, and module *declarations* (`mod foo;`, not `mod { ... }`)
must come before other items. We recommend that imports come before module
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_use]`, since that may be semantics changing.
Tools should make the above ordering optional.
must come before other items. Put imports before module declarations. Sort each
alphabetically, except that `self` and `super` must come before any other
names.
Don't automatically move module declarations annotated with `#[macro_use]`,
since that might change semantics.
### Function definitions
In Rust, people often find functions by searching for `fn [function-name]`, so
the formatting of function definitions shold enable this.
the formatting of function definitions must enable this.
The proper ordering and spacing is:
@ -83,9 +81,9 @@ enum FooBar {
}
```
If a struct variant is [*small*](index.html#small-items), 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 each brace:
If a struct variant is [*small*](index.html#small-items), format it on one
line. In this case, do not use a trailing comma for the field list, but do put
spaces around each brace:
```rust
enum FooBar {
@ -94,9 +92,9 @@ enum FooBar {
```
In an enum with multiple struct variants, if any struct variant is written on
multiple lines, then the multi-line formatting should be used for all struct
variants. However, such a situation might be an indication that you should
factor out the fields of the variant into their own struct.
multiple lines, use the multi-line formatting for all struct variants. However,
such a situation might be an indication that you should factor out the fields
of the variant into their own struct.
### Structs and Unions
@ -143,9 +141,9 @@ union Foo {
### Tuple structs
Put the whole struct on one line if possible. Types in the parentheses should be
separated by a comma and space with no trailing comma. No spaces around the
parentheses or semicolon:
Put the whole struct on one line if possible. Separate types within the
parentheses using a comma and space. Don't use a trailing comma for a
single-line tuple struct. Don't put spaces around the parentheses or semicolon:
```rust
pub struct Foo(String, u8);
@ -154,9 +152,11 @@ pub struct Foo(String, u8);
Prefer unit structs to empty tuple structs (these only exist to simplify code
generation), e.g., `struct Foo;` rather than `struct Foo();`.
For more than a few fields, prefer a proper struct with named fields. Given
this, a tuple struct should always fit on one line. If it does not, block format
the fields with a field on each line and a trailing comma:
For more than a few fields (in particular if the tuple struct does not fit on
one line), prefer a proper struct with named fields.
For a multi-line tuple struct, block-format the fields with a field on each
line and a trailing comma:
```rust
pub struct Foo(
@ -168,9 +168,9 @@ pub struct Foo(
### Traits
Trait items should be block-indented. If there are no items, the trait may be
formatted on a single line. Otherwise there should be line-breaks after the
opening brace and before the closing brace:
Use block-indent for trait items. If there are no items, format the trait (including its `{}`)
on a single line. Otherwise, break after the opening brace and before
the closing brace:
```rust
trait Foo {}
@ -180,8 +180,8 @@ pub trait Bar {
}
```
If the trait has bounds, there should be a space after the colon but not before
and before and after each `+`, e.g.,
If the trait has bounds, put a space after the colon but not before,
and put spaces around each `+`, e.g.,
```rust
trait Foo: Debug + Bar {}
@ -207,9 +207,9 @@ pub trait IndexRanges:
### Impls
Impl items should be block indented. If there are no items, the impl may be
formatted on a single line. Otherwise there should be line-breaks after the
opening brace and before the closing brace:
Use block-indent for impl items. If there are no items, format the impl
(including its `{}`) on a single line. Otherwise, break after the opening brace
and before the closing brace:
```rust
impl Foo {}
@ -267,12 +267,12 @@ macro_rules! foo {
Prefer to put a generics clause on one line. Break other parts of an item
declaration rather than line-breaking a generics clause. If a generics clause is
large enough to require line-breaking, you should prefer to use a `where` clause
instead.
large enough to require line-breaking, prefer a `where` clause instead.
Do not put spaces before or after `<` nor before `>`. Only put a space after `>`
if it is followed by a word or opening brace, not an opening parenthesis. There
should be a space after each comma and no trailing comma.
Do not put spaces before or after `<` nor before `>`. Only put a space after
`>` if it is followed by a word or opening brace, not an opening parenthesis.
Put a space after each comma. Do not use a trailing comma for a single-line
generics clause.
```rust
fn foo<T: Display, U: Debug>(x: Vec<T>, y: Vec<U>) ...
@ -280,10 +280,9 @@ fn foo<T: Display, U: Debug>(x: Vec<T>, y: Vec<U>) ...
impl<T: Display, U: Debug> SomeType<T, U> { ...
```
If the generics clause must be formatted across multiple lines, each parameter
should have its own block-indented line, there should be newlines after the
opening bracket and before the closing bracket, and there should be a trailing
comma.
If the generics clause must be formatted across multiple lines, put each
parameter on its own block-indented line, break after the opening `<` and
before the closing `>`, and use a trailing comma.
```rust
fn foo<
@ -292,8 +291,7 @@ fn foo<
>(x: Vec<T>, y: Vec<U>) ...
```
If an associated type is bound in a generic type, then there should be spaces on
either side of the `=`:
If an associated type is bound in a generic type, put spaces around the `=`:
```rust
<T: Example<Item = u32>>
@ -306,12 +304,14 @@ Prefer to use single-letter names for generic parameters.
These rules apply for `where` clauses on any item.
A `where` clause may immediately follow a closing bracket of any kind.
Otherwise, it must start a new line, with no indent. Each component of a `where`
clause must be on its own line and be block indented. There should be a trailing
If immediately following a closing bracket of any kind, write the keyword
`where` on the same line, with a space before it.
Otherwise, put `where` on a new line at the same indentation level. Put each
component of a `where` clause on its own line, block-indented. Use a trailing
comma, unless the clause is terminated with a semicolon. If the `where` clause
is followed by a block (or assignment), the block should be started on a new
line. Examples:
is followed by a block (or assignment), start that block on a new line.
Examples:
```rust
fn function<T, U>(args)
@ -355,12 +355,12 @@ where
= Bar<T>;
```
If a `where` clause is very short, we recommend using an inline bound on the
type parameter.
If a `where` clause is very short, prefer using an inline bound on the type
parameter.
If a component of a `where` clause is long, it may be broken before `+` and
further block indented. Each bound should go on its own line. E.g.,
If a component of a `where` clause does not fit and contains `+`, break it
before each `+` and block-indent the continuation lines. Put each bound on its
own line. E.g.,
```rust
impl<T: ?Sized, Idx> IndexRanges<Idx> for T
@ -369,40 +369,14 @@ where
+ Index<RangeTo<Idx>, Output = Self::Output>
+ Index<RangeFrom<Idx>, Output = Self::Output>
+ Index<RangeInclusive<Idx>, Output = Self::Output>
+ Index<RangeToInclusive<Idx>, Output = Self::Output> + Index<RangeFull>
+ Index<RangeToInclusive<Idx>, Output = Self::Output>
+ Index<RangeFull>,
```
#### 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
item's signature is also kept on one line. In this case, there is no need for a
trailing comma and if followed by a block, no need for a newline before the
block. E.g.,
```rust
// May be single-lined.
fn foo<T>(args) -> ReturnType
where T: Bound {
body
}
// Must be multi-lined.
fn foo<T>(
args
) -> ReturnType
where
T: Bound,
{
body
}
```
### Type aliases
Type aliases should generally be kept on one line. If necessary to break the
line, do so after the `=`; the right-hand-side should be block indented:
Keep type aliases on one line when they fit. If necessary to break the line, do
so after the `=`, and block-indent the right-hand side:
```rust
pub type Foo = Bar<T>;
@ -427,9 +401,8 @@ where
### Associated types
Associated types should follow the guidelines above for type aliases. Where an
associated type has a bound, there should be a space after the colon but not
before:
Format associated types like type aliases. Where an associated type has a
bound, put a space after the colon but not before:
```rust
pub type Foo: Bar;
@ -438,15 +411,14 @@ pub type Foo: Bar;
### extern items
When writing extern items (such as `extern "C" fn`), always be explicit about
the ABI. For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or
When writing extern items (such as `extern "C" fn`), always specify the ABI.
For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or
`extern "C" { ... }`.
### Imports (`use` statements)
If an import can be formatted on one line, do so. There should be no spaces
around braces.
Format imports on one line where possible. Don't put spaces around braces.
```rust
use a::b::c;
@ -458,7 +430,7 @@ use a::b::{foo, bar, baz};
#### Large list imports
Prefer to use multiple imports rather than a multi-line import. However, tools
should not split imports by default (they may offer this as an option).
should not split imports by default.
If an import does require multiple lines (either because a list of single names
does not fit within the max width, or because of the rules for nested imports
@ -521,14 +493,12 @@ example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
#### Normalisation
Tools must make the following normalisations:
Tools must make the following normalisations, recursively:
* `use a::self;` -> `use a;`
* `use a::{};` -> (nothing)
* `use a::{b};` -> `use a::b;`
And must apply these recursively.
Tools must not otherwise merge or un-merge import lists or adjust glob imports
(without an explicit option).

View File

@ -2,8 +2,8 @@
### Let statements
There should be spaces after the `:` and on both sides of the `=` (if they are
present). No space before the semicolon.
Put a space after the `:` and on both sides of the `=` (if they are present).
Don't put a space before the semicolon.
```rust
// A comment.
@ -14,19 +14,19 @@ let pattern: Type;
let pattern = expr;
```
If possible the declaration should be formatted on a single line. If this is not
possible, then try splitting after the `=`, if the declaration can fit on two
lines. The expression should be block indented.
If possible, format the declaration on a single line. If not possible, then try
splitting after the `=`, if the declaration fits on two lines. Block-indent the
expression.
```rust
let pattern: Type =
expr;
```
If the first line does not fit on a single line, then split after the colon,
using block indentation. If the type covers multiple lines, even after line-
breaking after the `:`, then the first line may be placed on the same line as
the `:`, subject to the [combining rules](https://github.com/rust-lang-nursery/fmt-rfcs/issues/61) (WIP).
If the first line still does not fit on a single line, split after the `:`, and
use block indentation. If the type requires multiple lines, even after
line-breaking after the `:`, then place the first line on the same line as the
`:`, subject to the [combining rules](expressions.html#combinable-expressions).
```rust
@ -51,12 +51,12 @@ let (abcd,
```
If the expression covers multiple lines, if the first line of the expression
fits in the remaining space, it stays on the same line as the `=`, the rest of the
expression is not indented. If the first line does not fit, then it should start
on the next lines, and should be block indented. If the expression is a block
and the type or pattern cover multiple lines, then the opening brace should be
on a new line and not indented (this provides separation for the interior of the
block from the type), otherwise the opening brace follows the `=`.
fits in the remaining space, it stays on the same line as the `=`, and the rest
of the expression is not further indented. If the first line does not fit, then
put the expression on subsequent lines, block indented. If the expression is a
block and the type or pattern cover multiple lines, put the opening brace on a
new line and not indented (this provides separation for the interior of the
block from the type); otherwise, the opening brace follows the `=`.
Examples:
@ -108,8 +108,8 @@ In this case, always apply the same formatting rules to the components preceding
the `else` block (i.e. the `let pattern: Type = initializer_expr` portion)
as described [for other let statements](#let-statements).
The entire let-else statement may be formatted on a single line if all the
following are true:
Format the entire let-else statement on a single line if all the following are
true:
* the entire statement is *short*
* the `else` block contains only a single-line expression and no statements
@ -120,9 +120,6 @@ following are true:
let Some(1) = opt else { return };
```
Formatters may allow users to configure the value of the threshold
used to determine whether a let-else statement is *short*.
Otherwise, the let-else statement requires some line breaks.
If breaking a let-else statement across multiple lines, never break between the
@ -157,9 +154,9 @@ before the `else`.
};
```
If the initializer expression is multi-line, the `else` keyword and opening
brace of the block (i.e. `else {`) should be put on the same line as the end of
the initializer expression, with a space between them, if and only if all the
If the initializer expression is multi-line, put the `else` keyword and opening
brace of the block (i.e. `else {`) on the same line as the end of the
initializer expression, with a space between them, if and only if all the
following are true:
* The initializer expression ends with one or more closing
@ -182,9 +179,9 @@ let Some(x) = y.foo(
}
```
Otherwise, the `else` keyword and opening brace should be placed on the next
line after the end of the initializer expression, and the `else` keyword should
have the same indentation level as the `let` keyword.
Otherwise, put the `else` keyword and opening brace on the next line after the
end of the initializer expression, with the `else` keyword at the same
indentation level as the `let` keyword.
For example:
@ -236,9 +233,9 @@ fn main() {
### Macros in statement position
A macro use in statement position should use parentheses or square brackets as
delimiters and should be terminated with a semicolon. There should be no spaces
between the name, `!`, the delimiters, or the `;`.
For a macro use in statement position, use parentheses or square brackets as
delimiters, and terminate it with a semicolon. Do not put spaces around the
name, `!`, the delimiters, or the `;`.
```rust
// A comment.
@ -248,14 +245,14 @@ a_macro!(...);
### Expressions in statement position
There should be no space between the expression and the semicolon.
Do not put space between the expression and the semicolon.
```
<expr>;
```
All expressions in statement position should be terminated with a semicolon,
unless they end with a block or are used as the value for a block.
Terminate all expressions in statement position with a semicolon, unless they
end with a block or are used as the value for a block.
E.g.,

View File

@ -7,14 +7,14 @@
* `*const T`, `*mut T` (no space after `*`, space before type)
* `&'a T`, `&T`, `&'a mut T`, `&mut T` (no space after `&`, single spaces separating other words)
* `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keywords and sigils, and after commas, no trailing commas, no spaces around brackets)
* `!` should be treated like any other type name, `Name`
* `!` gets treated like any other type name, `Name`
* `(A, B, C, D)` (spaces after commas, no spaces around parens, no trailing comma unless it is a one-tuple)
* `<Baz<T> as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`)
* `Foo::Bar<T, U, V>` (spaces after commas, no trailing comma, no spaces around angle brackets)
* `T + T + T` (single spaces between types, and `+`).
* `impl T + T + T` (single spaces between keyword, types, and `+`).
Parentheses used in types should not be surrounded by whitespace, e.g., `(Foo)`
Do not put space around parentheses used in types, e.g., `(Foo)`
### Line breaks
@ -37,13 +37,17 @@ Foo<Bar, Baz<
>>
```
`[T; expr]` may be broken after the `;` if necessary.
If a type requires line-breaks in order to fit, this section outlines where to
break such types if necessary.
Function types may be broken following the rules for function declarations.
Break `[T; expr]` after the `;` if necessary.
Generic types may be broken following the rules for generics.
Break function types following the rules for function declarations.
Types with `+` may be broken after any `+` using block indent and breaking before the `+`. When breaking such a type, all `+`s should be line broken, e.g.,
Break generic types following the rules for generics.
Break types with `+` by breaking before the `+` and block-indenting the
subsequent lines. When breaking such a type, break before *every* `+`:
```rust
impl Clone