|
| 1 | +- Feature Name: style-evolution |
| 2 | +- Start Date: 2022-10-26 |
| 3 | +- RFC PR: [rust-lang/rfcs#3338](https://github.com/rust-lang/rfcs/pull/3338) |
| 4 | +- Rust Issue: [rust-lang/rust#105336](https://github.com/rust-lang/rust/issues/105336) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +This RFC defines a mechanism for evolving the default Rust style over time |
| 10 | +without breaking backwards compatibility, via the Rust edition mechanism. |
| 11 | + |
| 12 | +# Motivation |
| 13 | +[motivation]: #motivation |
| 14 | + |
| 15 | +The current Rust style, as defined in the Rust Style Guide and as implemented |
| 16 | +by rustfmt, has some stability expectations associated with it. In particular, |
| 17 | +many projects implement continuous integration hooks that verify the style of |
| 18 | +Rust code (such as with `cargo fmt --check`), and changes to the style would |
| 19 | +break the CI of such projects, in addition to causing churn. |
| 20 | + |
| 21 | +This document proposes to evolve the current Rust style, without breaking |
| 22 | +backwards compatibility, by tying style evolution to Rust edition. Code in Rust |
| 23 | +2015, 2018, or 2021 will use the existing default style. Code in future |
| 24 | +editions (Rust 2024 and onwards) may use a new style edition. |
| 25 | + |
| 26 | +This RFC only defines the mechanism by which we evolve the Rust style; this RFC |
| 27 | +does *not* define any specific style changes. Future RFCs or style-guide PRs |
| 28 | +will define future style editions. This RFC does not propose or define any |
| 29 | +specific future style editions or other formatting changes. |
| 30 | + |
| 31 | +# Explanation |
| 32 | +[explanation]: #explanation |
| 33 | + |
| 34 | +`rustfmt`, and `cargo fmt`, will format code according to the default Rust |
| 35 | +style. The default Rust style varies by Rust edition. (Not every edition |
| 36 | +changes the Rust style, and thus some editions have identical default styles; |
| 37 | +Rust 2015, 2018, and 2021 all have the same default style.) |
| 38 | + |
| 39 | +Direct invocations of `rustfmt` obtain the edition used for parsing Rust code |
| 40 | +from the `edition` option in its configuration file (`rustfmt.toml` or |
| 41 | +`.rustfmt.toml`), or via the `--edition` command-line option; `cargo fmt` |
| 42 | +obtains the edition from the `edition` option in `Cargo.toml` and passes it to |
| 43 | +`rustfmt`. By default, `rustfmt` and `cargo fmt` will use the same edition for |
| 44 | +style as the Rust edition used for parsing. |
| 45 | + |
| 46 | +However, when transitioning between editions, projects may want to separately |
| 47 | +make and commit the changes for 1) transitioning to a new Rust edition and 2) |
| 48 | +transitioning to a new style edition. Keeping formatting changes in a separate |
| 49 | +commit also helps tooling ignore that commit, such as with git's |
| 50 | +`blame.ignoreRevsFile`. |
| 51 | + |
| 52 | +To allow for this, `rustfmt` also allows configuring the style edition |
| 53 | +directly, via a separate `style_edition` configuration option, or |
| 54 | +`--style-edition` command-line option. `style_edition` or `--style-edition`, if |
| 55 | +set, always overrides `edition` or `--edition` for the purposes of styling, |
| 56 | +though `edition` or `--edition` still determines the edition for the purposes |
| 57 | +of parsing Rust code. |
| 58 | + |
| 59 | +Note that rustfmt may not necessarily support all combinations of Rust edition |
| 60 | +and style edition; in particular, it may not support using a style edition that |
| 61 | +differs by more than one step from the Rust edition. Similarly, rustfmt need |
| 62 | +not support every existing configuration option in new style editions. |
| 63 | + |
| 64 | +New style editions will be initially introduced as nightly-only, to make them |
| 65 | +available for testing; such nightly-only editions will produce an error if |
| 66 | +requested in stable rustfmt. Nightly versions of style editions are subject to |
| 67 | +change and do not provide stability guarantees. New style editions will get |
| 68 | +stabilized contemporaneously with the corresponding Rust edition. |
| 69 | + |
| 70 | +The current version of the style guide will describe the latest Rust edition. |
| 71 | +Each distinct past style will have a corresponding archived version of the |
| 72 | +style guide. Note that archived versions of the style guide may not necessarily |
| 73 | +document formatting for newer Rust constructs that did not exist at the time |
| 74 | +that version of the style guide was archived. However, each style edition will |
| 75 | +still format all constructs valid in that Rust edition, with the style of those |
| 76 | +constructs coming from the first subsequent style edition providing formatting |
| 77 | +rules for that construct. |
| 78 | + |
| 79 | +# Rationale and alternatives |
| 80 | +[rationale-and-alternatives]: #rationale-and-alternatives |
| 81 | + |
| 82 | +We could have a completely separate configuration mechanism, unrelated to |
| 83 | +editions. This would increase the development and testing burden of rustfmt, |
| 84 | +and seems unlikely to provide commensurate value. This would also increase the |
| 85 | +complexity for end users, who would have to understand two separate mechanisms |
| 86 | +for handling forwards-compatibility and wonder how they differ. We feel that |
| 87 | +since we're providing a mechanism similar to editions, we should make it clear |
| 88 | +to users that it works like editions. |
| 89 | + |
| 90 | +We could allow style edition to vary completely independently of Rust edition. |
| 91 | +This would, for instance, allow projects to stay on old style editions |
| 92 | +indefinitely. However, this would substantially increase the development and |
| 93 | +testing burden for formatting tooling, and require more complex decisions about |
| 94 | +how old style editions format constructs that didn't exist in the corresponding |
| 95 | +Rust edition. In general, while the Rust edition mechanism allows projects to |
| 96 | +stay on old Rust editions, and projects doing so can similarly stay on the |
| 97 | +corresponding old style editions, the style edition mechanism does not exist to |
| 98 | +facilitate staying on old styles *indefinitely* while still moving forward to |
| 99 | +newer Rust editions. |
| 100 | + |
| 101 | +We could leave out the separate configuration of style edition, and keep style |
| 102 | +edition in lockstep with Rust edition. This would be easier to develop and |
| 103 | +test, but would mean larger and noisier commits in projects transitioning from |
| 104 | +one edition to another. |
| 105 | + |
| 106 | +We could keep the Rust style static forever, and never change it. |
| 107 | + |
| 108 | +We could evolve the Rust style without a backwards-compatibility mechanism. |
| 109 | +This would result in churn in people's repositories if collaborating |
| 110 | +developers have different versions of Rust, and would break |
| 111 | +continuous-integration checks that check formatting. |
| 112 | + |
| 113 | +# Prior art |
| 114 | +[prior-art]: #prior-art |
| 115 | + |
| 116 | +The Rust edition mechanism itself serves as prior art, as does the mechanism of |
| 117 | +nightly features remaining subject to change until stabilization. |
| 118 | + |
| 119 | +`rustfmt` has a still-unstable option `version = "Two"` to opt into new |
| 120 | +formatting, though the exact changes this makes are not documented. |
| 121 | + |
| 122 | +`rustfmt`'s stability guarantees are documented in [RFC |
| 123 | +2437](https://github.com/rust-lang/rfcs/pull/2437/). |
| 124 | + |
| 125 | +# Future possibilities |
| 126 | +[future-possibilities]: #future-possibilities |
| 127 | + |
| 128 | +Actual changes to the Rust style for Rust 2024 or future editions. |
0 commit comments