feat: implement Style Edition support

Adds the 'style_edition' configuration option along with
documentation, 'version' option deprecation, and mapping
of 'edition' and 'version' values for backwards compatibility
and adherence to the style evolution RFC
This commit is contained in:
Caleb Cartwright 2024-07-19 18:12:08 -05:00 committed by Caleb Cartwright
parent d8ae6a99e6
commit c2c9be5b2d
5 changed files with 97 additions and 8 deletions

View File

@ -534,7 +534,7 @@ Note that this option may be soft-deprecated in the future once the [ignore](#ig
Specifies which edition is used by the parser. Specifies which edition is used by the parser.
- **Default value**: `"2015"` - **Default value**: `"2015"`
- **Possible values**: `"2015"`, `"2018"`, `"2021"` - **Possible values**: `"2015"`, `"2018"`, `"2021"`, `"2024"`
- **Stable**: Yes - **Stable**: Yes
Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if executed Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if executed
@ -2692,6 +2692,17 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
## `style_edition`
Controls the edition of the [Rust Style Guide] to use for formatting ([RFC 3338])
- **Default value**: `"2015"`
- **Possible values**: `"2015"`, `"2018"`, `"2021"`, `"2024"` (unstable variant)
- **Stable**: Yes
[Rust Style Guide]: https://doc.rust-lang.org/nightly/style-guide/
[RFC 3338]: https://rust-lang.github.io/rfcs/3338-style-evolution.html
## `tab_spaces` ## `tab_spaces`
Number of spaces per tab Number of spaces per tab
@ -3051,9 +3062,7 @@ fn main() {
## `version` ## `version`
Which version of the formatting rules to use. `Version::One` is backwards-compatible This option is deprecated and has been replaced by [`style_edition`](#style_edition)
with Rustfmt 1.0. Other versions are only backwards compatible within a major
version number.
- **Default value**: `One` - **Default value**: `One`
- **Possible values**: `One`, `Two` - **Possible values**: `One`, `Two`

View File

@ -1,3 +1,3 @@
error_on_line_overflow = true error_on_line_overflow = true
error_on_unformatted = true error_on_unformatted = true
version = "Two" style_edition = "2024"

View File

@ -133,6 +133,8 @@ pub fn $i(&mut self, value: <$ty as StyleEditionDefault>::ConfigType) {
"merge_imports" => self.0.set_merge_imports(), "merge_imports" => self.0.set_merge_imports(),
"fn_args_layout" => self.0.set_fn_args_layout(), "fn_args_layout" => self.0.set_fn_args_layout(),
"hide_parse_errors" => self.0.set_hide_parse_errors(), "hide_parse_errors" => self.0.set_hide_parse_errors(),
"version" => self.0.set_version(),
"edition" => self.0.set_edition(),
&_ => (), &_ => (),
} }
} }
@ -259,6 +261,8 @@ fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Confi
self.set_merge_imports(); self.set_merge_imports();
self.set_fn_args_layout(); self.set_fn_args_layout();
self.set_hide_parse_errors(); self.set_hide_parse_errors();
self.set_version();
self.set_edition();
self self
} }
@ -360,6 +364,8 @@ pub fn override_value(&mut self, key: &str, val: &str)
"merge_imports" => self.set_merge_imports(), "merge_imports" => self.set_merge_imports(),
"fn_args_layout" => self.set_fn_args_layout(), "fn_args_layout" => self.set_fn_args_layout(),
"hide_parse_errors" => self.set_hide_parse_errors(), "hide_parse_errors" => self.set_hide_parse_errors(),
"version" => self.set_version(),
"edition" => self.set_edition(),
&_ => (), &_ => (),
} }
} }
@ -560,6 +566,44 @@ fn set_hide_parse_errors(&mut self) {
} }
} }
fn set_version(&mut self) {
if !self.was_set().version() {
return;
}
eprintln!(
"Warning: the `version` option is deprecated. \
Use `style_edition` instead."
);
if self.was_set().style_edition() {
eprintln!(
"Warning: the deprecated `version` option was \
used in conjunction with the `edition` or \
`style_edition` options which take precedence. \
The value of the `version` option will be ignored."
);
} else if matches!(self.version(), Version::Two) {
self.style_edition.2 = StyleEdition::Edition2024;
} else {
self.style_edition.2 = StyleEdition::Edition2015;
}
}
fn set_edition(&mut self) {
if self.was_set().style_edition() || self.was_set().version() {
return;
}
// User has explicitly specified an Edition value without
// explicitly specifying a Style Edition value, so the Style Edition
// must default to whatever value was provided for Edition
// as per: https://rust-lang.github.io/rfcs/3338-style-evolution.html#explanation
self.style_edition.2 = self.edition().into();
}
#[allow(unreachable_pub)] #[allow(unreachable_pub)]
/// Returns `true` if the config key was explicitly set and is the default value. /// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool { pub fn is_default(&self, key: &str) -> bool {

View File

@ -149,6 +149,7 @@
blank_lines_lower_bound: BlankLinesLowerBound, false, blank_lines_lower_bound: BlankLinesLowerBound, false,
"Minimum number of blank lines which must be put between items"; "Minimum number of blank lines which must be put between items";
edition: EditionConfig, true, "The edition of the parser (RFC 2052)"; edition: EditionConfig, true, "The edition of the parser (RFC 2052)";
style_edition: StyleEditionConfig, false, "The edition of the Style Guide (RFC 3338)";
version: VersionConfig, false, "Version of formatting rules"; version: VersionConfig, false, "Version of formatting rules";
inline_attribute_width: InlineAttributeWidth, false, inline_attribute_width: InlineAttributeWidth, false,
"Write an item and its attribute on the same line \ "Write an item and its attribute on the same line \
@ -502,6 +503,9 @@ pub(crate) enum PartiallyUnstableOption {
stable_option: StableOption, true, "A stable option"; stable_option: StableOption, true, "A stable option";
unstable_option: UnstableOption, false, "An unstable option"; unstable_option: UnstableOption, false, "An unstable option";
partially_unstable_option: PartiallyUnstable, true, "A partially unstable option"; partially_unstable_option: PartiallyUnstable, true, "A partially unstable option";
edition: EditionConfig, true, "blah";
style_edition: StyleEditionConfig, true, "blah";
version: VersionConfig, false, "blah blah"
} }
#[cfg(test)] #[cfg(test)]
@ -685,6 +689,7 @@ fn test_dump_default_config() {
blank_lines_upper_bound = 1 blank_lines_upper_bound = 1
blank_lines_lower_bound = 0 blank_lines_lower_bound = 0
edition = "2015" edition = "2015"
style_edition = "2015"
version = "One" version = "One"
inline_attribute_width = 0 inline_attribute_width = 0
format_generated_files = true format_generated_files = true

View File

@ -456,6 +456,17 @@ fn from(edition: Edition) -> Self {
} }
} }
impl From<Edition> for StyleEdition {
fn from(edition: Edition) -> Self {
match edition {
Edition::Edition2015 => StyleEdition::Edition2015,
Edition::Edition2018 => StyleEdition::Edition2018,
Edition::Edition2021 => StyleEdition::Edition2021,
Edition::Edition2024 => StyleEdition::Edition2024,
}
}
}
impl PartialOrd for Edition { impl PartialOrd for Edition {
fn partial_cmp(&self, other: &Edition) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Edition) -> Option<std::cmp::Ordering> {
rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into()) rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into())
@ -473,10 +484,11 @@ pub enum MatchArmLeadingPipe {
Preserve, Preserve,
} }
/// Defines the default values for each config according to [the style guide]. /// Defines the default values for each config according to the edition of the
/// rustfmt output may differ between style editions. /// [Style Guide] as per [RFC 3338]. Rustfmt output may differ between Style editions.
/// ///
/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/ /// [Style Guide]: https://doc.rust-lang.org/nightly/style-guide/
/// [RFC 3338]: https://rust-lang.github.io/rfcs/3338-style-evolution.html
#[config_type] #[config_type]
pub enum StyleEdition { pub enum StyleEdition {
#[value = "2015"] #[value = "2015"]
@ -493,10 +505,28 @@ pub enum StyleEdition {
Edition2021, Edition2021,
#[value = "2024"] #[value = "2024"]
#[doc_hint = "2024"] #[doc_hint = "2024"]
#[unstable_variant]
/// [Edition 2024](). /// [Edition 2024]().
Edition2024, Edition2024,
} }
impl From<StyleEdition> for rustc_span::edition::Edition {
fn from(edition: StyleEdition) -> Self {
match edition {
StyleEdition::Edition2015 => Self::Edition2015,
StyleEdition::Edition2018 => Self::Edition2018,
StyleEdition::Edition2021 => Self::Edition2021,
StyleEdition::Edition2024 => Self::Edition2024,
}
}
}
impl PartialOrd for StyleEdition {
fn partial_cmp(&self, other: &StyleEdition) -> Option<std::cmp::Ordering> {
rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into())
}
}
/// Defines unit structs to implement `StyleEditionDefault` for. /// Defines unit structs to implement `StyleEditionDefault` for.
#[macro_export] #[macro_export]
macro_rules! config_option_with_style_edition_default { macro_rules! config_option_with_style_edition_default {
@ -608,6 +638,7 @@ macro_rules! config_option_with_style_edition_default {
BlankLinesUpperBound, usize, _ => 1; BlankLinesUpperBound, usize, _ => 1;
BlankLinesLowerBound, usize, _ => 0; BlankLinesLowerBound, usize, _ => 0;
EditionConfig, Edition, _ => Edition::Edition2015; EditionConfig, Edition, _ => Edition::Edition2015;
StyleEditionConfig, StyleEdition, _ => StyleEdition::Edition2015;
VersionConfig, Version, Edition2024 => Version::Two, _ => Version::One; VersionConfig, Version, Edition2024 => Version::Two, _ => Version::One;
InlineAttributeWidth, usize, _ => 0; InlineAttributeWidth, usize, _ => 0;
FormatGeneratedFiles, bool, _ => true; FormatGeneratedFiles, bool, _ => true;