summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:42 +0000
commitcec1877e180393eba0f6ddb0cf97bf3a791631c7 (patch)
tree47b4dac2a9dd9a40c30c251b4d4a72d7ccf77e9f /src/tools/rustfmt
parentAdding debian version 1.74.1+dfsg1-1. (diff)
downloadrustc-cec1877e180393eba0f6ddb0cf97bf3a791631c7.tar.xz
rustc-cec1877e180393eba0f6ddb0cf97bf3a791631c7.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rustfmt')
-rw-r--r--src/tools/rustfmt/.github/workflows/check_diff.yml2
-rw-r--r--src/tools/rustfmt/CHANGELOG.md80
-rw-r--r--src/tools/rustfmt/CODE_OF_CONDUCT.md2
-rw-r--r--src/tools/rustfmt/Cargo.lock445
-rw-r--r--src/tools/rustfmt/Cargo.toml17
-rw-r--r--src/tools/rustfmt/Contributing.md12
-rw-r--r--src/tools/rustfmt/README.md2
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.bat6
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.sh6
-rwxr-xr-xsrc/tools/rustfmt/ci/check_diff.sh13
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.toml2
-rw-r--r--src/tools/rustfmt/rust-toolchain2
-rw-r--r--src/tools/rustfmt/src/attr.rs8
-rw-r--r--src/tools/rustfmt/src/attr/doc_comment.rs6
-rw-r--r--src/tools/rustfmt/src/bin/main.rs26
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/main.rs30
-rw-r--r--src/tools/rustfmt/src/chains.rs91
-rw-r--r--src/tools/rustfmt/src/closures.rs15
-rw-r--r--src/tools/rustfmt/src/comment.rs74
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs10
-rw-r--r--src/tools/rustfmt/src/config/file_lines.rs2
-rw-r--r--src/tools/rustfmt/src/config/macro_names.rs16
-rw-r--r--src/tools/rustfmt/src/config/mod.rs15
-rw-r--r--src/tools/rustfmt/src/config/options.rs4
-rw-r--r--src/tools/rustfmt/src/emitter.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/checkstyle.rs4
-rw-r--r--src/tools/rustfmt/src/emitter/checkstyle/xml.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/diff.rs6
-rw-r--r--src/tools/rustfmt/src/emitter/json.rs6
-rw-r--r--src/tools/rustfmt/src/emitter/stdout.rs4
-rw-r--r--src/tools/rustfmt/src/expr.rs139
-rw-r--r--src/tools/rustfmt/src/format-diff/main.rs15
-rw-r--r--src/tools/rustfmt/src/formatting.rs2
-rw-r--r--src/tools/rustfmt/src/git-rustfmt/main.rs11
-rw-r--r--src/tools/rustfmt/src/imports.rs26
-rw-r--r--src/tools/rustfmt/src/items.rs380
-rw-r--r--src/tools/rustfmt/src/lib.rs11
-rw-r--r--src/tools/rustfmt/src/lists.rs2
-rw-r--r--src/tools/rustfmt/src/macros.rs84
-rw-r--r--src/tools/rustfmt/src/matches.rs25
-rw-r--r--src/tools/rustfmt/src/pairs.rs45
-rw-r--r--src/tools/rustfmt/src/parse/session.rs3
-rw-r--r--src/tools/rustfmt/src/patterns.rs8
-rw-r--r--src/tools/rustfmt/src/rustfmt_diff.rs17
-rw-r--r--src/tools/rustfmt/src/skip.rs2
-rw-r--r--src/tools/rustfmt/src/source_file.rs2
-rw-r--r--src/tools/rustfmt/src/stmt.rs34
-rw-r--r--src/tools/rustfmt/src/string.rs4
-rw-r--r--src/tools/rustfmt/src/test/configuration_snippet.rs10
-rw-r--r--src/tools/rustfmt/src/test/mod.rs24
-rw-r--r--src/tools/rustfmt/src/types.rs46
-rw-r--r--src/tools/rustfmt/src/utils.rs43
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/main.rs2
-rw-r--r--src/tools/rustfmt/tests/config/issue-5816.toml1
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs6
-rw-r--r--src/tools/rustfmt/tests/source/immovable_coroutines.rs (renamed from src/tools/rustfmt/tests/source/immovable_generators.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3984.rs12
-rw-r--r--src/tools/rustfmt/tests/source/issue-4808.rs13
-rw-r--r--src/tools/rustfmt/tests/source/issue-5655/one.rs9
-rw-r--r--src/tools/rustfmt/tests/source/issue-5655/two.rs9
-rw-r--r--src/tools/rustfmt/tests/source/issue-5791.rs3
-rw-r--r--src/tools/rustfmt/tests/source/issue-5835.rs8
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/default.rs104
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/horizontal.rs106
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs106
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/issue_example.rs8
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/split.rs111
-rw-r--r--src/tools/rustfmt/tests/source/issue-5852/vertical.rs106
-rw-r--r--src/tools/rustfmt/tests/source/issue-5935.rs9
-rw-r--r--src/tools/rustfmt/tests/source/issue_5721.rs8
-rw-r--r--src/tools/rustfmt/tests/source/issue_5730.rs3
-rw-r--r--src/tools/rustfmt/tests/source/issue_5735.rs6
-rw-r--r--src/tools/rustfmt/tests/source/issue_5882.rs7
-rw-r--r--src/tools/rustfmt/tests/source/let_chains.rs121
-rw-r--r--src/tools/rustfmt/tests/source/let_else.rs20
-rw-r--r--src/tools/rustfmt/tests/source/let_else_v2.rs56
-rw-r--r--src/tools/rustfmt/tests/source/match.rs3
-rw-r--r--src/tools/rustfmt/tests/source/non-lifetime-binders.rs10
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs9
-rw-r--r--src/tools/rustfmt/tests/target/extern-rust.rs1
-rw-r--r--src/tools/rustfmt/tests/target/immovable_coroutines.rs (renamed from src/tools/rustfmt/tests/target/immovable_generators.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3984.rs12
-rw-r--r--src/tools/rustfmt/tests/target/issue-4808.rs13
-rw-r--r--src/tools/rustfmt/tests/target/issue-5568.rs14
-rw-r--r--src/tools/rustfmt/tests/target/issue-5655/one.rs9
-rw-r--r--src/tools/rustfmt/tests/target/issue-5655/two.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue-5791.rs3
-rw-r--r--src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs7
-rw-r--r--src/tools/rustfmt/tests/target/issue-5835.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/default.rs97
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/horizontal.rs99
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs99
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/issue_example.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/split.rs102
-rw-r--r--src/tools/rustfmt/tests/target/issue-5852/vertical.rs105
-rw-r--r--src/tools/rustfmt/tests/target/issue-5871.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue-5935.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue_4110.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue_5533.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue_5542.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue_5676.rs8
-rw-r--r--src/tools/rustfmt/tests/target/issue_5721.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue_5730.rs3
-rw-r--r--src/tools/rustfmt/tests/target/issue_5735.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue_5882.rs7
-rw-r--r--src/tools/rustfmt/tests/target/issue_5907.rs6
-rw-r--r--src/tools/rustfmt/tests/target/let_chains.rs129
-rw-r--r--src/tools/rustfmt/tests/target/let_else.rs31
-rw-r--r--src/tools/rustfmt/tests/target/let_else_v2.rs73
-rw-r--r--src/tools/rustfmt/tests/target/match.rs8
-rw-r--r--src/tools/rustfmt/tests/target/non-lifetime-binders.rs10
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs7
-rw-r--r--src/tools/rustfmt/triagebot.toml3
113 files changed, 2828 insertions, 795 deletions
diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml
index 8bfb58345..2f2beb769 100644
--- a/src/tools/rustfmt/.github/workflows/check_diff.yml
+++ b/src/tools/rustfmt/.github/workflows/check_diff.yml
@@ -30,4 +30,4 @@ jobs:
rustup target add x86_64-unknown-linux-gnu
- name: check diff
- run: bash ${GITHUB_WORKSPACE}/ci/check_diff.sh ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} ${{ github.event.inputs.commit_hash }} ${{ github.event.inputs.rustfmt_configs }}
+ run: bash ${GITHUB_WORKSPACE}/ci/check_diff.sh ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} ${{ github.event.inputs.commit_hash || github.event.inputs.branch_name }} ${{ github.event.inputs.rustfmt_configs }}
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index fbcd0a57f..ec4c682d2 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -3,6 +3,82 @@
## [Unreleased]
+## [1.7.0] 2023-10-22
+
+### Fixed
+
+- Sometimes when `format_code_in_doc_comments=true` was set some line comments were converted to block comments [#5533](https://github.com/rust-lang/rustfmt/issues/5533)
+- rustfmt will no longer remove the braces in match arms when the block has a labeled [#5676](https://github.com/rust-lang/rustfmt/issues/5676)
+ ```rust
+ fn main() {
+ match true {
+ true => 'a: {
+ break 'a
+ }
+ _ => (),
+ }
+ }
+ ```
+- Calling methods on float literals ending in `.` will now be wrapped in parenthesis. e.g. `0. .to_string()` will be formatted as `(0.).to_string()` [#5791](https://github.com/rust-lang/rustfmt/issues/5791)
+- Prevent ICE when formatting empty `macro_rules!` branch [#5730](https://github.com/rust-lang/rustfmt/issues/5730)
+ ```rust
+ macro_rules! statement {
+ () => {;};
+ }
+ ```
+- Prevent ICE when formatting `vec!{}` [#5735](https://github.com/rust-lang/rustfmt/issues/5735)
+- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` defintion e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882)
+- Formatting doc comment lines that start with `.` or `)` won't be treated as ordered markdown lists because `.` or `)` must be preceded by a number to start an ordered markdown list [#5835](https://github.com/rust-lang/rustfmt/pull/5835)
+- Add parenthesis around closures when they're used as method receives, don't have a block body, and end with `.` [#4808](https://github.com/rust-lang/rustfmt/issues/4808)
+ ```rust
+ fn main() {
+ || (10.).method();
+ (|| ..).method();
+ (|| 1..).method();
+ }
+ ```
+- Prevent removing `for<T>` when using the [`#![feature(non_lifetime_binders)]`](https://github.com/rust-lang/rust/issues/108185) [#5721](https://github.com/rust-lang/rustfmt/issues/5721)
+ ```rust
+ #![feature(non_lifetime_binders)]
+ #![allow(incomplete_features)]
+
+ trait Other<U: ?Sized> {}
+
+ trait Trait<U>
+ where
+ for<T> U: Other<T> {}
+ ```
+- Fix various issues with comments in imports [#5852](https://github.com/rust-lang/rustfmt/issues/5852) [#4708](https://github.com/rust-lang/rustfmt/issues/4708) [#3984](https://github.com/rust-lang/rustfmt/issues/3984)
+- When setting `version = Two` newlines between where clause bounds will be removed [#5655](https://github.com/rust-lang/rustfmt/issues/5655)
+ ```rust
+ fn foo<T>(_: T)
+ where
+ T: std::fmt::Debug,
+ T: std::fmt::Display,
+ {
+ }
+ ```
+- Improve formatting of `let-else` statements that have leading attributes When setting `version = Two` [#5901](https://github.com/rust-lang/rustfmt/issues/5901)
+- Prevent comment duplication in expressions wrapped in parenthesis. [#5871](https://github.com/rust-lang/rustfmt/issues/5871)
+- Adjust the span derivation used when rewriting const generics. The incorrect span derivation lead to invalid code after reformatting. [#5935](https://github.com/rust-lang/rustfmt/issues/5935)
+
+
+### Changed
+
+- rustfmt no longer removes explicit `Rust` ABIs. e.g `extern "Rust" fn im_a_rust_fn() {}` [#5701](https://github.com/rust-lang/rustfmt/issues/5701)
+- Setting `trailing_semicolon = false` will only remove trailing `;` on the last expression in a block [#5797](https://github.com/rust-lang/rustfmt/issues/5797)
+- Update the format of `cargo help fmt` to be more consistent with other standard commands [#5908](https://github.com/rust-lang/rustfmt/pull/5908)
+
+### Added
+
+- Users can now set `skip_macro_invocations` in `rustfmt.toml` [#5816](https://github.com/rust-lang/rustfmt/issues/5816)
+- Adds initial support for formatting `let-chains`. **`let-chains` are still a nightly feature and their formatting is subject to change** [#5910](https://github.com/rust-lang/rustfmt/pull/5910). Formatting was implemented following the rules outlined in [rust-lang/rust#110568](https://github.com/rust-lang/rust/pull/110568)
+
+### Misc
+
+- Support the experimental `dyn*` syntax, enabled by `#![feature(dyn_star)]` [#5542](https://github.com/rust-lang/rustfmt/issues/5542)
+- Replace `unicode_categories` dependency with `unicode-properties` [#5864](https://github.com/rust-lang/rustfmt/pull/5864)
+
## [1.6.0] 2023-07-02
### Added
@@ -10,7 +86,7 @@
- Support for formatting let-else statements [#5690]
- New config option, `single_line_let_else_max_width`, that allows users to configure the maximum length of single line `let-else` statements. `let-else` statements that otherwise meet the requirements to be formatted on a single line will have their divergent`else` block formatted over multiple lines if they exceed this length [#5684]
-[#5690]: (https://github.com/rust-lang/rustfmt/pulls/5690)
+[#5690]: https://github.com/rust-lang/rustfmt/pull/5690
[#5684]: https://github.com/rust-lang/rustfmt/issues/5684
## [1.5.3] 2023-06-20
@@ -19,7 +95,7 @@
- When formatting doc comments with `wrap_comments = true` rustfmt will no longer wrap markdown tables [#4210](https://github.com/rust-lang/rustfmt/issues/4210)
- Properly handle wrapping comments that include a numbered list in markdown [#5416](https://github.com/rust-lang/rustfmt/issues/5416)
-- Properly handle markdown sublists that utilize a `+` [#4041](https://github.com/rust-lang/rustfmt/issues/4210)
+- Properly handle markdown sublists that utilize a `+` [#4041](https://github.com/rust-lang/rustfmt/issues/4041)
- rustfmt will no longer use shorthand initialization when rewriting a tuple struct even when `use_field_init_shorthand = true` as this leads to code that could no longer compile.
Take the following struct as an example `struct MyStruct(u64);`. rustfmt will no longer format `MyStruct { 0: 0 }` as `MyStruct { 0 }` [#5488](https://github.com/rust-lang/rustfmt/issues/5488)
- rustfmt no longer panics when formatting an empty code block in a doc comment with `format_code_in_doc_comments = true` [#5234](https://github.com/rust-lang/rustfmt/issues/5234). For example:
diff --git a/src/tools/rustfmt/CODE_OF_CONDUCT.md b/src/tools/rustfmt/CODE_OF_CONDUCT.md
index d70b2b52a..2acddfeef 100644
--- a/src/tools/rustfmt/CODE_OF_CONDUCT.md
+++ b/src/tools/rustfmt/CODE_OF_CONDUCT.md
@@ -11,7 +11,7 @@ A version of this document [can be found online](https://www.rust-lang.org/condu
* Please be kind and courteous. There's no need to be mean or rude.
* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
-* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
+* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the <a href="https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index bd28df7a7..8fcefa974 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -23,42 +23,50 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.2.6"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
+checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
dependencies = [
"anstyle",
"anstyle-parse",
+ "anstyle-query",
"anstyle-wincon",
- "concolor-override",
- "concolor-query",
- "is-terminal",
+ "colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "0.3.5"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
+checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
[[package]]
name = "anstyle-parse"
-version = "0.1.1"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
+checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [
"utf8parse",
]
[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
name = "anstyle-wincon"
-version = "0.2.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
+checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
dependencies = [
"anstyle",
- "windows-sys 0.45.0",
+ "windows-sys",
]
[[package]]
@@ -90,11 +98,11 @@ dependencies = [
[[package]]
name = "bytecount"
-version = "0.6.2"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
+checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7"
dependencies = [
- "packed_simd_2",
+ "packed_simd",
]
[[package]]
@@ -130,12 +138,6 @@ dependencies = [
]
[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
-[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -143,33 +145,41 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
-version = "4.2.1"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
+checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6"
dependencies = [
"clap_builder",
"clap_derive",
- "once_cell",
+]
+
+[[package]]
+name = "clap-cargo"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "383f21342a464d4af96e9a4cad22a0b4f2880d4a5b3bbf5c9654dd1d9a224ee4"
+dependencies = [
+ "anstyle",
+ "clap",
]
[[package]]
name = "clap_builder"
-version = "4.2.1"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
+checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
dependencies = [
"anstream",
"anstyle",
- "bitflags",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
-version = "4.2.0"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
+checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [
"heck",
"proc-macro2",
@@ -179,24 +189,15 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
-name = "concolor-override"
+name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
-
-[[package]]
-name = "concolor-query"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
-dependencies = [
- "windows-sys 0.45.0",
-]
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "crossbeam-utils"
@@ -262,40 +263,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
-name = "env_logger"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
-dependencies = [
- "humantime",
- "is-terminal",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "errno"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -347,18 +314,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
-name = "hermit-abi"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
name = "ignore"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -387,29 +342,6 @@ dependencies = [
]
[[package]]
-name = "io-lifetimes"
-version = "1.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
-dependencies = [
- "hermit-abi",
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "is-terminal"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
-dependencies = [
- "hermit-abi",
- "io-lifetimes",
- "rustix",
- "windows-sys 0.48.0",
-]
-
-[[package]]
name = "itertools"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -438,15 +370,9 @@ checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libm"
-version = "0.1.4"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "log"
@@ -458,28 +384,69 @@ dependencies = [
]
[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata",
+]
+
+[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
-name = "packed_simd_2"
-version = "0.3.7"
+name = "overload"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "defdcfef86dcc44ad208f71d9ff4ce28df6537a4e0d6b0e8e845cb8ca10059a6"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "packed_simd"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"
dependencies = [
"cfg-if",
- "libm",
+ "num-traits",
]
[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
name = "proc-macro2"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -519,9 +486,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.5.5"
+version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
+checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
dependencies = [
"aho-corasick",
"memchr",
@@ -529,10 +496,19 @@ dependencies = [
]
[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax",
+]
+
+[[package]]
name = "regex-syntax"
-version = "0.6.25"
+version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "rustfmt-config_proc_macro"
@@ -545,21 +521,20 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
-version = "1.6.0"
+version = "1.7.0"
dependencies = [
"annotate-snippets",
"anyhow",
"bytecount",
"cargo_metadata",
"clap",
+ "clap-cargo",
"diff",
"dirs",
- "env_logger",
"getopts",
"ignore",
"itertools",
"lazy_static",
- "log",
"regex",
"rustfmt-config_proc_macro",
"serde",
@@ -567,23 +542,11 @@ dependencies = [
"term",
"thiserror",
"toml",
+ "tracing",
+ "tracing-subscriber",
+ "unicode-properties",
"unicode-segmentation",
"unicode-width",
- "unicode_categories",
-]
-
-[[package]]
-name = "rustix"
-version = "0.37.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
-dependencies = [
- "bitflags",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.48.0",
]
[[package]]
@@ -657,6 +620,21 @@ dependencies = [
]
[[package]]
+name = "sharded-slab"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -685,15 +663,6 @@ dependencies = [
]
[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -757,28 +726,90 @@ dependencies = [
]
[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+dependencies = [
+ "lazy_static",
+ "log",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
-name = "unicode-segmentation"
-version = "1.9.0"
+name = "unicode-properties"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
[[package]]
-name = "unicode-width"
-version = "0.1.9"
+name = "unicode-segmentation"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
-name = "unicode_categories"
-version = "0.1.1"
+name = "unicode-width"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "utf8parse"
@@ -787,6 +818,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -836,35 +873,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
-[[package]]
-name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets",
]
[[package]]
@@ -873,95 +886,53 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
-[[package]]
-name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
-[[package]]
-name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
-[[package]]
-name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
-[[package]]
-name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
-
-[[package]]
-name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 8c312f47a..00e0ed37a 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "rustfmt-nightly"
-version = "1.6.0"
+version = "1.7.0"
description = "Tool to find and fix Rust formatting issues"
repository = "https://github.com/rust-lang/rustfmt"
readme = "README.md"
-license = "Apache-2.0/MIT"
+license = "Apache-2.0 OR MIT"
build = "build.rs"
categories = ["development-tools"]
edition = "2021"
@@ -35,26 +35,27 @@ generic-simd = ["bytecount/generic-simd"]
[dependencies]
annotate-snippets = { version = "0.9", features = ["color"] }
anyhow = "1.0"
-bytecount = "0.6"
+bytecount = "0.6.4"
cargo_metadata = "0.15.4"
-clap = { version = "4.2.1", features = ["derive"] }
+clap = { version = "4.4.2", features = ["derive"] }
+clap-cargo = "0.12.0"
diff = "0.1"
dirs = "4.0"
-env_logger = "0.10.0"
getopts = "0.2"
ignore = "0.4"
itertools = "0.10"
lazy_static = "1.4"
-log = "0.4"
-regex = "1.5"
+regex = "1.7"
serde = { version = "1.0.160", features = ["derive"] }
serde_json = "1.0"
term = "0.7"
thiserror = "1.0.40"
toml = "0.7.4"
+tracing = "0.1.37"
+tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
unicode-segmentation = "1.9"
unicode-width = "0.1"
-unicode_categories = "0.1"
+unicode-properties = { version = "0.1", default-features = false, features = ["general-category"] }
rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" }
diff --git a/src/tools/rustfmt/Contributing.md b/src/tools/rustfmt/Contributing.md
index b986a887c..69a2c7636 100644
--- a/src/tools/rustfmt/Contributing.md
+++ b/src/tools/rustfmt/Contributing.md
@@ -95,10 +95,18 @@ wish there weren't. You can leave `FIXME`s, preferably with an issue number.
You may want to run a version of rustfmt from source code as part of a test or
hacking on the rustfmt codebase. It's strongly discouraged to install a version
-of rustfmt from source. Instead, run it using `cargo run`, and `--manifest-path`.
+of rustfmt from source.
+
+To run `rustfmt` on a file:
+
+```
+cargo run --bin rustfmt -- path/to/file.rs
+```
+
+If you want to test modified `cargo-fmt`, or run `rustfmt` on the whole project (You may need to build rustfmt first):
```
-cargo run --bin cargo-fmt -- --manifest-path path/to/project/you/want2test/Cargo.toml
+RUSTFMT="./target/debug/rustfmt" cargo run --bin cargo-fmt -- --manifest-path path/to/project/you/want2test/Cargo.toml
```
### Version-gate formatting changes
diff --git a/src/tools/rustfmt/README.md b/src/tools/rustfmt/README.md
index c05184fbb..b68a942e4 100644
--- a/src/tools/rustfmt/README.md
+++ b/src/tools/rustfmt/README.md
@@ -229,4 +229,4 @@ See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.
[rust]: https://github.com/rust-lang/rust
[fmt rfcs]: https://github.com/rust-dev-tools/fmt-rfcs
-[style guide]: https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md
+[style guide]: https://doc.rust-lang.org/nightly/style-guide/
diff --git a/src/tools/rustfmt/ci/build_and_test.bat b/src/tools/rustfmt/ci/build_and_test.bat
index 69dae1fff..16608a4aa 100755
--- a/src/tools/rustfmt/ci/build_and_test.bat
+++ b/src/tools/rustfmt/ci/build_and_test.bat
@@ -6,7 +6,11 @@ rustc -Vv || exit /b 1
cargo -V || exit /b 1
:: Build and test main crate
-cargo build --locked || exit /b 1
+if "%CFG_RELEASE_CHANNEL%"=="nightly" (
+ cargo build --locked --all-features || exit /b 1
+) else (
+ cargo build --locked || exit /b 1
+)
cargo test || exit /b 1
:: Build and test other crates
diff --git a/src/tools/rustfmt/ci/build_and_test.sh b/src/tools/rustfmt/ci/build_and_test.sh
index 949918532..207da362f 100755
--- a/src/tools/rustfmt/ci/build_and_test.sh
+++ b/src/tools/rustfmt/ci/build_and_test.sh
@@ -10,7 +10,11 @@ rustc -Vv
cargo -V
# Build and test main crate
-cargo build --locked
+if [ "$CFG_RELEASE_CHANNEL" == "nightly" ]; then
+ cargo build --locked --all-features
+else
+ cargo build --locked
+fi
cargo test
# Build and test other crates
diff --git a/src/tools/rustfmt/ci/check_diff.sh b/src/tools/rustfmt/ci/check_diff.sh
index 062c2dd86..50c58b1f4 100755
--- a/src/tools/rustfmt/ci/check_diff.sh
+++ b/src/tools/rustfmt/ci/check_diff.sh
@@ -1,5 +1,10 @@
#!/bin/bash
+set -e
+
+# https://github.com/rust-lang/rustfmt/issues/5675
+export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH
+
function print_usage() {
echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]"
}
@@ -110,7 +115,7 @@ function compile_rustfmt() {
git fetch feature $FEATURE_BRANCH
cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
- if [ -z "$OPTIONAL_COMMIT_HASH" ]; then
+ if [ -z "$OPTIONAL_COMMIT_HASH" ] || [ "$FEATURE_BRANCH" = "$OPTIONAL_COMMIT_HASH" ]; then
git switch $FEATURE_BRANCH
else
git switch $OPTIONAL_COMMIT_HASH --detach
@@ -140,9 +145,15 @@ function check_repo() {
init_submodules $SUBMODULES
fi
+
+ # rustfmt --check returns 1 if a diff was found
+ # Also check_diff returns 1 if there was a diff between master rustfmt and the feature branch
+ # so we want to ignore the exit status check
+ set +e
check_diff $REPO_NAME
# append the status of running `check_diff` to the STATUSES array
STATUSES+=($?)
+ set -e
echo "removing tmp_dir $tmp_dir"
rm -rf $tmp_dir
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.toml b/src/tools/rustfmt/config_proc_macro/Cargo.toml
index 34e8c237f..eda8a7fce 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.toml
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.toml
@@ -3,7 +3,7 @@ name = "rustfmt-config_proc_macro"
version = "0.3.0"
edition = "2018"
description = "A collection of procedural macros for rustfmt"
-license = "Apache-2.0/MIT"
+license = "Apache-2.0 OR MIT"
categories = ["development-tools::procedural-macro-helpers"]
repository = "https://github.com/rust-lang/rustfmt"
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 33ff8b03d..0057e2f37 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2023-07-01"
+channel = "nightly-2023-10-22"
components = ["llvm-tools", "rustc-dev"]
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index 22e45082a..4d83547d6 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -308,7 +308,7 @@ impl Rewrite for ast::MetaItem {
// See #2479 for example.
let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
.unwrap_or_else(|| context.snippet(lit.span).to_owned());
- format!("{} = {}", path, value)
+ format!("{path} = {value}")
}
})
}
@@ -342,7 +342,7 @@ impl Rewrite for ast::Attribute {
let literal_str = literal.as_str();
let doc_comment_formatter =
DocCommentFormatter::new(literal_str, comment_style);
- let doc_comment = format!("{}", doc_comment_formatter);
+ let doc_comment = format!("{doc_comment_formatter}");
return rewrite_doc_comment(
&doc_comment,
shape.comment(context.config),
@@ -406,9 +406,9 @@ impl Rewrite for [ast::Attribute] {
0,
)?;
let comment = if comment.is_empty() {
- format!("\n{}", mlb)
+ format!("\n{mlb}")
} else {
- format!("{}{}\n{}", mla, comment, mlb)
+ format!("{mla}{comment}\n{mlb}")
};
result.push_str(&comment);
result.push_str(&shape.indent.to_string(context.config));
diff --git a/src/tools/rustfmt/src/attr/doc_comment.rs b/src/tools/rustfmt/src/attr/doc_comment.rs
index 25c8158df..f55201839 100644
--- a/src/tools/rustfmt/src/attr/doc_comment.rs
+++ b/src/tools/rustfmt/src/attr/doc_comment.rs
@@ -20,15 +20,15 @@ impl Display for DocCommentFormatter<'_> {
// Handle `#[doc = ""]`.
if lines.peek().is_none() {
- return write!(formatter, "{}", opener);
+ return write!(formatter, "{opener}");
}
while let Some(line) = lines.next() {
let is_last_line = lines.peek().is_none();
if is_last_line {
- write!(formatter, "{}{}", opener, line)?;
+ write!(formatter, "{opener}{line}")?;
} else {
- writeln!(formatter, "{}{}", opener, line)?;
+ writeln!(formatter, "{opener}{line}")?;
}
}
Ok(())
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 03b75c1b0..6f5640836 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -6,6 +6,7 @@ use io::Error as IoError;
use thiserror::Error;
use rustfmt_nightly as rustfmt;
+use tracing_subscriber::EnvFilter;
use std::collections::HashMap;
use std::env;
@@ -29,13 +30,15 @@ extern crate rustc_driver;
fn main() {
rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| ());
- env_logger::Builder::from_env("RUSTFMT_LOG").init();
+ tracing_subscriber::fmt()
+ .with_env_filter(EnvFilter::from_env("RUSTFMT_LOG"))
+ .init();
let opts = make_opts();
let exit_code = match execute(&opts) {
Ok(code) => code,
Err(e) => {
- eprintln!("{:#}", e);
+ eprintln!("{e:#}");
1
}
};
@@ -281,7 +284,7 @@ fn format_string(input: String, options: GetOptsOptions) -> Result<i32> {
for f in config.file_lines().files() {
match *f {
FileName::Stdin => {}
- _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f),
+ _ => eprintln!("Warning: Extra file listed in file_lines option '{f}'"),
}
}
@@ -377,7 +380,7 @@ fn format_and_emit_report<T: Write>(session: &mut Session<'_, T>, input: Input)
}
}
Err(msg) => {
- eprintln!("Error writing files: {}", msg);
+ eprintln!("Error writing files: {msg}");
session.add_operational_error();
}
}
@@ -400,12 +403,9 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) {
let sep = if reason.is_empty() {
String::new()
} else {
- format!("{}\n\n", reason)
+ format!("{reason}\n\n")
};
- let msg = format!(
- "{}Format Rust code\n\nusage: rustfmt [options] <file>...",
- sep
- );
+ let msg = format!("{sep}Format Rust code\n\nusage: rustfmt [options] <file>...");
println!("{}", opts.usage(&msg));
}
@@ -419,7 +419,7 @@ are 1-based and inclusive of both end points. Specifying an empty array
will result in no files being formatted. For example,
```
-rustfmt --file-lines '[
+rustfmt src/lib.rs src/foo.rs --file-lines '[
{{\"file\":\"src/lib.rs\",\"range\":[7,13]}},
{{\"file\":\"src/lib.rs\",\"range\":[21,29]}},
{{\"file\":\"src/foo.rs\",\"range\":[10,11]}},
@@ -439,7 +439,7 @@ fn print_version() {
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
);
- println!("rustfmt {}", version_info);
+ println!("rustfmt {version_info}");
}
fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
@@ -644,9 +644,9 @@ impl GetOptsOptions {
match *f {
FileName::Real(ref f) if files.contains(f) => {}
FileName::Real(_) => {
- eprintln!("Warning: Extra file listed in file_lines option '{}'", f)
+ eprintln!("Warning: Extra file listed in file_lines option '{f}'")
}
- FileName::Stdin => eprintln!("Warning: Not a file '{}'", f),
+ FileName::Stdin => eprintln!("Warning: Not a file '{f}'"),
}
}
}
diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs
index bc9745275..a1ad1aafa 100644
--- a/src/tools/rustfmt/src/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/main.rs
@@ -22,27 +22,28 @@ use clap::{CommandFactory, Parser};
mod cargo_fmt_tests;
#[derive(Parser)]
-#[clap(
+#[command(
disable_version_flag = true,
bin_name = "cargo fmt",
about = "This utility formats all bin and lib files of \
the current crate using rustfmt."
)]
+#[command(styles = clap_cargo::style::CLAP_STYLING)]
pub struct Opts {
/// No output printed to stdout
- #[clap(short = 'q', long = "quiet")]
+ #[arg(short = 'q', long = "quiet")]
quiet: bool,
/// Use verbose output
- #[clap(short = 'v', long = "verbose")]
+ #[arg(short = 'v', long = "verbose")]
verbose: bool,
/// Print rustfmt version and exit
- #[clap(long = "version")]
+ #[arg(long = "version")]
version: bool,
/// Specify package to format
- #[clap(
+ #[arg(
short = 'p',
long = "package",
value_name = "package",
@@ -51,24 +52,24 @@ pub struct Opts {
packages: Vec<String>,
/// Specify path to Cargo.toml
- #[clap(long = "manifest-path", value_name = "manifest-path")]
+ #[arg(long = "manifest-path", value_name = "manifest-path")]
manifest_path: Option<String>,
/// Specify message-format: short|json|human
- #[clap(long = "message-format", value_name = "message-format")]
+ #[arg(long = "message-format", value_name = "message-format")]
message_format: Option<String>,
/// Options passed to rustfmt
// 'raw = true' to make `--` explicit.
- #[clap(name = "rustfmt_options", raw(true))]
+ #[arg(name = "rustfmt_options", raw = true)]
rustfmt_options: Vec<String>,
/// Format all packages, and also their local path-based dependencies
- #[clap(long = "all")]
+ #[arg(long = "all")]
format_all: bool,
/// Run rustfmt in check mode
- #[clap(long = "check")]
+ #[arg(long = "check")]
check: bool,
}
@@ -200,14 +201,13 @@ fn convert_message_format_to_rustfmt_args(
}
"human" => Ok(()),
_ => Err(format!(
- "invalid --message-format value: {}. Allowed values are: short|json|human",
- message_format
+ "invalid --message-format value: {message_format}. Allowed values are: short|json|human"
)),
}
}
fn print_usage_to_stderr(reason: &str) {
- eprintln!("{}", reason);
+ eprintln!("{reason}");
let app = Opts::command();
app.after_help("")
.write_help(&mut io::stderr())
@@ -460,7 +460,7 @@ fn get_targets_with_hitlist(
let package = workspace_hitlist.iter().next().unwrap();
Err(io::Error::new(
io::ErrorKind::InvalidInput,
- format!("package `{}` is not a member of the workspace", package),
+ format!("package `{package}` is not a member of the workspace"),
))
}
}
@@ -498,7 +498,7 @@ fn run_rustfmt(
if verbosity == Verbosity::Verbose {
print!("rustfmt");
- print!(" --edition {}", edition);
+ print!(" --edition {edition}");
fmt_args.iter().for_each(|f| print!(" {}", f));
files.iter().for_each(|f| print!(" {}", f.display()));
println!();
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index 0afce7cf6..ea23690ca 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -153,7 +153,13 @@ enum CommentPosition {
Top,
}
-// An expression plus trailing `?`s to be formatted together.
+/// Information about an expression in a chain.
+struct SubExpr {
+ expr: ast::Expr,
+ is_method_call_receiver: bool,
+}
+
+/// An expression plus trailing `?`s to be formatted together.
#[derive(Debug)]
struct ChainItem {
kind: ChainItemKind,
@@ -166,7 +172,10 @@ struct ChainItem {
// would remove a lot of cloning.
#[derive(Debug)]
enum ChainItemKind {
- Parent(ast::Expr),
+ Parent {
+ expr: ast::Expr,
+ parens: bool,
+ },
MethodCall(
ast::PathSegment,
Vec<ast::GenericArg>,
@@ -181,7 +190,7 @@ enum ChainItemKind {
impl ChainItemKind {
fn is_block_like(&self, context: &RewriteContext<'_>, reps: &str) -> bool {
match self {
- ChainItemKind::Parent(ref expr) => utils::is_block_expr(context, expr, reps),
+ ChainItemKind::Parent { expr, .. } => utils::is_block_expr(context, expr, reps),
ChainItemKind::MethodCall(..)
| ChainItemKind::StructField(..)
| ChainItemKind::TupleField(..)
@@ -199,7 +208,11 @@ impl ChainItemKind {
}
}
- fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) {
+ fn from_ast(
+ context: &RewriteContext<'_>,
+ expr: &ast::Expr,
+ is_method_call_receiver: bool,
+ ) -> (ChainItemKind, Span) {
let (kind, span) = match expr.kind {
ast::ExprKind::MethodCall(ref call) => {
let types = if let Some(ref generic_args) = call.seg.args {
@@ -236,7 +249,15 @@ impl ChainItemKind {
let span = mk_sp(nested.span.hi(), expr.span.hi());
(ChainItemKind::Await, span)
}
- _ => return (ChainItemKind::Parent(expr.clone()), expr.span),
+ _ => {
+ return (
+ ChainItemKind::Parent {
+ expr: expr.clone(),
+ parens: is_method_call_receiver && should_add_parens(expr),
+ },
+ expr.span,
+ );
+ }
};
// Remove comments from the span.
@@ -249,7 +270,14 @@ impl Rewrite for ChainItem {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
let shape = shape.sub_width(self.tries)?;
let rewrite = match self.kind {
- ChainItemKind::Parent(ref expr) => expr.rewrite(context, shape)?,
+ ChainItemKind::Parent {
+ ref expr,
+ parens: true,
+ } => crate::expr::rewrite_paren(context, &expr, shape, expr.span)?,
+ ChainItemKind::Parent {
+ ref expr,
+ parens: false,
+ } => expr.rewrite(context, shape)?,
ChainItemKind::MethodCall(ref segment, ref types, ref exprs) => {
Self::rewrite_method_call(segment.ident, types, exprs, self.span, context, shape)?
}
@@ -268,13 +296,14 @@ impl Rewrite for ChainItem {
rewrite_comment(comment, false, shape, context.config)?
}
};
- Some(format!("{}{}", rewrite, "?".repeat(self.tries)))
+ Some(format!("{rewrite}{}", "?".repeat(self.tries)))
}
}
impl ChainItem {
- fn new(context: &RewriteContext<'_>, expr: &ast::Expr, tries: usize) -> ChainItem {
- let (kind, span) = ChainItemKind::from_ast(context, expr);
+ fn new(context: &RewriteContext<'_>, expr: &SubExpr, tries: usize) -> ChainItem {
+ let (kind, span) =
+ ChainItemKind::from_ast(context, &expr.expr, expr.is_method_call_receiver);
ChainItem { kind, tries, span }
}
@@ -327,7 +356,7 @@ impl Chain {
let mut rev_children = vec![];
let mut sub_tries = 0;
for subexpr in &subexpr_list {
- match subexpr.kind {
+ match subexpr.expr.kind {
ast::ExprKind::Try(_) => sub_tries += 1,
_ => {
rev_children.push(ChainItem::new(context, subexpr, sub_tries));
@@ -442,11 +471,14 @@ impl Chain {
// Returns a Vec of the prefixes of the chain.
// E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a']
- fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext<'_>) -> Vec<ast::Expr> {
- let mut subexpr_list = vec![expr.clone()];
+ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext<'_>) -> Vec<SubExpr> {
+ let mut subexpr_list = vec![SubExpr {
+ expr: expr.clone(),
+ is_method_call_receiver: false,
+ }];
while let Some(subexpr) = Self::pop_expr_chain(subexpr_list.last().unwrap(), context) {
- subexpr_list.push(subexpr.clone());
+ subexpr_list.push(subexpr);
}
subexpr_list
@@ -454,12 +486,18 @@ impl Chain {
// Returns the expression's subexpression, if it exists. When the subexpr
// is a try! macro, we'll convert it to shorthand when the option is set.
- fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option<ast::Expr> {
- match expr.kind {
- ast::ExprKind::MethodCall(ref call) => Some(Self::convert_try(&call.receiver, context)),
+ fn pop_expr_chain(expr: &SubExpr, context: &RewriteContext<'_>) -> Option<SubExpr> {
+ match expr.expr.kind {
+ ast::ExprKind::MethodCall(ref call) => Some(SubExpr {
+ expr: Self::convert_try(&call.receiver, context),
+ is_method_call_receiver: true,
+ }),
ast::ExprKind::Field(ref subexpr, _)
| ast::ExprKind::Try(ref subexpr)
- | ast::ExprKind::Await(ref subexpr, _) => Some(Self::convert_try(subexpr, context)),
+ | ast::ExprKind::Await(ref subexpr, _) => Some(SubExpr {
+ expr: Self::convert_try(subexpr, context),
+ is_method_call_receiver: false,
+ }),
_ => None,
}
}
@@ -940,3 +978,22 @@ fn trim_tries(s: &str) -> String {
}
result
}
+
+/// Whether a method call's receiver needs parenthesis, like
+/// ```rust,ignore
+/// || .. .method();
+/// || 1.. .method();
+/// 1. .method();
+/// ```
+/// Which all need parenthesis or a space before `.method()`.
+fn should_add_parens(expr: &ast::Expr) -> bool {
+ match expr.kind {
+ ast::ExprKind::Lit(ref lit) => crate::expr::lit_ends_in_dot(lit),
+ ast::ExprKind::Closure(ref cl) => match cl.body.kind {
+ ast::ExprKind::Range(_, _, ast::RangeLimits::HalfOpen) => true,
+ ast::ExprKind::Lit(ref lit) => crate::expr::lit_ends_in_dot(lit),
+ _ => false,
+ },
+ _ => false,
+ }
+}
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index c95e9a97b..8a4089a56 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -12,7 +12,7 @@ use crate::overflow::OverflowableItem;
use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::Shape;
use crate::source_map::SpanUtils;
-use crate::types::rewrite_lifetime_param;
+use crate::types::rewrite_bound_params;
use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt};
// This module is pretty messy because of the rules around closures and blocks:
@@ -175,7 +175,7 @@ fn rewrite_closure_with_block(
shape,
false,
)?;
- Some(format!("{} {}", prefix, block))
+ Some(format!("{prefix} {block}"))
}
// Rewrite closure with a single expression without wrapping its body with block.
@@ -188,7 +188,7 @@ fn rewrite_closure_expr(
fn allow_multi_line(expr: &ast::Expr) -> bool {
match expr.kind {
ast::ExprKind::Match(..)
- | ast::ExprKind::Async(..)
+ | ast::ExprKind::Gen(..)
| ast::ExprKind::Block(..)
| ast::ExprKind::TryBlock(..)
| ast::ExprKind::Loop(..)
@@ -246,7 +246,7 @@ fn rewrite_closure_fn_decl(
"for<> ".to_owned()
}
ast::ClosureBinder::For { generic_params, .. } => {
- let lifetime_str = rewrite_lifetime_param(context, shape, generic_params)?;
+ let lifetime_str = rewrite_bound_params(context, shape, generic_params)?;
format!("for<{lifetime_str}> ")
}
ast::ClosureBinder::NotPresent => "".to_owned(),
@@ -264,7 +264,7 @@ fn rewrite_closure_fn_decl(
""
};
let is_async = if asyncness.is_async() { "async " } else { "" };
- let mover = if capture == ast::CaptureBy::Value {
+ let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
"move "
} else {
""
@@ -310,10 +310,7 @@ fn rewrite_closure_fn_decl(
.tactic(tactic)
.preserve_newline(true);
let list_str = write_list(&item_vec, &fmt)?;
- let mut prefix = format!(
- "{}{}{}{}{}|{}|",
- binder, const_, immovable, is_async, mover, list_str
- );
+ let mut prefix = format!("{binder}{const_}{immovable}{is_async}{mover}|{list_str}|");
if !ret_str.is_empty() {
if prefix.contains('\n') {
diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs
index 85918ecc1..7da0f79bd 100644
--- a/src/tools/rustfmt/src/comment.rs
+++ b/src/tools/rustfmt/src/comment.rs
@@ -58,25 +58,23 @@ fn custom_opener(s: &str) -> &str {
}
impl<'a> CommentStyle<'a> {
- /// Returns `true` if the commenting style covers a line only.
+ /// Returns `true` if the commenting style cannot span multiple lines.
pub(crate) fn is_line_comment(&self) -> bool {
- match *self {
+ matches!(
+ self,
CommentStyle::DoubleSlash
- | CommentStyle::TripleSlash
- | CommentStyle::Doc
- | CommentStyle::Custom(_) => true,
- _ => false,
- }
+ | CommentStyle::TripleSlash
+ | CommentStyle::Doc
+ | CommentStyle::Custom(_)
+ )
}
- /// Returns `true` if the commenting style can span over multiple lines.
+ /// Returns `true` if the commenting style can span multiple lines.
pub(crate) fn is_block_comment(&self) -> bool {
- match *self {
- CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => {
- true
- }
- _ => false,
- }
+ matches!(
+ self,
+ CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation
+ )
}
/// Returns `true` if the commenting style is for documentation.
@@ -367,7 +365,11 @@ fn identify_comment(
trim_left_preserve_layout(first_group, shape.indent, config)?
} else if !config.normalize_comments()
&& !config.wrap_comments()
- && !config.format_code_in_doc_comments()
+ && !(
+ // `format_code_in_doc_comments` should only take effect on doc comments,
+ // so we only consider it when this comment block is a doc comment block.
+ is_doc_comment && config.format_code_in_doc_comments()
+ )
{
light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)
} else {
@@ -484,7 +486,9 @@ impl ItemizedBlock {
// allowed.
for suffix in [". ", ") "] {
if let Some((prefix, _)) = trimmed.split_once(suffix) {
- if prefix.len() <= 2 && prefix.chars().all(|c| char::is_ascii_digit(&c)) {
+ let has_leading_digits = (1..=2).contains(&prefix.len())
+ && prefix.chars().all(|c| char::is_ascii_digit(&c));
+ if has_leading_digits {
return Some(prefix.len() + suffix.len());
}
}
@@ -623,7 +627,7 @@ impl<'a> CommentRewrite<'a> {
is_prev_line_multi_line: false,
code_block_attr: None,
item_block: None,
- comment_line_separator: format!("{}{}", indent_str, line_start),
+ comment_line_separator: format!("{indent_str}{line_start}"),
max_width,
indent_str,
fmt_indent: shape.indent,
@@ -953,7 +957,7 @@ const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### ";
fn hide_sharp_behind_comment(s: &str) -> Cow<'_, str> {
let s_trimmed = s.trim();
if s_trimmed.starts_with("# ") || s_trimmed == "#" {
- Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s))
+ Cow::from(format!("{RUSTFMT_CUSTOM_COMMENT_PREFIX}{s}"))
} else {
Cow::from(s)
}
@@ -1037,7 +1041,7 @@ pub(crate) fn recover_missing_comment_in_span(
} else {
Cow::from(" ")
};
- Some(format!("{}{}", sep, missing_comment))
+ Some(format!("{sep}{missing_comment}"))
}
}
@@ -1834,8 +1838,7 @@ fn remove_comment_header(comment: &str) -> &str {
} else {
assert!(
comment.starts_with("/*"),
- "string '{}' is not a comment",
- comment
+ "string '{comment}' is not a comment"
);
&comment[2..comment.len() - 2]
}
@@ -2071,26 +2074,13 @@ fn main() {
expected_line_start: &str,
) {
let block = ItemizedBlock::new(test_input).unwrap();
- assert_eq!(1, block.lines.len(), "test_input: {:?}", test_input);
- assert_eq!(
- expected_line, &block.lines[0],
- "test_input: {:?}",
- test_input
- );
- assert_eq!(
- expected_indent, block.indent,
- "test_input: {:?}",
- test_input
- );
- assert_eq!(
- expected_opener, &block.opener,
- "test_input: {:?}",
- test_input
- );
+ assert_eq!(1, block.lines.len(), "test_input: {test_input:?}");
+ assert_eq!(expected_line, &block.lines[0], "test_input: {test_input:?}");
+ assert_eq!(expected_indent, block.indent, "test_input: {test_input:?}");
+ assert_eq!(expected_opener, &block.opener, "test_input: {test_input:?}");
assert_eq!(
expected_line_start, &block.line_start,
- "test_input: {:?}",
- test_input
+ "test_input: {test_input:?}"
);
}
@@ -2142,13 +2132,15 @@ fn main() {
// https://spec.commonmark.org/0.30 says: "A start number may not be negative":
"-1. Not a list item.",
"-1 Not a list item.",
+ // Marker without prefix are not recognized as item markers:
+ ". Not a list item.",
+ ") Not a list item.",
];
for line in test_inputs.iter() {
let maybe_block = ItemizedBlock::new(line);
assert!(
maybe_block.is_none(),
- "The following line shouldn't be classified as a list item: {}",
- line
+ "The following line shouldn't be classified as a list item: {line}"
);
}
}
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index c836b4bbb..feb452d72 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -500,18 +500,16 @@ where
// Stable with an unstable option
(false, false, _) => {
eprintln!(
- "Warning: can't set `{} = {:?}`, unstable features are only \
- available in nightly channel.",
- option_name, option_value
+ "Warning: can't set `{option_name} = {option_value:?}`, unstable features are only \
+ available in nightly channel."
);
false
}
// Stable with a stable option, but an unstable variant
(false, true, false) => {
eprintln!(
- "Warning: can't set `{} = {:?}`, unstable variants are only \
- available in nightly channel.",
- option_name, option_value
+ "Warning: can't set `{option_name} = {option_value:?}`, unstable variants are only \
+ available in nightly channel."
);
false
}
diff --git a/src/tools/rustfmt/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs
index e4e51a3f3..e33fe9bb2 100644
--- a/src/tools/rustfmt/src/config/file_lines.rs
+++ b/src/tools/rustfmt/src/config/file_lines.rs
@@ -162,7 +162,7 @@ impl fmt::Display for FileLines {
None => write!(f, "None")?,
Some(map) => {
for (file_name, ranges) in map.iter() {
- write!(f, "{}: ", file_name)?;
+ write!(f, "{file_name}: ")?;
write!(f, "{}\n", ranges.iter().format(", "))?;
}
}
diff --git a/src/tools/rustfmt/src/config/macro_names.rs b/src/tools/rustfmt/src/config/macro_names.rs
index 26ad78d6d..edfe925c2 100644
--- a/src/tools/rustfmt/src/config/macro_names.rs
+++ b/src/tools/rustfmt/src/config/macro_names.rs
@@ -3,7 +3,7 @@
use itertools::Itertools;
use std::{fmt, str};
-use serde::{Deserialize, Serialize};
+use serde::{Deserialize, Deserializer, Serialize};
use serde_json as json;
use thiserror::Error;
@@ -30,12 +30,22 @@ impl From<MacroName> for String {
}
/// Defines a selector to match against a macro.
-#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)]
pub enum MacroSelector {
Name(MacroName),
All,
}
+impl<'de> Deserialize<'de> for MacroSelector {
+ fn deserialize<D>(de: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ let s = String::deserialize(de)?;
+ std::str::FromStr::from_str(&s).map_err(serde::de::Error::custom)
+ }
+}
+
impl fmt::Display for MacroSelector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -113,6 +123,6 @@ mod test {
#[test]
fn macro_names_display() {
let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
- assert_eq!(format!("{}", macro_names), "foo, *, bar");
+ assert_eq!(format!("{macro_names}"), "foo, *, bar");
}
}
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 6f41b299e..7538b2652 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -216,8 +216,8 @@ impl Config {
let required_version = self.required_version();
if version != required_version {
println!(
- "Error: rustfmt version ({}) doesn't match the required version ({})",
- version, required_version,
+ "Error: rustfmt version ({version}) doesn't match the required version \
+({required_version})"
);
return false;
}
@@ -310,20 +310,20 @@ impl Config {
.ok_or_else(|| String::from("Parsed config was not table"))?;
for key in table.keys() {
if !Config::is_valid_name(key) {
- let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
+ let msg = &format!("Warning: Unknown configuration option `{key}`\n");
err.push_str(msg)
}
}
match parsed.try_into() {
Ok(parsed_config) => {
if !err.is_empty() {
- eprint!("{}", err);
+ eprint!("{err}");
}
Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
}
Err(e) => {
err.push_str("Error: Decoding config file failed:\n");
- err.push_str(format!("{}\n", e).as_str());
+ err.push_str(format!("{e}\n").as_str());
err.push_str("Please check your config file.");
Err(err)
}
@@ -563,10 +563,7 @@ mod test {
let toml = used_options.to_toml().unwrap();
assert_eq!(
toml,
- format!(
- "merge_derives = {}\nskip_children = {}\n",
- merge_derives, skip_children,
- )
+ format!("merge_derives = {merge_derives}\nskip_children = {skip_children}\n",)
);
}
diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs
index 3aa1a4de9..03fd91eb1 100644
--- a/src/tools/rustfmt/src/config/options.rs
+++ b/src/tools/rustfmt/src/config/options.rs
@@ -1,3 +1,5 @@
+#![allow(unused_imports)]
+
use std::collections::{hash_set, HashSet};
use std::fmt;
use std::path::{Path, PathBuf};
@@ -243,7 +245,7 @@ pub struct WidthHeuristics {
impl fmt::Display for WidthHeuristics {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:?}", self)
+ write!(f, "{self:?}")
}
}
diff --git a/src/tools/rustfmt/src/emitter.rs b/src/tools/rustfmt/src/emitter.rs
index dc2c99a30..9c335314d 100644
--- a/src/tools/rustfmt/src/emitter.rs
+++ b/src/tools/rustfmt/src/emitter.rs
@@ -47,6 +47,6 @@ pub(crate) trait Emitter {
fn ensure_real_path(filename: &FileName) -> &Path {
match *filename {
FileName::Real(ref path) => path,
- _ => panic!("cannot format `{}` and emit to files", filename),
+ _ => panic!("cannot format `{filename}` and emit to files"),
}
}
diff --git a/src/tools/rustfmt/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs
index 545b25997..56d6a0ed6 100644
--- a/src/tools/rustfmt/src/emitter/checkstyle.rs
+++ b/src/tools/rustfmt/src/emitter/checkstyle.rs
@@ -43,7 +43,7 @@ pub(crate) fn output_checkstyle_file<T>(
where
T: Write,
{
- write!(writer, r#"<file name="{}">"#, filename)?;
+ write!(writer, r#"<file name="{filename}">"#)?;
for mismatch in diff {
let begin_line = mismatch.line_number;
let mut current_line;
@@ -82,7 +82,7 @@ mod tests {
);
assert_eq!(
&writer[..],
- format!(r#"<file name="{}"></file>"#, file_name).as_bytes()
+ format!(r#"<file name="{file_name}"></file>"#).as_bytes()
);
}
diff --git a/src/tools/rustfmt/src/emitter/checkstyle/xml.rs b/src/tools/rustfmt/src/emitter/checkstyle/xml.rs
index f251aabe8..d1d9af708 100644
--- a/src/tools/rustfmt/src/emitter/checkstyle/xml.rs
+++ b/src/tools/rustfmt/src/emitter/checkstyle/xml.rs
@@ -13,7 +13,7 @@ impl<'a> Display for XmlEscaped<'a> {
'"' => write!(formatter, "&quot;"),
'\'' => write!(formatter, "&apos;"),
'&' => write!(formatter, "&amp;"),
- _ => write!(formatter, "{}", char),
+ _ => write!(formatter, "{char}"),
}?;
}
diff --git a/src/tools/rustfmt/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs
index 5e1f13446..764cd136e 100644
--- a/src/tools/rustfmt/src/emitter/diff.rs
+++ b/src/tools/rustfmt/src/emitter/diff.rs
@@ -28,7 +28,7 @@ impl Emitter for DiffEmitter {
if has_diff {
if self.config.print_misformatted_file_names() {
- writeln!(output, "{}", filename)?;
+ writeln!(output, "{filename}")?;
} else {
print_diff(
mismatch,
@@ -40,7 +40,7 @@ impl Emitter for DiffEmitter {
// This occurs when the only difference between the original and formatted values
// is the newline style. This happens because The make_diff function compares the
// original and formatted values line by line, independent of line endings.
- writeln!(output, "Incorrect newline style in {}", filename)?;
+ writeln!(output, "Incorrect newline style in {filename}")?;
return Ok(EmitterResult { has_diff: true });
}
@@ -110,7 +110,7 @@ mod tests {
assert_eq!(
String::from_utf8(writer).unwrap(),
- format!("{}\n{}\n", bin_file, lib_file),
+ format!("{bin_file}\n{lib_file}\n"),
)
}
diff --git a/src/tools/rustfmt/src/emitter/json.rs b/src/tools/rustfmt/src/emitter/json.rs
index c7f68d467..5594196be 100644
--- a/src/tools/rustfmt/src/emitter/json.rs
+++ b/src/tools/rustfmt/src/emitter/json.rs
@@ -96,7 +96,7 @@ impl JsonEmitter {
});
}
self.mismatched_files.push(MismatchedFile {
- name: format!("{}", filename),
+ name: format!("{filename}"),
mismatches,
});
Ok(())
@@ -281,7 +281,7 @@ mod tests {
}])
.unwrap();
assert_eq!(result.has_diff, true);
- assert_eq!(&writer[..], format!("{}\n", exp_json).as_bytes());
+ assert_eq!(&writer[..], format!("{exp_json}\n").as_bytes());
}
#[test]
@@ -341,6 +341,6 @@ mod tests {
};
let exp_json = to_json_string(&vec![exp_bin, exp_lib]).unwrap();
- assert_eq!(&writer[..], format!("{}\n", exp_json).as_bytes());
+ assert_eq!(&writer[..], format!("{exp_json}\n").as_bytes());
}
}
diff --git a/src/tools/rustfmt/src/emitter/stdout.rs b/src/tools/rustfmt/src/emitter/stdout.rs
index 9fddd515e..0bbc7332d 100644
--- a/src/tools/rustfmt/src/emitter/stdout.rs
+++ b/src/tools/rustfmt/src/emitter/stdout.rs
@@ -24,9 +24,9 @@ impl Emitter for StdoutEmitter {
}: FormattedFile<'_>,
) -> Result<EmitterResult, io::Error> {
if self.verbosity != Verbosity::Quiet {
- writeln!(output, "{}:\n", filename)?;
+ writeln!(output, "{filename}:\n")?;
}
- write!(output, "{}", formatted_text)?;
+ write!(output, "{formatted_text}")?;
Ok(EmitterResult::default())
}
}
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 03cdddc41..fa941e614 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::cmp::min;
use itertools::Itertools;
-use rustc_ast::token::{Delimiter, LitKind};
+use rustc_ast::token::{Delimiter, Lit, LitKind};
use rustc_ast::{ast, ptr, token};
use rustc_span::{BytePos, Span};
@@ -26,6 +26,7 @@ use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::{Indent, Shape};
use crate::source_map::{LineRangeUtils, SpanUtils};
use crate::spanned::Spanned;
+use crate::stmt;
use crate::string::{rewrite_string, StringFormat};
use crate::types::{rewrite_path, PathContext};
use crate::utils::{
@@ -48,6 +49,10 @@ pub(crate) enum ExprType {
SubExpression,
}
+pub(crate) fn lit_ends_in_dot(lit: &Lit) -> bool {
+ matches!(lit, Lit { kind: LitKind::Float, suffix: None, symbol } if symbol.as_str().ends_with('.'))
+}
+
pub(crate) fn format_expr(
expr: &ast::Expr,
expr_type: ExprType,
@@ -127,7 +132,7 @@ pub(crate) fn format_expr(
ast::ExprKind::Tup(ref items) => {
rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1)
}
- ast::ExprKind::Let(..) => None,
+ ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr),
ast::ExprKind::If(..)
| ast::ExprKind::ForLoop(..)
| ast::ExprKind::Loop(..)
@@ -182,7 +187,7 @@ pub(crate) fn format_expr(
Some(label) => format!(" {}", label.ident),
None => String::new(),
};
- Some(format!("continue{}", id_str))
+ Some(format!("continue{id_str}"))
}
ast::ExprKind::Break(ref opt_label, ref opt_expr) => {
let id_str = match *opt_label {
@@ -191,9 +196,9 @@ pub(crate) fn format_expr(
};
if let Some(ref expr) = *opt_expr {
- rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape)
+ rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape)
} else {
- Some(format!("break{}", id_str))
+ Some(format!("break{id_str}"))
}
}
ast::ExprKind::Yield(ref opt_expr) => {
@@ -275,12 +280,7 @@ pub(crate) fn format_expr(
fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bool {
match lhs.kind {
- ast::ExprKind::Lit(token_lit) => match token_lit.kind {
- token::LitKind::Float if token_lit.suffix.is_none() => {
- context.snippet(lhs.span).ends_with('.')
- }
- _ => false,
- },
+ ast::ExprKind::Lit(token_lit) => lit_ends_in_dot(&token_lit),
ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
_ => false,
}
@@ -309,7 +309,7 @@ pub(crate) fn format_expr(
match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) {
(Some(lhs), Some(rhs)) => {
let sp_delim = if context.config.spaces_around_ranges() {
- format!(" {} ", delim)
+ format!(" {delim} ")
} else {
default_sp_delim(Some(lhs), Some(rhs))
};
@@ -324,7 +324,7 @@ pub(crate) fn format_expr(
}
(None, Some(rhs)) => {
let sp_delim = if context.config.spaces_around_ranges() {
- format!("{} ", delim)
+ format!("{delim} ")
} else {
default_sp_delim(None, Some(rhs))
};
@@ -332,7 +332,7 @@ pub(crate) fn format_expr(
}
(Some(lhs), None) => {
let sp_delim = if context.config.spaces_around_ranges() {
- format!(" {}", delim)
+ format!(" {delim}")
} else {
default_sp_delim(Some(lhs), None)
};
@@ -367,15 +367,15 @@ pub(crate) fn format_expr(
))
}
}
- ast::ExprKind::Async(capture_by, ref block) => {
- let mover = if capture_by == ast::CaptureBy::Value {
+ ast::ExprKind::Gen(capture_by, ref block, ref kind) => {
+ let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
"move "
} else {
""
};
if let rw @ Some(_) = rewrite_single_line_block(
context,
- format!("{}{}", "async ", mover).as_str(),
+ format!("{kind} {mover}").as_str(),
block,
Some(&expr.attrs),
None,
@@ -386,9 +386,7 @@ pub(crate) fn format_expr(
// 6 = `async `
let budget = shape.width.saturating_sub(6);
Some(format!(
- "{}{}{}",
- "async ",
- mover,
+ "{kind} {mover}{}",
rewrite_block(
block,
Some(&expr.attrs),
@@ -460,7 +458,7 @@ fn rewrite_empty_block(
}
if !block_contains_comment(context, block) && shape.width >= 2 {
- return Some(format!("{}{}{{}}", prefix, label_str));
+ return Some(format!("{prefix}{label_str}{{}}"));
}
// If a block contains only a single-line comment, then leave it on one line.
@@ -473,7 +471,7 @@ fn rewrite_empty_block(
&& !comment_str.starts_with("//")
&& comment_str.len() + 4 <= shape.width
{
- return Some(format!("{}{}{{ {} }}", prefix, label_str, comment_str));
+ return Some(format!("{prefix}{label_str}{{ {comment_str} }}"));
}
}
@@ -516,11 +514,11 @@ fn rewrite_single_line_block(
label: Option<ast::Label>,
shape: Shape,
) -> Option<String> {
- if is_simple_block(context, block, attrs) {
+ if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) {
let expr_shape = shape.offset_left(last_line_width(prefix))?;
- let expr_str = block.stmts[0].rewrite(context, expr_shape)?;
+ let expr_str = block_expr.rewrite(context, expr_shape)?;
let label_str = rewrite_label(label);
- let result = format!("{}{}{{ {} }}", prefix, label_str, expr_str);
+ let result = format!("{prefix}{label_str}{{ {expr_str} }}");
if result.len() <= shape.width && !result.contains('\n') {
return Some(result);
}
@@ -800,19 +798,19 @@ impl<'a> ControlFlow<'a> {
let fixed_cost = self.keyword.len() + " { } else { }".len();
if let ast::ExprKind::Block(ref else_node, _) = else_block.kind {
- if !is_simple_block(context, self.block, None)
- || !is_simple_block(context, else_node, None)
- || pat_expr_str.contains('\n')
- {
- return None;
- }
+ let (if_expr, else_expr) = match (
+ stmt::Stmt::from_simple_block(context, self.block, None),
+ stmt::Stmt::from_simple_block(context, else_node, None),
+ pat_expr_str.contains('\n'),
+ ) {
+ (Some(if_expr), Some(else_expr), false) => (if_expr, else_expr),
+ _ => return None,
+ };
let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?;
- let expr = &self.block.stmts[0];
- let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?;
+ let if_str = if_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?;
let new_width = new_width.checked_sub(if_str.len())?;
- let else_expr = &else_node.stmts[0];
let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?;
if if_str.contains('\n') || else_str.contains('\n') {
@@ -1100,7 +1098,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
result?
};
- let mut result = format!("{}{}", cond_str, block_str);
+ let mut result = format!("{cond_str}{block_str}");
if let Some(else_block) = self.else_block {
let shape = Shape::indented(shape.indent, context.config);
@@ -1160,8 +1158,7 @@ fn rewrite_label(opt_label: Option<ast::Label>) -> Cow<'static, str> {
fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match rewrite_missing_comment(span, shape, context) {
Some(ref comment) if !comment.is_empty() => Some(format!(
- "{indent}{}{indent}",
- comment,
+ "{indent}{comment}{indent}",
indent = shape.indent.to_string_with_newline(context.config)
)),
_ => None,
@@ -1374,7 +1371,7 @@ pub(crate) fn can_be_overflowed_expr(
}
// Handle always block-like expressions
- ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true,
+ ast::ExprKind::Gen(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true,
// Handle `[]` and `{}`-like expressions
ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => {
@@ -1436,7 +1433,7 @@ pub(crate) fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) ->
result
}
-fn rewrite_paren(
+pub(crate) fn rewrite_paren(
context: &RewriteContext<'_>,
mut subexpr: &ast::Expr,
shape: Shape,
@@ -1452,7 +1449,7 @@ fn rewrite_paren(
let remove_nested_parens = context.config.remove_nested_parens();
loop {
// 1 = "(" or ")"
- pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span.lo());
+ pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span().lo());
post_span = mk_sp(subexpr.span.hi(), span.hi() - BytePos(1));
pre_comment = rewrite_missing_comment(pre_span, shape, context)?;
post_comment = rewrite_missing_comment(post_span, shape, context)?;
@@ -1474,7 +1471,7 @@ fn rewrite_paren(
let subexpr_str = subexpr.rewrite(context, sub_shape)?;
let fits_single_line = !pre_comment.contains("//") && !post_comment.contains("//");
if fits_single_line {
- Some(format!("({}{}{})", pre_comment, subexpr_str, post_comment))
+ Some(format!("({pre_comment}{subexpr_str}{post_comment})"))
} else {
rewrite_paren_in_multi_line(context, subexpr, shape, pre_span, post_span)
}
@@ -1538,7 +1535,7 @@ fn rewrite_index(
// Return if index fits in a single line.
match orig_index_rw {
Some(ref index_str) if !index_str.contains('\n') => {
- return Some(format!("{}[{}]", expr_str, index_str));
+ return Some(format!("{expr_str}[{index_str}]"));
}
_ => (),
}
@@ -1561,7 +1558,7 @@ fn rewrite_index(
indent.to_string_with_newline(context.config),
new_index_str,
)),
- (Some(ref index_str), _) => Some(format!("{}[{}]", expr_str, index_str)),
+ (Some(ref index_str), _) => Some(format!("{expr_str}[{index_str}]")),
_ => None,
}
}
@@ -1593,9 +1590,9 @@ fn rewrite_struct_lit<'a>(
let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
let has_base_or_rest = match struct_rest {
- ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
+ ast::StructRest::None if fields.is_empty() => return Some(format!("{path_str} {{}}")),
ast::StructRest::Rest(_) if fields.is_empty() => {
- return Some(format!("{} {{ .. }}", path_str));
+ return Some(format!("{path_str} {{ .. }}"));
}
ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true,
_ => false,
@@ -1686,7 +1683,7 @@ fn rewrite_struct_lit<'a>(
let fields_str =
wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
- Some(format!("{} {{{}}}", path_str, fields_str))
+ Some(format!("{path_str} {{{fields_str}}}"))
// FIXME if context.config.indent_style() == Visual, but we run out
// of space, we should fall back to BlockIndent.
@@ -1716,7 +1713,7 @@ pub(crate) fn wrap_struct_field(
))
} else {
// One liner or visual indent.
- Some(format!(" {} ", fields_str))
+ Some(format!(" {fields_str} "))
}
} else {
Some(format!(
@@ -1765,7 +1762,7 @@ pub(crate) fn rewrite_field(
{
Some(attrs_str + name)
}
- Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)),
+ Some(e) => Some(format!("{attrs_str}{name}{separator}{e}")),
None => {
let expr_offset = shape.indent.block_indent(context.config);
let expr = field
@@ -1830,7 +1827,41 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>(
.ends_with_newline(false);
let list_str = write_list(&item_vec, &fmt)?;
- Some(format!("({})", list_str))
+ Some(format!("({list_str})"))
+}
+
+fn rewrite_let(
+ context: &RewriteContext<'_>,
+ shape: Shape,
+ pat: &ast::Pat,
+ expr: &ast::Expr,
+) -> Option<String> {
+ let mut result = "let ".to_owned();
+
+ // TODO(ytmimi) comments could appear between `let` and the `pat`
+
+ // 4 = "let ".len()
+ let pat_shape = shape.offset_left(4)?;
+ let pat_str = pat.rewrite(context, pat_shape)?;
+ result.push_str(&pat_str);
+
+ // TODO(ytmimi) comments could appear between `pat` and `=`
+ result.push_str(" =");
+
+ let comments_lo = context
+ .snippet_provider
+ .span_after(expr.span.with_lo(pat.span.hi()), "=");
+ let comments_span = mk_sp(comments_lo, expr.span.lo());
+ rewrite_assign_rhs_with_comments(
+ context,
+ result,
+ expr,
+ shape,
+ &RhsAssignKind::Expr(&expr.kind, expr.span),
+ RhsTactics::Default,
+ comments_span,
+ true,
+ )
}
pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>(
@@ -2072,7 +2103,7 @@ fn choose_rhs<R: Rewrite>(
Some(ref new_str)
if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
{
- Some(format!(" {}", new_str))
+ Some(format!(" {new_str}"))
}
_ => {
// Expression did not fit on the same line as the identifier.
@@ -2089,21 +2120,21 @@ fn choose_rhs<R: Rewrite>(
(Some(ref orig_rhs), Some(ref new_rhs))
if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) =>
{
- Some(format!("{}{}", before_space_str, orig_rhs))
+ Some(format!("{before_space_str}{orig_rhs}"))
}
(Some(ref orig_rhs), Some(ref new_rhs))
if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) =>
{
- Some(format!("{}{}", new_indent_str, new_rhs))
+ Some(format!("{new_indent_str}{new_rhs}"))
}
- (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)),
+ (None, Some(ref new_rhs)) => Some(format!("{new_indent_str}{new_rhs}")),
(None, None) if rhs_tactics == RhsTactics::AllowOverflow => {
let shape = shape.infinite_width();
expr.rewrite(context, shape)
.map(|s| format!("{}{}", before_space_str, s))
}
(None, None) => None,
- (Some(orig_rhs), _) => Some(format!("{}{}", before_space_str, orig_rhs)),
+ (Some(orig_rhs), _) => Some(format!("{before_space_str}{orig_rhs}")),
}
}
}
diff --git a/src/tools/rustfmt/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs
index f6b739e1c..61e2cb711 100644
--- a/src/tools/rustfmt/src/format-diff/main.rs
+++ b/src/tools/rustfmt/src/format-diff/main.rs
@@ -5,11 +5,12 @@
#![deny(warnings)]
#[macro_use]
-extern crate log;
+extern crate tracing;
use serde::{Deserialize, Serialize};
use serde_json as json;
use thiserror::Error;
+use tracing_subscriber::EnvFilter;
use std::collections::HashSet;
use std::env;
@@ -63,10 +64,12 @@ pub struct Opts {
}
fn main() {
- env_logger::Builder::from_env("RUSTFMT_LOG").init();
+ tracing_subscriber::fmt()
+ .with_env_filter(EnvFilter::from_env("RUSTFMT_LOG"))
+ .init();
let opts = Opts::parse();
if let Err(e) = run(opts) {
- println!("{}", e);
+ println!("{e}");
Opts::command()
.print_help()
.expect("cannot write to stdout");
@@ -110,7 +113,7 @@ fn run_rustfmt(files: &HashSet<String>, ranges: &[Range]) -> Result<(), FormatDi
if !exit_status.success() {
return Err(FormatDiffError::IoError(io::Error::new(
io::ErrorKind::Other,
- format!("rustfmt failed with {}", exit_status),
+ format!("rustfmt failed with {exit_status}"),
)));
}
Ok(())
@@ -126,12 +129,12 @@ fn scan_diff<R>(
where
R: io::Read,
{
- let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix);
+ let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{skip_prefix}}}(\S*)");
let diff_pattern = Regex::new(&diff_pattern).unwrap();
let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap();
- let file_filter = Regex::new(&format!("^{}$", file_filter))?;
+ let file_filter = Regex::new(&format!("^{file_filter}$"))?;
let mut current_file = None;
diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index 1f4ad6960..cd57a025b 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/src/formatting.rs
@@ -296,7 +296,7 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> {
Ok(ref result) if result.has_diff => report.add_diff(),
Err(e) => {
// Create a new error with path_str to help users see which files failed
- let err_msg = format!("{}: {}", path, e);
+ let err_msg = format!("{path}: {e}");
return Err(io::Error::new(e.kind(), err_msg).into());
}
_ => {}
diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs
index 579778edb..3059d917c 100644
--- a/src/tools/rustfmt/src/git-rustfmt/main.rs
+++ b/src/tools/rustfmt/src/git-rustfmt/main.rs
@@ -1,5 +1,5 @@
#[macro_use]
-extern crate log;
+extern crate tracing;
use std::env;
use std::io::stdout;
@@ -9,6 +9,7 @@ use std::str::FromStr;
use getopts::{Matches, Options};
use rustfmt_nightly as rustfmt;
+use tracing_subscriber::EnvFilter;
use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session};
@@ -42,7 +43,7 @@ fn git_diff(commits: &str) -> String {
let mut cmd = Command::new("git");
cmd.arg("diff");
if commits != "0" {
- cmd.arg(format!("HEAD~{}", commits));
+ cmd.arg(format!("HEAD~{commits}"));
}
let output = cmd.output().expect("Couldn't execute `git diff`");
String::from_utf8_lossy(&output.stdout).into_owned()
@@ -107,7 +108,7 @@ fn check_uncommitted() {
if !uncommitted.is_empty() {
println!("Found untracked changes:");
for f in &uncommitted {
- println!(" {}", f);
+ println!(" {f}");
}
println!("Commit your work, or run with `-u`.");
println!("Exiting.");
@@ -170,7 +171,9 @@ impl Config {
}
fn main() {
- env_logger::Builder::from_env("RUSTFMT_LOG").init();
+ tracing_subscriber::fmt()
+ .with_env_filter(EnvFilter::from_env("RUSTFMT_LOG"))
+ .init();
let opts = make_opts();
let matches = opts
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index 339e5cef5..f8e7fa628 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -191,7 +191,7 @@ impl UseSegment {
"crate" => UseSegmentKind::Crate(None),
_ => {
let mod_sep = if modsep { "::" } else { "" };
- UseSegmentKind::Ident(format!("{}{}", mod_sep, name), None)
+ UseSegmentKind::Ident(format!("{mod_sep}{name}"), None)
}
};
@@ -295,8 +295,8 @@ impl fmt::Display for UseSegmentKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
UseSegmentKind::Glob => write!(f, "*"),
- UseSegmentKind::Ident(ref s, Some(ref alias)) => write!(f, "{} as {}", s, alias),
- UseSegmentKind::Ident(ref s, None) => write!(f, "{}", s),
+ UseSegmentKind::Ident(ref s, Some(ref alias)) => write!(f, "{s} as {alias}"),
+ UseSegmentKind::Ident(ref s, None) => write!(f, "{s}"),
UseSegmentKind::Slf(..) => write!(f, "self"),
UseSegmentKind::Super(..) => write!(f, "super"),
UseSegmentKind::Crate(..) => write!(f, "crate"),
@@ -306,7 +306,7 @@ impl fmt::Display for UseSegmentKind {
if i != 0 {
write!(f, ", ")?;
}
- write!(f, "{}", item)?;
+ write!(f, "{item}")?;
}
write!(f, "}}")
}
@@ -319,7 +319,7 @@ impl fmt::Display for UseTree {
if i != 0 {
write!(f, "::")?;
}
- write!(f, "{}", segment)?;
+ write!(f, "{segment}")?;
}
Ok(())
}
@@ -589,7 +589,7 @@ impl UseTree {
// Normalise foo::{bar} -> foo::bar
if let UseSegmentKind::List(ref list) = last.kind {
- if list.len() == 1 && list[0].to_string() != "self" {
+ if list.len() == 1 && list[0].to_string() != "self" && !list[0].has_comment() {
normalize_sole_list = true;
}
}
@@ -1032,7 +1032,9 @@ fn rewrite_nested_use_tree(
let list_str = write_list(&list_items, &fmt)?;
- let result = if (list_str.contains('\n') || list_str.len() > remaining_width)
+ let result = if (list_str.contains('\n')
+ || list_str.len() > remaining_width
+ || tactic == DefinitiveListTactic::Vertical)
&& context.config.imports_indent() == IndentStyle::Block
{
format!(
@@ -1042,7 +1044,7 @@ fn rewrite_nested_use_tree(
shape.indent.to_string(context.config)
)
} else {
- format!("{{{}}}", list_str)
+ format!("{{{list_str}}}")
};
Some(result)
@@ -1052,14 +1054,14 @@ impl Rewrite for UseSegment {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
Some(match self.kind {
UseSegmentKind::Ident(ref ident, Some(ref rename)) => {
- format!("{} as {}", ident, rename)
+ format!("{ident} as {rename}")
}
UseSegmentKind::Ident(ref ident, None) => ident.clone(),
- UseSegmentKind::Slf(Some(ref rename)) => format!("self as {}", rename),
+ UseSegmentKind::Slf(Some(ref rename)) => format!("self as {rename}"),
UseSegmentKind::Slf(None) => "self".to_owned(),
- UseSegmentKind::Super(Some(ref rename)) => format!("super as {}", rename),
+ UseSegmentKind::Super(Some(ref rename)) => format!("super as {rename}"),
UseSegmentKind::Super(None) => "super".to_owned(),
- UseSegmentKind::Crate(Some(ref rename)) => format!("crate as {}", rename),
+ UseSegmentKind::Crate(Some(ref rename)) => format!("crate as {rename}"),
UseSegmentKind::Crate(None) => "crate".to_owned(),
UseSegmentKind::Glob => "*".to_owned(),
UseSegmentKind::List(ref use_tree_list) => rewrite_nested_use_tree(
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index d5bc38303..edb5a5b62 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -75,6 +75,7 @@ impl Rewrite for ast::Local {
false,
)?
};
+ let let_kw_offset = result.len() - "let ".len();
// 4 = "let ".len()
let pat_shape = shape.offset_left(4)?;
@@ -127,8 +128,15 @@ impl Rewrite for ast::Local {
if let Some(block) = else_block {
let else_kw_span = init.span.between(block.span);
+ // Strip attributes and comments to check if newline is needed before the else
+ // keyword from the initializer part. (#5901)
+ let init_str = if context.config.version() == Version::Two {
+ &result[let_kw_offset..]
+ } else {
+ result.as_str()
+ };
let force_newline_else = pat_str.contains('\n')
- || !same_line_else_kw_and_brace(&result, context, else_kw_span, nested_shape);
+ || !same_line_else_kw_and_brace(init_str, context, else_kw_span, nested_shape);
let else_kw = rewrite_else_kw_with_comments(
force_newline_else,
true,
@@ -146,11 +154,16 @@ impl Rewrite for ast::Local {
std::cmp::min(shape.width, context.config.single_line_let_else_max_width());
// If available_space hits zero we know for sure this will be a multi-lined block
- let available_space = max_width.saturating_sub(result.len());
+ let assign_str_with_else_kw = if context.config.version() == Version::Two {
+ &result[let_kw_offset..]
+ } else {
+ result.as_str()
+ };
+ let available_space = max_width.saturating_sub(assign_str_with_else_kw.len());
let allow_single_line = !force_newline_else
&& available_space > 0
- && allow_single_line_let_else_block(&result, block);
+ && allow_single_line_let_else_block(assign_str_with_else_kw, block);
let mut rw_else_block =
rewrite_let_else_block(block, allow_single_line, context, shape)?;
@@ -248,7 +261,6 @@ impl<'a> Item<'a> {
abi: format_extern(
ast::Extern::from_abi(fm.abi, DUMMY_SP),
config.force_explicit_abi(),
- true,
),
vis: None,
body: fm
@@ -306,22 +318,20 @@ impl<'a> FnSig<'a> {
defaultness: ast::Defaultness,
) -> FnSig<'a> {
match *fn_kind {
- visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, generics, _) => match fn_ctxt {
- visit::FnCtxt::Assoc(..) => {
- let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
- fn_sig.defaultness = defaultness;
- fn_sig
- }
- _ => FnSig {
- decl,
- generics,
- ext: fn_sig.header.ext,
- constness: fn_sig.header.constness,
- is_async: Cow::Borrowed(&fn_sig.header.asyncness),
- defaultness,
- unsafety: fn_sig.header.unsafety,
- visibility: vis,
- },
+ visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, fn_sig, vis, generics, _) => {
+ let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
+ fn_sig.defaultness = defaultness;
+ fn_sig
+ }
+ visit::FnKind::Fn(_, _, fn_sig, vis, generics, _) => FnSig {
+ decl,
+ generics,
+ ext: fn_sig.header.ext,
+ constness: fn_sig.header.constness,
+ is_async: Cow::Borrowed(&fn_sig.header.asyncness),
+ defaultness,
+ unsafety: fn_sig.header.unsafety,
+ visibility: vis,
},
_ => unreachable!(),
}
@@ -338,7 +348,6 @@ impl<'a> FnSig<'a> {
result.push_str(&format_extern(
self.ext,
context.config.force_explicit_abi(),
- false,
));
result
}
@@ -472,7 +481,7 @@ impl<'a> FmtVisitor<'a> {
&& self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width()
&& !last_line_contains_single_line_comment(fn_str)
{
- return Some(format!("{} {{}}", fn_str));
+ return Some(format!("{fn_str} {{}}"));
}
if !self.config.fn_single_line() || !is_simple_block_stmt(&context, block, None) {
@@ -484,7 +493,7 @@ impl<'a> FmtVisitor<'a> {
let width = self.block_indent.width() + fn_str.len() + res.len() + 5;
if !res.contains('\n') && width <= self.config.max_width() {
- Some(format!("{} {{ {} }}", fn_str, res))
+ Some(format!("{fn_str} {{ {res} }}"))
} else {
None
}
@@ -666,7 +675,7 @@ impl<'a> FmtVisitor<'a> {
};
let variant_body = if let Some(ref expr) = field.disr_expr {
- let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to);
+ let lhs = format!("{variant_body:pad_discrim_ident_to$} =");
let ex = &*expr.value;
rewrite_assign_rhs_with(
&context,
@@ -829,7 +838,7 @@ pub(crate) fn format_impl(
if generics.where_clause.predicates.len() == 1 {
result.push(',');
}
- result.push_str(&format!("{}{{{}}}", sep, sep));
+ result.push_str(&format!("{sep}{{{sep}}}"));
} else {
result.push_str(" {}");
}
@@ -1020,7 +1029,7 @@ fn rewrite_trait_ref(
let shape = Shape::indented(offset + used_space, context.config);
if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) {
if !trait_ref_str.contains('\n') {
- return Some(format!(" {}{}", polarity_str, trait_ref_str));
+ return Some(format!(" {polarity_str}{trait_ref_str}"));
}
}
// We could not make enough space for trait_ref, so put it on new line.
@@ -1118,172 +1127,172 @@ pub(crate) fn format_trait(
item: &ast::Item,
offset: Indent,
) -> Option<String> {
- if let ast::ItemKind::Trait(trait_kind) = &item.kind {
- let ast::Trait {
- is_auto,
- unsafety,
- ref generics,
- ref bounds,
- ref items,
- } = **trait_kind;
- let mut result = String::with_capacity(128);
- let header = format!(
- "{}{}{}trait ",
- format_visibility(context, &item.vis),
- format_unsafety(unsafety),
- format_auto(is_auto),
- );
- result.push_str(&header);
+ let ast::ItemKind::Trait(trait_kind) = &item.kind else {
+ unreachable!();
+ };
+ let ast::Trait {
+ is_auto,
+ unsafety,
+ ref generics,
+ ref bounds,
+ ref items,
+ } = **trait_kind;
- let body_lo = context.snippet_provider.span_after(item.span, "{");
+ let mut result = String::with_capacity(128);
+ let header = format!(
+ "{}{}{}trait ",
+ format_visibility(context, &item.vis),
+ format_unsafety(unsafety),
+ format_auto(is_auto),
+ );
+ result.push_str(&header);
- let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
- let generics_str =
- rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
- result.push_str(&generics_str);
+ let body_lo = context.snippet_provider.span_after(item.span, "{");
- // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
- if !bounds.is_empty() {
- let ident_hi = context
- .snippet_provider
- .span_after(item.span, item.ident.as_str());
- let bound_hi = bounds.last().unwrap().span().hi();
- let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
- if contains_comment(snippet) {
- return None;
- }
+ let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
+ let generics_str =
+ rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
+ result.push_str(&generics_str);
- result = rewrite_assign_rhs_with(
- context,
- result + ":",
- bounds,
- shape,
- &RhsAssignKind::Bounds,
- RhsTactics::ForceNextLineWithoutIndent,
- )?;
+ // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
+ if !bounds.is_empty() {
+ let ident_hi = context
+ .snippet_provider
+ .span_after(item.span, item.ident.as_str());
+ let bound_hi = bounds.last().unwrap().span().hi();
+ let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
+ if contains_comment(snippet) {
+ return None;
}
- // Rewrite where-clause.
- if !generics.where_clause.predicates.is_empty() {
- let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
+ result = rewrite_assign_rhs_with(
+ context,
+ result + ":",
+ bounds,
+ shape,
+ &RhsAssignKind::Bounds,
+ RhsTactics::ForceNextLineWithoutIndent,
+ )?;
+ }
+
+ // Rewrite where-clause.
+ if !generics.where_clause.predicates.is_empty() {
+ let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
- let where_budget = context.budget(last_line_width(&result));
- let pos_before_where = if bounds.is_empty() {
- generics.where_clause.span.lo()
+ let where_budget = context.budget(last_line_width(&result));
+ let pos_before_where = if bounds.is_empty() {
+ generics.where_clause.span.lo()
+ } else {
+ bounds[bounds.len() - 1].span().hi()
+ };
+ let option = WhereClauseOption::snuggled(&generics_str);
+ let where_clause_str = rewrite_where_clause(
+ context,
+ &generics.where_clause.predicates,
+ generics.where_clause.span,
+ context.config.brace_style(),
+ Shape::legacy(where_budget, offset.block_only()),
+ where_on_new_line,
+ "{",
+ None,
+ pos_before_where,
+ option,
+ )?;
+ // If the where-clause cannot fit on the same line,
+ // put the where-clause on a new line
+ if !where_clause_str.contains('\n')
+ && last_line_width(&result) + where_clause_str.len() + offset.width()
+ > context.config.comment_width()
+ {
+ let width = offset.block_indent + context.config.tab_spaces() - 1;
+ let where_indent = Indent::new(0, width);
+ result.push_str(&where_indent.to_string_with_newline(context.config));
+ }
+ result.push_str(&where_clause_str);
+ } else {
+ let item_snippet = context.snippet(item.span);
+ if let Some(lo) = item_snippet.find('/') {
+ // 1 = `{`
+ let comment_hi = if generics.params.len() > 0 {
+ generics.span.lo() - BytePos(1)
} else {
- bounds[bounds.len() - 1].span().hi()
+ body_lo - BytePos(1)
};
- let option = WhereClauseOption::snuggled(&generics_str);
- let where_clause_str = rewrite_where_clause(
- context,
- &generics.where_clause.predicates,
- generics.where_clause.span,
- context.config.brace_style(),
- Shape::legacy(where_budget, offset.block_only()),
- where_on_new_line,
- "{",
- None,
- pos_before_where,
- option,
- )?;
- // If the where-clause cannot fit on the same line,
- // put the where-clause on a new line
- if !where_clause_str.contains('\n')
- && last_line_width(&result) + where_clause_str.len() + offset.width()
- > context.config.comment_width()
- {
- let width = offset.block_indent + context.config.tab_spaces() - 1;
- let where_indent = Indent::new(0, width);
- result.push_str(&where_indent.to_string_with_newline(context.config));
- }
- result.push_str(&where_clause_str);
- } else {
- let item_snippet = context.snippet(item.span);
- if let Some(lo) = item_snippet.find('/') {
- // 1 = `{`
- let comment_hi = if generics.params.len() > 0 {
- generics.span.lo() - BytePos(1)
- } else {
- body_lo - BytePos(1)
- };
- let comment_lo = item.span.lo() + BytePos(lo as u32);
- if comment_lo < comment_hi {
- match recover_missing_comment_in_span(
- mk_sp(comment_lo, comment_hi),
- Shape::indented(offset, context.config),
- context,
- last_line_width(&result),
- ) {
- Some(ref missing_comment) if !missing_comment.is_empty() => {
- result.push_str(missing_comment);
- }
- _ => (),
+ let comment_lo = item.span.lo() + BytePos(lo as u32);
+ if comment_lo < comment_hi {
+ match recover_missing_comment_in_span(
+ mk_sp(comment_lo, comment_hi),
+ Shape::indented(offset, context.config),
+ context,
+ last_line_width(&result),
+ ) {
+ Some(ref missing_comment) if !missing_comment.is_empty() => {
+ result.push_str(missing_comment);
}
+ _ => (),
}
}
}
+ }
- let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
- let snippet = context.snippet(block_span);
- let open_pos = snippet.find_uncommented("{")? + 1;
+ let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+ let snippet = context.snippet(block_span);
+ let open_pos = snippet.find_uncommented("{")? + 1;
- match context.config.brace_style() {
- _ if last_line_contains_single_line_comment(&result)
- || last_line_width(&result) + 2 > context.budget(offset.width()) =>
- {
- result.push_str(&offset.to_string_with_newline(context.config));
- }
- _ if context.config.empty_item_single_line()
- && items.is_empty()
- && !result.contains('\n')
- && !contains_comment(&snippet[open_pos..]) =>
+ match context.config.brace_style() {
+ _ if last_line_contains_single_line_comment(&result)
+ || last_line_width(&result) + 2 > context.budget(offset.width()) =>
+ {
+ result.push_str(&offset.to_string_with_newline(context.config));
+ }
+ _ if context.config.empty_item_single_line()
+ && items.is_empty()
+ && !result.contains('\n')
+ && !contains_comment(&snippet[open_pos..]) =>
+ {
+ result.push_str(" {}");
+ return Some(result);
+ }
+ BraceStyle::AlwaysNextLine => {
+ result.push_str(&offset.to_string_with_newline(context.config));
+ }
+ BraceStyle::PreferSameLine => result.push(' '),
+ BraceStyle::SameLineWhere => {
+ if result.contains('\n')
+ || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
{
- result.push_str(" {}");
- return Some(result);
- }
- BraceStyle::AlwaysNextLine => {
result.push_str(&offset.to_string_with_newline(context.config));
- }
- BraceStyle::PreferSameLine => result.push(' '),
- BraceStyle::SameLineWhere => {
- if result.contains('\n')
- || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
- {
- result.push_str(&offset.to_string_with_newline(context.config));
- } else {
- result.push(' ');
- }
+ } else {
+ result.push(' ');
}
}
- result.push('{');
-
- let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
+ }
+ result.push('{');
- if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
- let mut visitor = FmtVisitor::from_context(context);
- visitor.block_indent = offset.block_only().block_indent(context.config);
- visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
+ let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
- for item in items {
- visitor.visit_trait_item(item);
- }
+ if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
+ let mut visitor = FmtVisitor::from_context(context);
+ visitor.block_indent = offset.block_only().block_indent(context.config);
+ visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
- visitor.format_missing(item.span.hi() - BytePos(1));
+ for item in items {
+ visitor.visit_trait_item(item);
+ }
- let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
+ visitor.format_missing(item.span.hi() - BytePos(1));
- result.push_str(&inner_indent_str);
- result.push_str(visitor.buffer.trim());
- result.push_str(&outer_indent_str);
- } else if result.contains('\n') {
- result.push_str(&outer_indent_str);
- }
+ let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
- result.push('}');
- Some(result)
- } else {
- unreachable!();
+ result.push_str(&inner_indent_str);
+ result.push_str(visitor.buffer.trim());
+ result.push_str(&outer_indent_str);
+ } else if result.contains('\n') {
+ result.push_str(&outer_indent_str);
}
+
+ result.push('}');
+ Some(result)
}
pub(crate) struct TraitAliasBounds<'a> {
@@ -1322,7 +1331,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
shape.indent.to_string_with_newline(context.config)
};
- Some(format!("{}{}{}", generic_bounds_str, space, where_str))
+ Some(format!("{generic_bounds_str}{space}{where_str}"))
}
}
@@ -1339,7 +1348,7 @@ pub(crate) fn format_trait_alias(
let g_shape = shape.offset_left(6)?.sub_width(2)?;
let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
let vis_str = format_visibility(context, vis);
- let lhs = format!("{}trait {} =", vis_str, generics_str);
+ let lhs = format!("{vis_str}trait {generics_str} =");
// 1 = ";"
let trait_alias_bounds = TraitAliasBounds {
generic_bounds,
@@ -1376,7 +1385,7 @@ fn format_unit_struct(
} else {
String::new()
};
- Some(format!("{}{};", header_str, generics_str))
+ Some(format!("{header_str}{generics_str};"))
}
pub(crate) fn format_struct_struct(
@@ -1466,7 +1475,7 @@ pub(crate) fn format_struct_struct(
&& items_str.len() <= one_line_budget
&& !last_line_contains_single_line_comment(&items_str)
{
- Some(format!("{} {} }}", result, items_str))
+ Some(format!("{result} {items_str} }}"))
} else {
Some(format!(
"{}\n{}{}\n{}}}",
@@ -1696,7 +1705,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
}?;
match defaultness {
- ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+ ast::Defaultness::Default(..) => Some(format!("default {result}")),
_ => Some(result),
}
}
@@ -1803,14 +1812,14 @@ fn rewrite_ty<R: Rewrite>(
true,
)?
}
- _ => format!("{}=", result),
+ _ => format!("{result}="),
};
// 1 = `;`
let shape = Shape::indented(indent, context.config).sub_width(1)?;
rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
} else {
- Some(format!("{};", result))
+ Some(format!("{result};"))
}
}
@@ -2019,7 +2028,7 @@ fn rewrite_static(
let expr_lo = expr.span.lo();
let comments_span = mk_sp(comments_lo, expr_lo);
- let lhs = format!("{}{} =", prefix, ty_str);
+ let lhs = format!("{prefix}{ty_str} =");
// 1 = ;
let remaining_width = context.budget(offset.block_indent + 1);
@@ -2036,7 +2045,7 @@ fn rewrite_static(
.and_then(|res| recover_comment_removed(res, static_parts.span, context))
.map(|s| if s.ends_with(';') { s } else { s + ";" })
} else {
- Some(format!("{}{};", prefix, ty_str))
+ Some(format!("{prefix}{ty_str};"))
}
}
@@ -2229,7 +2238,7 @@ fn rewrite_explicit_self(
Some(combine_strs_with_missing_comments(
context,
param_attrs,
- &format!("&{} {}self", lifetime_str, mut_str),
+ &format!("&{lifetime_str} {mut_str}self"),
span,
shape,
!has_multiple_attr_lines,
@@ -2238,7 +2247,7 @@ fn rewrite_explicit_self(
None => Some(combine_strs_with_missing_comments(
context,
param_attrs,
- &format!("&{}self", mut_str),
+ &format!("&{mut_str}self"),
span,
shape,
!has_multiple_attr_lines,
@@ -2599,7 +2608,8 @@ fn rewrite_fn_base(
if where_clause_str.is_empty() {
if let ast::FnRetTy::Default(ret_span) = fd.output {
match recover_missing_comment_in_span(
- mk_sp(params_span.hi(), ret_span.hi()),
+ // from after the closing paren to right before block or semicolon
+ mk_sp(ret_span.lo(), span.hi()),
shape,
context,
last_line_width(&result),
@@ -2908,7 +2918,7 @@ fn rewrite_where_clause_rfc_style(
clause_shape.indent.to_string_with_newline(context.config)
};
- Some(format!("{}{}{}", where_keyword, clause_sep, preds_str))
+ Some(format!("{where_keyword}{clause_sep}{preds_str}"))
}
/// Rewrite `where` and comment around it.
@@ -2948,8 +2958,8 @@ fn rewrite_where_keyword(
let newline_before_where = comment_separator(&comment_before, shape);
let newline_after_where = comment_separator(&comment_after, clause_shape);
let result = format!(
- "{}{}{}where{}{}",
- starting_newline, comment_before, newline_before_where, newline_after_where, comment_after
+ "{starting_newline}{comment_before}{newline_before_where}where\
+{newline_after_where}{comment_after}"
);
let allow_single_line = where_clause_option.allow_single_line
&& comment_before.is_empty()
@@ -3000,10 +3010,12 @@ fn rewrite_bounds_on_where_clause(
DefinitiveListTactic::Vertical
};
+ let preserve_newline = context.config.version() == Version::One;
+
let fmt = ListFormatting::new(shape, context.config)
.tactic(shape_tactic)
.trailing_separator(comma_tactic)
- .preserve_newline(true);
+ .preserve_newline(preserve_newline);
write_list(&items.collect::<Vec<_>>(), &fmt)
}
@@ -3104,7 +3116,7 @@ fn rewrite_where_clause(
preds_str
))
} else {
- Some(format!(" where {}", preds_str))
+ Some(format!(" where {preds_str}"))
}
}
@@ -3233,7 +3245,7 @@ fn format_generics(
if brace_pos == BracePos::None {
span.hi()
} else {
- context.snippet_provider.span_before(span, "{")
+ context.snippet_provider.span_before_last(span, "{")
},
),
shape,
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 567628f63..877d057a3 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -9,7 +9,7 @@
#[macro_use]
extern crate lazy_static;
#[macro_use]
-extern crate log;
+extern crate tracing;
// N.B. these crates are loaded from the sysroot, so they need extern crate.
extern crate rustc_ast;
@@ -29,6 +29,7 @@ extern crate thin_vec;
extern crate rustc_driver;
use std::cell::RefCell;
+use std::cmp::min;
use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
@@ -386,9 +387,15 @@ fn format_code_block(
.snippet
.rfind('}')
.unwrap_or_else(|| formatted.snippet.len());
+
+ // It's possible that `block_len < FN_MAIN_PREFIX.len()`. This can happen if the code block was
+ // formatted into the empty string, leading to the enclosing `fn main() {\n}` being formatted
+ // into `fn main() {}`. In this case no unindentation is done.
+ let block_start = min(FN_MAIN_PREFIX.len(), block_len);
+
let mut is_indented = true;
let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config);
- for (kind, ref line) in LineClasses::new(&formatted.snippet[FN_MAIN_PREFIX.len()..block_len]) {
+ for (kind, ref line) in LineClasses::new(&formatted.snippet[block_start..block_len]) {
if !is_first {
result.push('\n');
} else {
diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs
index a878e6cf9..41afef279 100644
--- a/src/tools/rustfmt/src/lists.rs
+++ b/src/tools/rustfmt/src/lists.rs
@@ -637,7 +637,7 @@ pub(crate) fn extract_post_comment(
post_snippet.trim_matches(white_space)
}
// not comment or over two lines
- else if post_snippet.ends_with(',')
+ else if post_snippet.ends_with(separator)
&& (!post_snippet.trim().starts_with("//") || post_snippet.trim().contains('\n'))
{
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 4f45d0c74..76553466e 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -103,7 +103,7 @@ fn rewrite_macro_name(
format!("{}!", pprust::path_to_string(path))
};
match extra_ident {
- Some(ident) if ident.name != kw::Empty => format!("{} {}", name, ident),
+ Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"),
_ => name,
}
}
@@ -214,14 +214,14 @@ fn rewrite_macro_inner(
if ts.is_empty() && !has_comment {
return match style {
Delimiter::Parenthesis if position == MacroPosition::Item => {
- Some(format!("{}();", macro_name))
+ Some(format!("{macro_name}();"))
}
Delimiter::Bracket if position == MacroPosition::Item => {
- Some(format!("{}[];", macro_name))
+ Some(format!("{macro_name}[];"))
}
- Delimiter::Parenthesis => Some(format!("{}()", macro_name)),
- Delimiter::Bracket => Some(format!("{}[]", macro_name)),
- Delimiter::Brace => Some(format!("{} {{}}", macro_name)),
+ Delimiter::Parenthesis => Some(format!("{macro_name}()")),
+ Delimiter::Bracket => Some(format!("{macro_name}[]")),
+ Delimiter::Brace => Some(format!("{macro_name} {{}}")),
_ => unreachable!(),
};
}
@@ -255,6 +255,7 @@ fn rewrite_macro_inner(
&macro_name,
shape,
style,
+ original_style,
position,
mac.span(),
);
@@ -295,20 +296,19 @@ fn rewrite_macro_inner(
// If we are rewriting `vec!` macro or other special macros,
// then we can rewrite this as a usual array literal.
// Otherwise, we must preserve the original existence of trailing comma.
- let macro_name = &macro_name.as_str();
let mut force_trailing_comma = if trailing_comma {
Some(SeparatorTactic::Always)
} else {
Some(SeparatorTactic::Never)
};
- if FORCED_BRACKET_MACROS.contains(macro_name) && !is_nested_macro {
+ if is_forced_bracket && !is_nested_macro {
context.leave_macro();
if context.use_block_indent() {
force_trailing_comma = Some(SeparatorTactic::Vertical);
};
}
let rewrite = rewrite_array(
- macro_name,
+ &macro_name,
arg_vec.iter(),
mac.span(),
context,
@@ -321,7 +321,7 @@ fn rewrite_macro_inner(
_ => "",
};
- Some(format!("{}{}", rewrite, comma))
+ Some(format!("{rewrite}{comma}"))
}
}
Delimiter::Brace => {
@@ -330,8 +330,8 @@ fn rewrite_macro_inner(
// anything in between the braces (for now).
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
match trim_left_preserve_layout(snippet, shape.indent, context.config) {
- Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
- None => Some(format!("{} {}", macro_name, snippet)),
+ Some(macro_body) => Some(format!("{macro_name} {macro_body}")),
+ None => Some(format!("{macro_name} {snippet}")),
}
}
_ => unreachable!(),
@@ -362,7 +362,7 @@ fn handle_vec_semi(
&& lhs.len() + rhs.len() + total_overhead <= shape.width
{
// macro_name(lhs; rhs) or macro_name[lhs; rhs]
- Some(format!("{}{}{}; {}{}", macro_name, left, lhs, rhs, right))
+ Some(format!("{macro_name}{left}{lhs}; {rhs}{right}"))
} else {
// macro_name(\nlhs;\nrhs\n) or macro_name[\nlhs;\nrhs\n]
Some(format!(
@@ -379,6 +379,23 @@ fn handle_vec_semi(
}
}
+fn rewrite_empty_macro_def_body(
+ context: &RewriteContext<'_>,
+ span: Span,
+ shape: Shape,
+) -> Option<String> {
+ // Create an empty, dummy `ast::Block` representing an empty macro body
+ let block = ast::Block {
+ stmts: vec![].into(),
+ id: rustc_ast::node_id::DUMMY_NODE_ID,
+ rules: ast::BlockCheckMode::Default,
+ span: span,
+ tokens: None,
+ could_be_bare_literal: false,
+ };
+ block.rewrite(context, shape)
+}
+
pub(crate) fn rewrite_macro_def(
context: &RewriteContext<'_>,
shape: Shape,
@@ -419,6 +436,13 @@ pub(crate) fn rewrite_macro_def(
shape
};
+ if parsed_def.branches.len() == 0 {
+ let lo = context.snippet_provider.span_before(span, "{");
+ result += " ";
+ result += &rewrite_empty_macro_def_body(context, span.with_lo(lo), shape)?;
+ return Some(result);
+ }
+
let branch_items = itemize_list(
context.snippet_provider,
parsed_def.branches.iter(),
@@ -572,8 +596,8 @@ fn delim_token_to_str(
.block_indent(context.config)
.to_string_with_newline(context.config);
(
- format!("{}{}", lhs, nested_indent_str),
- format!("{}{}", indent_str, rhs),
+ format!("{lhs}{nested_indent_str}"),
+ format!("{indent_str}{rhs}"),
)
} else {
(lhs.to_owned(), rhs.to_owned())
@@ -630,7 +654,7 @@ impl MacroArgKind {
};
match *self {
- MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${}:{}", name, ty)),
+ MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${name}:{ty}")),
MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => {
let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?;
let another = another
@@ -639,14 +663,14 @@ impl MacroArgKind {
.unwrap_or_else(|| "".to_owned());
let repeat_tok = pprust::token_to_string(tok);
- Some(format!("${}{}{}{}{}", lhs, inner, rhs, another, repeat_tok))
+ Some(format!("${lhs}{inner}{rhs}{another}{repeat_tok}"))
}
MacroArgKind::Delimited(delim_tok, ref args) => {
rewrite_delimited_inner(delim_tok, args)
.map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs))
}
- MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{}{} ", prefix, sep)),
- MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{}{}", prefix, inner)),
+ MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{prefix}{sep} ")),
+ MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{prefix}{inner}")),
}
}
}
@@ -1378,15 +1402,19 @@ fn rewrite_macro_with_items(
macro_name: &str,
shape: Shape,
style: Delimiter,
+ original_style: Delimiter,
position: MacroPosition,
span: Span,
) -> Option<String> {
- let (opener, closer) = match style {
- Delimiter::Parenthesis => ("(", ")"),
- Delimiter::Bracket => ("[", "]"),
- Delimiter::Brace => (" {", "}"),
- _ => return None,
+ let style_to_delims = |style| match style {
+ Delimiter::Parenthesis => Some(("(", ")")),
+ Delimiter::Bracket => Some(("[", "]")),
+ Delimiter::Brace => Some((" {", "}")),
+ _ => None,
};
+
+ let (opener, closer) = style_to_delims(style)?;
+ let (original_opener, _) = style_to_delims(original_style)?;
let trailing_semicolon = match style {
Delimiter::Parenthesis | Delimiter::Bracket if position == MacroPosition::Item => ";",
_ => "",
@@ -1394,7 +1422,13 @@ fn rewrite_macro_with_items(
let mut visitor = FmtVisitor::from_context(context);
visitor.block_indent = shape.indent.block_indent(context.config);
- visitor.last_pos = context.snippet_provider.span_after(span, opener.trim());
+
+ // The current opener may be different from the original opener. This can happen
+ // if our macro is a forced bracket macro originally written with non-bracket
+ // delimiters. We need to use the original opener to locate the span after it.
+ visitor.last_pos = context
+ .snippet_provider
+ .span_after(span, original_opener.trim());
for item in items {
let item = match item {
MacroArg::Item(item) => item,
diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 4c37116f1..95b0ed16d 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/src/matches.rs
@@ -124,7 +124,7 @@ pub(crate) fn rewrite_match(
if arms.is_empty() {
let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1)));
if snippet.trim().is_empty() {
- Some(format!("match {} {{}}", cond_str))
+ Some(format!("match {cond_str} {{}}"))
} else {
// Empty match with comments or inner attributes? We are not going to bother, sorry ;)
Some(context.snippet(span).to_owned())
@@ -246,8 +246,18 @@ fn rewrite_match_arm(
};
// Patterns
- // 5 = ` => {`
- let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?;
+ let pat_shape = match &arm.body.kind {
+ ast::ExprKind::Block(_, Some(label)) => {
+ // Some block with a label ` => 'label: {`
+ // 7 = ` => : {`
+ let label_len = label.ident.as_str().len();
+ shape.sub_width(7 + label_len)?.offset_left(pipe_offset)?
+ }
+ _ => {
+ // 5 = ` => {`
+ shape.sub_width(5)?.offset_left(pipe_offset)?
+ }
+ };
let pats_str = arm.pat.rewrite(context, pat_shape)?;
// Guard
@@ -264,7 +274,7 @@ fn rewrite_match_arm(
let lhs_str = combine_strs_with_missing_comments(
context,
&attrs_str,
- &format!("{}{}{}", pipe_str, pats_str, guard_str),
+ &format!("{pipe_str}{pats_str}{guard_str}"),
missing_span,
shape,
false,
@@ -296,8 +306,9 @@ fn block_can_be_flattened<'a>(
expr: &'a ast::Expr,
) -> Option<&'a ast::Block> {
match expr.kind {
- ast::ExprKind::Block(ref block, _)
- if !is_unsafe_block(block)
+ ast::ExprKind::Block(ref block, label)
+ if label.is_none()
+ && !is_unsafe_block(block)
&& !context.inside_macro()
&& is_simple_block(context, block, Some(&expr.attrs))
&& !stmt_is_expr_mac(&block.stmts[0]) =>
@@ -532,7 +543,7 @@ fn rewrite_guard(
if let Some(cond_shape) = cond_shape {
if let Some(cond_str) = guard.rewrite(context, cond_shape) {
if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() {
- return Some(format!(" if {}", cond_str));
+ return Some(format!(" if {cond_str}"));
}
}
}
diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs
index d135da7e3..07c051937 100644
--- a/src/tools/rustfmt/src/pairs.rs
+++ b/src/tools/rustfmt/src/pairs.rs
@@ -42,9 +42,13 @@ pub(crate) fn rewrite_all_pairs(
context: &RewriteContext<'_>,
) -> Option<String> {
expr.flatten(context, shape).and_then(|list| {
- // First we try formatting on one line.
- rewrite_pairs_one_line(&list, shape, context)
- .or_else(|| rewrite_pairs_multiline(&list, shape, context))
+ if list.let_chain_count() > 0 && !list.can_rewrite_let_chain_single_line() {
+ rewrite_pairs_multiline(&list, shape, context)
+ } else {
+ // First we try formatting on one line.
+ rewrite_pairs_one_line(&list, shape, context)
+ .or_else(|| rewrite_pairs_multiline(&list, shape, context))
+ }
})
}
@@ -234,8 +238,8 @@ where
let rhs_result = rhs.rewrite(context, rhs_shape)?;
let indent_str = rhs_shape.indent.to_string_with_newline(context.config);
let infix_with_sep = match separator_place {
- SeparatorPlace::Back => format!("{}{}", infix, indent_str),
- SeparatorPlace::Front => format!("{}{}", indent_str, infix),
+ SeparatorPlace::Back => format!("{infix}{indent_str}"),
+ SeparatorPlace::Front => format!("{indent_str}{infix}"),
};
Some(format!(
"{}{}{}{}",
@@ -255,6 +259,37 @@ struct PairList<'a, 'b, T: Rewrite> {
separators: Vec<&'a str>,
}
+fn is_ident(expr: &ast::Expr) -> bool {
+ match &expr.kind {
+ ast::ExprKind::Path(None, path) if path.segments.len() == 1 => true,
+ ast::ExprKind::Unary(_, expr)
+ | ast::ExprKind::AddrOf(_, _, expr)
+ | ast::ExprKind::Paren(expr)
+ | ast::ExprKind::Try(expr) => is_ident(expr),
+ _ => false,
+ }
+}
+
+impl<'a, 'b> PairList<'a, 'b, ast::Expr> {
+ fn let_chain_count(&self) -> usize {
+ self.list
+ .iter()
+ .filter(|(expr, _)| matches!(expr.kind, ast::ExprKind::Let(..)))
+ .count()
+ }
+
+ fn can_rewrite_let_chain_single_line(&self) -> bool {
+ if self.list.len() != 2 {
+ return false;
+ }
+
+ let fist_item_is_ident = is_ident(self.list[0].0);
+ let second_item_is_let_chain = matches!(self.list[1].0.kind, ast::ExprKind::Let(..));
+
+ fist_item_is_ident && second_item_is_let_chain
+ }
+}
+
impl FlattenPair for ast::Expr {
fn flatten(
&self,
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 3f94bb299..0573df9de 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -316,8 +316,7 @@ impl LineRangeUtils for ParseSess {
debug_assert_eq!(
lo.sf.name, hi.sf.name,
- "span crossed file boundary: lo: {:?}, hi: {:?}",
- lo, hi
+ "span crossed file boundary: lo: {lo:?}, hi: {hi:?}"
);
// in case the span starts with a newline, the line range is off by 1 without the
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 3f3351725..33f3b4b8a 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -208,7 +208,7 @@ impl Rewrite for Pat {
None => "",
Some(_) => " ",
};
- format!("{}{}{}", lhs_spacing, infix, rhs_spacing)
+ format!("{lhs_spacing}{infix}{rhs_spacing}")
} else {
infix.to_owned()
};
@@ -283,7 +283,7 @@ fn rewrite_struct_pat(
let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
if fields.is_empty() && !ellipsis {
- return Some(format!("{} {{}}", path_str));
+ return Some(format!("{path_str} {{}}"));
}
let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };
@@ -344,7 +344,7 @@ fn rewrite_struct_pat(
// ast::Pat doesn't have attrs so use &[]
let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?;
- Some(format!("{} {{{}}}", path_str, fields_str))
+ Some(format!("{path_str} {{{fields_str}}}"))
}
impl Rewrite for PatField {
@@ -376,7 +376,7 @@ impl Rewrite for PatField {
let id_str = rewrite_ident(context, self.ident);
let one_line_width = id_str.len() + 2 + pat_str.len();
let pat_and_id_str = if one_line_width <= shape.width {
- format!("{}: {}", id_str, pat_str)
+ format!("{id_str}: {pat_str}")
} else {
format!(
"{}:\n{}{}",
diff --git a/src/tools/rustfmt/src/rustfmt_diff.rs b/src/tools/rustfmt/src/rustfmt_diff.rs
index 1724a0f87..c98834521 100644
--- a/src/tools/rustfmt/src/rustfmt_diff.rs
+++ b/src/tools/rustfmt/src/rustfmt_diff.rs
@@ -95,7 +95,7 @@ impl fmt::Display for ModifiedLines {
)?;
for line in &chunk.lines {
- writeln!(f, "{}", line)?;
+ writeln!(f, "{line}")?;
}
}
@@ -166,12 +166,12 @@ impl OutputWriter {
if let Some(color) = color {
t.fg(color).unwrap();
}
- writeln!(t, "{}", msg).unwrap();
+ writeln!(t, "{msg}").unwrap();
if color.is_some() {
t.reset().unwrap();
}
}
- None => println!("{}", msg),
+ None => println!("{msg}"),
}
}
}
@@ -265,16 +265,15 @@ where
for line in mismatch.lines {
match line {
DiffLine::Context(ref str) => {
- writer.writeln(&format!(" {}{}", str, line_terminator), None)
+ writer.writeln(&format!(" {str}{line_terminator}"), None)
}
DiffLine::Expected(ref str) => writer.writeln(
- &format!("+{}{}", str, line_terminator),
+ &format!("+{str}{line_terminator}"),
Some(term::color::GREEN),
),
- DiffLine::Resulting(ref str) => writer.writeln(
- &format!("-{}{}", str, line_terminator),
- Some(term::color::RED),
- ),
+ DiffLine::Resulting(ref str) => {
+ writer.writeln(&format!("-{str}{line_terminator}"), Some(term::color::RED))
+ }
}
}
}
diff --git a/src/tools/rustfmt/src/skip.rs b/src/tools/rustfmt/src/skip.rs
index 68f85b2ad..d733f7068 100644
--- a/src/tools/rustfmt/src/skip.rs
+++ b/src/tools/rustfmt/src/skip.rs
@@ -105,7 +105,7 @@ pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool {
fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec<String> {
let mut skip_names = vec![];
- let path = format!("{}::{}::{}", RUSTFMT, SKIP, kind);
+ let path = format!("{RUSTFMT}::{SKIP}::{kind}");
for attr in attrs {
// rustc_ast::ast::Path is implemented partialEq
// but it is designed for segments.len() == 1
diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs
index 56d4ab400..958f9b015 100644
--- a/src/tools/rustfmt/src/source_file.rs
+++ b/src/tools/rustfmt/src/source_file.rs
@@ -62,7 +62,7 @@ where
fn ensure_real_path(filename: &FileName) -> &Path {
match *filename {
FileName::Real(ref path) => path,
- _ => panic!("cannot format `{}` and emit to files", filename),
+ _ => panic!("cannot format `{filename}` and emit to files"),
}
}
diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs
index 0b3854425..e3fe4ebca 100644
--- a/src/tools/rustfmt/src/stmt.rs
+++ b/src/tools/rustfmt/src/stmt.rs
@@ -3,7 +3,7 @@ use rustc_span::Span;
use crate::comment::recover_comment_removed;
use crate::config::Version;
-use crate::expr::{format_expr, ExprType};
+use crate::expr::{format_expr, is_simple_block, ExprType};
use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::Shape;
use crate::source_map::LineRangeUtils;
@@ -33,6 +33,21 @@ impl<'a> Stmt<'a> {
}
}
+ pub(crate) fn from_simple_block(
+ context: &RewriteContext<'_>,
+ block: &'a ast::Block,
+ attrs: Option<&[ast::Attribute]>,
+ ) -> Option<Self> {
+ if is_simple_block(context, block, attrs) {
+ let inner = &block.stmts[0];
+ // Simple blocks only contain one expr and no stmts
+ let is_last = true;
+ Some(Stmt { inner, is_last })
+ } else {
+ None
+ }
+ }
+
pub(crate) fn from_ast_node(inner: &'a ast::Stmt, is_last: bool) -> Self {
Stmt { inner, is_last }
}
@@ -80,13 +95,13 @@ impl<'a> Rewrite for Stmt<'a> {
} else {
ExprType::Statement
};
- format_stmt(context, shape, self.as_ast_node(), expr_type)
- }
-}
-
-impl Rewrite for ast::Stmt {
- fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
- format_stmt(context, shape, self, ExprType::Statement)
+ format_stmt(
+ context,
+ shape,
+ self.as_ast_node(),
+ expr_type,
+ self.is_last_expr(),
+ )
}
}
@@ -95,13 +110,14 @@ fn format_stmt(
shape: Shape,
stmt: &ast::Stmt,
expr_type: ExprType,
+ is_last_expr: bool,
) -> Option<String> {
skip_out_of_file_lines_range!(context, stmt.span());
let result = match stmt.kind {
ast::StmtKind::Local(ref local) => local.rewrite(context, shape),
ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => {
- let suffix = if semicolon_for_stmt(context, stmt) {
+ let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) {
";"
} else {
""
diff --git a/src/tools/rustfmt/src/string.rs b/src/tools/rustfmt/src/string.rs
index 78b72a50c..cb666fff6 100644
--- a/src/tools/rustfmt/src/string.rs
+++ b/src/tools/rustfmt/src/string.rs
@@ -1,7 +1,7 @@
// Format string literals.
use regex::Regex;
-use unicode_categories::UnicodeCategories;
+use unicode_properties::{GeneralCategory, UnicodeGeneralCategory};
use unicode_segmentation::UnicodeSegmentation;
use crate::config::Config;
@@ -366,7 +366,7 @@ fn is_whitespace(grapheme: &str) -> bool {
fn is_punctuation(grapheme: &str) -> bool {
grapheme
.chars()
- .all(UnicodeCategories::is_punctuation_other)
+ .all(|c| c.general_category() == GeneralCategory::OtherPunctuation)
}
fn graphemes_width(graphemes: &[&str]) -> usize {
diff --git a/src/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs
index c70b3c5fa..80b61c88a 100644
--- a/src/tools/rustfmt/src/test/configuration_snippet.rs
+++ b/src/tools/rustfmt/src/test/configuration_snippet.rs
@@ -233,13 +233,11 @@ impl ConfigCodeBlock {
Some(ConfigurationSection::ConfigName(name)) => {
assert!(
Config::is_valid_name(&name),
- "an unknown configuration option was found: {}",
- name
+ "an unknown configuration option was found: {name}"
);
assert!(
hash_set.remove(&name),
- "multiple configuration guides found for option {}",
- name
+ "multiple configuration guides found for option {name}"
);
code_block.set_config_name(Some(name));
}
@@ -266,7 +264,7 @@ fn configuration_snippet_tests() {
// Display results.
println!("Ran {} configurations tests.", blocks.len());
- assert_eq!(failures, 0, "{} configurations tests failed", failures);
+ assert_eq!(failures, 0, "{failures} configurations tests failed");
}
// Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one
@@ -289,7 +287,7 @@ fn get_code_blocks() -> Vec<ConfigCodeBlock> {
for name in hash_set {
if !Config::is_hidden_option(&name) {
- panic!("{} does not have a configuration guide", name);
+ panic!("{name} does not have a configuration guide");
}
}
diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs
index 37854ead2..47f89c187 100644
--- a/src/tools/rustfmt/src/test/mod.rs
+++ b/src/tools/rustfmt/src/test/mod.rs
@@ -47,7 +47,7 @@ const FILE_SKIP_LIST: &[&str] = &[
];
fn init_log() {
- let _ = env_logger::builder().is_test(true).try_init();
+ let _ = tracing_subscriber::fmt().with_test_writer().try_init();
}
struct TestSetting {
@@ -203,8 +203,8 @@ fn coverage_tests() {
let files = get_test_files(Path::new("tests/coverage/source"), true);
let (_reports, count, fails) = check_files(files, &None);
- println!("Ran {} tests in coverage mode.", count);
- assert_eq!(fails, 0, "{} tests failed", fails);
+ println!("Ran {count} tests in coverage mode.");
+ assert_eq!(fails, 0, "{fails} tests failed");
}
#[test]
@@ -396,8 +396,8 @@ fn self_tests() {
let mut warnings = 0;
// Display results.
- println!("Ran {} self tests.", count);
- assert_eq!(fails, 0, "{} self tests failed", fails);
+ println!("Ran {count} self tests.");
+ assert_eq!(fails, 0, "{fails} self tests failed");
for format_report in reports {
println!(
@@ -407,11 +407,7 @@ fn self_tests() {
warnings += format_report.warning_count();
}
- assert_eq!(
- warnings, 0,
- "Rustfmt's code generated {} warnings",
- warnings
- );
+ assert_eq!(warnings, 0, "Rustfmt's code generated {warnings} warnings");
}
#[test]
@@ -606,7 +602,7 @@ fn stdin_handles_mod_inner_ignore_attr() {
fn format_lines_errors_are_reported() {
init_log();
let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap();
- let input = Input::Text(format!("fn {}() {{}}", long_identifier));
+ let input = Input::Text(format!("fn {long_identifier}() {{}}"));
let mut config = Config::default();
config.set().error_on_line_overflow(true);
let mut session = Session::<io::Stdout>::new(config, None);
@@ -618,7 +614,7 @@ fn format_lines_errors_are_reported() {
fn format_lines_errors_are_reported_with_tabs() {
init_log();
let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap();
- let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier));
+ let input = Input::Text(format!("fn a() {{\n\t{long_identifier}\n}}"));
let mut config = Config::default();
config.set().error_on_line_overflow(true);
config.set().hard_tabs(true);
@@ -829,11 +825,11 @@ fn handle_result(
for (file_name, fmt_text) in result {
// If file is in tests/source, compare to file with same name in tests/target.
let target = get_target(&file_name, target);
- let open_error = format!("couldn't open target {:?}", target);
+ let open_error = format!("couldn't open target {target:?}");
let mut f = fs::File::open(&target).expect(&open_error);
let mut text = String::new();
- let read_error = format!("failed reading target {:?}", target);
+ let read_error = format!("failed reading target {target:?}");
f.read_to_string(&mut text).expect(&read_error);
// Ignore LF and CRLF difference for Windows.
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 5e8edd8f8..127aff913 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -301,7 +301,7 @@ where
let output = match *output {
FnRetTy::Ty(ref ty) => {
let type_str = ty.rewrite(context, ty_shape)?;
- format!(" -> {}", type_str)
+ format!(" -> {type_str}")
}
FnRetTy::Default(..) => String::new(),
};
@@ -373,7 +373,7 @@ where
|| !context.use_block_indent()
|| is_inputs_empty
{
- format!("({})", list_str)
+ format!("({list_str})")
} else {
format!(
"({}{}{})",
@@ -383,7 +383,7 @@ where
)
};
if output.is_empty() || last_line_width(&args) + first_line_width(&output) <= shape.width {
- Some(format!("{}{}", args, output))
+ Some(format!("{args}{output}"))
} else {
Some(format!(
"{}\n{}{}",
@@ -426,12 +426,12 @@ impl Rewrite for ast::WherePredicate {
}) => {
let type_str = bounded_ty.rewrite(context, shape)?;
let colon = type_bound_colon(context).trim_end();
- let lhs = if let Some(lifetime_str) =
- rewrite_lifetime_param(context, shape, bound_generic_params)
+ let lhs = if let Some(binder_str) =
+ rewrite_bound_params(context, shape, bound_generic_params)
{
- format!("for<{}> {}{}", lifetime_str, type_str, colon)
+ format!("for<{binder_str}> {type_str}{colon}")
} else {
- format!("{}{}", type_str, colon)
+ format!("{type_str}{colon}")
};
rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)?
@@ -657,8 +657,7 @@ impl Rewrite for ast::GenericParam {
impl Rewrite for ast::PolyTraitRef {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
- if let Some(lifetime_str) =
- rewrite_lifetime_param(context, shape, &self.bound_generic_params)
+ if let Some(lifetime_str) = rewrite_bound_params(context, shape, &self.bound_generic_params)
{
// 6 is "for<> ".len()
let extra_offset = lifetime_str.len() + 6;
@@ -666,7 +665,7 @@ impl Rewrite for ast::PolyTraitRef {
.trait_ref
.rewrite(context, shape.offset_left(extra_offset)?)?;
- Some(format!("for<{}> {}", lifetime_str, path_str))
+ Some(format!("for<{lifetime_str}> {path_str}"))
} else {
self.trait_ref.rewrite(context, shape)
}
@@ -684,9 +683,11 @@ impl Rewrite for ast::Ty {
match self.kind {
ast::TyKind::TraitObject(ref bounds, tobj_syntax) => {
// we have to consider 'dyn' keyword is used or not!!!
- let is_dyn = tobj_syntax == ast::TraitObjectSyntax::Dyn;
- // 4 is length of 'dyn '
- let shape = if is_dyn { shape.offset_left(4)? } else { shape };
+ let (shape, prefix) = match tobj_syntax {
+ ast::TraitObjectSyntax::Dyn => (shape.offset_left(4)?, "dyn "),
+ ast::TraitObjectSyntax::DynStar => (shape.offset_left(5)?, "dyn* "),
+ ast::TraitObjectSyntax::None => (shape, ""),
+ };
let mut res = bounds.rewrite(context, shape)?;
// We may have falsely removed a trailing `+` inside macro call.
if context.inside_macro() && bounds.len() == 1 {
@@ -694,11 +695,7 @@ impl Rewrite for ast::Ty {
res.push('+');
}
}
- if is_dyn {
- Some(format!("dyn {}", res))
- } else {
- Some(res)
- }
+ Some(format!("{prefix}{res}"))
}
ast::TyKind::Ptr(ref mt) => {
let prefix = match mt.mutbl {
@@ -794,7 +791,7 @@ impl Rewrite for ast::Ty {
if let Some(sh) = shape.sub_width(2) {
if let Some(ref s) = ty.rewrite(context, sh) {
if !s.contains('\n') {
- return Some(format!("({})", s));
+ return Some(format!("({s})"));
}
}
}
@@ -883,8 +880,7 @@ fn rewrite_bare_fn(
let mut result = String::with_capacity(128);
- if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params)
- {
+ if let Some(ref lifetime_str) = rewrite_bound_params(context, shape, &bare_fn.generic_params) {
result.push_str("for<");
// 6 = "for<> ".len(), 4 = "for<".
// This doesn't work out so nicely for multiline situation with lots of
@@ -898,7 +894,6 @@ fn rewrite_bare_fn(
result.push_str(&format_extern(
bare_fn.ext,
context.config.force_explicit_abi(),
- false,
));
result.push_str("fn");
@@ -1124,16 +1119,15 @@ pub(crate) fn can_be_overflowed_type(
}
}
-/// Returns `None` if there is no `LifetimeDef` in the given generic parameters.
-pub(crate) fn rewrite_lifetime_param(
+/// Returns `None` if there is no `GenericParam` in the list
+pub(crate) fn rewrite_bound_params(
context: &RewriteContext<'_>,
shape: Shape,
generic_params: &[ast::GenericParam],
) -> Option<String> {
let result = generic_params
.iter()
- .filter(|p| matches!(p.kind, ast::GenericParamKind::Lifetime))
- .map(|lt| lt.rewrite(context, shape))
+ .map(|param| param.rewrite(context, shape))
.collect::<Option<Vec<_>>>()?
.join(", ");
if result.is_empty() {
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 4fc5a9b68..fd49030bf 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -69,7 +69,7 @@ pub(crate) fn format_visibility(
let path = segments_iter.collect::<Vec<_>>().join("::");
let in_str = if is_keyword(&path) { "" } else { "in " };
- Cow::from(format!("pub({}{}) ", in_str, path))
+ Cow::from(format!("pub({in_str}{path}) "))
}
}
}
@@ -131,23 +131,18 @@ pub(crate) fn format_mutability(mutability: ast::Mutability) -> &'static str {
}
#[inline]
-pub(crate) fn format_extern(
- ext: ast::Extern,
- explicit_abi: bool,
- is_mod: bool,
-) -> Cow<'static, str> {
- let abi = match ext {
- ast::Extern::None => "Rust".to_owned(),
- ast::Extern::Implicit(_) => "C".to_owned(),
- ast::Extern::Explicit(abi, _) => abi.symbol_unescaped.to_string(),
- };
-
- if abi == "Rust" && !is_mod {
- Cow::from("")
- } else if abi == "C" && !explicit_abi {
- Cow::from("extern ")
- } else {
- Cow::from(format!(r#"extern "{}" "#, abi))
+pub(crate) fn format_extern(ext: ast::Extern, explicit_abi: bool) -> Cow<'static, str> {
+ match ext {
+ ast::Extern::None => Cow::from(""),
+ ast::Extern::Implicit(_) if explicit_abi => Cow::from("extern \"C\" "),
+ ast::Extern::Implicit(_) => Cow::from("extern "),
+ // turn `extern "C"` into `extern` when `explicit_abi` is set to false
+ ast::Extern::Explicit(abi, _) if abi.symbol_unescaped == sym::C && !explicit_abi => {
+ Cow::from("extern ")
+ }
+ ast::Extern::Explicit(abi, _) => {
+ Cow::from(format!(r#"extern "{}" "#, abi.symbol_unescaped))
+ }
}
}
@@ -292,14 +287,20 @@ pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr)
}
#[inline]
-pub(crate) fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool {
+pub(crate) fn semicolon_for_stmt(
+ context: &RewriteContext<'_>,
+ stmt: &ast::Stmt,
+ is_last_expr: bool,
+) -> bool {
match stmt.kind {
ast::StmtKind::Semi(ref expr) => match expr.kind {
ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => {
false
}
ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => {
- context.config.trailing_semicolon()
+ // The only time we can skip the semi-colon is if the config option is set to false
+ // **and** this is the last expr (even though any following exprs are unreachable)
+ context.config.trailing_semicolon() || !is_last_expr
}
_ => true,
},
@@ -472,7 +473,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
| ast::ExprKind::If(..)
| ast::ExprKind::Block(..)
| ast::ExprKind::ConstBlock(..)
- | ast::ExprKind::Async(..)
+ | ast::ExprKind::Gen(..)
| ast::ExprKind::Loop(..)
| ast::ExprKind::ForLoop(..)
| ast::ExprKind::TryBlock(..)
diff --git a/src/tools/rustfmt/tests/cargo-fmt/main.rs b/src/tools/rustfmt/tests/cargo-fmt/main.rs
index 701c36fad..63573bf34 100644
--- a/src/tools/rustfmt/tests/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/tests/cargo-fmt/main.rs
@@ -26,7 +26,7 @@ fn cargo_fmt(args: &[&str]) -> (String, String) {
String::from_utf8(output.stdout).expect("utf-8"),
String::from_utf8(output.stderr).expect("utf-8"),
),
- Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e),
+ Err(e) => panic!("failed to run `{cmd:?} {args:?}`: {e}"),
}
}
diff --git a/src/tools/rustfmt/tests/config/issue-5816.toml b/src/tools/rustfmt/tests/config/issue-5816.toml
new file mode 100644
index 000000000..00375746e
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/issue-5816.toml
@@ -0,0 +1 @@
+skip_macro_invocations=["*", "println"]
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 4936a7174..7dcf7c841 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -27,7 +27,7 @@ fn rustfmt(args: &[&str]) -> (String, String) {
String::from_utf8(output.stdout).expect("utf-8"),
String::from_utf8(output.stderr).expect("utf-8"),
),
- Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e),
+ Err(e) => panic!("failed to run `{cmd:?} {args:?}`: {e}"),
}
}
@@ -71,9 +71,7 @@ fn print_config() {
]);
assert!(
Path::new("minimal-config").exists(),
- "stdout:\n{}\nstderr:\n{}",
- stdout,
- stderr
+ "stdout:\n{stdout}\nstderr:\n{stderr}"
);
remove_file("minimal-config").unwrap();
}
diff --git a/src/tools/rustfmt/tests/source/immovable_generators.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
index c57a1e144..3b94af0c9 100644
--- a/src/tools/rustfmt/tests/source/immovable_generators.rs
+++ b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
unsafe fn foo() {
let mut ga = static || {
diff --git a/src/tools/rustfmt/tests/source/issue-3984.rs b/src/tools/rustfmt/tests/source/issue-3984.rs
new file mode 100644
index 000000000..c9bcfa406
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-3984.rs
@@ -0,0 +1,12 @@
+use a::{item /* comment */};
+use b::{
+ a,
+ // comment
+ item,
+};
+use c::item /* comment */;
+use d::item; // really long comment (with `use` exactly 100 characters) ____________________________
+
+use std::e::{/* it's a comment! */ bar /* and another */};
+use std::f::{/* it's a comment! */ bar};
+use std::g::{bar /* and another */};
diff --git a/src/tools/rustfmt/tests/source/issue-4808.rs b/src/tools/rustfmt/tests/source/issue-4808.rs
new file mode 100644
index 000000000..93076edcd
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4808.rs
@@ -0,0 +1,13 @@
+trait Trait {
+ fn method(&self) {}
+}
+
+impl<F: Fn() -> T, T> Trait for F {}
+
+impl Trait for f32 {}
+
+fn main() {
+ || 10. .method();
+ || .. .method();
+ || 1.. .method();
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5655/one.rs b/src/tools/rustfmt/tests/source/issue-5655/one.rs
new file mode 100644
index 000000000..1758ec56f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5655/one.rs
@@ -0,0 +1,9 @@
+// rustfmt-version: One
+
+fn foo<T>(_: T)
+where
+ T: std::fmt::Debug,
+
+ T: std::fmt::Display,
+{
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5655/two.rs b/src/tools/rustfmt/tests/source/issue-5655/two.rs
new file mode 100644
index 000000000..e37ebbea8
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5655/two.rs
@@ -0,0 +1,9 @@
+// rustfmt-version: Two
+
+fn foo<T>(_: T)
+where
+ T: std::fmt::Debug,
+
+ T: std::fmt::Display,
+{
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5791.rs b/src/tools/rustfmt/tests/source/issue-5791.rs
new file mode 100644
index 000000000..40bc6daa9
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5791.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+ 0. .to_string();
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5835.rs b/src/tools/rustfmt/tests/source/issue-5835.rs
new file mode 100644
index 000000000..3e4da3492
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5835.rs
@@ -0,0 +1,8 @@
+// rustfmt-wrap_comments: true
+
+/// . a
+pub fn foo() {}
+
+pub fn main() {
+ // . a
+}
diff --git a/src/tools/rustfmt/tests/source/issue-5852/default.rs b/src/tools/rustfmt/tests/source/issue-5852/default.rs
new file mode 100644
index 000000000..df84f8f58
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/default.rs
@@ -0,0 +1,104 @@
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
+
+use foo :: bar
+;
+
+use foo::{bar};
+
+use foo::{
+ bar
+ // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar
+};
+
+use foo::{
+ self
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self
+};
+
+use foo::{
+ self // a
+ ,
+};
+
+use foo::{ self /* a */ };
+
+use foo::{ self /* a */, };
+
+use foo::{
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ // abc
+ bar,
+ abc
+};
+
+use foo::{
+ bar,
+ // abc
+ abc
+};
+
+use foo::{
+ bar,
+ abc
+ // abc
+};
+
+use foo::{
+ bar,
+ abc,
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz
+ }
+};
+
+use path::{self /*comment*/,};
diff --git a/src/tools/rustfmt/tests/source/issue-5852/horizontal.rs b/src/tools/rustfmt/tests/source/issue-5852/horizontal.rs
new file mode 100644
index 000000000..63bfb7e57
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/horizontal.rs
@@ -0,0 +1,106 @@
+// rustfmt-imports_layout: Horizontal
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
+
+use foo :: bar
+;
+
+use foo::{bar};
+
+use foo::{
+ bar
+ // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar
+};
+
+use foo::{
+ self
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self
+};
+
+use foo::{
+ self // a
+ ,
+};
+
+use foo::{ self /* a */ };
+
+use foo::{ self /* a */, };
+
+use foo::{
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ // abc
+ bar,
+ abc
+};
+
+use foo::{
+ bar,
+ // abc
+ abc
+};
+
+use foo::{
+ bar,
+ abc
+ // abc
+};
+
+use foo::{
+ bar,
+ abc,
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz
+ }
+};
+
+use path::{self /*comment*/,};
diff --git a/src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs b/src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs
new file mode 100644
index 000000000..3f3ce0669
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs
@@ -0,0 +1,106 @@
+// rustfmt-imports_layout: HorizontalVertical
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
+
+use foo :: bar
+;
+
+use foo::{bar};
+
+use foo::{
+ bar
+ // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar
+};
+
+use foo::{
+ self
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self
+};
+
+use foo::{
+ self // a
+ ,
+};
+
+use foo::{ self /* a */ };
+
+use foo::{ self /* a */, };
+
+use foo::{
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ // abc
+ bar,
+ abc
+};
+
+use foo::{
+ bar,
+ // abc
+ abc
+};
+
+use foo::{
+ bar,
+ abc
+ // abc
+};
+
+use foo::{
+ bar,
+ abc,
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz
+ }
+};
+
+use path::{self /*comment*/,};
diff --git a/src/tools/rustfmt/tests/source/issue-5852/issue_example.rs b/src/tools/rustfmt/tests/source/issue-5852/issue_example.rs
new file mode 100644
index 000000000..20c2b7640
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/issue_example.rs
@@ -0,0 +1,8 @@
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
diff --git a/src/tools/rustfmt/tests/source/issue-5852/split.rs b/src/tools/rustfmt/tests/source/issue-5852/split.rs
new file mode 100644
index 000000000..14e9ea1b6
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/split.rs
@@ -0,0 +1,111 @@
+// rustfmt-imports_granularity: Item
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
+
+use foo :: bar
+;
+
+use foo::{bar};
+
+use foo::{
+ bar
+ // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar
+};
+
+use foo::{
+ self
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self
+};
+
+use foo::{
+ self // a
+ ,
+};
+
+use foo::{ self /* a */ };
+
+use foo::{ self /* a */, };
+
+use foo::{
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ bar,
+ abc
+};
+
+use foo::{
+ // abc
+ bar,
+ abc
+};
+
+use foo::{
+ bar,
+ // abc
+ abc
+};
+
+use foo::{
+ bar,
+ abc
+ // abc
+};
+
+use foo::{
+ bar,
+ abc,
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz
+ }
+};
+
+use path::{self /*comment*/,};
diff --git a/src/tools/rustfmt/tests/source/issue-5852/vertical.rs b/src/tools/rustfmt/tests/source/issue-5852/vertical.rs
new file mode 100644
index 000000000..b9ba99889
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5852/vertical.rs
@@ -0,0 +1,106 @@
+// rustfmt-imports_layout: Vertical
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self // this is important
+};
+
+use foo :: bar
+;
+
+use foo::{bar};
+
+use foo::{
+ bar
+ // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar
+};
+
+use foo::{
+ self
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self
+};
+
+use foo::{
+ self // a
+ ,
+};
+
+use foo::{ self /* a */ };
+
+use foo::{ self /* a */, };
+
+use foo::{
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ // abc
+ bar,
+ abc
+};
+
+use foo::{
+ bar,
+ // abc
+ abc
+};
+
+use foo::{
+ bar,
+ abc
+ // abc
+};
+
+use foo::{
+ bar,
+ abc,
+ // abc
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz
+ // 123
+ }
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz
+ }
+};
+
+use path::{self /*comment*/,};
diff --git a/src/tools/rustfmt/tests/source/issue-5935.rs b/src/tools/rustfmt/tests/source/issue-5935.rs
new file mode 100644
index 000000000..a1aac0562
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5935.rs
@@ -0,0 +1,9 @@
+struct Regs<
+ const BEGIN: u64,
+ const END: u64,
+ const DIM: usize,
+ const N: usize = { (END - BEGIN) as usize / (8 * DIM) + 1 },
+>
+{
+ _foo: u64,
+} \ No newline at end of file
diff --git a/src/tools/rustfmt/tests/source/issue_5721.rs b/src/tools/rustfmt/tests/source/issue_5721.rs
new file mode 100644
index 000000000..e5ae9612c
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_5721.rs
@@ -0,0 +1,8 @@
+#![feature(non_lifetime_binders)]
+#![allow(incomplete_features)]
+
+trait Other<U: ?Sized> {}
+
+trait Trait<U>
+where
+ for<T> U: Other<T> {}
diff --git a/src/tools/rustfmt/tests/source/issue_5730.rs b/src/tools/rustfmt/tests/source/issue_5730.rs
new file mode 100644
index 000000000..9a3f4f0d0
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_5730.rs
@@ -0,0 +1,3 @@
+macro_rules! statement {
+ () => {;};
+}
diff --git a/src/tools/rustfmt/tests/source/issue_5735.rs b/src/tools/rustfmt/tests/source/issue_5735.rs
new file mode 100644
index 000000000..7708d028b
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_5735.rs
@@ -0,0 +1,6 @@
+fn find_errors(mut self) {
+ let errors: Vec<> = vec!{
+ #[debug_format = "A({})"]
+ struct A {}
+ };
+}
diff --git a/src/tools/rustfmt/tests/source/issue_5882.rs b/src/tools/rustfmt/tests/source/issue_5882.rs
new file mode 100644
index 000000000..e36f99654
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_5882.rs
@@ -0,0 +1,7 @@
+macro_rules!foo{}
+macro_rules!bar{/*comment*/}
+macro_rules!baz{//comment
+}
+macro_rules!foobar{
+//comment
+}
diff --git a/src/tools/rustfmt/tests/source/let_chains.rs b/src/tools/rustfmt/tests/source/let_chains.rs
new file mode 100644
index 000000000..b7c1f8110
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/let_chains.rs
@@ -0,0 +1,121 @@
+fn main() {
+ if let x = x && x {}
+
+ if xxx && let x = x {}
+
+ if aaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaa && aaaaaaaaa && let Some(x) = xxxxxxxxxxxx && aaaaaaa && let None = aaaaaaaaaa {}
+
+ if aaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaa && aaaaaaaaa && let Some(x) = xxxxxxxxxxxx && aaaaaaa && let None = aaaaaaaaaa {}
+
+ if let Some(Struct { x:TS(1,2) }) = path::to::<_>(hehe)
+ && let [Simple, people] = /* get ready */ create_universe(/* hi */ GreatPowers).initialize_badminton().populate_swamps() &&
+ let everybody = (Loops { hi /*hi*/ , ..loopy() }) && summons::triumphantly() { todo!() }
+
+ if let XXXXXXXXX { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzz} = xxxxxxx()
+ && let Foo = bar() { todo!() }
+}
+
+fn test_single_line_let_chain() {
+ // first item in let-chain is an ident
+ if a && let Some(b) = foo() {
+ }
+
+ // first item in let-chain is a unary ! with an ident
+ let unary_not = if !from_hir_call
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is a unary * with an ident
+ let unary_deref = if *some_deref
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is a unary - (neg) with an ident
+ let unary_neg = if -some_ident
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is a try (?) with an ident
+ let try_ = if some_try?
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is an ident wrapped in parens
+ let in_parens = if (some_ident)
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is a ref & with an ident
+ let _ref = if &some_ref
+ && let Some(p) = parent
+ {
+ };
+
+ // first item in let-chain is a ref &mut with an ident
+ let mut_ref = if &mut some_ref
+ && let Some(p) = parent
+ {
+ };
+
+ // chain unary ref and try
+ let chain_of_unary_ref_and_try = if !&*some_ref?
+ && let Some(p) = parent {
+ };
+}
+
+fn test_multi_line_let_chain() {
+ // Can only single line the let-chain if the first item is an ident
+ if let Some(x) = y && a {
+
+ }
+
+ // More than one let-chain must be formatted on multiple lines
+ if let Some(x) = y && let Some(a) = b {
+
+ }
+
+ // The ident isn't long enough so we don't wrap the first let-chain
+ if a && let Some(x) = y && let Some(a) = b {
+
+ }
+
+ // The ident is long enough so both let-chains are wrapped
+ if aaa && let Some(x) = y && let Some(a) = b {
+
+ }
+
+ // function call
+ if a() && let Some(x) = y {
+
+ }
+
+ // bool literal
+ if true && let Some(x) = y {
+
+ }
+
+ // cast to a bool
+ if 1 as bool && let Some(x) = y {
+
+ }
+
+ // matches! macro call
+ if matches!(a, some_type) && let Some(x) = y {
+
+ }
+
+ // block expression returning bool
+ if { true } && let Some(x) = y {
+
+ }
+
+ // field access
+ if a.x && let Some(x) = y {
+
+ }
+}
diff --git a/src/tools/rustfmt/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs
index 85b3604ad..cb2859e80 100644
--- a/src/tools/rustfmt/tests/source/let_else.rs
+++ b/src/tools/rustfmt/tests/source/let_else.rs
@@ -160,3 +160,23 @@ fn with_trailing_try_operator() {
// Maybe this is a workaround?
let Ok(Some(next_bucket)) = ranking_rules[cur_ranking_rule_index].next_bucket(ctx, logger, &ranking_rule_universes[cur_ranking_rule_index]) else { return };
}
+
+fn issue5901() {
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = foo else { todo!() };
+
+ // The else block will be multi-lined because attributes and comments before `let`
+ // are included when calculating max width
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo() else { todo!() };
+}
diff --git a/src/tools/rustfmt/tests/source/let_else_v2.rs b/src/tools/rustfmt/tests/source/let_else_v2.rs
new file mode 100644
index 000000000..a420fbcf9
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/let_else_v2.rs
@@ -0,0 +1,56 @@
+// rustfmt-version: Two
+// rustfmt-single_line_let_else_max_width: 100
+
+fn issue5901() {
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = foo else { todo!() };
+
+ // The else block is multi-lined
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo else { return; };
+
+ // The else block will be single-lined because attributes and comments before `let`
+ // are no longer included when calculating max width
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo else { todo!() };
+
+ // Some more test cases for v2 formatting with attributes
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = opt
+ // pre else keyword line-comment
+ else { return; };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = opt else
+ // post else keyword line-comment
+ { return; };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Foo {x: Bar(..), y: FooBar(..), z: Baz(..)} = opt else {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) = opt else {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = very_very_very_very_very_very_very_very_very_very_very_very_long_expression_in_assign_rhs() else { return; };
+}
diff --git a/src/tools/rustfmt/tests/source/match.rs b/src/tools/rustfmt/tests/source/match.rs
index b5dc9957a..d1d8d7f2c 100644
--- a/src/tools/rustfmt/tests/source/match.rs
+++ b/src/tools/rustfmt/tests/source/match.rs
@@ -292,6 +292,9 @@ fn guards() {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
if fooooooooooooooooooooo &&
(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {}
+ Hi { friend } if let None = friend => {}
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if let Some(foooooooooooooo) = hiiiiiiiiiiiiiii => {}
+ aaaaaaaaaaaaaaaaa if let Superman { powers: Some(goteem), .. } = all::get_random_being::<Super>() => {}
}
}
diff --git a/src/tools/rustfmt/tests/source/non-lifetime-binders.rs b/src/tools/rustfmt/tests/source/non-lifetime-binders.rs
new file mode 100644
index 000000000..c26393c8f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/non-lifetime-binders.rs
@@ -0,0 +1,10 @@
+fn main() where for<'a, T: Sized + 'a, const C: usize> [&'a T; C]: Sized {
+ let x = for<T>
+ || {};
+
+ let y: dyn
+ for<T> Into<T>;
+
+ let z: for<T>
+ fn(T);
+}
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs
new file mode 100644
index 000000000..e0f5ddf52
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs
@@ -0,0 +1,9 @@
+// rustfmt-unstable: true
+// rustfmt-config: issue-5816.toml
+
+fn main() {
+ println!( "Hello, world!");
+ let x =
+7
+;
+}
diff --git a/src/tools/rustfmt/tests/target/extern-rust.rs b/src/tools/rustfmt/tests/target/extern-rust.rs
new file mode 100644
index 000000000..32824c912
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/extern-rust.rs
@@ -0,0 +1 @@
+extern "Rust" fn uwu() {}
diff --git a/src/tools/rustfmt/tests/target/immovable_generators.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
index 0bf7a2d91..f52cfa00f 100644
--- a/src/tools/rustfmt/tests/target/immovable_generators.rs
+++ b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
unsafe fn foo() {
let mut ga = static || {
diff --git a/src/tools/rustfmt/tests/target/issue-3984.rs b/src/tools/rustfmt/tests/target/issue-3984.rs
new file mode 100644
index 000000000..9e700c0f7
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-3984.rs
@@ -0,0 +1,12 @@
+use a::{item /* comment */};
+use b::{
+ a,
+ // comment
+ item,
+};
+use c::item; /* comment */
+use d::item; // really long comment (with `use` exactly 100 characters) ____________________________
+
+use std::e::{/* it's a comment! */ bar /* and another */};
+use std::f::{/* it's a comment! */ bar};
+use std::g::{bar /* and another */};
diff --git a/src/tools/rustfmt/tests/target/issue-4808.rs b/src/tools/rustfmt/tests/target/issue-4808.rs
new file mode 100644
index 000000000..cdef53a1b
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4808.rs
@@ -0,0 +1,13 @@
+trait Trait {
+ fn method(&self) {}
+}
+
+impl<F: Fn() -> T, T> Trait for F {}
+
+impl Trait for f32 {}
+
+fn main() {
+ || (10.).method();
+ (|| ..).method();
+ (|| 1..).method();
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5568.rs b/src/tools/rustfmt/tests/target/issue-5568.rs
new file mode 100644
index 000000000..03ca3a452
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5568.rs
@@ -0,0 +1,14 @@
+// rustfmt-max_width: 119
+// rustfmt-format_code_in_doc_comments: true
+
+mod libs {
+ fn mrbgems_sources() {
+ [
+ "mrbgems/mruby-compiler/core/codegen.c", // Ruby parser and bytecode generation
+ "mrbgems/mruby-compiler/core/y.tab.c", // Ruby parser and bytecode generation
+ "mrbgems/mruby-metaprog/src/metaprog.c", // APIs on Kernel and Module for accessing classes and variables
+ "mrbgems/mruby-method/src/method.c", // `Method`, `UnboundMethod`, and method APIs on Kernel and Module
+ "mrbgems/mruby-pack/src/pack.c", // Array#pack and String#unpack
+ ]
+ }
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5655/one.rs b/src/tools/rustfmt/tests/target/issue-5655/one.rs
new file mode 100644
index 000000000..1758ec56f
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5655/one.rs
@@ -0,0 +1,9 @@
+// rustfmt-version: One
+
+fn foo<T>(_: T)
+where
+ T: std::fmt::Debug,
+
+ T: std::fmt::Display,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5655/two.rs b/src/tools/rustfmt/tests/target/issue-5655/two.rs
new file mode 100644
index 000000000..14fbc3d13
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5655/two.rs
@@ -0,0 +1,8 @@
+// rustfmt-version: Two
+
+fn foo<T>(_: T)
+where
+ T: std::fmt::Debug,
+ T: std::fmt::Display,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5791.rs b/src/tools/rustfmt/tests/target/issue-5791.rs
new file mode 100644
index 000000000..3a44cf19a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5791.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+ (0.).to_string();
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs b/src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs
new file mode 100644
index 000000000..851073971
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs
@@ -0,0 +1,7 @@
+// rustfmt-trailing_semicolon: false
+
+fn foo() {}
+fn main() {
+ return;
+ foo()
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5835.rs b/src/tools/rustfmt/tests/target/issue-5835.rs
new file mode 100644
index 000000000..3e4da3492
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5835.rs
@@ -0,0 +1,8 @@
+// rustfmt-wrap_comments: true
+
+/// . a
+pub fn foo() {}
+
+pub fn main() {
+ // . a
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5852/default.rs b/src/tools/rustfmt/tests/target/issue-5852/default.rs
new file mode 100644
index 000000000..a86872a68
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/default.rs
@@ -0,0 +1,97 @@
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
+
+use foo::bar;
+
+use foo::bar;
+
+use foo::{
+ bar, // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar,
+};
+
+use foo::{
+ self, // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self,
+};
+
+use foo::{
+ self, // a
+};
+
+use foo::{self /* a */};
+
+use foo::{self /* a */};
+
+use foo::{
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ // abc
+ abc,
+ bar,
+};
+
+use foo::{
+ abc, // abc
+ bar,
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz,
+ },
+};
+
+use path::{self /*comment*/};
diff --git a/src/tools/rustfmt/tests/target/issue-5852/horizontal.rs b/src/tools/rustfmt/tests/target/issue-5852/horizontal.rs
new file mode 100644
index 000000000..017d83c9f
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/horizontal.rs
@@ -0,0 +1,99 @@
+// rustfmt-imports_layout: Horizontal
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
+
+use foo::bar;
+
+use foo::bar;
+
+use foo::{
+ bar, // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar,
+};
+
+use foo::{
+ self, // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self,
+};
+
+use foo::{
+ self, // a
+};
+
+use foo::{self /* a */};
+
+use foo::{self /* a */};
+
+use foo::{
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ // abc
+ abc,
+ bar,
+};
+
+use foo::{
+ abc, // abc
+ bar,
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz,
+ },
+};
+
+use path::{self /*comment*/};
diff --git a/src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs b/src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs
new file mode 100644
index 000000000..35e2d0a26
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs
@@ -0,0 +1,99 @@
+// rustfmt-imports_layout: HorizontalVertical
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
+
+use foo::bar;
+
+use foo::bar;
+
+use foo::{
+ bar, // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar,
+};
+
+use foo::{
+ self, // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self,
+};
+
+use foo::{
+ self, // a
+};
+
+use foo::{self /* a */};
+
+use foo::{self /* a */};
+
+use foo::{
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ // abc
+ abc,
+ bar,
+};
+
+use foo::{
+ abc, // abc
+ bar,
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz,
+ },
+};
+
+use path::{self /*comment*/};
diff --git a/src/tools/rustfmt/tests/target/issue-5852/issue_example.rs b/src/tools/rustfmt/tests/target/issue-5852/issue_example.rs
new file mode 100644
index 000000000..463262914
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/issue_example.rs
@@ -0,0 +1,8 @@
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
diff --git a/src/tools/rustfmt/tests/target/issue-5852/split.rs b/src/tools/rustfmt/tests/target/issue-5852/split.rs
new file mode 100644
index 000000000..e00086dd4
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/split.rs
@@ -0,0 +1,102 @@
+// rustfmt-imports_granularity: Item
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
+
+use foo::bar;
+
+use foo::bar;
+
+use foo::{
+ bar, // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar,
+};
+
+use foo::{
+ self, // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self,
+};
+
+use foo::{
+ self, // a
+};
+
+use foo::{self /* a */};
+
+use foo::{self /* a */};
+
+use foo::{
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::abc;
+use foo::bar;
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ // abc
+ abc,
+ bar,
+};
+
+use foo::{
+ abc, // abc
+ bar,
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz,
+ },
+};
+
+use path::{self /*comment*/};
diff --git a/src/tools/rustfmt/tests/target/issue-5852/vertical.rs b/src/tools/rustfmt/tests/target/issue-5852/vertical.rs
new file mode 100644
index 000000000..f53a68c94
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5852/vertical.rs
@@ -0,0 +1,105 @@
+// rustfmt-imports_layout: Vertical
+
+use std::{
+ fs,
+ // (temporarily commented, we'll need this again in a second) io,
+};
+
+use foo::{
+ self, // this is important
+};
+
+use foo::bar;
+
+use foo::bar;
+
+use foo::{
+ bar, // abc
+};
+
+use foo::{
+ bar,
+ // abc
+};
+
+use foo::{
+ // 345
+ bar,
+};
+
+use foo::{
+ self, // abc
+};
+
+use foo::{
+ self,
+ // abc
+};
+
+use foo::{
+ // 345
+ self,
+};
+
+use foo::{
+ self, // a
+};
+
+use foo::{
+ self, /* a */
+};
+
+use foo::{
+ self, /* a */
+};
+
+use foo::{
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ // abc
+ abc,
+ bar,
+};
+
+use foo::{
+ abc, // abc
+ bar,
+};
+
+use foo::{
+ abc,
+ // abc
+ bar,
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ xyz, // 123
+ },
+};
+
+use foo::{
+ self,
+ // abc
+ abc::{
+ // 123
+ xyz,
+ },
+};
+
+use path::{
+ self, /*comment*/
+};
diff --git a/src/tools/rustfmt/tests/target/issue-5871.rs b/src/tools/rustfmt/tests/target/issue-5871.rs
new file mode 100644
index 000000000..3116533bc
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5871.rs
@@ -0,0 +1,8 @@
+#![feature(stmt_expr_attributes)]
+fn okay() -> u32 {
+ (
+ // Comments in parentheses-expressions caused attributes to be duplicated.
+ #[allow(unused_variables)]
+ 0
+ )
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5935.rs b/src/tools/rustfmt/tests/target/issue-5935.rs
new file mode 100644
index 000000000..ebc62c464
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5935.rs
@@ -0,0 +1,8 @@
+struct Regs<
+ const BEGIN: u64,
+ const END: u64,
+ const DIM: usize,
+ const N: usize = { (END - BEGIN) as usize / (8 * DIM) + 1 },
+> {
+ _foo: u64,
+}
diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs
index d3734e90b..ea8fa3b73 100644
--- a/src/tools/rustfmt/tests/target/issue_4110.rs
+++ b/src/tools/rustfmt/tests/target/issue_4110.rs
@@ -12,7 +12,7 @@ fn bindings() {
span,
..
},
- ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+ ) if borrow_spans.for_coroutine() | borrow_spans.for_closure() => self
.report_escaping_closure_capture(
borrow_spans,
borrow_span,
diff --git a/src/tools/rustfmt/tests/target/issue_5533.rs b/src/tools/rustfmt/tests/target/issue_5533.rs
new file mode 100644
index 000000000..c3095a440
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5533.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_code_in_doc_comments: true
+
+struct TestStruct {
+ position_currency: String, // Currency for position of this contract. If not null, 1 contract = 1 positionCurrency.
+ pu: Option<i64>, // Previous event update sequense ("u" of previous message), -1 also means None
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5542.rs b/src/tools/rustfmt/tests/target/issue_5542.rs
new file mode 100644
index 000000000..730bb7b68
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5542.rs
@@ -0,0 +1,10 @@
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+use core::fmt::Debug;
+
+fn main() {
+ let i = 42;
+ let dyn_i = i as dyn* Debug;
+ dbg!(dyn_i);
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5676.rs b/src/tools/rustfmt/tests/target/issue_5676.rs
new file mode 100644
index 000000000..258771105
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5676.rs
@@ -0,0 +1,8 @@
+fn main() {
+ match true {
+ true => 'a: {
+ break 'a;
+ }
+ _ => (),
+ }
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5721.rs b/src/tools/rustfmt/tests/target/issue_5721.rs
new file mode 100644
index 000000000..d073b09ca
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5721.rs
@@ -0,0 +1,10 @@
+#![feature(non_lifetime_binders)]
+#![allow(incomplete_features)]
+
+trait Other<U: ?Sized> {}
+
+trait Trait<U>
+where
+ for<T> U: Other<T>,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5730.rs b/src/tools/rustfmt/tests/target/issue_5730.rs
new file mode 100644
index 000000000..7922fdcc9
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5730.rs
@@ -0,0 +1,3 @@
+macro_rules! statement {
+ () => {};
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5735.rs b/src/tools/rustfmt/tests/target/issue_5735.rs
new file mode 100644
index 000000000..2d1376303
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5735.rs
@@ -0,0 +1,6 @@
+fn find_errors(mut self) {
+ let errors: Vec = vec![
+ #[debug_format = "A({})"]
+ struct A {}
+ ];
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5882.rs b/src/tools/rustfmt/tests/target/issue_5882.rs
new file mode 100644
index 000000000..565fb434a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5882.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {}
+macro_rules! bar { /*comment*/ }
+macro_rules! baz { //comment
+}
+macro_rules! foobar {
+ //comment
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5907.rs b/src/tools/rustfmt/tests/target/issue_5907.rs
new file mode 100644
index 000000000..144de636b
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5907.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_code_in_doc_comments: true
+
+// ```
+// [
+// ]
+// ```
diff --git a/src/tools/rustfmt/tests/target/let_chains.rs b/src/tools/rustfmt/tests/target/let_chains.rs
new file mode 100644
index 000000000..1ceecac8a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/let_chains.rs
@@ -0,0 +1,129 @@
+fn main() {
+ if let x = x
+ && x
+ {}
+
+ if xxx && let x = x {}
+
+ if aaaaaaaaaaaaaaaaaaaaa
+ && aaaaaaaaaaaaaaa
+ && aaaaaaaaa
+ && let Some(x) = xxxxxxxxxxxx
+ && aaaaaaa
+ && let None = aaaaaaaaaa
+ {}
+
+ if aaaaaaaaaaaaaaaaaaaaa
+ && aaaaaaaaaaaaaaa
+ && aaaaaaaaa
+ && let Some(x) = xxxxxxxxxxxx
+ && aaaaaaa
+ && let None = aaaaaaaaaa
+ {}
+
+ if let Some(Struct { x: TS(1, 2) }) = path::to::<_>(hehe)
+ && let [Simple, people] = /* get ready */
+ create_universe(/* hi */ GreatPowers)
+ .initialize_badminton()
+ .populate_swamps()
+ && let everybody = (Loops {
+ hi, /*hi*/
+ ..loopy()
+ })
+ && summons::triumphantly()
+ {
+ todo!()
+ }
+
+ if let XXXXXXXXX {
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
+ yyyyyyyyyyyyy,
+ zzzzzzzzzzzzz,
+ } = xxxxxxx()
+ && let Foo = bar()
+ {
+ todo!()
+ }
+}
+
+fn test_single_line_let_chain() {
+ // first item in let-chain is an ident
+ if a && let Some(b) = foo() {}
+
+ // first item in let-chain is a unary ! with an ident
+ let unary_not = if !from_hir_call && let Some(p) = parent {};
+
+ // first item in let-chain is a unary * with an ident
+ let unary_deref = if *some_deref && let Some(p) = parent {};
+
+ // first item in let-chain is a unary - (neg) with an ident
+ let unary_neg = if -some_ident && let Some(p) = parent {};
+
+ // first item in let-chain is a try (?) with an ident
+ let try_ = if some_try? && let Some(p) = parent {};
+
+ // first item in let-chain is an ident wrapped in parens
+ let in_parens = if (some_ident) && let Some(p) = parent {};
+
+ // first item in let-chain is a ref & with an ident
+ let _ref = if &some_ref && let Some(p) = parent {};
+
+ // first item in let-chain is a ref &mut with an ident
+ let mut_ref = if &mut some_ref && let Some(p) = parent {};
+
+ // chain unary ref and try
+ let chain_of_unary_ref_and_try = if !&*some_ref? && let Some(p) = parent {};
+}
+
+fn test_multi_line_let_chain() {
+ // Can only single line the let-chain if the first item is an ident
+ if let Some(x) = y
+ && a
+ {}
+
+ // More than one let-chain must be formatted on multiple lines
+ if let Some(x) = y
+ && let Some(a) = b
+ {}
+
+ // The ident isn't long enough so we don't wrap the first let-chain
+ if a && let Some(x) = y
+ && let Some(a) = b
+ {}
+
+ // The ident is long enough so both let-chains are wrapped
+ if aaa
+ && let Some(x) = y
+ && let Some(a) = b
+ {}
+
+ // function call
+ if a()
+ && let Some(x) = y
+ {}
+
+ // bool literal
+ if true
+ && let Some(x) = y
+ {}
+
+ // cast to a bool
+ if 1 as bool
+ && let Some(x) = y
+ {}
+
+ // matches! macro call
+ if matches!(a, some_type)
+ && let Some(x) = y
+ {}
+
+ // block expression returning bool
+ if { true }
+ && let Some(x) = y
+ {}
+
+ // field access
+ if a.x
+ && let Some(x) = y
+ {}
+}
diff --git a/src/tools/rustfmt/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs
index 6554a0961..f6560e854 100644
--- a/src/tools/rustfmt/tests/target/let_else.rs
+++ b/src/tools/rustfmt/tests/target/let_else.rs
@@ -252,3 +252,34 @@ fn with_trailing_try_operator() {
return;
};
}
+
+fn issue5901() {
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo
+ else {
+ todo!()
+ };
+
+ #[cfg(target_os = "linux")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo
+ else {
+ todo!()
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = foo
+ else {
+ todo!()
+ };
+
+ // The else block will be multi-lined because attributes and comments before `let`
+ // are included when calculating max width
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo() else {
+ todo!()
+ };
+}
diff --git a/src/tools/rustfmt/tests/target/let_else_v2.rs b/src/tools/rustfmt/tests/target/let_else_v2.rs
new file mode 100644
index 000000000..b25ac1609
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/let_else_v2.rs
@@ -0,0 +1,73 @@
+// rustfmt-version: Two
+// rustfmt-single_line_let_else_max_width: 100
+
+fn issue5901() {
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo else { todo!() };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = foo else { todo!() };
+
+ // The else block is multi-lined
+ #[cfg(target_os = "linux")]
+ let Some(x) = foo else {
+ return;
+ };
+
+ // The else block will be single-lined because attributes and comments before `let`
+ // are no longer included when calculating max width
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ // Some comments between attributes and let-else statement
+ let Some(x) = foo else { todo!() };
+
+ // Some more test cases for v2 formatting with attributes
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = opt
+ // pre else keyword line-comment
+ else {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) = opt else
+ // post else keyword line-comment
+ {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Foo {
+ x: Bar(..),
+ y: FooBar(..),
+ z: Baz(..),
+ } = opt
+ else {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) =
+ opt
+ else {
+ return;
+ };
+
+ #[cfg(target_os = "linux")]
+ #[cfg(target_arch = "x86_64")]
+ let Some(x) =
+ very_very_very_very_very_very_very_very_very_very_very_very_long_expression_in_assign_rhs()
+ else {
+ return;
+ };
+}
diff --git a/src/tools/rustfmt/tests/target/match.rs b/src/tools/rustfmt/tests/target/match.rs
index 1bf3fb758..0e7815a81 100644
--- a/src/tools/rustfmt/tests/target/match.rs
+++ b/src/tools/rustfmt/tests/target/match.rs
@@ -317,6 +317,14 @@ fn guards() {
if fooooooooooooooooooooo
&& (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|| cccccccccccccccccccccccccccccccccccccccc) => {}
+ Hi { friend } if let None = friend => {}
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ if let Some(foooooooooooooo) = hiiiiiiiiiiiiiii => {}
+ aaaaaaaaaaaaaaaaa
+ if let Superman {
+ powers: Some(goteem),
+ ..
+ } = all::get_random_being::<Super>() => {}
}
}
diff --git a/src/tools/rustfmt/tests/target/non-lifetime-binders.rs b/src/tools/rustfmt/tests/target/non-lifetime-binders.rs
new file mode 100644
index 000000000..ca6941a0c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/non-lifetime-binders.rs
@@ -0,0 +1,10 @@
+fn main()
+where
+ for<'a, T: Sized + 'a, const C: usize> [&'a T; C]: Sized,
+{
+ let x = for<T> || {};
+
+ let y: dyn for<T> Into<T>;
+
+ let z: for<T> fn(T);
+}
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs
new file mode 100644
index 000000000..008e28db4
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs
@@ -0,0 +1,7 @@
+// rustfmt-unstable: true
+// rustfmt-config: issue-5816.toml
+
+fn main() {
+ println!( "Hello, world!");
+ let x = 7;
+}
diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml
index fa0824ac5..b8691192e 100644
--- a/src/tools/rustfmt/triagebot.toml
+++ b/src/tools/rustfmt/triagebot.toml
@@ -1 +1,4 @@
+[autolabel."pr-not-reviewed"]
+new_pr = true
+
[assign]