From 5230e8fbe672321d43438fad0d0c00d4118e566e Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 15 Sep 2024 12:07:07 +0200 Subject: [PATCH 1/8] Non-panicking Display for Path --- src/bin/main.rs | 4 ++-- src/config/file_lines.rs | 2 +- src/test/mod.rs | 12 ++++-------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 0d593c6c416..c7d3a060d54 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -341,10 +341,10 @@ fn format( for file in files { if !file.exists() { - eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); + eprintln!("Error: file `{}` does not exist", file.display()); session.add_operational_error(); } else if file.is_dir() { - eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); + eprintln!("Error: `{}` is a directory", file.display()); session.add_operational_error(); } else { // Check the file directory if the config-path could not be read or not provided diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 7f32765195d..c53ec6371e9 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -38,7 +38,7 @@ impl From for FileName { impl fmt::Display for FileName { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()), + FileName::Real(p) => write!(f, "{}", p.display()), FileName::Stdin => write!(f, ""), } } diff --git a/src/test/mod.rs b/src/test/mod.rs index 28f95ee54e5..d62da08fff8 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -105,10 +105,9 @@ fn is_file_skip(path: &Path) -> bool { fn get_test_files(path: &Path, recursive: bool) -> Vec { let mut files = vec![]; if path.is_dir() { - for entry in fs::read_dir(path).expect(&format!( - "couldn't read directory {}", - path.to_str().unwrap() - )) { + for entry in + fs::read_dir(path).expect(&format!("couldn't read directory {}", path.display())) + { let entry = entry.expect("couldn't get `DirEntry`"); let path = entry.path(); if path.is_dir() && recursive { @@ -122,10 +121,7 @@ fn get_test_files(path: &Path, recursive: bool) -> Vec { } fn verify_config_used(path: &Path, config_name: &str) { - for entry in fs::read_dir(path).expect(&format!( - "couldn't read {} directory", - path.to_str().unwrap() - )) { + for entry in fs::read_dir(path).expect(&format!("couldn't read {} directory", path.display())) { let entry = entry.expect("couldn't get directory entry"); let path = entry.path(); if path.extension().map_or(false, |f| f == "rs") { From 019578f924e7c70a26262bd882e442dd8faa5299 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Tue, 17 Sep 2024 14:16:43 +0200 Subject: [PATCH 2/8] Use `usize::MAX` instead of deprecated `usize::max_value` --- src/config/mod.rs | 8 ++++---- src/config/options.rs | 8 ++++---- src/macros.rs | 6 +++--- src/string.rs | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 8e67d452d43..ea257c0a8ba 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1049,10 +1049,10 @@ make_backup = false max_width = 100 "#; let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap(); - assert_eq!(config.array_width(), usize::max_value()); - assert_eq!(config.attr_fn_like_width(), usize::max_value()); - assert_eq!(config.chain_width(), usize::max_value()); - assert_eq!(config.fn_call_width(), usize::max_value()); + assert_eq!(config.array_width(), usize::MAX); + assert_eq!(config.attr_fn_like_width(), usize::MAX); + assert_eq!(config.chain_width(), usize::MAX); + assert_eq!(config.fn_call_width(), usize::MAX); assert_eq!(config.single_line_if_else_max_width(), 0); assert_eq!(config.struct_lit_width(), 0); assert_eq!(config.struct_variant_width(), 0); diff --git a/src/config/options.rs b/src/config/options.rs index 45496fd4e48..c526b5c678f 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -255,12 +255,12 @@ impl WidthHeuristics { // Using this WidthHeuristics means we ignore heuristics. pub fn null() -> WidthHeuristics { WidthHeuristics { - fn_call_width: usize::max_value(), - attr_fn_like_width: usize::max_value(), + fn_call_width: usize::MAX, + attr_fn_like_width: usize::MAX, struct_lit_width: 0, struct_variant_width: 0, - array_width: usize::max_value(), - chain_width: usize::max_value(), + array_width: usize::MAX, + chain_width: usize::MAX, single_line_if_else_max_width: 0, single_line_let_else_max_width: 0, } diff --git a/src/macros.rs b/src/macros.rs index 06495e2f8e9..5a35e115d8f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1163,9 +1163,9 @@ pub(crate) fn convert_try_mac( pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> Delimiter { let snippet = context.snippet(mac.span()); - let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); - let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); - let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); + let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::MAX); + let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::MAX); + let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::MAX); if paren_pos < bracket_pos && paren_pos < brace_pos { Delimiter::Parenthesis diff --git a/src/string.rs b/src/string.rs index 41fddeb517e..3b971188cd5 100644 --- a/src/string.rs +++ b/src/string.rs @@ -84,7 +84,7 @@ pub(crate) fn rewrite_string<'a>( stripped_str .len() .checked_next_power_of_two() - .unwrap_or(usize::max_value()), + .unwrap_or(usize::MAX), ); result.push_str(fmt.opener); From 008b3df97d430f12d0b7dbdebacc048d1aa0666f Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sat, 14 Sep 2024 19:56:35 +0200 Subject: [PATCH 3/8] Avoid allocating `Vec` in `light_rewrite_comment` --- src/comment.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index 1b3b88d68a5..b7d7a396a67 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, iter}; -use itertools::{MultiPeek, multipeek}; +use itertools::{Itertools as _, MultiPeek, multipeek}; use rustc_span::Span; use tracing::{debug, trace}; @@ -1056,8 +1056,7 @@ fn light_rewrite_comment( config: &Config, is_doc_comment: bool, ) -> String { - let lines: Vec<&str> = orig - .lines() + orig.lines() .map(|l| { // This is basically just l.trim(), but in the case that a line starts // with `*` we want to leave one space before it, so it aligns with the @@ -1075,8 +1074,7 @@ fn light_rewrite_comment( // Preserve markdown's double-space line break syntax in doc comment. trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment) }) - .collect(); - lines.join(&format!("\n{}", offset.to_string(config))) + .join(&format!("\n{}", offset.to_string(config))) } /// Trims comment characters and possibly a single space from the left of a string. From b552eb9e3a01c17f5ecf7679038baa2d0a295940 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sat, 14 Sep 2024 20:25:30 +0200 Subject: [PATCH 4/8] Avoid an allocation in `rewrite_int_lit` --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index d6646d48d3e..77c9818b66b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1330,7 +1330,7 @@ fn rewrite_int_lit( format!( "0x{}{}", hex_lit, - token_lit.suffix.map_or(String::new(), |s| s.to_string()) + token_lit.suffix.as_ref().map_or("", |s| s.as_str()) ), context.config.max_width(), shape, From 31e799f17f9d6d0dc0cb11500633ec42a97ef3af Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 16 Sep 2024 20:54:07 -0400 Subject: [PATCH 5/8] Document changes for the next release --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5800a592f4c..417f8219d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,64 @@ ## [Unreleased] +### Fixed +- Fix issue where rustfmt would crash on Windows when using the `ignore` option [#6178](https://github.com/rust-lang/rustfmt/issues/6178) + +### Changed +- `rustfmt --version` now prints a commit hash that is 10 characters long [#6258](https://github.com/rust-lang/rustfmt/pull/6258) +- `rustfmt --version` will no longer print empty git information when git information isn't available at build time. + For example, git information is not available when building rustfmt from a source tarball [#6266](https://github.com/rust-lang/rustfmt/pull/6266) +- `version` has been soft deprecated and replaced by `style_edition`. + `style_edition=2024` is equivalent to `version=Two` and `style_edition={2015|2018|2021}` + are equivalent to `version=One` [#6247](https://github.com/rust-lang/rustfmt/pull/6247) +- When `style_edition=2024` is configured `overflow_delimited_expr` will default to `true` [#6260](https://github.com/rust-lang/rustfmt/pull/6260). + ```rust + // with style_edition=2015 + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + // with style_edition=2024 + do_thing(x, Bar { + x: value, + y: value2, + }); + ``` +- When `style_edition=2024` is configured rustfmt will apply the [style guide's version sorting algorithm] + when sorting imports [#6284](https://github.com/rust-lang/rustfmt/pull/6284) + ```rust + // with style_edition=2015 + use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8}; + + // with style_edition=2024 + use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64}; + ``` + [style guide's version sorting algorithm]: https://doc.rust-lang.org/nightly/style-guide/#sorting +- When parsing rustfmt configurations fails, rustfmt will now include the path to the toml file in the erorr message [#6302](https://github.com/rust-lang/rustfmt/issues/6302) + +### Added +- rustfmt now formats trailing where clauses in type aliases [#5887](https://github.com/rust-lang/rustfmt/pull/5887) + ```rust + type Foo + = Bar + where + A: B, + C: D; + ``` +- Users can now configure which `style_edition` rustfmt uses when formatting their code as specified + in [RFC 3338](https://rust-lang.github.io/rfcs/3338-style-evolution.html). Users are encouraged to configure `style_edition` + in their `rustfmt.toml` files, but the value can also be specified via the cli with `--unstable-features --style-edition={style_edition}`. + When `style_edition` is not explicitly configured it will be inferred from the `edition` configuration. + When neither `style_edition` nor `edition` are configured `style_edition` defaults to `2015` [#6247](https://github.com/rust-lang/rustfmt/pull/6247) + +### Misc +- Removed `tracing-attributes` dependency [#6208](https://github.com/rust-lang/rustfmt/pull/6208) +- Reduced syn's features in the internal `config_proc_macro` crate [#6237](https://github.com/rust-lang/rustfmt/pull/6237) + ## [1.7.1] 2024-06-24 ### Fixed From b23b69900eab1260be510b2bd8922f4b6de6cf1e Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Thu, 19 Sep 2024 15:39:04 -0400 Subject: [PATCH 6/8] chore: prep v1.8.0 release --- CHANGELOG.md | 2 +- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 417f8219d70..8af60f60dc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [Unreleased] +## [1.8.0] 2024-09-20 ### Fixed - Fix issue where rustfmt would crash on Windows when using the `ignore` option [#6178](https://github.com/rust-lang/rustfmt/issues/6178) diff --git a/Cargo.lock b/Cargo.lock index d4b165c4dd4..e2ceb668ebd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -499,7 +499,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.7.1" +version = "1.8.0" dependencies = [ "annotate-snippets", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index a3f0cca20a0..e497b792342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.7.1" +version = "1.8.0" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" From 0339b963414ee7468614f6519183f08d390f03dd Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Thu, 19 Sep 2024 18:31:07 +0200 Subject: [PATCH 7/8] Avoid allocation in `JsonEmitter::emit_footer` Write directly to the output instead of creating an intermediate `String`. --- src/emitter/json.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/emitter/json.rs b/src/emitter/json.rs index a99626f783d..39eae1ab0f2 100644 --- a/src/emitter/json.rs +++ b/src/emitter/json.rs @@ -1,7 +1,7 @@ use super::*; use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff}; use serde::Serialize; -use serde_json::to_string as to_json_string; +use serde_json::to_writer as to_json_writer; #[derive(Debug, Default)] pub(crate) struct JsonEmitter { @@ -26,7 +26,8 @@ struct MismatchedFile { impl Emitter for JsonEmitter { fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> { - writeln!(output, "{}", &to_json_string(&self.mismatched_files)?) + to_json_writer(&mut *output, &self.mismatched_files)?; + writeln!(output) } fn emit_formatted_file( @@ -252,7 +253,7 @@ mod tests { ) .unwrap(); let _ = emitter.emit_footer(&mut writer); - let exp_json = to_json_string(&vec![MismatchedFile { + let exp_json = serde_json::to_string(&vec![MismatchedFile { name: String::from(file_name), mismatches: vec![ MismatchedBlock { @@ -338,7 +339,7 @@ mod tests { }], }; - let exp_json = to_json_string(&vec![exp_bin, exp_lib]).unwrap(); + let exp_json = serde_json::to_string(&vec![exp_bin, exp_lib]).unwrap(); assert_eq!(&writer[..], format!("{exp_json}\n").as_bytes()); } } From 6157568e1cec55ce6df09342ba0ae9686dec99c9 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Thu, 19 Sep 2024 18:36:00 +0200 Subject: [PATCH 8/8] Preallocate missmatches in `JsonEmitter::add_misformatted_file` The mismatches length is known to be equal to `diff.len()`. --- src/emitter/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emitter/json.rs b/src/emitter/json.rs index 39eae1ab0f2..8c84ff72d04 100644 --- a/src/emitter/json.rs +++ b/src/emitter/json.rs @@ -57,7 +57,7 @@ impl JsonEmitter { filename: &FileName, diff: Vec, ) -> Result<(), io::Error> { - let mut mismatches = vec![]; + let mut mismatches = Vec::with_capacity(diff.len()); for mismatch in diff { let original_begin_line = mismatch.line_number_orig; let expected_begin_line = mismatch.line_number;