summaryrefslogtreecommitdiffstats
path: root/src/doc/style-guide
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /src/doc/style-guide
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/style-guide')
-rw-r--r--src/doc/style-guide/src/README.md68
-rw-r--r--src/doc/style-guide/src/SUMMARY.md9
-rw-r--r--src/doc/style-guide/src/advice.md6
-rw-r--r--src/doc/style-guide/src/cargo.md21
-rw-r--r--src/doc/style-guide/src/expressions.md33
-rw-r--r--src/doc/style-guide/src/items.md30
-rw-r--r--src/doc/style-guide/src/nightly.md5
-rw-r--r--src/doc/style-guide/src/principles.md32
-rw-r--r--src/doc/style-guide/src/statements.md133
9 files changed, 210 insertions, 127 deletions
diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md
index adb73a7ee..b8aa64ba1 100644
--- a/src/doc/style-guide/src/README.md
+++ b/src/doc/style-guide/src/README.md
@@ -16,9 +16,21 @@ Rust code has similar formatting, less mental effort is required to comprehend a
new project, lowering the barrier to entry for new developers.
Thus, there are productivity benefits to using a formatting tool (such as
-rustfmt), and even larger benefits by using a community-consistent formatting,
-typically by using a formatting tool's default settings.
+`rustfmt`), and even larger benefits by using a community-consistent
+formatting, typically by using a formatting tool's default settings.
+## The default Rust style
+
+The Rust Style Guide defines the default Rust style, and *recommends* that
+developers and tools follow the default Rust style. Tools such as `rustfmt` use
+the style guide as a reference for the default style. Everything in this style
+guide, whether or not it uses language such as "must" or the imperative mood
+such as "insert a space ..." or "break the line after ...", refers to the
+default style.
+
+This should not be interpreted as forbidding developers from following a
+non-default style, or forbidding tools from adding any particular configuration
+options.
## Formatting conventions
@@ -28,8 +40,47 @@ typically by using a formatting tool's default settings.
* 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 should be configurable for all three of these variables.
+* A tool may choose to make some of these configurable.
+
+#### Block indent
+
+Prefer block indent over visual indent:
+
+```rust
+// Block indent
+a_function_call(
+ foo,
+ bar,
+);
+
+// Visual indent
+a_function_call(foo,
+ bar);
+```
+This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
+example) and less rightward drift.
+
+### Trailing commas
+
+Lists should have a trailing comma when followed by a newline:
+
+```rust
+function_call(
+ argument,
+ another_argument,
+);
+
+let array = [
+ element,
+ another_element,
+ yet_another_element,
+];
+```
+
+This makes moving code (e.g., by copy and paste) easier, and makes diffs
+smaller, as appending or removing items does not require modifying another line
+to add or remove a comma.
### Blank lines
@@ -48,11 +99,7 @@ fn bar() {}
fn baz() {}
```
-Formatting tools should make the bounds on blank lines configurable: there
-should be separate minimum and maximum numbers of newlines between both
-statements and (top-level) items (i.e., four options). As described above, the
-defaults for both statements and items should be minimum: 1, maximum: 2.
-
+Formatting tools may wish to make the bounds on blank lines configurable.
### [Module-level items](items.md)
### [Statements](statements.md)
@@ -139,6 +186,11 @@ For attributes with argument lists, format like functions.
```rust
#[repr(C)]
#[foo(foo, bar)]
+#[long_multi_line_attribute(
+ split,
+ across,
+ lines,
+)]
struct CRepr {
#![repr(C)]
x: f32,
diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md
index 004692fa6..606485bfb 100644
--- a/src/doc/style-guide/src/SUMMARY.md
+++ b/src/doc/style-guide/src/SUMMARY.md
@@ -2,10 +2,11 @@
[Introduction](README.md)
-- [Module-level items](items.md)
+- [Items](items.md)
- [Statements](statements.md)
- [Expressions](expressions.md)
-- [Types](types.md)
-- [Non-formatting conventions](advice.md)
+- [Types and Bounds](types.md)
+- [Other style advice](advice.md)
- [`Cargo.toml` conventions](cargo.md)
-- [Principles used for deciding these guidelines](principles.md)
+- [Guiding principles and rationale](principles.md)
+- [Nightly-only syntax](nightly.md)
diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md
index ab4b92b0a..9a617be50 100644
--- a/src/doc/style-guide/src/advice.md
+++ b/src/doc/style-guide/src/advice.md
@@ -25,9 +25,9 @@ if y {
* Local variables shall be `snake_case`,
* Macro names shall be `snake_case`,
* Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`.
- * When a name is forbidden because it is a reserved word (e.g., `crate`), use a
- trailing underscore to make the name legal (e.g., `crate_`), or use raw
- identifiers if possible.
+ * When a name is forbidden because it is a reserved word (such as `crate`),
+ either use a raw identifier (`r#crate`) or use a trailing underscore
+ (`crate_`). Don't misspell the word (`krate`).
### Modules
diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md
index 13b96ca8c..d3b67ae45 100644
--- a/src/doc/style-guide/src/cargo.md
+++ b/src/doc/style-guide/src/cargo.md
@@ -1,4 +1,4 @@
-# Cargo.toml conventions
+# `Cargo.toml` conventions
## Formatting conventions
@@ -25,16 +25,17 @@ not indent any key names; start all key names at the start of a line.
Use multi-line strings (rather than newline escape sequences) for any string
values that include multiple lines, such as the crate description.
-For array values, such as a list of authors, put the entire list on the same
+For array values, such as a list of features, put the entire list on the same
line as the key, if it fits. Otherwise, use block indentation: put a newline
after the opening square bracket, indent each item by one indentation level,
put a comma after each item (including the last), and put the closing square
bracket at the start of a line by itself after the last item.
```rust
-authors = [
- "A Uthor <a.uthor@example.org>",
- "Another Author <author@example.net>",
+some_feature = [
+ "another_feature",
+ "yet_another_feature",
+ "some_dependency?/some_feature",
]
```
@@ -54,11 +55,11 @@ version = "4.5.6"
## Metadata conventions
-The authors list should consist of strings that each contain an author name
-followed by an email address in angle brackets: `Full Name <email@address>`.
-It should not contain bare email addresses, or names without email addresses.
-(The authors list may also include a mailing list address without an associated
-name.)
+The authors list, if present, should consist of strings that each contain an
+author name followed by an email address in angle brackets: `Full Name
+<email@address>`. It should not contain bare email addresses, or names without
+email addresses. (The authors list may also include a mailing list address
+without an associated name.)
The license field must contain a valid [SPDX
expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 96f66c89c..143161da6 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -288,14 +288,16 @@ and other assignment operators such as `+=` or `*=`).
For comparison operators, because for `T op U`, `&T op &U` is also implemented:
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.
+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.
Tools should not automatically insert or remove parentheses. Do not use spaces
to indicate precedence.
-If line-breaking, put the operator on a new line and block indent. Put each
-sub-expression on its own line. E.g.,
+If line-breaking, block-indent each subsequent line. For assignment operators,
+break after the operator; for all other operators, put the operator on the
+subsequent line. Put each sub-expression on its own line:
```rust
foo_bar
@@ -690,7 +692,7 @@ 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.
```rust
- // Assuming the following line does done fit in the max width
+ // Assuming the following line does not fit in the max width
a_very_long_pattern | another_pattern => ALongStructName {
...
},
@@ -751,9 +753,9 @@ not put the `if` clause on a newline. E.g.,
}
```
-If every clause in a pattern is *small*, but 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 `|`:
+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 `|`:
```rust
foo | bar | baz
@@ -762,17 +764,18 @@ possible. Again break before a `|`:
}
```
-We define a pattern clause to be *small* if it matches the following grammar:
+We define a pattern clause to be *small* if it fits on a single line and
+matches "small" in the following grammar:
```
-[small, ntp]:
- - single token
- - `&[single-line, ntp]`
+small:
+ - small_no_tuple
+ - unary tuple constructor: `(` small_no_tuple `,` `)`
+ - `&` small
-[small]:
- - `[small, ntp]`
- - unary tuple constructor `([small, ntp])`
- - `&[small]`
+small_no_tuple:
+ - single token
+ - `&` small_no_tuple
```
E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md
index 283597535..1e0e60248 100644
--- a/src/doc/style-guide/src/items.md
+++ b/src/doc/style-guide/src/items.md
@@ -1,5 +1,10 @@
## Items
+Items consist of the set of things permitted at the top level of a module.
+However, Rust also allows some items to appear within some other types of
+items, such as within a function. The same formatting conventions apply whether
+an item appears at module level or within another item.
+
`extern crate` statements must be first in a file. They must be ordered
alphabetically.
@@ -15,8 +20,8 @@ Tools should make the above ordering optional.
### Function definitions
-In Rust, one finds functions by searching for `fn [function-name]`; It's
-important that you style your code so that it's very searchable in this way.
+In Rust, people often find functions by searching for `fn [function-name]`, so
+the formatting of function definitions shold enable this.
The proper ordering and spacing is:
@@ -63,8 +68,9 @@ let y = (11, 22, 33);
In the declaration, put each variant on its own line, block indented.
-Format each variant accordingly as either a struct, tuple struct, or identifier,
-which doesn't require special formatting (but without the `struct` keyword.
+Format each variant accordingly as either a struct (but without the `struct`
+keyword), a tuple struct, or an identifier (which doesn't require special
+formatting):
```rust
enum FooBar {
@@ -139,7 +145,7 @@ union Foo {
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 semi-colon:
+parentheses or semicolon:
```rust
pub struct Foo(String, u8);
@@ -230,7 +236,7 @@ impl Bar
`extern crate foo;`
-Use spaces around keywords, no spaces around the semi-colon.
+Use spaces around keywords, no spaces around the semicolon.
### Modules
@@ -245,7 +251,7 @@ mod foo;
```
Use spaces around keywords and before the opening brace, no spaces around the
-semi-colon.
+semicolon.
### macro\_rules!
@@ -478,8 +484,8 @@ foo::{
A *group* of imports is a set of imports on the same or sequential lines. One or
more blank lines or other items (e.g., a function) separate groups of imports.
-Within a group of imports, imports must be sorted ascii-betically. Groups of
-imports must not be merged or re-ordered.
+Within a group of imports, imports must be sorted ASCIIbetically (uppercase
+before lowercase). Groups of imports must not be merged or re-ordered.
E.g., input:
@@ -505,13 +511,9 @@ use b;
Because of `macro_use`, attributes must also start a new group and prevent
re-ordering.
-Note that tools which only have access to syntax (such as Rustfmt) cannot tell
-which imports are from an external crate or the std lib, etc.
-
-
#### Ordering list import
-Names in a list import must be sorted ascii-betically, but with `self` and
+Names in a list import must be sorted ASCIIbetically, but with `self` and
`super` first, and groups and glob imports last. This applies recursively. For
example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
`use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`.
diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md
new file mode 100644
index 000000000..031811b0e
--- /dev/null
+++ b/src/doc/style-guide/src/nightly.md
@@ -0,0 +1,5 @@
+This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section.
+
+Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization.
+
+There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter.
diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md
index 2d203f264..d548693e3 100644
--- a/src/doc/style-guide/src/principles.md
+++ b/src/doc/style-guide/src/principles.md
@@ -1,7 +1,7 @@
# Guiding principles and rationale
-When deciding on style guidelines, the style team tried to be guided by the
-following principles (in rough priority order):
+When deciding on style guidelines, the style team follows these guiding
+principles (in rough priority order):
* readability
- scan-ability
@@ -19,35 +19,11 @@ following principles (in rough priority order):
* specifics
- compatibility with version control practices - preserving diffs,
merge-friendliness, etc.
- - preventing right-ward drift
+ - preventing rightward drift
- minimising vertical space
* application
- ease of manual application
- - ease of implementation (in Rustfmt, and in other tools/editors/code generators)
+ - ease of implementation (in `rustfmt`, and in other tools/editors/code generators)
- internal consistency
- simplicity of formatting rules
-
-
-## Overarching guidelines
-
-Prefer block indent over visual indent. E.g.,
-
-```rust
-// Block indent
-a_function_call(
- foo,
- bar,
-);
-
-// Visual indent
-a_function_call(foo,
- bar);
-```
-
-This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
-example) and less rightward drift.
-
-Lists should have a trailing comma when followed by a newline, see the block
-indent example above. This choice makes moving code (e.g., by copy and paste)
-easier and makes smaller diffs.
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
index 671e6d31a..a5cd6da10 100644
--- a/src/doc/style-guide/src/statements.md
+++ b/src/doc/style-guide/src/statements.md
@@ -1,7 +1,9 @@
+## Statements
+
### Let statements
There should be spaces after the `:` and on both sides of the `=` (if they are
-present). No space before the semi-colon.
+present). No space before the semicolon.
```rust
// A comment.
@@ -101,22 +103,69 @@ let Foo {
#### else blocks (let-else statements)
-If a let statement contains an `else` component, also known as a let-else statement,
-then the `else` component should be formatted according to the same rules as the `else` block
-in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions).
-Apply the same formatting rules to the components preceding
-the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion)
-as described [above](#let-statements)
+A let statement can contain an `else` component, making it a let-else statement.
+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:
-Similarly to if-else expressions, if the initializer
-expression is multi-lined, then 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 preceding space if all the following are true:
+* the entire statement is *short*
+* the `else` block contains only a single-line expression and no statements
+* the `else` block contains no comments
+* the let statement components preceding the `else` block can be formatted on a single line
+
+```rust
+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
+`else` and the `{`, and always break before the `}`.
+
+If the let statement components preceding the `else` can be formatted on a
+single line, but the let-else does not qualify to be placed entirely on a
+single line, put the `else {` on the same line as the initializer expression,
+with a space between them, then break the line after the `{`. Indent the
+closing `}` to match the `let`, and indent the contained block one step
+further.
+
+```rust
+let Some(1) = opt else {
+ return;
+};
+
+let Some(1) = opt else {
+ // nope
+ return
+};
+```
+
+If the let statement components preceding the `else` can be formatted on a
+single line, but the `else {` does not fit on the same line, break the line
+before the `else`.
+
+```rust
+ let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name
+ else {
+ return;
+ };
+```
+
+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
+following are true:
* The initializer expression ends with one or more closing
parentheses, square brackets, and/or braces
* There is nothing else on that line
-* That line is not indented beyond the indent of the first line containing the `let` keyword
+* That line has the same indentation level as the initial `let` keyword.
For example:
@@ -133,7 +182,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 should not be indented (the `else` keyword should be aligned with the `let` keyword).
+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.
For example:
@@ -153,48 +204,40 @@ fn main() {
return
};
- let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name
+ let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
else {
return;
};
- let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ let LongStructName(AnotherStruct {
+ multi,
+ line,
+ pattern,
+ }) = slice.as_ref()
else {
return;
};
-}
-```
-
-##### Single line let-else statements
-
-The entire let-else statement may be formatted on a single line if all the following are true:
-
-* the entire statement is *short*
-* the `else` block contains a single-line expression and no statements
-* the `else` block contains no comments
-* the let statement components preceding the `else` block can be formatted on a single line
-
-```rust
-let Some(1) = opt else { return };
-
-let Some(1) = opt else {
- return;
-};
-let Some(1) = opt else {
- // nope
- return
-};
+ let LongStructName(AnotherStruct {
+ multi,
+ line,
+ pattern,
+ }) = multi_line_function_call(
+ arg1,
+ arg2,
+ arg3,
+ arg4,
+ ) else {
+ return;
+ };
+}
```
-Formatters may allow users to configure the value of the threshold
-used to determine whether a let-else statement is *short*.
-
### Macros in statement position
A macro use in statement position should use parentheses or square brackets as
-delimiters and should be terminated with a semi-colon. There should be no spaces
+delimiters and should be terminated with a semicolon. There should be no spaces
between the name, `!`, the delimiters, or the `;`.
```rust
@@ -205,13 +248,13 @@ a_macro!(...);
### Expressions in statement position
-There should be no space between the expression and the semi-colon.
+There should be no space between the expression and the semicolon.
```
<expr>;
```
-All expressions in statement position should be terminated with a semi-colon,
+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.
E.g.,
@@ -229,7 +272,7 @@ loop {
}
```
-Use a semi-colon where an expression has void type, even if it could be
+Use a semicolon where an expression has void type, even if it could be
propagated. E.g.,
```rust