summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rustfmt')
-rw-r--r--src/tools/rustfmt/.github/workflows/check_diff.yml33
-rw-r--r--src/tools/rustfmt/.github/workflows/integration.yml4
-rw-r--r--src/tools/rustfmt/CHANGELOG.md28
-rw-r--r--src/tools/rustfmt/Cargo.lock4
-rw-r--r--src/tools/rustfmt/Cargo.toml4
-rw-r--r--src/tools/rustfmt/Configurations.md185
-rw-r--r--src/tools/rustfmt/Processes.md2
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.bat1
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.sh1
-rwxr-xr-xsrc/tools/rustfmt/ci/check_diff.sh199
-rwxr-xr-xsrc/tools/rustfmt/ci/integration.sh18
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.lock2
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.toml2
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/attrs.rs27
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/item_enum.rs40
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/lib.rs13
-rw-r--r--src/tools/rustfmt/config_proc_macro/tests/smoke.rs1
-rw-r--r--src/tools/rustfmt/rust-toolchain4
-rw-r--r--src/tools/rustfmt/src/attr.rs4
-rw-r--r--src/tools/rustfmt/src/bin/main.rs2
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/main.rs12
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/test/mod.rs4
-rw-r--r--src/tools/rustfmt/src/chains.rs124
-rw-r--r--src/tools/rustfmt/src/closures.rs3
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs122
-rw-r--r--src/tools/rustfmt/src/config/macro_names.rs118
-rw-r--r--src/tools/rustfmt/src/config/mod.rs149
-rw-r--r--src/tools/rustfmt/src/expr.rs14
-rw-r--r--src/tools/rustfmt/src/imports.rs4
-rw-r--r--src/tools/rustfmt/src/items.rs10
-rw-r--r--src/tools/rustfmt/src/lib.rs1
-rw-r--r--src/tools/rustfmt/src/lists.rs16
-rw-r--r--src/tools/rustfmt/src/macros.rs26
-rw-r--r--src/tools/rustfmt/src/modules.rs13
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs3
-rw-r--r--src/tools/rustfmt/src/parse/session.rs9
-rw-r--r--src/tools/rustfmt/src/skip.rs79
-rw-r--r--src/tools/rustfmt/src/test/configuration_snippet.rs7
-rw-r--r--src/tools/rustfmt/src/test/mod.rs6
-rw-r--r--src/tools/rustfmt/src/types.rs44
-rw-r--r--src/tools/rustfmt/src/utils.rs6
-rw-r--r--src/tools/rustfmt/src/visitor.rs13
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/main.rs29
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml8
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs13
-rw-r--r--src/tools/rustfmt/tests/config/small_tabs.toml2
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt2
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt2
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs21
-rw-r--r--src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/rustfmt/tests/source/comments_unicode.rs140
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/enum.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn-custom-7.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn-custom.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs26
-rw-r--r--src/tools/rustfmt/tests/source/issue-4643.rs23
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/one.rs149
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/two.rs149
-rw-r--r--src/tools/rustfmt/tests/source/issue_1306.rs29
-rw-r--r--src/tools/rustfmt/tests/source/issue_3245.rs4
-rw-r--r--src/tools/rustfmt/tests/source/issue_3561.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs16
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs32
-rw-r--r--src/tools/rustfmt/tests/source/tuple.rs2
-rw-r--r--src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs2
-rw-r--r--src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/rustfmt/tests/target/comments_unicode.rs140
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/enum.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn-custom-7.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn-custom.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs26
-rw-r--r--src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs21
-rw-r--r--src/tools/rustfmt/tests/target/issue-4643.rs19
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/one.rs150
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/two.rs152
-rw-r--r--src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5358.rs4
-rw-r--r--src/tools/rustfmt/tests/target/issue_1306.rs33
-rw-r--r--src/tools/rustfmt/tests/target/issue_3033.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue_3245.rs4
-rw-r--r--src/tools/rustfmt/tests/target/issue_3561.rs7
-rw-r--r--src/tools/rustfmt/tests/target/issue_4350.rs13
-rw-r--r--src/tools/rustfmt/tests/target/issue_5668.rs8
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs16
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs32
-rw-r--r--src/tools/rustfmt/tests/target/tuple.rs2
-rw-r--r--src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs2
113 files changed, 2621 insertions, 204 deletions
diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml
new file mode 100644
index 000000000..8bfb58345
--- /dev/null
+++ b/src/tools/rustfmt/.github/workflows/check_diff.yml
@@ -0,0 +1,33 @@
+name: Diff Check
+on:
+ workflow_dispatch:
+ inputs:
+ clone_url:
+ description: 'Git url of a rustfmt fork to compare against the latest master rustfmt'
+ required: true
+ branch_name:
+ description: 'Name of the feature branch on the forked repo'
+ required: true
+ commit_hash:
+ description: 'Optional commit hash from the feature branch'
+ required: false
+ rustfmt_configs:
+ description: 'Optional comma separated list of rustfmt config options to pass when running the feature branch'
+ required: false
+
+jobs:
+ diff_check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+
+ - name: install rustup
+ run: |
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+ sh rustup-init.sh -y --default-toolchain none
+ 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 }}
diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml
index 4d8899b43..314ce0e84 100644
--- a/src/tools/rustfmt/.github/workflows/integration.yml
+++ b/src/tools/rustfmt/.github/workflows/integration.yml
@@ -27,7 +27,6 @@ jobs:
tempdir,
futures-rs,
rust-clippy,
- failure,
]
include:
# Allowed Failures
@@ -63,9 +62,6 @@ jobs:
# Original comment was: temporal build failure due to breaking changes in the nightly compiler
- integration: rust-semverver
allow-failure: true
- # Can be moved back to include section after https://github.com/rust-lang-nursery/failure/pull/298 is merged
- - integration: failure
- allow-failure: true
steps:
- name: checkout
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 0c1893bf8..60f961fa1 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -2,6 +2,32 @@
## [Unreleased]
+## [1.5.2] 2023-01-24
+
+### Fixed
+
+- Resolve issue when comments are found within const generic defaults in unit structs [#5668](https://github.com/rust-lang/rustfmt/issues/5668)
+- Resolve issue when block comments are found within trait generics [#5358](https://github.com/rust-lang/rustfmt/issues/5358)
+- Correctly handle alignment of comments containing unicode characters [#5504](https://github.com/rust-lang/rustfmt/issues/5504)
+- Properly indent a single generic bound that requires being written across multiple lines [#4689](https://github.com/rust-lang/rustfmt/issues/4689) (n.b. this change is version gated and will only appear when the `version` configuration option is set to `Two`)
+
+### Changed
+
+- Renamed `fn_args_layout` configuration option to `fn_params_layout` [#4149](https://github.com/rust-lang/rustfmt/issues/4149). Note that `fn_args_layout` has only been soft deprecated: `fn_args_layout` will continue to work without issue, but rustfmt will display a warning to encourage users to switch to the new name
+
+### Added
+
+- New configuration option (`skip_macro_invocations`)[https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations] [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726)
+
+### Misc
+
+- rustfmt now internally supports the ability to have both stable and unstable variants of a configuration option [#5378](https://github.com/rust-lang/rustfmt/issues/5378). This ability will allow the rustfmt team to make certain configuration options available on stable toolchains more quickly because we no longer have to wait for _every_ variant to be stable-ready before stabilizing _any_ variant.
+
+### Install/Download Options
+- **rustup (nightly)** - nightly-2023-01-24
+- **GitHub Release Binaries** - [Release v1.5.2](https://github.com/rust-lang/rustfmt/releases/tag/v1.5.2)
+- **Build from source** - [Tag v1.5.2](https://github.com/rust-lang/rustfmt/tree/v1.5.2), see instructions for how to [install rustfmt from source][install-from-source]
+
## [1.5.1] 2022-06-24
**N.B** A bug was introduced in v1.5.0/nightly-2022-06-15 which modified formatting. If you happened to run rustfmt over your code with one of those ~10 nightlies it's possible you may have seen formatting changes, and you may see additional changes after this fix since that bug has now been reverted.
@@ -840,7 +866,7 @@ from formatting an attribute #3665
- Fix formatting of raw string literals #2983
- Handle chain with try operators with spaces #2986
- Use correct shape in Visual tuple rewriting #2987
-- Impove formatting of arguments with `visual_style = "Visual"` option #2988
+- Improve formatting of arguments with `visual_style = "Visual"` option #2988
- Change `print_diff` to output the correct line number 992b179
- Propagate errors about failing to rewrite a macro 6f318e3
- Handle formatting of long function signature #3010
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index 311df226d..24166d51c 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -476,7 +476,7 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb"
[[package]]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@@ -485,7 +485,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
-version = "1.5.1"
+version = "1.5.2"
dependencies = [
"annotate-snippets",
"anyhow",
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 7a4e02d69..87ce59d02 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustfmt-nightly"
-version = "1.5.1"
+version = "1.5.2"
description = "Tool to find and fix Rust formatting issues"
repository = "https://github.com/rust-lang/rustfmt"
readme = "README.md"
@@ -57,7 +57,7 @@ unicode-segmentation = "1.9"
unicode-width = "0.1"
unicode_categories = "0.1"
-rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
+rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" }
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index 8b96b9d36..49e7e4e64 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -1,6 +1,6 @@
# Configuring Rustfmt
-Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/1.0.4/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
+Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this:
@@ -425,7 +425,7 @@ fn example() {
## `comment_width`
-Maximum length of comments. No effect unless`wrap_comments = true`.
+Maximum length of comments. No effect unless `wrap_comments = true`.
- **Default value**: `80`
- **Possible values**: any positive integer
@@ -589,7 +589,7 @@ doesn't get ignored when aligning.
#### `0` (default):
```rust
-enum Bar {
+enum Foo {
A = 0,
Bb = 1,
RandomLongVariantGoesHere = 10,
@@ -645,7 +645,8 @@ trailing whitespaces.
## `fn_args_layout`
-Control the layout of arguments in a function
+This option is deprecated and has been renamed to `fn_params_layout` to better communicate that
+it affects the layout of parameters in function signatures.
- **Default value**: `"Tall"`
- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
@@ -753,6 +754,8 @@ trait Lorem {
}
```
+See also [`fn_params_layout`](#fn_params_layout)
+
## `fn_call_width`
Maximum width of the args of a function call before falling back to vertical formatting.
@@ -765,6 +768,117 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
+## `fn_params_layout`
+
+Control the layout of parameters in function signatures.
+
+- **Default value**: `"Tall"`
+- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
+- **Stable**: Yes
+
+#### `"Tall"` (default):
+
+```rust
+trait Lorem {
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet);
+
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+#### `"Compressed"`:
+
+```rust
+trait Lorem {
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet);
+
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur,
+ adipiscing: Adipiscing, elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur,
+ adipiscing: Adipiscing, elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+#### `"Vertical"`:
+
+```rust
+trait Lorem {
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ ) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+
## `fn_single_line`
Put single-expression functions on a single line
@@ -1014,6 +1128,62 @@ macro_rules! foo {
See also [`format_macro_matchers`](#format_macro_matchers).
+## `skip_macro_invocations`
+
+Skip formatting the bodies of macro invocations with the following names.
+
+rustfmt will not format any macro invocation for macros with names set in this list.
+Including the special value "*" will prevent any macro invocations from being formatted.
+
+Note: This option does not have any impact on how rustfmt formats macro definitions.
+
+- **Default value**: `[]`
+- **Possible values**: a list of macro name idents, `["name_0", "name_1", ..., "*"]`
+- **Stable**: No (tracking issue: [#5346](https://github.com/rust-lang/rustfmt/issues/5346))
+
+#### `[]` (default):
+
+rustfmt will follow its standard approach to formatting macro invocations.
+
+No macro invocations will be skipped based on their name. More information about rustfmt's standard macro invocation formatting behavior can be found in [#5437](https://github.com/rust-lang/rustfmt/discussions/5437).
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
+
+#### `["lorem"]`:
+
+The named macro invocations will be skipped.
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
+
+#### `["*"]`:
+
+The special selector `*` will skip all macro invocations.
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
## `format_strings`
@@ -1687,13 +1857,16 @@ pub enum Foo {}
## `imports_granularity`
-How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity.
+Controls how imports are structured in `use` statements. Imports will be merged or split to the configured level of granularity.
+
+Similar to other `import` related configuration options, this option operates within the bounds of user-defined groups of imports. See [`group_imports`](#group_imports) for more information on import groups.
+
+Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments.
- **Default value**: `Preserve`
- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
- **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991))
-Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments.
#### `Preserve` (default):
diff --git a/src/tools/rustfmt/Processes.md b/src/tools/rustfmt/Processes.md
index f763b5714..61abc87ee 100644
--- a/src/tools/rustfmt/Processes.md
+++ b/src/tools/rustfmt/Processes.md
@@ -2,7 +2,7 @@ This document outlines processes regarding management of rustfmt.
# Stabilising an Option
-In this Section, we describe how to stabilise an option of the rustfmt's configration.
+In this Section, we describe how to stabilise an option of the rustfmt's configuration.
## Conditions
diff --git a/src/tools/rustfmt/ci/build_and_test.bat b/src/tools/rustfmt/ci/build_and_test.bat
index ef4101778..69dae1fff 100755
--- a/src/tools/rustfmt/ci/build_and_test.bat
+++ b/src/tools/rustfmt/ci/build_and_test.bat
@@ -1,4 +1,5 @@
set "RUSTFLAGS=-D warnings"
+set "RUSTFMT_CI=1"
:: Print version information
rustc -Vv || exit /b 1
diff --git a/src/tools/rustfmt/ci/build_and_test.sh b/src/tools/rustfmt/ci/build_and_test.sh
index 8fa0f67b0..949918532 100755
--- a/src/tools/rustfmt/ci/build_and_test.sh
+++ b/src/tools/rustfmt/ci/build_and_test.sh
@@ -3,6 +3,7 @@
set -euo pipefail
export RUSTFLAGS="-D warnings"
+export RUSTFMT_CI=1
# Print version information
rustc -Vv
diff --git a/src/tools/rustfmt/ci/check_diff.sh b/src/tools/rustfmt/ci/check_diff.sh
new file mode 100755
index 000000000..062c2dd86
--- /dev/null
+++ b/src/tools/rustfmt/ci/check_diff.sh
@@ -0,0 +1,199 @@
+#!/bin/bash
+
+function print_usage() {
+ echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]"
+}
+
+if [ $# -le 1 ]; then
+ print_usage
+ exit 1
+fi
+
+REMOTE_REPO=$1
+FEATURE_BRANCH=$2
+OPTIONAL_COMMIT_HASH=$3
+OPTIONAL_RUSTFMT_CONFIGS=$4
+
+# OUTPUT array used to collect all the status of running diffs on various repos
+STATUSES=()
+
+# Clone a git repository and cd into it.
+#
+# Parameters:
+# $1: git clone url
+# $2: directory where the repo should be cloned
+function clone_repo() {
+ GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2
+}
+
+# Initialize Git submoduels for the repo.
+#
+# Parameters
+# $1: list of directories to initialize
+function init_submodules() {
+ git submodule update --init $1
+}
+
+# Run rusfmt with the --check flag to see if a diff is produced.
+#
+# Parameters:
+# $1: Path to a rustfmt binary
+# $2: Output file path for the diff
+# $3: Any additional configuration options to pass to rustfmt
+#
+# Globlas:
+# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
+function create_diff() {
+ local config;
+ if [ -z "$3" ]; then
+ config="--config=error_on_line_overflow=false,error_on_unformatted=false"
+ else
+ config="--config=error_on_line_overflow=false,error_on_unformatted=false,$OPTIONAL_RUSTFMT_CONFIGS"
+ fi
+
+ for i in `find . | grep "\.rs$"`
+ do
+ $1 --unstable-features --skip-children --check --color=always $config $i >> $2 2>/dev/null
+ done
+}
+
+# Run the master rustfmt binary and the feature branch binary in the current directory and compare the diffs
+#
+# Parameters
+# $1: Name of the repository (used for logging)
+#
+# Globlas:
+# $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt`
+# $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt`
+# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
+function check_diff() {
+ echo "running rustfmt (master) on $1"
+ create_diff $RUSFMT_BIN rustfmt_diff.txt
+
+ echo "running rustfmt (feature) on $1"
+ create_diff $FEATURE_BIN feature_diff.txt $OPTIONAL_RUSTFMT_CONFIGS
+
+ echo "checking diff"
+ local diff;
+ # we don't add color to the diff since we added color when running rustfmt --check.
+ # tail -n + 6 removes the git diff header info
+ # cut -c 2- removes the leading diff characters("+","-"," ") from running git diff.
+ # Again, the diff output we care about was already added when we ran rustfmt --check
+ diff=$(
+ git --no-pager diff --color=never \
+ --unified=0 --no-index rustfmt_diff.txt feature_diff.txt 2>&1 | tail -n +6 | cut -c 2-
+ )
+
+ if [ -z "$diff" ]; then
+ echo "no diff detected between rustfmt and the feture branch"
+ return 0
+ else
+ echo "$diff"
+ return 1
+ fi
+}
+
+# Compiles and produces two rustfmt binaries.
+# One for the current master, and another for the feature branch
+#
+# Parameters:
+# $1: Directory where rustfmt will be cloned
+#
+# Globlas:
+# $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test
+# $FEATURE_BRANCH: Name of the feature branch
+# $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided
+function compile_rustfmt() {
+ RUSTFMT_REPO="https://github.com/rust-lang/rustfmt.git"
+ clone_repo $RUSTFMT_REPO $1
+ git remote add feature $REMOTE_REPO
+ git fetch feature $FEATURE_BRANCH
+
+ cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
+ if [ -z "$OPTIONAL_COMMIT_HASH" ]; then
+ git switch $FEATURE_BRANCH
+ else
+ git switch $OPTIONAL_COMMIT_HASH --detach
+ fi
+ cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt
+ RUSFMT_BIN=$1/rustfmt
+ FEATURE_BIN=$1/feature_rustfmt
+}
+
+# Check the diff for running rustfmt and the feature branch on all the .rs files in the repo.
+#
+# Parameters
+# $1: Clone URL for the repo
+# $2: Name of the repo (mostly used for logging)
+# $3: Path to any submodules that should be initialized
+function check_repo() {
+ WORKDIR=$(pwd)
+ REPO_URL=$1
+ REPO_NAME=$2
+ SUBMODULES=$3
+
+ local tmp_dir;
+ tmp_dir=$(mktemp -d -t $REPO_NAME-XXXXXXXX)
+ clone_repo $REPO_URL $tmp_dir
+
+ if [ ! -z "$SUBMODULES" ]; then
+ init_submodules $SUBMODULES
+ fi
+
+ check_diff $REPO_NAME
+ # append the status of running `check_diff` to the STATUSES array
+ STATUSES+=($?)
+
+ echo "removing tmp_dir $tmp_dir"
+ rm -rf $tmp_dir
+ cd $WORKDIR
+}
+
+function main() {
+ tmp_dir=$(mktemp -d -t rustfmt-XXXXXXXX)
+ echo Created tmp_dir $tmp_dir
+
+ compile_rustfmt $tmp_dir
+
+ # run checks
+ check_repo "https://github.com/rust-lang/rust.git" rust-lang-rust
+ check_repo "https://github.com/rust-lang/cargo.git" cargo
+ check_repo "https://github.com/rust-lang/miri.git" miri
+ check_repo "https://github.com/rust-lang/rust-analyzer.git" rust-analyzer
+ check_repo "https://github.com/bitflags/bitflags.git" bitflags
+ check_repo "https://github.com/rust-lang/log.git" log
+ check_repo "https://github.com/rust-lang/mdBook.git" mdBook
+ check_repo "https://github.com/rust-lang/packed_simd.git" packed_simd
+ check_repo "https://github.com/rust-lang/rust-semverver.git" check_repo
+ check_repo "https://github.com/Stebalien/tempfile.git" tempfile
+ check_repo "https://github.com/rust-lang/futures-rs.git" futures-rs
+ check_repo "https://github.com/dtolnay/anyhow.git" anyhow
+ check_repo "https://github.com/dtolnay/thiserror.git" thiserror
+ check_repo "https://github.com/dtolnay/syn.git" syn
+ check_repo "https://github.com/serde-rs/serde.git" serde
+ check_repo "https://github.com/rust-lang/rustlings.git" rustlings
+ check_repo "https://github.com/rust-lang/rustup.git" rustup
+ check_repo "https://github.com/SergioBenitez/Rocket.git" Rocket
+ check_repo "https://github.com/rustls/rustls.git" rustls
+ check_repo "https://github.com/rust-lang/rust-bindgen.git" rust-bindgen
+ check_repo "https://github.com/hyperium/hyper.git" hyper
+ check_repo "https://github.com/actix/actix.git" actix
+ check_repo "https://github.com/denoland/deno.git" denoland_deno
+
+ # cleanup temp dir
+ echo removing tmp_dir $tmp_dir
+ rm -rf $tmp_dir
+
+ # figure out the exit code
+ for status in ${STATUSES[@]}
+ do
+ if [ $status -eq 1 ]; then
+ echo "formatting diff found 💔"
+ return 1
+ fi
+ done
+
+ echo "no diff found 😊"
+}
+
+main
diff --git a/src/tools/rustfmt/ci/integration.sh b/src/tools/rustfmt/ci/integration.sh
index 562d5d70c..19d502bc5 100755
--- a/src/tools/rustfmt/ci/integration.sh
+++ b/src/tools/rustfmt/ci/integration.sh
@@ -91,14 +91,28 @@ case ${INTEGRATION} in
cd -
;;
crater)
- git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git
+ git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git
cd ${INTEGRATION}
show_head
check_fmt_with_lib_tests
cd -
;;
+ bitflags)
+ git clone --depth=1 https://github.com/bitflags/${INTEGRATION}.git
+ cd ${INTEGRATION}
+ show_head
+ check_fmt_with_all_tests
+ cd -
+ ;;
+ error-chain | tempdir)
+ git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git
+ cd ${INTEGRATION}
+ show_head
+ check_fmt_with_all_tests
+ cd -
+ ;;
*)
- git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git
+ git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git
cd ${INTEGRATION}
show_head
check_fmt_with_all_tests
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.lock b/src/tools/rustfmt/config_proc_macro/Cargo.lock
index ecf561f28..49f2f72a8 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.lock
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.lock
@@ -22,7 +22,7 @@ dependencies = [
[[package]]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.toml b/src/tools/rustfmt/config_proc_macro/Cargo.toml
index a41b3a5e6..d10d0469c 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.toml
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
edition = "2018"
description = "A collection of procedural macros for rustfmt"
license = "Apache-2.0/MIT"
diff --git a/src/tools/rustfmt/config_proc_macro/src/attrs.rs b/src/tools/rustfmt/config_proc_macro/src/attrs.rs
index 0baba046f..dd18ff572 100644
--- a/src/tools/rustfmt/config_proc_macro/src/attrs.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/attrs.rs
@@ -1,8 +1,10 @@
//! This module provides utilities for handling attributes on variants
-//! of `config_type` enum. Currently there are two types of attributes
-//! that could appear on the variants of `config_type` enum: `doc_hint`
-//! and `value`. Both comes in the form of name-value pair whose value
-//! is string literal.
+//! of `config_type` enum. Currently there are the following attributes
+//! that could appear on the variants of `config_type` enum:
+//!
+//! - `doc_hint`: name-value pair whose value is string literal
+//! - `value`: name-value pair whose value is string literal
+//! - `unstable_variant`: name only
/// Returns the value of the first `doc_hint` attribute in the given slice or
/// `None` if `doc_hint` attribute is not available.
@@ -27,6 +29,11 @@ pub fn find_config_value(attrs: &[syn::Attribute]) -> Option<String> {
attrs.iter().filter_map(config_value).next()
}
+/// Returns `true` if the there is at least one `unstable` attribute in the given slice.
+pub fn any_unstable_variant(attrs: &[syn::Attribute]) -> bool {
+ attrs.iter().any(is_unstable_variant)
+}
+
/// Returns a string literal value if the given attribute is `value`
/// attribute or `None` otherwise.
pub fn config_value(attr: &syn::Attribute) -> Option<String> {
@@ -38,6 +45,11 @@ pub fn is_config_value(attr: &syn::Attribute) -> bool {
is_attr_name_value(attr, "value")
}
+/// Returns `true` if the given attribute is an `unstable` attribute.
+pub fn is_unstable_variant(attr: &syn::Attribute) -> bool {
+ is_attr_path(attr, "unstable_variant")
+}
+
fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
attr.parse_meta().ok().map_or(false, |meta| match meta {
syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true,
@@ -45,6 +57,13 @@ fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
})
}
+fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool {
+ attr.parse_meta().ok().map_or(false, |meta| match meta {
+ syn::Meta::Path(path) if path.is_ident(name) => true,
+ _ => false,
+ })
+}
+
fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> {
attr.parse_meta().ok().and_then(|meta| match meta {
syn::Meta::NameValue(syn::MetaNameValue {
diff --git a/src/tools/rustfmt/config_proc_macro/src/item_enum.rs b/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
index dcee77a85..731a7ea06 100644
--- a/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
@@ -1,5 +1,6 @@
use proc_macro2::TokenStream;
-use quote::quote;
+use quote::{quote, quote_spanned};
+use syn::spanned::Spanned;
use crate::attrs::*;
use crate::utils::*;
@@ -47,12 +48,23 @@ fn process_variant(variant: &syn::Variant) -> TokenStream {
let metas = variant
.attrs
.iter()
- .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr));
+ .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr));
let attrs = fold_quote(metas, |meta| quote!(#meta));
let syn::Variant { ident, fields, .. } = variant;
quote!(#attrs #ident #fields)
}
+/// Return the correct syntax to pattern match on the enum variant, discarding all
+/// internal field data.
+fn fields_in_variant(variant: &syn::Variant) -> TokenStream {
+ // With thanks to https://stackoverflow.com/a/65182902
+ match &variant.fields {
+ syn::Fields::Unnamed(_) => quote_spanned! { variant.span() => (..) },
+ syn::Fields::Unit => quote_spanned! { variant.span() => },
+ syn::Fields::Named(_) => quote_spanned! { variant.span() => {..} },
+ }
+}
+
fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let doc_hint = variants
.iter()
@@ -60,12 +72,26 @@ fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream {
.collect::<Vec<_>>()
.join("|");
let doc_hint = format!("[{}]", doc_hint);
+
+ let variant_stables = variants
+ .iter()
+ .map(|v| (&v.ident, fields_in_variant(&v), !unstable_of_variant(v)));
+ let match_patterns = fold_quote(variant_stables, |(v, fields, stable)| {
+ quote! {
+ #ident::#v #fields => #stable,
+ }
+ });
quote! {
use crate::config::ConfigType;
impl ConfigType for #ident {
fn doc_hint() -> String {
#doc_hint.to_owned()
}
+ fn stable_variant(&self) -> bool {
+ match self {
+ #match_patterns
+ }
+ }
}
}
}
@@ -123,13 +149,21 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream {
}
fn doc_hint_of_variant(variant: &syn::Variant) -> String {
- find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string())
+ let mut text = find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string());
+ if unstable_of_variant(&variant) {
+ text.push_str(" (unstable)")
+ };
+ text
}
fn config_value_of_variant(variant: &syn::Variant) -> String {
find_config_value(&variant.attrs).unwrap_or(variant.ident.to_string())
}
+fn unstable_of_variant(variant: &syn::Variant) -> bool {
+ any_unstable_variant(&variant.attrs)
+}
+
fn impl_serde(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let arms = fold_quote(variants.iter(), |v| {
let v_ident = &v.ident;
diff --git a/src/tools/rustfmt/config_proc_macro/src/lib.rs b/src/tools/rustfmt/config_proc_macro/src/lib.rs
index e772c53f4..0c54c132c 100644
--- a/src/tools/rustfmt/config_proc_macro/src/lib.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/lib.rs
@@ -69,3 +69,16 @@ pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
TokenStream::from_str("").unwrap()
}
}
+
+/// Used to conditionally output the TokenStream for tests that should be run as part of rustfmts
+/// test suite, but should be ignored when running in the rust-lang/rust test suite.
+#[proc_macro_attribute]
+pub fn rustfmt_only_ci_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+ if option_env!("RUSTFMT_CI").is_some() {
+ input
+ } else {
+ let mut token_stream = TokenStream::from_str("#[ignore]").unwrap();
+ token_stream.extend(input);
+ token_stream
+ }
+}
diff --git a/src/tools/rustfmt/config_proc_macro/tests/smoke.rs b/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
index 940a8a0c2..c8a83e39c 100644
--- a/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
+++ b/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
@@ -1,6 +1,7 @@
pub mod config {
pub trait ConfigType: Sized {
fn doc_hint() -> String;
+ fn stable_variant(&self) -> bool;
}
}
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 2640a9e0e..22283b3d6 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-06-21"
-components = ["rustc-dev"]
+channel = "nightly-2023-01-24"
+components = ["llvm-tools", "rustc-dev"]
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index c503eeeb9..5648e1254 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -336,7 +336,7 @@ impl Rewrite for ast::Attribute {
} else {
let should_skip = self
.ident()
- .map(|s| context.skip_context.skip_attribute(s.name.as_str()))
+ .map(|s| context.skip_context.attributes.skip(s.name.as_str()))
.unwrap_or(false);
let prefix = attr_prefix(self);
@@ -390,7 +390,7 @@ impl Rewrite for [ast::Attribute] {
// Determine if the source text is annotated with `#[rustfmt::skip::attributes(derive)]`
// or `#![rustfmt::skip::attributes(derive)]`
- let skip_derives = context.skip_context.skip_attribute("derive");
+ let skip_derives = context.skip_context.attributes.skip("derive");
// This is not just a simple map because we need to handle doc comments
// (where we take as many doc comment attributes as possible) and possibly
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 8e871e61f..be64559e8 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -136,7 +136,7 @@ fn make_opts() -> Options {
"l",
"files-with-diff",
"Prints the names of mismatched files that were formatted. Prints the names of \
- files that would be formated when used with `--check` mode. ",
+ files that would be formatted when used with `--check` mode. ",
);
opts.optmulti(
"",
diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs
index 9031d29b4..2b714b68d 100644
--- a/src/tools/rustfmt/src/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/main.rs
@@ -198,12 +198,10 @@ fn convert_message_format_to_rustfmt_args(
Ok(())
}
"human" => Ok(()),
- _ => {
- return Err(format!(
- "invalid --message-format value: {}. Allowed values are: short|json|human",
- message_format
- ));
- }
+ _ => Err(format!(
+ "invalid --message-format value: {}. Allowed values are: short|json|human",
+ message_format
+ )),
}
}
@@ -215,7 +213,7 @@ fn print_usage_to_stderr(reason: &str) {
.expect("failed to write to stderr");
}
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Verbosity {
Verbose,
Normal,
diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
index 56e52fbab..696326e4f 100644
--- a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
@@ -70,9 +70,9 @@ fn mandatory_separator() {
.is_err()
);
assert!(
- !Opts::command()
+ Opts::command()
.try_get_matches_from(&["test", "--", "--emit"])
- .is_err()
+ .is_ok()
);
}
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index a1a73cf4b..cbe523c6c 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -70,10 +70,66 @@ use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::Shape;
use crate::source_map::SpanUtils;
use crate::utils::{
- self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident,
- trimmed_last_line_width, wrap_str,
+ self, filtered_str_fits, first_line_width, last_line_extendable, last_line_width, mk_sp,
+ rewrite_ident, trimmed_last_line_width, wrap_str,
};
+use thin_vec::ThinVec;
+
+/// Provides the original input contents from the span
+/// of a chain element with trailing spaces trimmed.
+fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option<String> {
+ context.snippet_provider.span_to_snippet(span).map(|s| {
+ s.lines()
+ .map(|l| l.trim_end())
+ .collect::<Vec<_>>()
+ .join("\n")
+ })
+}
+
+fn format_chain_item(
+ item: &ChainItem,
+ context: &RewriteContext<'_>,
+ rewrite_shape: Shape,
+ allow_overflow: bool,
+) -> Option<String> {
+ if allow_overflow {
+ item.rewrite(context, rewrite_shape)
+ .or_else(|| format_overflow_style(item.span, context))
+ } else {
+ item.rewrite(context, rewrite_shape)
+ }
+}
+
+fn get_block_child_shape(
+ prev_ends_with_block: bool,
+ context: &RewriteContext<'_>,
+ shape: Shape,
+) -> Shape {
+ if prev_ends_with_block {
+ shape.block_indent(0)
+ } else {
+ shape.block_indent(context.config.tab_spaces())
+ }
+ .with_max_width(context.config)
+}
+
+fn get_visual_style_child_shape(
+ context: &RewriteContext<'_>,
+ shape: Shape,
+ offset: usize,
+ parent_overflowing: bool,
+) -> Option<Shape> {
+ if !parent_overflowing {
+ shape
+ .with_max_width(context.config)
+ .offset_left(offset)
+ .map(|s| s.visual_indent(0))
+ } else {
+ Some(shape.visual_indent(offset))
+ }
+}
+
pub(crate) fn rewrite_chain(
expr: &ast::Expr,
context: &RewriteContext<'_>,
@@ -114,7 +170,7 @@ enum ChainItemKind {
MethodCall(
ast::PathSegment,
Vec<ast::GenericArg>,
- Vec<ptr::P<ast::Expr>>,
+ ThinVec<ptr::P<ast::Expr>>,
),
StructField(symbol::Ident),
TupleField(symbol::Ident, bool),
@@ -496,6 +552,8 @@ struct ChainFormatterShared<'a> {
// The number of children in the chain. This is not equal to `self.children.len()`
// because `self.children` will change size as we process the chain.
child_count: usize,
+ // Whether elements are allowed to overflow past the max_width limit
+ allow_overflow: bool,
}
impl<'a> ChainFormatterShared<'a> {
@@ -505,6 +563,8 @@ impl<'a> ChainFormatterShared<'a> {
rewrites: Vec::with_capacity(chain.children.len() + 1),
fits_single_line: false,
child_count: chain.children.len(),
+ // TODO(calebcartwright)
+ allow_overflow: false,
}
}
@@ -517,6 +577,14 @@ impl<'a> ChainFormatterShared<'a> {
}
}
+ fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
+ for item in &self.children[..self.children.len() - 1] {
+ let rewrite = format_chain_item(item, context, child_shape, self.allow_overflow)?;
+ self.rewrites.push(rewrite);
+ }
+ Some(())
+ }
+
// Rewrite the last child. The last child of a chain requires special treatment. We need to
// know whether 'overflowing' the last child make a better formatting:
//
@@ -729,22 +797,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
}
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
- Some(
- if self.root_ends_with_block {
- shape.block_indent(0)
- } else {
- shape.block_indent(context.config.tab_spaces())
- }
- .with_max_width(context.config),
- )
+ let block_end = self.root_ends_with_block;
+ Some(get_block_child_shape(block_end, context, shape))
}
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
- for item in &self.shared.children[..self.shared.children.len() - 1] {
- let rewrite = item.rewrite(context, child_shape)?;
- self.shared.rewrites.push(rewrite);
- }
- Some(())
+ self.shared.format_children(context, child_shape)
}
fn format_last_child(
@@ -808,15 +866,14 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
.visual_indent(self.offset)
.sub_width(self.offset)?;
let rewrite = item.rewrite(context, child_shape)?;
- match wrap_str(rewrite, context.config.max_width(), shape) {
- Some(rewrite) => root_rewrite.push_str(&rewrite),
- None => {
- // We couldn't fit in at the visual indent, try the last
- // indent.
- let rewrite = item.rewrite(context, parent_shape)?;
- root_rewrite.push_str(&rewrite);
- self.offset = 0;
- }
+ if filtered_str_fits(&rewrite, context.config.max_width(), shape) {
+ root_rewrite.push_str(&rewrite);
+ } else {
+ // We couldn't fit in at the visual indent, try the last
+ // indent.
+ let rewrite = item.rewrite(context, parent_shape)?;
+ root_rewrite.push_str(&rewrite);
+ self.offset = 0;
}
self.shared.children = &self.shared.children[1..];
@@ -827,18 +884,17 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
}
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
- shape
- .with_max_width(context.config)
- .offset_left(self.offset)
- .map(|s| s.visual_indent(0))
+ get_visual_style_child_shape(
+ context,
+ shape,
+ self.offset,
+ // TODO(calebcartwright): self.shared.permissibly_overflowing_parent,
+ false,
+ )
}
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
- for item in &self.shared.children[..self.shared.children.len() - 1] {
- let rewrite = item.rewrite(context, child_shape)?;
- self.shared.rewrites.push(rewrite);
- }
- Some(())
+ self.shared.format_children(context, child_shape)
}
fn format_last_child(
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 8fd0fcf8f..340113866 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -1,5 +1,6 @@
use rustc_ast::{ast, ptr};
use rustc_span::Span;
+use thin_vec::thin_vec;
use crate::attr::get_attrs_from_stmt;
use crate::config::lists::*;
@@ -150,7 +151,7 @@ fn rewrite_closure_with_block(
}
let block = ast::Block {
- stmts: vec![ast::Stmt {
+ stmts: thin_vec![ast::Stmt {
id: ast::NodeId::root(),
kind: ast::StmtKind::Expr(ptr::P(body.clone())),
span: body.span,
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index c5e61658a..54ca7676d 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -1,4 +1,5 @@
use crate::config::file_lines::FileLines;
+use crate::config::macro_names::MacroSelectors;
use crate::config::options::{IgnoreList, WidthHeuristics};
/// Trait for types that can be used in `Config`.
@@ -6,6 +7,14 @@ pub(crate) trait ConfigType: Sized {
/// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
/// pipe-separated list of variants; for other types it returns `<type>`.
fn doc_hint() -> String;
+
+ /// Return `true` if the variant (i.e. value of this type) is stable.
+ ///
+ /// By default, return true for all values. Enums annotated with `#[config_type]`
+ /// are automatically implemented, based on the `#[unstable_variant]` annotation.
+ fn stable_variant(&self) -> bool {
+ true
+ }
}
impl ConfigType for bool {
@@ -38,6 +47,12 @@ impl ConfigType for FileLines {
}
}
+impl ConfigType for MacroSelectors {
+ fn doc_hint() -> String {
+ String::from("[<string>, ...]")
+ }
+}
+
impl ConfigType for WidthHeuristics {
fn doc_hint() -> String {
String::new()
@@ -51,6 +66,13 @@ impl ConfigType for IgnoreList {
}
macro_rules! create_config {
+ // Options passed in to the macro.
+ //
+ // - $i: the ident name of the option
+ // - $ty: the type of the option value
+ // - $def: the default value of the option
+ // - $stb: true if the option is stable
+ // - $dstring: description of the option
($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
#[cfg(test)]
use std::collections::HashSet;
@@ -61,9 +83,12 @@ macro_rules! create_config {
#[derive(Clone)]
#[allow(unreachable_pub)]
pub struct Config {
- // For each config item, we store a bool indicating whether it has
- // been accessed and the value, and a bool whether the option was
- // manually initialised, or taken from the default,
+ // For each config item, we store:
+ //
+ // - 0: true if the value has been access
+ // - 1: true if the option was manually initialized
+ // - 2: the option value
+ // - 3: true if the option is unstable
$($i: (Cell<bool>, bool, $ty, bool)),+
}
@@ -102,6 +127,7 @@ macro_rules! create_config {
| "array_width"
| "chain_width" => self.0.set_heuristics(),
"merge_imports" => self.0.set_merge_imports(),
+ "fn_args_layout" => self.0.set_fn_args_layout(),
&_ => (),
}
}
@@ -143,24 +169,20 @@ macro_rules! create_config {
fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
$(
- if let Some(val) = parsed.$i {
- if self.$i.3 {
+ if let Some(option_value) = parsed.$i {
+ let option_stable = self.$i.3;
+ if $crate::config::config_type::is_stable_option_and_value(
+ stringify!($i), option_stable, &option_value
+ ) {
self.$i.1 = true;
- self.$i.2 = val;
- } else {
- if crate::is_nightly_channel!() {
- self.$i.1 = true;
- self.$i.2 = val;
- } else {
- eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \
- available in nightly channel.", stringify!($i), val);
- }
+ self.$i.2 = option_value;
}
}
)+
self.set_heuristics();
self.set_ignore(dir);
self.set_merge_imports();
+ self.set_fn_args_layout();
self
}
@@ -221,12 +243,22 @@ macro_rules! create_config {
match key {
$(
stringify!($i) => {
- self.$i.1 = true;
- self.$i.2 = val.parse::<$ty>()
+ let option_value = val.parse::<$ty>()
.expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
stringify!($i),
val,
stringify!($ty)));
+
+ // Users are currently allowed to set unstable
+ // options/variants via the `--config` options override.
+ //
+ // There is ongoing discussion about how to move forward here:
+ // https://github.com/rust-lang/rustfmt/pull/5379
+ //
+ // For now, do not validate whether the option or value is stable,
+ // just always set it.
+ self.$i.1 = true;
+ self.$i.2 = option_value;
}
)+
_ => panic!("Unknown config key in override: {}", key)
@@ -243,14 +275,21 @@ macro_rules! create_config {
| "array_width"
| "chain_width" => self.set_heuristics(),
"merge_imports" => self.set_merge_imports(),
+ "fn_args_layout" => self.set_fn_args_layout(),
&_ => (),
}
}
#[allow(unreachable_pub)]
pub fn is_hidden_option(name: &str) -> bool {
- const HIDE_OPTIONS: [&str; 5] =
- ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"];
+ const HIDE_OPTIONS: [&str; 6] = [
+ "verbose",
+ "verbose_diff",
+ "file_lines",
+ "width_heuristics",
+ "merge_imports",
+ "fn_args_layout"
+ ];
HIDE_OPTIONS.contains(&name)
}
@@ -400,6 +439,18 @@ macro_rules! create_config {
}
}
+ fn set_fn_args_layout(&mut self) {
+ if self.was_set().fn_args_layout() {
+ eprintln!(
+ "Warning: the `fn_args_layout` option is deprecated. \
+ Use `fn_params_layout`. instead"
+ );
+ if !self.was_set().fn_params_layout() {
+ self.fn_params_layout.2 = self.fn_args_layout();
+ }
+ }
+ }
+
#[allow(unreachable_pub)]
/// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool {
@@ -424,3 +475,38 @@ macro_rules! create_config {
}
)
}
+
+pub(crate) fn is_stable_option_and_value<T>(
+ option_name: &str,
+ option_stable: bool,
+ option_value: &T,
+) -> bool
+where
+ T: PartialEq + std::fmt::Debug + ConfigType,
+{
+ let nightly = crate::is_nightly_channel!();
+ let variant_stable = option_value.stable_variant();
+ match (nightly, option_stable, variant_stable) {
+ // Stable with an unstable option
+ (false, false, _) => {
+ eprintln!(
+ "Warning: can't set `{} = {:?}`, unstable features are only \
+ available in nightly channel.",
+ option_name, option_value
+ );
+ 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
+ );
+ false
+ }
+ // Nightly: everything allowed
+ // Stable with stable option and variant: allowed
+ (true, _, _) | (false, true, true) => true,
+ }
+}
diff --git a/src/tools/rustfmt/src/config/macro_names.rs b/src/tools/rustfmt/src/config/macro_names.rs
new file mode 100644
index 000000000..26ad78d6d
--- /dev/null
+++ b/src/tools/rustfmt/src/config/macro_names.rs
@@ -0,0 +1,118 @@
+//! This module contains types and functions to support formatting specific macros.
+
+use itertools::Itertools;
+use std::{fmt, str};
+
+use serde::{Deserialize, Serialize};
+use serde_json as json;
+use thiserror::Error;
+
+/// Defines the name of a macro.
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+pub struct MacroName(String);
+
+impl MacroName {
+ pub fn new(other: String) -> Self {
+ Self(other)
+ }
+}
+
+impl fmt::Display for MacroName {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl From<MacroName> for String {
+ fn from(other: MacroName) -> Self {
+ other.0
+ }
+}
+
+/// Defines a selector to match against a macro.
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+pub enum MacroSelector {
+ Name(MacroName),
+ All,
+}
+
+impl fmt::Display for MacroSelector {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Name(name) => name.fmt(f),
+ Self::All => write!(f, "*"),
+ }
+ }
+}
+
+impl str::FromStr for MacroSelector {
+ type Err = std::convert::Infallible;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Ok(match s {
+ "*" => MacroSelector::All,
+ name => MacroSelector::Name(MacroName(name.to_owned())),
+ })
+ }
+}
+
+/// A set of macro selectors.
+#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
+pub struct MacroSelectors(pub Vec<MacroSelector>);
+
+impl fmt::Display for MacroSelectors {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.0.iter().format(", "))
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum MacroSelectorsError {
+ #[error("{0}")]
+ Json(json::Error),
+}
+
+// This impl is needed for `Config::override_value` to work for use in tests.
+impl str::FromStr for MacroSelectors {
+ type Err = MacroSelectorsError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let raw: Vec<&str> = json::from_str(s).map_err(MacroSelectorsError::Json)?;
+ Ok(Self(
+ raw.into_iter()
+ .map(|raw| {
+ MacroSelector::from_str(raw).expect("MacroSelector from_str is infallible")
+ })
+ .collect(),
+ ))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use std::str::FromStr;
+
+ #[test]
+ fn macro_names_from_str() {
+ let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
+ assert_eq!(
+ macro_names,
+ MacroSelectors(
+ [
+ MacroSelector::Name(MacroName("foo".to_owned())),
+ MacroSelector::All,
+ MacroSelector::Name(MacroName("bar".to_owned()))
+ ]
+ .into_iter()
+ .collect()
+ )
+ );
+ }
+
+ #[test]
+ fn macro_names_display() {
+ let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
+ 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 f49c18d3a..14f27f3f8 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -13,15 +13,20 @@ pub use crate::config::file_lines::{FileLines, FileName, Range};
#[allow(unreachable_pub)]
pub use crate::config::lists::*;
#[allow(unreachable_pub)]
+pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
+#[allow(unreachable_pub)]
pub use crate::config::options::*;
#[macro_use]
pub(crate) mod config_type;
#[macro_use]
+#[allow(unreachable_pub)]
pub(crate) mod options;
pub(crate) mod file_lines;
+#[allow(unreachable_pub)]
pub(crate) mod lists;
+pub(crate) mod macro_names;
// This macro defines configuration options used in rustfmt. Each option
// is defined as follows:
@@ -67,6 +72,8 @@ create_config! {
format_macro_matchers: bool, false, false,
"Format the metavariable matching patterns in macros";
format_macro_bodies: bool, true, false, "Format the bodies of macros";
+ skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
+ "Skip formatting the bodies of macros invoked with the following names.";
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
"Format hexadecimal integer literals";
@@ -119,7 +126,9 @@ create_config! {
force_multiline_blocks: bool, false, false,
"Force multiline closure bodies and match arms to be wrapped in a block";
fn_args_layout: Density, Density::Tall, true,
- "Control the layout of arguments in a function";
+ "(deprecated: use fn_params_layout instead)";
+ fn_params_layout: Density, Density::Tall, true,
+ "Control the layout of parameters in function signatures.";
brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
"Brace style for control flow constructs";
@@ -175,7 +184,7 @@ create_config! {
make_backup: bool, false, false, "Backup changed files";
print_misformatted_file_names: bool, false, true,
"Prints the names of mismatched files that were formatted. Prints the names of \
- files that would be formated when used with `--check` mode. ";
+ files that would be formatted when used with `--check` mode. ";
}
#[derive(Error, Debug)]
@@ -191,6 +200,7 @@ impl PartialConfig {
cloned.width_heuristics = None;
cloned.print_misformatted_file_names = None;
cloned.merge_imports = None;
+ cloned.fn_args_layout = None;
::toml::to_string(&cloned).map_err(ToTomlError)
}
@@ -403,11 +413,21 @@ mod test {
use super::*;
use std::str;
+ use crate::config::macro_names::MacroName;
use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
#[allow(dead_code)]
mod mock {
use super::super::*;
+ use rustfmt_config_proc_macro::config_type;
+
+ #[config_type]
+ pub(crate) enum PartiallyUnstableOption {
+ V1,
+ V2,
+ #[unstable_variant]
+ V3,
+ }
create_config! {
// Options that are used by the generated functions
@@ -427,6 +447,12 @@ mod test {
"Merge imports";
merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";
+ // fn_args_layout renamed to fn_params_layout
+ fn_args_layout: Density, Density::Tall, true,
+ "(deprecated: use fn_params_layout instead)";
+ fn_params_layout: Density, Density::Tall, true,
+ "Control the layout of parameters in a function signatures.";
+
// Width Heuristics
use_small_heuristics: Heuristics, Heuristics::Default, true,
"Whether to use different formatting for items and \
@@ -451,6 +477,63 @@ mod test {
// Options that are used by the tests
stable_option: bool, false, true, "A stable option";
unstable_option: bool, false, false, "An unstable option";
+ partially_unstable_option: PartiallyUnstableOption, PartiallyUnstableOption::V1, true,
+ "A partially unstable option";
+ }
+
+ #[cfg(test)]
+ mod partially_unstable_option {
+ use super::{Config, PartialConfig, PartiallyUnstableOption};
+ use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
+ use std::path::Path;
+
+ /// From the config file, we can fill with a stable variant
+ #[test]
+ fn test_from_toml_stable_value() {
+ let toml = r#"
+ partially_unstable_option = "V2"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V2
+ );
+ }
+
+ /// From the config file, we cannot fill with an unstable variant (stable only)
+ #[stable_only_test]
+ #[test]
+ fn test_from_toml_unstable_value_on_stable() {
+ let toml = r#"
+ partially_unstable_option = "V3"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ // default value from config, i.e. fill failed
+ PartiallyUnstableOption::V1
+ );
+ }
+
+ /// From the config file, we can fill with an unstable variant (nightly only)
+ #[nightly_only_test]
+ #[test]
+ fn test_from_toml_unstable_value_on_nightly() {
+ let toml = r#"
+ partially_unstable_option = "V3"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V3
+ );
+ }
}
}
@@ -489,6 +572,11 @@ mod test {
assert_eq!(config.was_set().verbose(), false);
}
+ const PRINT_DOCS_STABLE_OPTION: &str = "stable_option <boolean> Default: false";
+ const PRINT_DOCS_UNSTABLE_OPTION: &str = "unstable_option <boolean> Default: false (unstable)";
+ const PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION: &str =
+ "partially_unstable_option [V1|V2|V3 (unstable)] Default: V1";
+
#[test]
fn test_print_docs_exclude_unstable() {
use self::mock::Config;
@@ -497,10 +585,9 @@ mod test {
Config::print_docs(&mut output, false);
let s = str::from_utf8(&output).unwrap();
-
- assert_eq!(s.contains("stable_option"), true);
- assert_eq!(s.contains("unstable_option"), false);
- assert_eq!(s.contains("(unstable)"), false);
+ assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), false);
+ assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true);
}
#[test]
@@ -511,9 +598,9 @@ mod test {
Config::print_docs(&mut output, true);
let s = str::from_utf8(&output).unwrap();
- assert_eq!(s.contains("stable_option"), true);
- assert_eq!(s.contains("unstable_option"), true);
- assert_eq!(s.contains("(unstable)"), true);
+ assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true);
}
#[test]
@@ -541,6 +628,7 @@ normalize_doc_attributes = false
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
+skip_macro_invocations = []
hex_literal_case = "Preserve"
empty_item_single_line = true
struct_lit_single_line = true
@@ -567,7 +655,7 @@ enum_discrim_align_threshold = 0
match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
-fn_args_layout = "Tall"
+fn_params_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
@@ -921,4 +1009,45 @@ make_backup = false
assert_eq!(config.single_line_if_else_max_width(), 100);
}
}
+
+ #[cfg(test)]
+ mod partially_unstable_option {
+ use super::mock::{Config, PartiallyUnstableOption};
+ use super::*;
+
+ /// From the command line, we can override with a stable variant.
+ #[test]
+ fn test_override_stable_value() {
+ let mut config = Config::default();
+ config.override_value("partially_unstable_option", "V2");
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V2
+ );
+ }
+
+ /// From the command line, we can override with an unstable variant.
+ #[test]
+ fn test_override_unstable_value() {
+ let mut config = Config::default();
+ config.override_value("partially_unstable_option", "V3");
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V3
+ );
+ }
+ }
+
+ #[test]
+ fn test_override_skip_macro_invocations() {
+ let mut config = Config::default();
+ config.override_value("skip_macro_invocations", r#"["*", "println"]"#);
+ assert_eq!(
+ config.skip_macro_invocations(),
+ MacroSelectors(vec![
+ MacroSelector::All,
+ MacroSelector::Name(MacroName::new("println".to_owned()))
+ ])
+ );
+ }
}
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 868ff045a..3f0f217f8 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -29,9 +29,9 @@ use crate::spanned::Spanned;
use crate::string::{rewrite_string, StringFormat};
use crate::types::{rewrite_path, PathContext};
use crate::utils::{
- colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes,
- last_line_extendable, last_line_width, mk_sp, outer_attributes, semicolon_for_expr,
- unicode_str_width, wrap_str,
+ colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with,
+ inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes,
+ semicolon_for_expr, unicode_str_width, wrap_str,
};
use crate::vertical::rewrite_with_alignment;
use crate::visitor::FmtVisitor;
@@ -400,7 +400,10 @@ pub(crate) fn format_expr(
}
}
ast::ExprKind::Underscore => Some("_".to_owned()),
- ast::ExprKind::IncludedBytes(..) => unreachable!(),
+ ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => {
+ // These do not occur in the AST because macros aren't expanded.
+ unreachable!()
+ }
ast::ExprKind::Err => None,
};
@@ -2050,8 +2053,7 @@ fn choose_rhs<R: Rewrite>(
match (orig_rhs, new_rhs) {
(Some(ref orig_rhs), Some(ref new_rhs))
- if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape)
- .is_none() =>
+ if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) =>
{
Some(format!("{}{}", before_space_str, orig_rhs))
}
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index d9dc8d004..339e5cef5 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -251,8 +251,8 @@ fn flatten_use_trees(
use_trees: Vec<UseTree>,
import_granularity: ImportGranularity,
) -> Vec<UseTree> {
- // Return non-sorted single occurance of the use-trees text string;
- // order is by first occurance of the use-tree.
+ // Return non-sorted single occurrence of the use-trees text string;
+ // order is by first occurrence of the use-tree.
use_trees
.into_iter()
.flat_map(|tree| tree.flatten(import_granularity))
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index a2a73f0a5..25e8a0248 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1084,7 +1084,11 @@ pub(crate) fn format_trait(
let item_snippet = context.snippet(item.span);
if let Some(lo) = item_snippet.find('/') {
// 1 = `{`
- let comment_hi = body_lo - BytePos(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(
@@ -1241,7 +1245,7 @@ fn format_unit_struct(
) -> Option<String> {
let header_str = format_header(context, p.prefix, p.ident, p.vis, offset);
let generics_str = if let Some(generics) = p.generics {
- let hi = context.snippet_provider.span_before(p.span, ";");
+ let hi = context.snippet_provider.span_before_last(p.span, ";");
format_generics(
context,
generics,
@@ -2602,7 +2606,7 @@ fn rewrite_params(
&param_items,
context
.config
- .fn_args_layout()
+ .fn_params_layout()
.to_list_tactic(param_items.len()),
Separator::Comma,
one_line_budget,
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 0c27bcacf..b27405efd 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -23,6 +23,7 @@ extern crate rustc_expand;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
+extern crate thin_vec;
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
// files.
diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs
index e87850507..a878e6cf9 100644
--- a/src/tools/rustfmt/src/lists.rs
+++ b/src/tools/rustfmt/src/lists.rs
@@ -297,9 +297,9 @@ where
} else {
inner_item.as_ref()
};
- let mut item_last_line_width = item_last_line.len() + item_sep_len;
+ let mut item_last_line_width = unicode_str_width(item_last_line) + item_sep_len;
if item_last_line.starts_with(&**indent_str) {
- item_last_line_width -= indent_str.len();
+ item_last_line_width -= unicode_str_width(indent_str);
}
if !item.is_substantial() {
@@ -449,7 +449,7 @@ where
} else if starts_with_newline(comment) {
false
} else {
- comment.trim().contains('\n') || comment.trim().len() > width
+ comment.trim().contains('\n') || unicode_str_width(comment.trim()) > width
};
rewrite_comment(
@@ -465,7 +465,7 @@ where
if !starts_with_newline(comment) {
if formatting.align_comments {
let mut comment_alignment =
- post_comment_alignment(item_max_width, inner_item.len());
+ post_comment_alignment(item_max_width, unicode_str_width(inner_item));
if first_line_width(&formatted_comment)
+ last_line_width(&result)
+ comment_alignment
@@ -475,7 +475,7 @@ where
item_max_width = None;
formatted_comment = rewrite_post_comment(&mut item_max_width)?;
comment_alignment =
- post_comment_alignment(item_max_width, inner_item.len());
+ post_comment_alignment(item_max_width, unicode_str_width(inner_item));
}
for _ in 0..=comment_alignment {
result.push(' ');
@@ -533,7 +533,7 @@ where
let mut first = true;
for item in items.clone().into_iter().skip(i) {
let item = item.as_ref();
- let inner_item_width = item.inner_as_ref().len();
+ let inner_item_width = unicode_str_width(item.inner_as_ref());
if !first
&& (item.is_different_group()
|| item.post_comment.is_none()
@@ -552,8 +552,8 @@ where
max_width
}
-fn post_comment_alignment(item_max_width: Option<usize>, inner_item_len: usize) -> usize {
- item_max_width.unwrap_or(0).saturating_sub(inner_item_len)
+fn post_comment_alignment(item_max_width: Option<usize>, inner_item_width: usize) -> usize {
+ item_max_width.unwrap_or(0).saturating_sub(inner_item_width)
}
pub(crate) struct ListItems<'a, I, F1, F2, F3>
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index df9493880..7978d8cba 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -13,7 +13,7 @@ use std::collections::HashMap;
use std::panic::{catch_unwind, AssertUnwindSafe};
use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::{ast, ptr};
use rustc_ast_pretty::pprust;
use rustc_span::{
@@ -35,8 +35,8 @@ use crate::shape::{Indent, Shape};
use crate::source_map::SpanUtils;
use crate::spanned::Spanned;
use crate::utils::{
- format_visibility, indent_next_line, is_empty_line, mk_sp, remove_trailing_white_spaces,
- rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt,
+ filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp,
+ remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt,
};
use crate::visitor::FmtVisitor;
@@ -157,7 +157,8 @@ pub(crate) fn rewrite_macro(
) -> Option<String> {
let should_skip = context
.skip_context
- .skip_macro(context.snippet(mac.path.span));
+ .macros
+ .skip(context.snippet(mac.path.span));
if should_skip {
None
} else {
@@ -735,7 +736,7 @@ impl MacroArgParser {
self.buf.clear();
}
- fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
+ fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> {
match iter.next() {
Some(TokenTree::Token(
Token {
@@ -767,7 +768,7 @@ impl MacroArgParser {
&mut self,
inner: Vec<ParsedMacroArg>,
delim: Delimiter,
- iter: &mut Cursor,
+ iter: &mut TokenTreeCursor,
) -> Option<()> {
let mut buffer = String::new();
let mut first = true;
@@ -1120,7 +1121,7 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D
// Currently we do not attempt to parse any further than that.
#[derive(new)]
struct MacroParser {
- toks: Cursor,
+ toks: TokenTreeCursor,
}
impl MacroParser {
@@ -1265,15 +1266,14 @@ impl MacroBranch {
}
}
};
- let new_body = wrap_str(
- new_body_snippet.snippet.to_string(),
- config.max_width(),
- shape,
- )?;
+
+ if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) {
+ return None;
+ }
// Indent the body since it is in a block.
let indent_str = body_indent.to_string(&config);
- let mut new_body = LineClasses::new(new_body.trim_end())
+ let mut new_body = LineClasses::new(new_body_snippet.snippet.trim_end())
.enumerate()
.fold(
(String::new(), true),
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 7a0d1736c..af9a154a6 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -6,6 +6,7 @@ use rustc_ast::ast;
use rustc_ast::visit::Visitor;
use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::Span;
+use thin_vec::ThinVec;
use thiserror::Error;
use crate::attr::MetaVisitor;
@@ -25,7 +26,7 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
#[derive(Debug, Clone)]
pub(crate) struct Module<'a> {
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
- pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+ pub(crate) items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
inner_attr: ast::AttrVec,
pub(crate) span: Span,
}
@@ -34,7 +35,7 @@ impl<'a> Module<'a> {
pub(crate) fn new(
mod_span: Span,
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
- mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+ mod_items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
mod_attrs: Cow<'a, ast::AttrVec>,
) -> Self {
let inner_attr = mod_attrs
@@ -157,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
module_item.item.span,
Some(Cow::Owned(sub_mod_kind.clone())),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Owned(ast::AttrVec::new()),
),
)?;
@@ -169,7 +170,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
/// Visit modules defined inside macro calls.
fn visit_mod_outside_ast(
&mut self,
- items: Vec<rustc_ast::ptr::P<ast::Item>>,
+ items: ThinVec<rustc_ast::ptr::P<ast::Item>>,
) -> Result<(), ModuleResolutionError> {
for item in items {
if is_cfg_if(&item) {
@@ -184,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
span,
Some(Cow::Owned(sub_mod_kind.clone())),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Owned(ast::AttrVec::new()),
),
)?;
@@ -210,7 +211,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
span,
Some(Cow::Borrowed(sub_mod_kind)),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Borrowed(&item.attrs),
),
)?;
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index e0bd06551..7ab042506 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -6,6 +6,7 @@ use rustc_ast::{ast, ptr};
use rustc_errors::Diagnostic;
use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
use rustc_span::{sym, Span};
+use thin_vec::ThinVec;
use crate::attr::first_attr_value_str_by_name;
use crate::parse::session::ParseSess;
@@ -109,7 +110,7 @@ impl<'a> Parser<'a> {
sess: &'a ParseSess,
path: &Path,
span: Span,
- ) -> Result<(ast::AttrVec, Vec<ptr::P<ast::Item>>, Span), ParserError> {
+ ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
let result = catch_unwind(AssertUnwindSafe(|| {
let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
match parser.parse_mod(&TokenKind::Eof) {
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 6bfec79cd..a64963db6 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use rustc_data_structures::sync::{Lrc, Send};
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::translation::Translate;
-use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
+use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel, TerminalUrl};
use rustc_session::parse::ParseSess as RawParseSess;
use rustc_span::{
source_map::{FilePathMapping, SourceMap},
@@ -123,8 +123,10 @@ fn default_handler(
let emitter = if hide_parse_errors {
silent_emitter()
} else {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
Box::new(EmitterWriter::stderr(
color_cfg,
Some(source_map.clone()),
@@ -135,6 +137,7 @@ fn default_handler(
None,
false,
false,
+ TerminalUrl::No,
))
};
Handler::with_emitter(
diff --git a/src/tools/rustfmt/src/skip.rs b/src/tools/rustfmt/src/skip.rs
index 032922d42..68f85b2ad 100644
--- a/src/tools/rustfmt/src/skip.rs
+++ b/src/tools/rustfmt/src/skip.rs
@@ -2,33 +2,84 @@
use rustc_ast::ast;
use rustc_ast_pretty::pprust;
+use std::collections::HashSet;
-/// Take care of skip name stack. You can update it by attributes slice or
-/// by other context. Query this context to know if you need skip a block.
+/// Track which blocks of code are to be skipped when formatting.
+///
+/// You can update it by:
+///
+/// - attributes slice
+/// - manually feeding values into the underlying contexts
+///
+/// Query this context to know if you need to skip a block.
#[derive(Default, Clone)]
pub(crate) struct SkipContext {
- macros: Vec<String>,
- attributes: Vec<String>,
+ pub(crate) macros: SkipNameContext,
+ pub(crate) attributes: SkipNameContext,
}
impl SkipContext {
pub(crate) fn update_with_attrs(&mut self, attrs: &[ast::Attribute]) {
- self.macros.append(&mut get_skip_names("macros", attrs));
- self.attributes
- .append(&mut get_skip_names("attributes", attrs));
+ self.macros.extend(get_skip_names("macros", attrs));
+ self.attributes.extend(get_skip_names("attributes", attrs));
}
- pub(crate) fn update(&mut self, mut other: SkipContext) {
- self.macros.append(&mut other.macros);
- self.attributes.append(&mut other.attributes);
+ pub(crate) fn update(&mut self, other: SkipContext) {
+ let SkipContext { macros, attributes } = other;
+ self.macros.update(macros);
+ self.attributes.update(attributes);
+ }
+}
+
+/// Track which names to skip.
+///
+/// Query this context with a string to know whether to skip it.
+#[derive(Clone)]
+pub(crate) enum SkipNameContext {
+ All,
+ Values(HashSet<String>),
+}
+
+impl Default for SkipNameContext {
+ fn default() -> Self {
+ Self::Values(Default::default())
+ }
+}
+
+impl Extend<String> for SkipNameContext {
+ fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
+ match self {
+ Self::All => {}
+ Self::Values(values) => values.extend(iter),
+ }
+ }
+}
+
+impl SkipNameContext {
+ pub(crate) fn update(&mut self, other: Self) {
+ match (self, other) {
+ // If we're already skipping everything, nothing more can be added
+ (Self::All, _) => {}
+ // If we want to skip all, set it
+ (this, Self::All) => {
+ *this = Self::All;
+ }
+ // If we have some new values to skip, add them
+ (Self::Values(existing_values), Self::Values(new_values)) => {
+ existing_values.extend(new_values)
+ }
+ }
}
- pub(crate) fn skip_macro(&self, name: &str) -> bool {
- self.macros.iter().any(|n| n == name)
+ pub(crate) fn skip(&self, name: &str) -> bool {
+ match self {
+ Self::All => true,
+ Self::Values(values) => values.contains(name),
+ }
}
- pub(crate) fn skip_attribute(&self, name: &str) -> bool {
- self.attributes.iter().any(|n| n == name)
+ pub(crate) fn skip_all(&mut self) {
+ *self = Self::All;
}
}
diff --git a/src/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs
index c8fda7c85..c70b3c5fa 100644
--- a/src/tools/rustfmt/src/test/configuration_snippet.rs
+++ b/src/tools/rustfmt/src/test/configuration_snippet.rs
@@ -27,8 +27,13 @@ impl ConfigurationSection {
lazy_static! {
static ref CONFIG_NAME_REGEX: regex::Regex =
regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern");
+ // Configuration values, which will be passed to `from_str`:
+ //
+ // - must be prefixed with `####`
+ // - must be wrapped in backticks
+ // - may by wrapped in double quotes (which will be stripped)
static ref CONFIG_VALUE_REGEX: regex::Regex =
- regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#)
+ regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#)
.expect("failed creating configuration value pattern");
}
diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs
index 6b5bc2b30..cfad4a8ed 100644
--- a/src/tools/rustfmt/src/test/mod.rs
+++ b/src/tools/rustfmt/src/test/mod.rs
@@ -982,11 +982,7 @@ fn rustfmt() -> PathBuf {
assert!(
me.is_file() || me.with_extension("exe").is_file(),
"{}",
- if cfg!(release) {
- "no rustfmt bin, try running `cargo build --release` before testing"
- } else {
- "no rustfmt bin, try running `cargo build` before testing"
- }
+ "no rustfmt bin, try running `cargo build` or `cargo build --release` before testing"
);
me
}
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index c1991e8d2..01e2fb6e6 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -941,6 +941,28 @@ fn join_bounds_inner(
ast::GenericBound::Trait(..) => last_line_extendable(s),
};
+ // Whether a GenericBound item is a PathSegment segment that includes internal array
+ // that contains more than one item
+ let is_item_with_multi_items_array = |item: &ast::GenericBound| match item {
+ ast::GenericBound::Trait(ref poly_trait_ref, ..) => {
+ let segments = &poly_trait_ref.trait_ref.path.segments;
+ if segments.len() > 1 {
+ true
+ } else {
+ if let Some(args_in) = &segments[0].args {
+ matches!(
+ args_in.deref(),
+ ast::GenericArgs::AngleBracketed(bracket_args)
+ if bracket_args.args.len() > 1
+ )
+ } else {
+ false
+ }
+ }
+ }
+ _ => false,
+ };
+
let result = items.iter().enumerate().try_fold(
(String::new(), None, false),
|(strs, prev_trailing_span, prev_extendable), (i, item)| {
@@ -1035,10 +1057,24 @@ fn join_bounds_inner(
},
)?;
- if !force_newline
- && items.len() > 1
- && (result.0.contains('\n') || result.0.len() > shape.width)
- {
+ // Whether to retry with a forced newline:
+ // Only if result is not already multiline and did not exceed line width,
+ // and either there is more than one item;
+ // or the single item is of type `Trait`,
+ // and any of the internal arrays contains more than one item;
+ let retry_with_force_newline = match context.config.version() {
+ Version::One => {
+ !force_newline
+ && items.len() > 1
+ && (result.0.contains('\n') || result.0.len() > shape.width)
+ }
+ Version::Two if force_newline => false,
+ Version::Two if (!result.0.contains('\n') && result.0.len() <= shape.width) => false,
+ Version::Two if items.len() > 1 => true,
+ Version::Two => is_item_with_multi_items_array(&items[0]),
+ };
+
+ if retry_with_force_newline {
join_bounds_inner(context, shape, items, need_indent, true)
} else {
Some(result.0)
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 3e884419f..1e89f3ae7 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -384,14 +384,15 @@ macro_rules! skip_out_of_file_lines_range_visitor {
// Wraps String in an Option. Returns Some when the string adheres to the
// Rewrite constraints defined for the Rewrite trait and None otherwise.
pub(crate) fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option<String> {
- if is_valid_str(&filter_normal_code(&s), max_width, shape) {
+ if filtered_str_fits(&s, max_width, shape) {
Some(s)
} else {
None
}
}
-fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool {
+pub(crate) fn filtered_str_fits(snippet: &str, max_width: usize, shape: Shape) -> bool {
+ let snippet = &filter_normal_code(snippet);
if !snippet.is_empty() {
// First line must fits with `shape.width`.
if first_line_width(snippet) > shape.width {
@@ -462,6 +463,7 @@ pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool {
pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool {
match expr.kind {
ast::ExprKind::MacCall(..)
+ | ast::ExprKind::FormatArgs(..)
| ast::ExprKind::Call(..)
| ast::ExprKind::MethodCall(..)
| ast::ExprKind::Array(..)
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9c3cc7820..f4d84d138 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -8,7 +8,7 @@ use rustc_span::{symbol, BytePos, Pos, Span};
use crate::attr::*;
use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices};
use crate::config::Version;
-use crate::config::{BraceStyle, Config};
+use crate::config::{BraceStyle, Config, MacroSelector};
use crate::coverage::transform_missing_snippet;
use crate::items::{
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
@@ -770,6 +770,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
snippet_provider: &'a SnippetProvider,
report: FormatReport,
) -> FmtVisitor<'a> {
+ let mut skip_context = SkipContext::default();
+ let mut macro_names = Vec::new();
+ for macro_selector in config.skip_macro_invocations().0 {
+ match macro_selector {
+ MacroSelector::Name(name) => macro_names.push(name.to_string()),
+ MacroSelector::All => skip_context.macros.skip_all(),
+ }
+ }
+ skip_context.macros.extend(macro_names);
FmtVisitor {
parent_context: None,
parse_sess: parse_session,
@@ -784,7 +793,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
is_macro_def: false,
macro_rewrite_failure: false,
report,
- skip_context: Default::default(),
+ skip_context,
}
}
diff --git a/src/tools/rustfmt/tests/cargo-fmt/main.rs b/src/tools/rustfmt/tests/cargo-fmt/main.rs
index 348876cd2..701c36fad 100644
--- a/src/tools/rustfmt/tests/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/tests/cargo-fmt/main.rs
@@ -4,6 +4,8 @@ use std::env;
use std::path::Path;
use std::process::Command;
+use rustfmt_config_proc_macro::rustfmt_only_ci_test;
+
/// Run the cargo-fmt executable and return its output.
fn cargo_fmt(args: &[&str]) -> (String, String) {
let mut bin_dir = env::current_exe().unwrap();
@@ -47,7 +49,7 @@ macro_rules! assert_that {
};
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn version() {
assert_that!(&["--version"], starts_with("rustfmt "));
@@ -56,7 +58,7 @@ fn version() {
assert_that!(&["--", "--version"], starts_with("rustfmt "));
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn print_config() {
assert_that!(
@@ -65,7 +67,7 @@ fn print_config() {
);
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn rustfmt_help() {
assert_that!(&["--", "--help"], contains("Format Rust code"));
@@ -73,7 +75,7 @@ fn rustfmt_help() {
assert_that!(&["--", "--help=config"], contains("Configuration Options:"));
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn cargo_fmt_out_of_line_test_modules() {
// See also https://github.com/rust-lang/rustfmt/issues/5119
@@ -96,3 +98,22 @@ fn cargo_fmt_out_of_line_test_modules() {
assert!(stdout.contains(&format!("Diff in {}", path.display())))
}
}
+
+#[rustfmt_only_ci_test]
+#[test]
+fn cargo_fmt_emits_error_on_line_overflow_true() {
+ // See also https://github.com/rust-lang/rustfmt/issues/3164
+ let args = [
+ "--check",
+ "--manifest-path",
+ "tests/cargo-fmt/source/issue_3164/Cargo.toml",
+ "--",
+ "--config",
+ "error_on_line_overflow=true",
+ ];
+
+ let (_stdout, stderr) = cargo_fmt(&args);
+ assert!(stderr.contains(
+ "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
+ ))
+}
diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml
new file mode 100644
index 000000000..580ef7e6e
--- /dev/null
+++ b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "issue_3164"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs
new file mode 100644
index 000000000..9330107ac
--- /dev/null
+++ b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs
@@ -0,0 +1,13 @@
+#[allow(unused_macros)]
+macro_rules! foo {
+ ($id:ident) => {
+ macro_rules! bar {
+ ($id2:tt) => {
+ #[cfg(any(target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2))]
+ fn $id() {}
+ };
+ }
+ };
+}
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/config/small_tabs.toml b/src/tools/rustfmt/tests/config/small_tabs.toml
index c3cfd3431..4c3710089 100644
--- a/src/tools/rustfmt/tests/config/small_tabs.toml
+++ b/src/tools/rustfmt/tests/config/small_tabs.toml
@@ -3,7 +3,7 @@ comment_width = 80
tab_spaces = 2
newline_style = "Unix"
brace_style = "SameLineWhere"
-fn_args_layout = "Tall"
+fn_params_layout = "Tall"
trailing_comma = "Vertical"
indent_style = "Block"
reorder_imports = false
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
index 92c9e3021..254102eba 100644
--- a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
+++ b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
@@ -9,7 +9,7 @@ The directory name './lib/c/d/' conflicts with the './lib/c/d.rs' file name.
* mod g;
Module resolution will fail if we look for './lib/c/d/e.rs' or './lib/c/d/e/mod.rs',
-so we should fall back to looking for './lib/c/e.rs', which correctly finds the modlue, that
+so we should fall back to looking for './lib/c/e.rs', which correctly finds the module, that
rustfmt should format.
'./lib/c/d/f.rs' and './lib/c/d/g/mod.rs' exist at the default submodule paths so we should be able
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
index d436a8076..90464def8 100644
--- a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
+++ b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
@@ -9,7 +9,7 @@ The directory name './lib' conflicts with the './lib.rs' file name.
* mod c;
Module resolution will fail if we look for './lib/a.rs' or './lib/a/mod.rs',
-so we should fall back to looking for './a.rs', which correctly finds the modlue that
+so we should fall back to looking for './a.rs', which correctly finds the module that
rustfmt should format.
'./lib/b.rs' and './lib/c/mod.rs' exist at the default submodule paths so we should be able
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 4c6d52726..7ff301e80 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -5,6 +5,8 @@ use std::fs::remove_file;
use std::path::Path;
use std::process::Command;
+use rustfmt_config_proc_macro::rustfmt_only_ci_test;
+
/// Run the rustfmt executable and return its output.
fn rustfmt(args: &[&str]) -> (String, String) {
let mut bin_dir = env::current_exe().unwrap();
@@ -47,7 +49,7 @@ macro_rules! assert_that {
};
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn print_config() {
assert_that!(
@@ -76,7 +78,7 @@ fn print_config() {
remove_file("minimal-config").unwrap();
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn inline_config() {
// single invocation
@@ -157,3 +159,18 @@ fn mod_resolution_error_path_attribute_does_not_exist() {
// The path attribute points to a file that does not exist
assert!(stderr.contains("does_not_exist.rs does not exist"));
}
+
+#[test]
+fn rustfmt_emits_error_on_line_overflow_true() {
+ // See also https://github.com/rust-lang/rustfmt/issues/3164
+ let args = [
+ "--config",
+ "error_on_line_overflow=true",
+ "tests/cargo-fmt/source/issue_3164/src/main.rs",
+ ];
+
+ let (_stdout, stderr) = rustfmt(&args);
+ assert!(stderr.contains(
+ "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
+ ))
+}
diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
index d26f4ee89..131cbb855 100644
--- a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
@@ -329,7 +329,7 @@ pub enum Feature {
tbm,
/// POPCNT (Population Count)
popcnt,
- /// FXSR (Floating-point context fast save and restor)
+ /// FXSR (Floating-point context fast save and restore)
fxsr,
/// XSAVE (Save Processor Extended States)
xsave,
diff --git a/src/tools/rustfmt/tests/source/comments_unicode.rs b/src/tools/rustfmt/tests/source/comments_unicode.rs
new file mode 100644
index 000000000..e65a245ba
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/comments_unicode.rs
@@ -0,0 +1,140 @@
+impl Default for WhitespaceCharacters {
+ fn default() -> Self {
+ Self {
+ space: '·', // U+00B7
+ nbsp: '⍽', // U+237D
+ tab: '→', // U+2192
+ newline: '⏎', // U+23CE
+ }
+ }
+}
+
+const RAINBOWS: &[&str] = &[
+ "rаinЬοѡ", // hue: 0
+ "raіnЬοw", // hue: 2
+ "rаіɴЬow", // hue: 2
+ "raіɴЬoѡ", // hue: 8
+ "ʀainЬow", // hue: 8
+ "ʀaіɴboѡ", // hue: 8
+ "ʀаіnbοw", // hue: 11
+ "rainЬoѡ", // hue: 14
+ "raіɴbow", // hue: 14
+ "rаiɴЬow", // hue: 20
+ "raіnЬow", // hue: 26
+ "ʀaiɴbοw", // hue: 32
+ "raіɴboѡ", // hue: 35
+ "rаiɴbow", // hue: 35
+ "rаіnbοw", // hue: 38
+ "rаinЬow", // hue: 47
+ "ʀaіnboѡ", // hue: 47
+ "ʀaіnЬoѡ", // hue: 47
+ "ʀаіɴbοw", // hue: 53
+ "ʀaіnЬοѡ", // hue: 57
+ "raiɴЬoѡ", // hue: 68
+ "ʀainbοѡ", // hue: 68
+ "ʀаinboѡ", // hue: 68
+ "ʀаiɴbοw", // hue: 68
+ "ʀаіnbow", // hue: 68
+ "rаіnЬοѡ", // hue: 69
+ "ʀainЬοw", // hue: 71
+ "raiɴbow", // hue: 73
+ "raіnЬoѡ", // hue: 74
+ "rаіɴbοw", // hue: 77
+ "raіnЬοѡ", // hue: 81
+ "raiɴЬow", // hue: 83
+ "ʀainbοw", // hue: 83
+ "ʀаinbow", // hue: 83
+ "ʀаiɴbοѡ", // hue: 83
+ "ʀаіnboѡ", // hue: 83
+ "ʀаіɴЬοѡ", // hue: 84
+ "rainЬow", // hue: 85
+ "ʀаiɴЬοw", // hue: 86
+ "ʀаіnbοѡ", // hue: 89
+ "ʀаіnЬοw", // hue: 92
+ "rаiɴbοw", // hue: 95
+ "ʀаіɴbοѡ", // hue: 98
+ "ʀаiɴЬοѡ", // hue: 99
+ "raіnbοw", // hue: 101
+ "ʀаіɴЬοw", // hue: 101
+ "ʀaiɴboѡ", // hue: 104
+ "ʀаinbοѡ", // hue: 104
+ "rаiɴbοѡ", // hue: 107
+ "ʀаinЬοw", // hue: 107
+ "rаiɴЬοw", // hue: 110
+ "rаіnboѡ", // hue: 110
+ "rаіnbοѡ", // hue: 113
+ "ʀainЬοѡ", // hue: 114
+ "rаіnЬοw", // hue: 116
+ "ʀaіɴЬow", // hue: 116
+ "rаinbοw", // hue: 122
+ "ʀаіɴboѡ", // hue: 125
+ "rаinbοѡ", // hue: 131
+ "rainbow", // hue: 134
+ "rаinЬοw", // hue: 134
+ "ʀаiɴboѡ", // hue: 140
+ "rainЬοѡ", // hue: 141
+ "raіɴЬow", // hue: 143
+ "ʀainЬoѡ", // hue: 143
+ "ʀaіɴbow", // hue: 143
+ "ʀainbow", // hue: 148
+ "rаіɴboѡ", // hue: 149
+ "ʀainboѡ", // hue: 155
+ "ʀaіnbow", // hue: 155
+ "ʀaіnЬow", // hue: 155
+ "raiɴbοw", // hue: 158
+ "ʀаiɴЬoѡ", // hue: 158
+ "rainbοw", // hue: 160
+ "rаinbow", // hue: 160
+ "ʀaіɴbοѡ", // hue: 164
+ "ʀаiɴbow", // hue: 164
+ "ʀаіnЬoѡ", // hue: 164
+ "ʀaiɴЬοѡ", // hue: 165
+ "rаiɴboѡ", // hue: 167
+ "ʀaіɴЬοw", // hue: 167
+ "ʀaіɴЬοѡ", // hue: 171
+ "raіnboѡ", // hue: 173
+ "ʀаіɴЬoѡ", // hue: 173
+ "rаіɴbοѡ", // hue: 176
+ "ʀаinЬow", // hue: 176
+ "rаiɴЬοѡ", // hue: 177
+ "rаіɴЬοw", // hue: 179
+ "ʀаinЬoѡ", // hue: 179
+ "ʀаіɴbow", // hue: 179
+ "rаiɴЬoѡ", // hue: 182
+ "raіɴbοѡ", // hue: 188
+ "rаіnЬoѡ", // hue: 188
+ "raiɴЬοѡ", // hue: 189
+ "raіɴЬοw", // hue: 191
+ "ʀaіɴbοw", // hue: 191
+ "ʀаіnЬow", // hue: 191
+ "rainbοѡ", // hue: 194
+ "rаinboѡ", // hue: 194
+ "rаіnbow", // hue: 194
+ "rainЬοw", // hue: 197
+ "rаinЬoѡ", // hue: 206
+ "rаіɴbow", // hue: 206
+ "rаіɴЬοѡ", // hue: 210
+ "ʀaiɴЬow", // hue: 212
+ "raіɴbοw", // hue: 218
+ "rаіnЬow", // hue: 218
+ "ʀaiɴbοѡ", // hue: 221
+ "ʀaiɴЬοw", // hue: 224
+ "ʀaіnbοѡ", // hue: 227
+ "raiɴboѡ", // hue: 230
+ "ʀaіnbοw", // hue: 230
+ "ʀaіnЬοw", // hue: 230
+ "ʀаinЬοѡ", // hue: 231
+ "rainboѡ", // hue: 232
+ "raіnbow", // hue: 232
+ "ʀаіɴЬow", // hue: 233
+ "ʀaіɴЬoѡ", // hue: 239
+ "ʀаіnЬοѡ", // hue: 246
+ "raiɴbοѡ", // hue: 248
+ "ʀаiɴЬow", // hue: 248
+ "raіɴЬοѡ", // hue: 249
+ "raiɴЬοw", // hue: 251
+ "rаіɴЬoѡ", // hue: 251
+ "ʀaiɴbow", // hue: 251
+ "ʀаinbοw", // hue: 251
+ "raіnbοѡ", // hue: 254
+];
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs
index 66a371c25..eb573d312 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs
index f11e86fd3..4be34f0fe 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Tall
+// rustfmt-fn_params_layout: Tall
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs
index a23cc0252..674968023 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/enum.rs b/src/tools/rustfmt/tests/source/enum.rs
index 0ed9651ab..a7b961692 100644
--- a/src/tools/rustfmt/tests/source/enum.rs
+++ b/src/tools/rustfmt/tests/source/enum.rs
@@ -36,7 +36,7 @@ enum StructLikeVariants {
Normal(u32, String, ),
StructLike { x: i32, // Test comment
// Pre-comment
- #[Attr50] y: SomeType, // Aanother Comment
+ #[Attr50] y: SomeType, // Another Comment
}, SL { a: A }
}
diff --git a/src/tools/rustfmt/tests/source/fn-custom-7.rs b/src/tools/rustfmt/tests/source/fn-custom-7.rs
index d5330196b..3ecd87017 100644
--- a/src/tools/rustfmt/tests/source/fn-custom-7.rs
+++ b/src/tools/rustfmt/tests/source/fn-custom-7.rs
@@ -1,5 +1,5 @@
// rustfmt-normalize_comments: true
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// rustfmt-brace_style: AlwaysNextLine
// Case with only one variable.
diff --git a/src/tools/rustfmt/tests/source/fn-custom.rs b/src/tools/rustfmt/tests/source/fn-custom.rs
index 77ced4c5e..64ef0ecfa 100644
--- a/src/tools/rustfmt/tests/source/fn-custom.rs
+++ b/src/tools/rustfmt/tests/source/fn-custom.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Test some of the ways function signatures can be customised.
// Test compressed layout of args.
diff --git a/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
index 759bc83d0..fd6e3f044 100644
--- a/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
+++ b/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Empty list should stay on one line.
fn do_bar(
diff --git a/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs
new file mode 100644
index 000000000..9af114fbe
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs
@@ -0,0 +1,26 @@
+// rustfmt-format_macro_bodies: true
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 +
+ 42
+ ),
+ };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/source/issue-4643.rs b/src/tools/rustfmt/tests/source/issue-4643.rs
new file mode 100644
index 000000000..382072d90
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4643.rs
@@ -0,0 +1,23 @@
+// output doesn't get corrupted when using comments within generic type parameters of a trait
+
+pub trait Something<
+ A,
+ // some comment
+ B,
+ C
+> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
+
+pub trait SomethingElse<
+ A,
+ /* some comment */
+ B,
+ C
+> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
diff --git a/src/tools/rustfmt/tests/source/issue-4689/one.rs b/src/tools/rustfmt/tests/source/issue-4689/one.rs
new file mode 100644
index 000000000..d048eb10f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4689/one.rs
@@ -0,0 +1,149 @@
+// rustfmt-version: One
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write1 + fmt::Write2
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer1<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + Printer2<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+>,
+> {
+}
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+> + fmt::Write1
++ fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+)
+{
+}
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+) + fmt::Write
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+mut entries: entryyyyyyyy,
+) -> (
+impl Fn(
+AlphabeticalTraversal,
+Seconddddddddddddddddddddddddddddddddddd
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
++ Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+for<'b> &'b Self: Send
++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/source/issue-4689/two.rs b/src/tools/rustfmt/tests/source/issue-4689/two.rs
new file mode 100644
index 000000000..ea7feda82
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4689/two.rs
@@ -0,0 +1,149 @@
+// rustfmt-version: Two
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write1 + fmt::Write2
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer1<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + Printer2<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+>,
+> {
+}
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+> + fmt::Write1
++ fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+)
+{
+}
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+) + fmt::Write
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+mut entries: entryyyyyyyy,
+) -> (
+impl Fn(
+AlphabeticalTraversal,
+Seconddddddddddddddddddddddddddddddddddd
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
++ Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+for<'b> &'b Self: Send
++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/source/issue_1306.rs b/src/tools/rustfmt/tests/source/issue_1306.rs
new file mode 100644
index 000000000..03b78e341
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_1306.rs
@@ -0,0 +1,29 @@
+// rustfmt-max_width: 160
+// rustfmt-fn_call_width: 96
+// rustfmt-fn_args_layout: Compressed
+// rustfmt-trailing_comma: Always
+// rustfmt-wrap_comments: true
+
+fn foo() {
+ for elem in try!(gen_epub_book::ops::parse_descriptor_file(&mut try!(File::open(&opts.source_file.1).map_err(|_| {
+ gen_epub_book::Error::Io {
+ desc: "input file",
+ op: "open",
+ more: None,
+ }
+ })),
+ "input file")) {
+ println!("{}", elem);
+ }
+}
+
+fn write_content() {
+ io::copy(try!(File::open(in_f).map_err(|_| {
+ Error::Io {
+ desc: "Content",
+ op: "open",
+ more: None,
+ }
+ })),
+ w);
+}
diff --git a/src/tools/rustfmt/tests/source/issue_3245.rs b/src/tools/rustfmt/tests/source/issue_3245.rs
new file mode 100644
index 000000000..0279246ed
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_3245.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x = 1;
+ ;let y = 3;
+}
diff --git a/src/tools/rustfmt/tests/source/issue_3561.rs b/src/tools/rustfmt/tests/source/issue_3561.rs
new file mode 100644
index 000000000..8f6cd8f9f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_3561.rs
@@ -0,0 +1,6 @@
+fn main() {;7
+}
+
+fn main() {
+ ;7
+}
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs
new file mode 100644
index 000000000..d0437ee10
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs
new file mode 100644
index 000000000..1f6722344
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*","items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should also skip this invocation, as the wildcard covers it
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs
new file mode 100644
index 000000000..f3dd89dc4
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: []
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs
new file mode 100644
index 000000000..7fa5d3a6f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs
new file mode 100644
index 000000000..d56695325
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["unknown"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs
new file mode 100644
index 000000000..a920381a4
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs
@@ -0,0 +1,16 @@
+// rustfmt-skip_macro_invocations: ["foo","bar"]
+
+// Should skip this invocation
+foo!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+bar!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+baz!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs
new file mode 100644
index 000000000..61296869a
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should not skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs
new file mode 100644
index 000000000..9398918a9
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs
new file mode 100644
index 000000000..4e3eb542d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs
new file mode 100644
index 000000000..43cb8015d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs
@@ -0,0 +1,32 @@
+// rustfmt-skip_macro_invocations: ["aaa","ccc"]
+
+// These tests demonstrate a realistic use case with use aliases.
+// The use statements should not impact functionality in any way.
+
+use crate::{aaa, bbb, ddd};
+
+// No use alias, invocation in list
+// Should skip this invocation
+aaa!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation in list
+// Should skip this invocation
+use crate::bbb as ccc;
+ccc!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation not in list
+// Should not skip this invocation
+use crate::ddd as eee;
+eee!(
+ const _: u8 = 0;
+);
+
+// No use alias, invocation not in list
+// Should not skip this invocation
+fff!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/tuple.rs b/src/tools/rustfmt/tests/source/tuple.rs
index 9a0f979fb..5189a7454 100644
--- a/src/tools/rustfmt/tests/source/tuple.rs
+++ b/src/tools/rustfmt/tests/source/tuple.rs
@@ -1,4 +1,4 @@
-// Test tuple litterals
+// Test tuple literals
fn foo() {
let a = (a, a, a, a, a);
diff --git a/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
index 78b3ce146..56064e4a4 100644
--- a/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
+++ b/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
@@ -11,6 +11,6 @@
///
fn foo() {}
-/// A long commment for wrapping
+/// A long comment for wrapping
/// This is a long long long long long long long long long long long long long long long long long long long long sentence.
fn bar() {}
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
index 02d5eed1c..47210cae2 100644
--- a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
@@ -314,7 +314,7 @@ pub enum Feature {
tbm,
/// POPCNT (Population Count)
popcnt,
- /// FXSR (Floating-point context fast save and restor)
+ /// FXSR (Floating-point context fast save and restore)
fxsr,
/// XSAVE (Save Processor Extended States)
xsave,
diff --git a/src/tools/rustfmt/tests/target/comments_unicode.rs b/src/tools/rustfmt/tests/target/comments_unicode.rs
new file mode 100644
index 000000000..3e1b6b0a2
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/comments_unicode.rs
@@ -0,0 +1,140 @@
+impl Default for WhitespaceCharacters {
+ fn default() -> Self {
+ Self {
+ space: '·', // U+00B7
+ nbsp: '⍽', // U+237D
+ tab: '→', // U+2192
+ newline: '⏎', // U+23CE
+ }
+ }
+}
+
+const RAINBOWS: &[&str] = &[
+ "rаinЬοѡ", // hue: 0
+ "raіnЬοw", // hue: 2
+ "rаіɴЬow", // hue: 2
+ "raіɴЬoѡ", // hue: 8
+ "ʀainЬow", // hue: 8
+ "ʀaіɴboѡ", // hue: 8
+ "ʀаіnbοw", // hue: 11
+ "rainЬoѡ", // hue: 14
+ "raіɴbow", // hue: 14
+ "rаiɴЬow", // hue: 20
+ "raіnЬow", // hue: 26
+ "ʀaiɴbοw", // hue: 32
+ "raіɴboѡ", // hue: 35
+ "rаiɴbow", // hue: 35
+ "rаіnbοw", // hue: 38
+ "rаinЬow", // hue: 47
+ "ʀaіnboѡ", // hue: 47
+ "ʀaіnЬoѡ", // hue: 47
+ "ʀаіɴbοw", // hue: 53
+ "ʀaіnЬοѡ", // hue: 57
+ "raiɴЬoѡ", // hue: 68
+ "ʀainbοѡ", // hue: 68
+ "ʀаinboѡ", // hue: 68
+ "ʀаiɴbοw", // hue: 68
+ "ʀаіnbow", // hue: 68
+ "rаіnЬοѡ", // hue: 69
+ "ʀainЬοw", // hue: 71
+ "raiɴbow", // hue: 73
+ "raіnЬoѡ", // hue: 74
+ "rаіɴbοw", // hue: 77
+ "raіnЬοѡ", // hue: 81
+ "raiɴЬow", // hue: 83
+ "ʀainbοw", // hue: 83
+ "ʀаinbow", // hue: 83
+ "ʀаiɴbοѡ", // hue: 83
+ "ʀаіnboѡ", // hue: 83
+ "ʀаіɴЬοѡ", // hue: 84
+ "rainЬow", // hue: 85
+ "ʀаiɴЬοw", // hue: 86
+ "ʀаіnbοѡ", // hue: 89
+ "ʀаіnЬοw", // hue: 92
+ "rаiɴbοw", // hue: 95
+ "ʀаіɴbοѡ", // hue: 98
+ "ʀаiɴЬοѡ", // hue: 99
+ "raіnbοw", // hue: 101
+ "ʀаіɴЬοw", // hue: 101
+ "ʀaiɴboѡ", // hue: 104
+ "ʀаinbοѡ", // hue: 104
+ "rаiɴbοѡ", // hue: 107
+ "ʀаinЬοw", // hue: 107
+ "rаiɴЬοw", // hue: 110
+ "rаіnboѡ", // hue: 110
+ "rаіnbοѡ", // hue: 113
+ "ʀainЬοѡ", // hue: 114
+ "rаіnЬοw", // hue: 116
+ "ʀaіɴЬow", // hue: 116
+ "rаinbοw", // hue: 122
+ "ʀаіɴboѡ", // hue: 125
+ "rаinbοѡ", // hue: 131
+ "rainbow", // hue: 134
+ "rаinЬοw", // hue: 134
+ "ʀаiɴboѡ", // hue: 140
+ "rainЬοѡ", // hue: 141
+ "raіɴЬow", // hue: 143
+ "ʀainЬoѡ", // hue: 143
+ "ʀaіɴbow", // hue: 143
+ "ʀainbow", // hue: 148
+ "rаіɴboѡ", // hue: 149
+ "ʀainboѡ", // hue: 155
+ "ʀaіnbow", // hue: 155
+ "ʀaіnЬow", // hue: 155
+ "raiɴbοw", // hue: 158
+ "ʀаiɴЬoѡ", // hue: 158
+ "rainbοw", // hue: 160
+ "rаinbow", // hue: 160
+ "ʀaіɴbοѡ", // hue: 164
+ "ʀаiɴbow", // hue: 164
+ "ʀаіnЬoѡ", // hue: 164
+ "ʀaiɴЬοѡ", // hue: 165
+ "rаiɴboѡ", // hue: 167
+ "ʀaіɴЬοw", // hue: 167
+ "ʀaіɴЬοѡ", // hue: 171
+ "raіnboѡ", // hue: 173
+ "ʀаіɴЬoѡ", // hue: 173
+ "rаіɴbοѡ", // hue: 176
+ "ʀаinЬow", // hue: 176
+ "rаiɴЬοѡ", // hue: 177
+ "rаіɴЬοw", // hue: 179
+ "ʀаinЬoѡ", // hue: 179
+ "ʀаіɴbow", // hue: 179
+ "rаiɴЬoѡ", // hue: 182
+ "raіɴbοѡ", // hue: 188
+ "rаіnЬoѡ", // hue: 188
+ "raiɴЬοѡ", // hue: 189
+ "raіɴЬοw", // hue: 191
+ "ʀaіɴbοw", // hue: 191
+ "ʀаіnЬow", // hue: 191
+ "rainbοѡ", // hue: 194
+ "rаinboѡ", // hue: 194
+ "rаіnbow", // hue: 194
+ "rainЬοw", // hue: 197
+ "rаinЬoѡ", // hue: 206
+ "rаіɴbow", // hue: 206
+ "rаіɴЬοѡ", // hue: 210
+ "ʀaiɴЬow", // hue: 212
+ "raіɴbοw", // hue: 218
+ "rаіnЬow", // hue: 218
+ "ʀaiɴbοѡ", // hue: 221
+ "ʀaiɴЬοw", // hue: 224
+ "ʀaіnbοѡ", // hue: 227
+ "raiɴboѡ", // hue: 230
+ "ʀaіnbοw", // hue: 230
+ "ʀaіnЬοw", // hue: 230
+ "ʀаinЬοѡ", // hue: 231
+ "rainboѡ", // hue: 232
+ "raіnbow", // hue: 232
+ "ʀаіɴЬow", // hue: 233
+ "ʀaіɴЬoѡ", // hue: 239
+ "ʀаіnЬοѡ", // hue: 246
+ "raiɴbοѡ", // hue: 248
+ "ʀаiɴЬow", // hue: 248
+ "raіɴЬοѡ", // hue: 249
+ "raiɴЬοw", // hue: 251
+ "rаіɴЬoѡ", // hue: 251
+ "ʀaiɴbow", // hue: 251
+ "ʀаinbοw", // hue: 251
+ "raіnbοѡ", // hue: 254
+];
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs
index f189446e2..ff32f0f1d 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs
index 20f308973..25a86799a 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Tall
+// rustfmt-fn_params_layout: Tall
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs
index 6c695a75d..7a0e42415 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/enum.rs b/src/tools/rustfmt/tests/target/enum.rs
index 9a25126b4..70fc8ab37 100644
--- a/src/tools/rustfmt/tests/target/enum.rs
+++ b/src/tools/rustfmt/tests/target/enum.rs
@@ -43,7 +43,7 @@ enum StructLikeVariants {
x: i32, // Test comment
// Pre-comment
#[Attr50]
- y: SomeType, // Aanother Comment
+ y: SomeType, // Another Comment
},
SL {
a: A,
diff --git a/src/tools/rustfmt/tests/target/fn-custom-7.rs b/src/tools/rustfmt/tests/target/fn-custom-7.rs
index 2c20ac5a7..f6a1a90c3 100644
--- a/src/tools/rustfmt/tests/target/fn-custom-7.rs
+++ b/src/tools/rustfmt/tests/target/fn-custom-7.rs
@@ -1,5 +1,5 @@
// rustfmt-normalize_comments: true
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// rustfmt-brace_style: AlwaysNextLine
// Case with only one variable.
diff --git a/src/tools/rustfmt/tests/target/fn-custom.rs b/src/tools/rustfmt/tests/target/fn-custom.rs
index 2eb2a973d..506d9de34 100644
--- a/src/tools/rustfmt/tests/target/fn-custom.rs
+++ b/src/tools/rustfmt/tests/target/fn-custom.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Test some of the ways function signatures can be customised.
// Test compressed layout of args.
diff --git a/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
index da0ac981d..bfeca15c9 100644
--- a/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
+++ b/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Empty list should stay on one line.
fn do_bar() -> u8 {
diff --git a/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs
new file mode 100644
index 000000000..2038ed7f1
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_macro_matchers: false
+
+macro_rules! foo {
+ ($a:ident : $b:ty) => {};
+ ($a:ident $b:ident $c:ident) => {};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs
new file mode 100644
index 000000000..01d939add
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_macro_matchers: true
+
+macro_rules! foo {
+ ($a:ident : $b:ty) => {};
+ ($a:ident $b:ident $c:ident) => {};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs
new file mode 100644
index 000000000..1352b762e
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs
@@ -0,0 +1,26 @@
+// rustfmt-format_macro_bodies: false
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 +
+ 42
+ ),
+ };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs
new file mode 100644
index 000000000..88d57159c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs
@@ -0,0 +1,21 @@
+// rustfmt-format_macro_bodies: true
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct { field: (42 + 42) };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-4643.rs b/src/tools/rustfmt/tests/target/issue-4643.rs
new file mode 100644
index 000000000..ef99e4db3
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4643.rs
@@ -0,0 +1,19 @@
+// output doesn't get corrupted when using comments within generic type parameters of a trait
+
+pub trait Something<
+ A,
+ // some comment
+ B,
+ C,
+>
+{
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
+
+pub trait SomethingElse<A, /* some comment */ B, C> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
diff --git a/src/tools/rustfmt/tests/target/issue-4689/one.rs b/src/tools/rustfmt/tests/target/issue-4689/one.rs
new file mode 100644
index 000000000..7735e34f3
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4689/one.rs
@@ -0,0 +1,150 @@
+// rustfmt-version: One
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+>
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write1
+ + fmt::Write2
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer1<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + Printer2<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ >,
+> {
+}
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ > + fmt::Write1
+ + fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ),
+{
+}
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ) + fmt::Write,
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+ mut entries: entryyyyyyyy,
+) -> (impl Fn(
+ AlphabeticalTraversal,
+ Seconddddddddddddddddddddddddddddddddddd,
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ + Sendddddddddddddddddddddddddddddddddddddddddddd) {
+}
+
+pub trait SomeTrait:
+ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+ for<'b> &'b Self: Send
+ + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/target/issue-4689/two.rs b/src/tools/rustfmt/tests/target/issue-4689/two.rs
new file mode 100644
index 000000000..e3b5cd228
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4689/two.rs
@@ -0,0 +1,152 @@
+// rustfmt-version: Two
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write1
+ + fmt::Write2
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer1<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + Printer2<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ >,
+> {
+}
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ > + fmt::Write1
+ + fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ),
+{
+}
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ) + fmt::Write,
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+ mut entries: entryyyyyyyy,
+) -> (
+ impl Fn(
+ AlphabeticalTraversal,
+ Seconddddddddddddddddddddddddddddddddddd,
+ ) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ + Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+ for<'b> &'b Self: Send
+ + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs b/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
index 588656b53..29f6bda90 100644
--- a/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
+++ b/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
@@ -1,7 +1,7 @@
// rustfmt-brace_style: SameLineWhere
// rustfmt-comment_width: 100
// rustfmt-edition: 2018
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// rustfmt-hard_tabs: false
// rustfmt-match_block_trailing_comma: true
// rustfmt-max_width: 100
diff --git a/src/tools/rustfmt/tests/target/issue-5358.rs b/src/tools/rustfmt/tests/target/issue-5358.rs
new file mode 100644
index 000000000..d4bf4909a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5358.rs
@@ -0,0 +1,4 @@
+// Test /* comment */ inside trait generics does not get duplicated.
+trait Test</* comment */ T> {}
+
+trait TestTwo</* comment */ T, /* comment */ V> {}
diff --git a/src/tools/rustfmt/tests/target/issue_1306.rs b/src/tools/rustfmt/tests/target/issue_1306.rs
new file mode 100644
index 000000000..6bb514cdf
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_1306.rs
@@ -0,0 +1,33 @@
+// rustfmt-max_width: 160
+// rustfmt-fn_call_width: 96
+// rustfmt-fn_args_layout: Compressed
+// rustfmt-trailing_comma: Always
+// rustfmt-wrap_comments: true
+
+fn foo() {
+ for elem in try!(gen_epub_book::ops::parse_descriptor_file(
+ &mut try!(File::open(&opts.source_file.1).map_err(|_| {
+ gen_epub_book::Error::Io {
+ desc: "input file",
+ op: "open",
+ more: None,
+ }
+ })),
+ "input file"
+ )) {
+ println!("{}", elem);
+ }
+}
+
+fn write_content() {
+ io::copy(
+ try!(File::open(in_f).map_err(|_| {
+ Error::Io {
+ desc: "Content",
+ op: "open",
+ more: None,
+ }
+ })),
+ w,
+ );
+}
diff --git a/src/tools/rustfmt/tests/target/issue_3033.rs b/src/tools/rustfmt/tests/target/issue_3033.rs
new file mode 100644
index 000000000..e12249a6d
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3033.rs
@@ -0,0 +1,2 @@
+use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerBinding::
+ BluetoothRemoteGATTServerMethods;
diff --git a/src/tools/rustfmt/tests/target/issue_3245.rs b/src/tools/rustfmt/tests/target/issue_3245.rs
new file mode 100644
index 000000000..8f442f118
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3245.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x = 1;
+ let y = 3;
+}
diff --git a/src/tools/rustfmt/tests/target/issue_3561.rs b/src/tools/rustfmt/tests/target/issue_3561.rs
new file mode 100644
index 000000000..846a14d86
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3561.rs
@@ -0,0 +1,7 @@
+fn main() {
+ 7
+}
+
+fn main() {
+ 7
+}
diff --git a/src/tools/rustfmt/tests/target/issue_4350.rs b/src/tools/rustfmt/tests/target/issue_4350.rs
new file mode 100644
index 000000000..a94c5c321
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_4350.rs
@@ -0,0 +1,13 @@
+//rustfmt-format_macro_bodies: true
+
+macro_rules! mto_text_left {
+ ($buf:ident, $n:ident, $pos:ident, $state:ident) => {{
+ let cursor = loop {
+ state = match iter.next() {
+ None if $pos == DP::Start => break last_char_idx($buf),
+ None /*some comment */ => break 0,
+ };
+ };
+ Ok(saturate_cursor($buf, cursor))
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5668.rs b/src/tools/rustfmt/tests/target/issue_5668.rs
new file mode 100644
index 000000000..bbd9a530b
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5668.rs
@@ -0,0 +1,8 @@
+type Foo = impl Send;
+struct Struct<
+ const C: usize = {
+ let _: Foo = ();
+ //~^ ERROR: mismatched types
+ 0
+ },
+>;
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs
new file mode 100644
index 000000000..d0437ee10
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs
new file mode 100644
index 000000000..1f6722344
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*","items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should also skip this invocation, as the wildcard covers it
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs
new file mode 100644
index 000000000..4a398cc59
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: []
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs
new file mode 100644
index 000000000..c4d577269
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs
new file mode 100644
index 000000000..7ab144039
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["unknown"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs
new file mode 100644
index 000000000..c6b41ff93
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs
@@ -0,0 +1,16 @@
+// rustfmt-skip_macro_invocations: ["foo","bar"]
+
+// Should skip this invocation
+foo!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+bar!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+baz!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs
new file mode 100644
index 000000000..6e372c726
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should not skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs
new file mode 100644
index 000000000..9398918a9
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs
new file mode 100644
index 000000000..aa57a2a65
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs
new file mode 100644
index 000000000..799dd8c08
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs
@@ -0,0 +1,32 @@
+// rustfmt-skip_macro_invocations: ["aaa","ccc"]
+
+// These tests demonstrate a realistic use case with use aliases.
+// The use statements should not impact functionality in any way.
+
+use crate::{aaa, bbb, ddd};
+
+// No use alias, invocation in list
+// Should skip this invocation
+aaa!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation in list
+// Should skip this invocation
+use crate::bbb as ccc;
+ccc!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation not in list
+// Should not skip this invocation
+use crate::ddd as eee;
+eee!(
+ const _: u8 = 0;
+);
+
+// No use alias, invocation not in list
+// Should not skip this invocation
+fff!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/tuple.rs b/src/tools/rustfmt/tests/target/tuple.rs
index 68bb2f3bc..24fcf8cfd 100644
--- a/src/tools/rustfmt/tests/target/tuple.rs
+++ b/src/tools/rustfmt/tests/target/tuple.rs
@@ -1,4 +1,4 @@
-// Test tuple litterals
+// Test tuple literals
fn foo() {
let a = (a, a, a, a, a);
diff --git a/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
index d61d4d7c2..6ccecc7e0 100644
--- a/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
+++ b/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
@@ -10,7 +10,7 @@
/// ```
fn foo() {}
-/// A long commment for wrapping
+/// A long comment for wrapping
/// This is a long long long long long long long long long long long long long
/// long long long long long long long sentence.
fn bar() {}