-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3338 from joshtriplett/style-evolution
Style evolution
- Loading branch information
Showing
1 changed file
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
- Feature Name: style-evolution | ||
- Start Date: 2022-10-26 | ||
- RFC PR: [rust-lang/rfcs#3338](https://github.com/rust-lang/rfcs/pull/3338) | ||
- Rust Issue: [rust-lang/rust#105336](https://github.com/rust-lang/rust/issues/105336) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
This RFC defines a mechanism for evolving the default Rust style over time | ||
without breaking backwards compatibility, via the Rust edition mechanism. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
The current Rust style, as defined in the Rust Style Guide and as implemented | ||
by rustfmt, has some stability expectations associated with it. In particular, | ||
many projects implement continuous integration hooks that verify the style of | ||
Rust code (such as with `cargo fmt --check`), and changes to the style would | ||
break the CI of such projects, in addition to causing churn. | ||
|
||
This document proposes to evolve the current Rust style, without breaking | ||
backwards compatibility, by tying style evolution to Rust edition. Code in Rust | ||
2015, 2018, or 2021 will use the existing default style. Code in future | ||
editions (Rust 2024 and onwards) may use a new style edition. | ||
|
||
This RFC only defines the mechanism by which we evolve the Rust style; this RFC | ||
does *not* define any specific style changes. Future RFCs or style-guide PRs | ||
will define future style editions. This RFC does not propose or define any | ||
specific future style editions or other formatting changes. | ||
|
||
# Explanation | ||
[explanation]: #explanation | ||
|
||
`rustfmt`, and `cargo fmt`, will format code according to the default Rust | ||
style. The default Rust style varies by Rust edition. (Not every edition | ||
changes the Rust style, and thus some editions have identical default styles; | ||
Rust 2015, 2018, and 2021 all have the same default style.) | ||
|
||
Direct invocations of `rustfmt` obtain the edition used for parsing Rust code | ||
from the `edition` option in its configuration file (`rustfmt.toml` or | ||
`.rustfmt.toml`), or via the `--edition` command-line option; `cargo fmt` | ||
obtains the edition from the `edition` option in `Cargo.toml` and passes it to | ||
`rustfmt`. By default, `rustfmt` and `cargo fmt` will use the same edition for | ||
style as the Rust edition used for parsing. | ||
|
||
However, when transitioning between editions, projects may want to separately | ||
make and commit the changes for 1) transitioning to a new Rust edition and 2) | ||
transitioning to a new style edition. Keeping formatting changes in a separate | ||
commit also helps tooling ignore that commit, such as with git's | ||
`blame.ignoreRevsFile`. | ||
|
||
To allow for this, `rustfmt` also allows configuring the style edition | ||
directly, via a separate `style_edition` configuration option, or | ||
`--style-edition` command-line option. `style_edition` or `--style-edition`, if | ||
set, always overrides `edition` or `--edition` for the purposes of styling, | ||
though `edition` or `--edition` still determines the edition for the purposes | ||
of parsing Rust code. | ||
|
||
Note that rustfmt may not necessarily support all combinations of Rust edition | ||
and style edition; in particular, it may not support using a style edition that | ||
differs by more than one step from the Rust edition. Similarly, rustfmt need | ||
not support every existing configuration option in new style editions. | ||
|
||
New style editions will be initially introduced as nightly-only, to make them | ||
available for testing; such nightly-only editions will produce an error if | ||
requested in stable rustfmt. Nightly versions of style editions are subject to | ||
change and do not provide stability guarantees. New style editions will get | ||
stabilized contemporaneously with the corresponding Rust edition. | ||
|
||
The current version of the style guide will describe the latest Rust edition. | ||
Each distinct past style will have a corresponding archived version of the | ||
style guide. Note that archived versions of the style guide may not necessarily | ||
document formatting for newer Rust constructs that did not exist at the time | ||
that version of the style guide was archived. However, each style edition will | ||
still format all constructs valid in that Rust edition, with the style of those | ||
constructs coming from the first subsequent style edition providing formatting | ||
rules for that construct. | ||
|
||
# Rationale and alternatives | ||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
We could have a completely separate configuration mechanism, unrelated to | ||
editions. This would increase the development and testing burden of rustfmt, | ||
and seems unlikely to provide commensurate value. This would also increase the | ||
complexity for end users, who would have to understand two separate mechanisms | ||
for handling forwards-compatibility and wonder how they differ. We feel that | ||
since we're providing a mechanism similar to editions, we should make it clear | ||
to users that it works like editions. | ||
|
||
We could allow style edition to vary completely independently of Rust edition. | ||
This would, for instance, allow projects to stay on old style editions | ||
indefinitely. However, this would substantially increase the development and | ||
testing burden for formatting tooling, and require more complex decisions about | ||
how old style editions format constructs that didn't exist in the corresponding | ||
Rust edition. In general, while the Rust edition mechanism allows projects to | ||
stay on old Rust editions, and projects doing so can similarly stay on the | ||
corresponding old style editions, the style edition mechanism does not exist to | ||
facilitate staying on old styles *indefinitely* while still moving forward to | ||
newer Rust editions. | ||
|
||
We could leave out the separate configuration of style edition, and keep style | ||
edition in lockstep with Rust edition. This would be easier to develop and | ||
test, but would mean larger and noisier commits in projects transitioning from | ||
one edition to another. | ||
|
||
We could keep the Rust style static forever, and never change it. | ||
|
||
We could evolve the Rust style without a backwards-compatibility mechanism. | ||
This would result in churn in people's repositories if collaborating | ||
developers have different versions of Rust, and would break | ||
continuous-integration checks that check formatting. | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
The Rust edition mechanism itself serves as prior art, as does the mechanism of | ||
nightly features remaining subject to change until stabilization. | ||
|
||
`rustfmt` has a still-unstable option `version = "Two"` to opt into new | ||
formatting, though the exact changes this makes are not documented. | ||
|
||
`rustfmt`'s stability guarantees are documented in [RFC | ||
2437](https://github.com/rust-lang/rfcs/pull/2437/). | ||
|
||
# Future possibilities | ||
[future-possibilities]: #future-possibilities | ||
|
||
Actual changes to the Rust style for Rust 2024 or future editions. |