From 80d196d789fdd9adb43b474d9a3a74af4633937f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 11 Jan 2023 22:25:29 +0100 Subject: [PATCH 01/29] Update rustfmt for ast::ExprKind::FormatArgs. Rustfmt doesn't expand macros, so that's easy: FormatArgs nodes do not occur in the unexpanded AST. --- src/expr.rs | 5 ++++- src/utils.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 414e767690b..cdbdcedd58f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -399,7 +399,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, }; diff --git a/src/utils.rs b/src/utils.rs index 3e884419f1a..80dce525e39 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -462,6 +462,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(..) From 2791cc37e6f882f8ab7fa6c234885be652f930c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jan 2023 22:36:46 +0000 Subject: [PATCH 02/29] Teach parser to understand fake anonymous enum syntax Parse `-> Ty | OtherTy`. Parse type ascription in top level patterns. --- src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index c1991e8d2c8..f065ec680d7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -839,7 +839,9 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { + Some(context.snippet(self.span).to_owned()) + } ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", From 4e3ed18e1d3724f223bbdec5593263653b7158e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jan 2023 14:29:53 +0000 Subject: [PATCH 03/29] review comment: Remove AST AnonTy --- src/types.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index f065ec680d7..c1991e8d2c8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -839,9 +839,7 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { - Some(context.snippet(self.span).to_owned()) - } + ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", From 094b7f599cb1e3420021e496c72d9e1dd36043a0 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 24 Jan 2023 14:16:03 -0600 Subject: [PATCH 04/29] Merge commit '1d8491b120223272b13451fc81265aa64f7f4d5b' into sync-from-rustfmt --- .github/workflows/check_diff.yml | 33 +++ .github/workflows/integration.yml | 4 - CHANGELOG.md | 28 ++- Cargo.lock | 4 +- Cargo.toml | 4 +- Configurations.md | 185 +++++++++++++++- Processes.md | 2 +- ci/build_and_test.bat | 1 + ci/build_and_test.sh | 1 + ci/check_diff.sh | 199 ++++++++++++++++++ ci/integration.sh | 18 +- config_proc_macro/Cargo.lock | 2 +- config_proc_macro/Cargo.toml | 2 +- config_proc_macro/src/attrs.rs | 27 ++- config_proc_macro/src/item_enum.rs | 40 +++- config_proc_macro/src/lib.rs | 13 ++ config_proc_macro/tests/smoke.rs | 1 + rust-toolchain | 4 +- src/attr.rs | 4 +- src/bin/main.rs | 2 +- src/cargo-fmt/main.rs | 12 +- src/cargo-fmt/test/mod.rs | 4 +- src/chains.rs | 120 ++++++++--- src/config/config_type.rs | 122 +++++++++-- src/config/macro_names.rs | 118 +++++++++++ src/config/mod.rs | 149 ++++++++++++- src/expr.rs | 9 +- src/imports.rs | 4 +- src/items.rs | 10 +- src/lists.rs | 16 +- src/macros.rs | 18 +- src/skip.rs | 79 +++++-- src/test/configuration_snippet.rs | 7 +- src/test/mod.rs | 6 +- src/types.rs | 44 +++- src/utils.rs | 5 +- src/visitor.rs | 13 +- tests/cargo-fmt/main.rs | 29 ++- tests/cargo-fmt/source/issue_3164/Cargo.toml | 8 + tests/cargo-fmt/source/issue_3164/src/main.rs | 13 ++ tests/config/small_tabs.toml | 2 +- .../issue-5198/lib/c/d/explanation.txt | 2 +- .../issue-5198/lib/explanation.txt | 2 +- tests/rustfmt/main.rs | 21 +- tests/source/cfg_if/detect/arch/x86.rs | 2 +- tests/source/comments_unicode.rs | 140 ++++++++++++ .../compressed.rs | 2 +- .../tall.rs | 2 +- .../vertical.rs | 2 +- tests/source/enum.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom.rs | 2 +- tests/source/fn_args_layout-vertical.rs | 2 +- .../issue-3987/format_macro_bodies_true.rs | 26 +++ tests/source/issue-4643.rs | 23 ++ tests/source/issue-4689/one.rs | 149 +++++++++++++ tests/source/issue-4689/two.rs | 149 +++++++++++++ tests/source/issue_1306.rs | 29 +++ tests/source/issue_3245.rs | 4 + tests/source/issue_3561.rs | 6 + tests/source/skip_macro_invocations/all.rs | 11 + .../skip_macro_invocations/all_and_name.rs | 11 + tests/source/skip_macro_invocations/empty.rs | 11 + tests/source/skip_macro_invocations/name.rs | 11 + .../skip_macro_invocations/name_unknown.rs | 6 + tests/source/skip_macro_invocations/names.rs | 16 ++ .../path_qualified_invocation_mismatch.rs | 6 + .../path_qualified_match.rs | 6 + .../path_qualified_name_mismatch.rs | 6 + .../use_alias_examples.rs | 32 +++ tests/source/tuple.rs | 2 +- ...ts_should_not_imply_format_doc_comments.rs | 2 +- tests/target/cfg_if/detect/arch/x86.rs | 2 +- tests/target/comments_unicode.rs | 140 ++++++++++++ .../compressed.rs | 2 +- .../tall.rs | 2 +- .../vertical.rs | 2 +- tests/target/enum.rs | 2 +- tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom.rs | 2 +- tests/target/fn_args_layout-vertical.rs | 2 +- .../issue-2534/format_macro_matchers_false.rs | 6 + .../issue-2534/format_macro_matchers_true.rs | 6 + .../issue-3987/format_macro_bodies_false.rs | 26 +++ .../issue-3987/format_macro_bodies_true.rs | 21 ++ tests/target/issue-4643.rs | 19 ++ tests/target/issue-4689/one.rs | 150 +++++++++++++ tests/target/issue-4689/two.rs | 152 +++++++++++++ tests/target/issue-4791/issue_4928.rs | 2 +- tests/target/issue-5358.rs | 4 + tests/target/issue_1306.rs | 33 +++ tests/target/issue_3033.rs | 2 + tests/target/issue_3245.rs | 4 + tests/target/issue_3561.rs | 7 + tests/target/issue_4350.rs | 13 ++ tests/target/issue_5668.rs | 8 + tests/target/skip_macro_invocations/all.rs | 11 + .../skip_macro_invocations/all_and_name.rs | 11 + tests/target/skip_macro_invocations/empty.rs | 11 + tests/target/skip_macro_invocations/name.rs | 11 + .../skip_macro_invocations/name_unknown.rs | 6 + tests/target/skip_macro_invocations/names.rs | 16 ++ .../path_qualified_invocation_mismatch.rs | 6 + .../path_qualified_match.rs | 6 + .../path_qualified_name_mismatch.rs | 6 + .../use_alias_examples.rs | 32 +++ tests/target/tuple.rs | 2 +- ...ts_should_not_imply_format_doc_comments.rs | 2 +- 108 files changed, 2591 insertions(+), 187 deletions(-) create mode 100644 .github/workflows/check_diff.yml create mode 100755 ci/check_diff.sh create mode 100644 src/config/macro_names.rs create mode 100644 tests/cargo-fmt/source/issue_3164/Cargo.toml create mode 100644 tests/cargo-fmt/source/issue_3164/src/main.rs create mode 100644 tests/source/comments_unicode.rs rename tests/source/configs/{fn_args_layout => fn_params_layout}/compressed.rs (92%) rename tests/source/configs/{fn_args_layout => fn_params_layout}/tall.rs (93%) rename tests/source/configs/{fn_args_layout => fn_params_layout}/vertical.rs (92%) create mode 100644 tests/source/issue-3987/format_macro_bodies_true.rs create mode 100644 tests/source/issue-4643.rs create mode 100644 tests/source/issue-4689/one.rs create mode 100644 tests/source/issue-4689/two.rs create mode 100644 tests/source/issue_1306.rs create mode 100644 tests/source/issue_3245.rs create mode 100644 tests/source/issue_3561.rs create mode 100644 tests/source/skip_macro_invocations/all.rs create mode 100644 tests/source/skip_macro_invocations/all_and_name.rs create mode 100644 tests/source/skip_macro_invocations/empty.rs create mode 100644 tests/source/skip_macro_invocations/name.rs create mode 100644 tests/source/skip_macro_invocations/name_unknown.rs create mode 100644 tests/source/skip_macro_invocations/names.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_match.rs create mode 100644 tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs create mode 100644 tests/source/skip_macro_invocations/use_alias_examples.rs create mode 100644 tests/target/comments_unicode.rs rename tests/target/configs/{fn_args_layout => fn_params_layout}/compressed.rs (92%) rename tests/target/configs/{fn_args_layout => fn_params_layout}/tall.rs (94%) rename tests/target/configs/{fn_args_layout => fn_params_layout}/vertical.rs (94%) create mode 100644 tests/target/issue-2534/format_macro_matchers_false.rs create mode 100644 tests/target/issue-2534/format_macro_matchers_true.rs create mode 100644 tests/target/issue-3987/format_macro_bodies_false.rs create mode 100644 tests/target/issue-3987/format_macro_bodies_true.rs create mode 100644 tests/target/issue-4643.rs create mode 100644 tests/target/issue-4689/one.rs create mode 100644 tests/target/issue-4689/two.rs create mode 100644 tests/target/issue-5358.rs create mode 100644 tests/target/issue_1306.rs create mode 100644 tests/target/issue_3033.rs create mode 100644 tests/target/issue_3245.rs create mode 100644 tests/target/issue_3561.rs create mode 100644 tests/target/issue_4350.rs create mode 100644 tests/target/issue_5668.rs create mode 100644 tests/target/skip_macro_invocations/all.rs create mode 100644 tests/target/skip_macro_invocations/all_and_name.rs create mode 100644 tests/target/skip_macro_invocations/empty.rs create mode 100644 tests/target/skip_macro_invocations/name.rs create mode 100644 tests/target/skip_macro_invocations/name_unknown.rs create mode 100644 tests/target/skip_macro_invocations/names.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_match.rs create mode 100644 tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs create mode 100644 tests/target/skip_macro_invocations/use_alias_examples.rs diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml new file mode 100644 index 00000000000..8bfb5834519 --- /dev/null +++ b/.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/.github/workflows/integration.yml b/.github/workflows/integration.yml index 4d8899b434b..314ce0e84c6 100644 --- a/.github/workflows/integration.yml +++ b/.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/CHANGELOG.md b/CHANGELOG.md index 0c1893bf8c3..60f961fa12a 100644 --- a/CHANGELOG.md +++ b/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/Cargo.lock b/Cargo.lock index 311df226da1..24166d51c51 100644 --- a/Cargo.lock +++ b/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/Cargo.toml b/Cargo.toml index 7a4e02d69ed..87ce59d0217 100644 --- a/Cargo.toml +++ b/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/Configurations.md b/Configurations.md index 8b96b9d3689..49e7e4e6489 100644 --- a/Configurations.md +++ b/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/Processes.md b/Processes.md index f763b5714ce..61abc87eec9 100644 --- a/Processes.md +++ b/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/ci/build_and_test.bat b/ci/build_and_test.bat index ef41017783f..69dae1fff7b 100755 --- a/ci/build_and_test.bat +++ b/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/ci/build_and_test.sh b/ci/build_and_test.sh index 8fa0f67b0d0..94991853263 100755 --- a/ci/build_and_test.sh +++ b/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/ci/check_diff.sh b/ci/check_diff.sh new file mode 100755 index 00000000000..062c2dd8673 --- /dev/null +++ b/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/ci/integration.sh b/ci/integration.sh index 562d5d70c70..19d502bc5c7 100755 --- a/ci/integration.sh +++ b/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/config_proc_macro/Cargo.lock b/config_proc_macro/Cargo.lock index ecf561f28fb..49f2f72a8d2 100644 --- a/config_proc_macro/Cargo.lock +++ b/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/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index a41b3a5e6bf..d10d0469cc4 100644 --- a/config_proc_macro/Cargo.toml +++ b/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/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index 0baba046f9e..dd18ff572cb 100644 --- a/config_proc_macro/src/attrs.rs +++ b/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 { 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 { @@ -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 { attr.parse_meta().ok().and_then(|meta| match meta { syn::Meta::NameValue(syn::MetaNameValue { diff --git a/config_proc_macro/src/item_enum.rs b/config_proc_macro/src/item_enum.rs index dcee77a8549..731a7ea0607 100644 --- a/config_proc_macro/src/item_enum.rs +++ b/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::>() .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/config_proc_macro/src/lib.rs b/config_proc_macro/src/lib.rs index e772c53f423..0c54c132c97 100644 --- a/config_proc_macro/src/lib.rs +++ b/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/config_proc_macro/tests/smoke.rs b/config_proc_macro/tests/smoke.rs index 940a8a0c251..c8a83e39c9e 100644 --- a/config_proc_macro/tests/smoke.rs +++ b/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/rust-toolchain b/rust-toolchain index 2640a9e0ecc..22283b3d620 100644 --- a/rust-toolchain +++ b/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/attr.rs b/src/attr.rs index c503eeeb9b3..5648e1254ed 100644 --- a/src/attr.rs +++ b/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/bin/main.rs b/src/bin/main.rs index 8e871e61f26..be64559e877 100644 --- a/src/bin/main.rs +++ b/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/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 9031d29b45f..2b714b68df0 100644 --- a/src/cargo-fmt/main.rs +++ b/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/cargo-fmt/test/mod.rs b/src/cargo-fmt/test/mod.rs index 56e52fbabb6..696326e4f94 100644 --- a/src/cargo-fmt/test/mod.rs +++ b/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/chains.rs b/src/chains.rs index a1a73cf4bd5..39b8d687809 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -70,10 +70,64 @@ 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, }; +/// 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 { + context.snippet_provider.span_to_snippet(span).map(|s| { + s.lines() + .map(|l| l.trim_end()) + .collect::>() + .join("\n") + }) +} + +fn format_chain_item( + item: &ChainItem, + context: &RewriteContext<'_>, + rewrite_shape: Shape, + allow_overflow: bool, +) -> Option { + 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 { + 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<'_>, @@ -496,6 +550,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 +561,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 +575,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 +795,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { } fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - 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 +864,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 +882,17 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - 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/config/config_type.rs b/src/config/config_type.rs index c5e61658ad1..54ca7676dfc 100644 --- a/src/config/config_type.rs +++ b/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 ``. 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("[, ...]") + } +} + 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, $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( + 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/config/macro_names.rs b/src/config/macro_names.rs new file mode 100644 index 00000000000..26ad78d6dca --- /dev/null +++ b/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 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 { + 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); + +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 { + 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/config/mod.rs b/src/config/mod.rs index f49c18d3a46..14f27f3f8b6 100644 --- a/src/config/mod.rs +++ b/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 Default: false"; + const PRINT_DOCS_UNSTABLE_OPTION: &str = "unstable_option 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/expr.rs b/src/expr.rs index 868ff045ab7..0be4c3cf168 100644 --- a/src/expr.rs +++ b/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; @@ -2050,8 +2050,7 @@ fn choose_rhs( 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/imports.rs b/src/imports.rs index d9dc8d004af..339e5cef5af 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -251,8 +251,8 @@ fn flatten_use_trees( use_trees: Vec, import_granularity: ImportGranularity, ) -> Vec { - // 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/items.rs b/src/items.rs index a2a73f0a5fb..25e8a024857 100644 --- a/src/items.rs +++ b/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 { 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( ¶m_items, context .config - .fn_args_layout() + .fn_params_layout() .to_list_tactic(param_items.len()), Separator::Comma, one_line_budget, diff --git a/src/lists.rs b/src/lists.rs index e8785050782..a878e6cf9b2 100644 --- a/src/lists.rs +++ b/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, inner_item_len: usize) -> usize { - item_max_width.unwrap_or(0).saturating_sub(inner_item_len) +fn post_comment_alignment(item_max_width: Option, 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/macros.rs b/src/macros.rs index df949388037..d58f7547fef 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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 { 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 { @@ -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/skip.rs b/src/skip.rs index 032922d421d..68f85b2ade4 100644 --- a/src/skip.rs +++ b/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, - attributes: Vec, + 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), +} + +impl Default for SkipNameContext { + fn default() -> Self { + Self::Values(Default::default()) + } +} + +impl Extend for SkipNameContext { + fn extend>(&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/test/configuration_snippet.rs b/src/test/configuration_snippet.rs index c8fda7c8556..c70b3c5facd 100644 --- a/src/test/configuration_snippet.rs +++ b/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/test/mod.rs b/src/test/mod.rs index 6b5bc2b30dd..cfad4a8ed0e 100644 --- a/src/test/mod.rs +++ b/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/types.rs b/src/types.rs index c1991e8d2c8..01e2fb6e61e 100644 --- a/src/types.rs +++ b/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/utils.rs b/src/utils.rs index 3e884419f1a..f681f55b37b 100644 --- a/src/utils.rs +++ b/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 { - 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 { diff --git a/src/visitor.rs b/src/visitor.rs index 9c3cc7820d2..f4d84d1381f 100644 --- a/src/visitor.rs +++ b/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/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs index 348876cd264..701c36fadea 100644 --- a/tests/cargo-fmt/main.rs +++ b/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/tests/cargo-fmt/source/issue_3164/Cargo.toml b/tests/cargo-fmt/source/issue_3164/Cargo.toml new file mode 100644 index 00000000000..580ef7e6e24 --- /dev/null +++ b/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/tests/cargo-fmt/source/issue_3164/src/main.rs b/tests/cargo-fmt/source/issue_3164/src/main.rs new file mode 100644 index 00000000000..9330107ac8d --- /dev/null +++ b/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/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index c3cfd34317a..4c37100894f 100644 --- a/tests/config/small_tabs.toml +++ b/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/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt index 92c9e302143..254102ebabd 100644 --- a/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt +++ b/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/tests/mod-resolver/issue-5198/lib/explanation.txt b/tests/mod-resolver/issue-5198/lib/explanation.txt index d436a8076cd..90464def8eb 100644 --- a/tests/mod-resolver/issue-5198/lib/explanation.txt +++ b/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/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 4c6d52726f3..7ff301e8019 100644 --- a/tests/rustfmt/main.rs +++ b/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/tests/source/cfg_if/detect/arch/x86.rs b/tests/source/cfg_if/detect/arch/x86.rs index d26f4ee894f..131cbb855f1 100644 --- a/tests/source/cfg_if/detect/arch/x86.rs +++ b/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/tests/source/comments_unicode.rs b/tests/source/comments_unicode.rs new file mode 100644 index 00000000000..e65a245ba93 --- /dev/null +++ b/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/tests/source/configs/fn_args_layout/compressed.rs b/tests/source/configs/fn_params_layout/compressed.rs similarity index 92% rename from tests/source/configs/fn_args_layout/compressed.rs rename to tests/source/configs/fn_params_layout/compressed.rs index 66a371c259f..eb573d3121f 100644 --- a/tests/source/configs/fn_args_layout/compressed.rs +++ b/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/tests/source/configs/fn_args_layout/tall.rs b/tests/source/configs/fn_params_layout/tall.rs similarity index 93% rename from tests/source/configs/fn_args_layout/tall.rs rename to tests/source/configs/fn_params_layout/tall.rs index f11e86fd313..4be34f0fe4a 100644 --- a/tests/source/configs/fn_args_layout/tall.rs +++ b/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/tests/source/configs/fn_args_layout/vertical.rs b/tests/source/configs/fn_params_layout/vertical.rs similarity index 92% rename from tests/source/configs/fn_args_layout/vertical.rs rename to tests/source/configs/fn_params_layout/vertical.rs index a23cc025225..674968023f9 100644 --- a/tests/source/configs/fn_args_layout/vertical.rs +++ b/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/tests/source/enum.rs b/tests/source/enum.rs index 0ed9651abe7..a7b9616929c 100644 --- a/tests/source/enum.rs +++ b/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/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index d5330196bf7..3ecd8701727 100644 --- a/tests/source/fn-custom-7.rs +++ b/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/tests/source/fn-custom.rs b/tests/source/fn-custom.rs index 77ced4c5e0e..64ef0ecfaae 100644 --- a/tests/source/fn-custom.rs +++ b/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/tests/source/fn_args_layout-vertical.rs b/tests/source/fn_args_layout-vertical.rs index 759bc83d015..fd6e3f0442e 100644 --- a/tests/source/fn_args_layout-vertical.rs +++ b/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/tests/source/issue-3987/format_macro_bodies_true.rs b/tests/source/issue-3987/format_macro_bodies_true.rs new file mode 100644 index 00000000000..9af114fbe57 --- /dev/null +++ b/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/tests/source/issue-4643.rs b/tests/source/issue-4643.rs new file mode 100644 index 00000000000..382072d9004 --- /dev/null +++ b/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/tests/source/issue-4689/one.rs b/tests/source/issue-4689/one.rs new file mode 100644 index 00000000000..d048eb10fb1 --- /dev/null +++ b/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(foo2: F) +where +F: Fn( +// this comment is deleted +) +{ +} +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) + fmt::Write +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +), +{ +} +fn elaborate_bounds(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/tests/source/issue-4689/two.rs b/tests/source/issue-4689/two.rs new file mode 100644 index 00000000000..ea7feda825d --- /dev/null +++ b/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(foo2: F) +where +F: Fn( +// this comment is deleted +) +{ +} +fn foo(foo2: F) +where +F: Fn( +// this comment is deleted +) + fmt::Write +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where +F: for<> FnMut( +&mut ProbeContext<>, +ty::PolyTraitRefffffffffffffffffffffffffffffffff<>, +tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, +), +{ +} +fn elaborate_bounds(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/tests/source/issue_1306.rs b/tests/source/issue_1306.rs new file mode 100644 index 00000000000..03b78e34108 --- /dev/null +++ b/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/tests/source/issue_3245.rs b/tests/source/issue_3245.rs new file mode 100644 index 00000000000..0279246ed6a --- /dev/null +++ b/tests/source/issue_3245.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + ;let y = 3; +} diff --git a/tests/source/issue_3561.rs b/tests/source/issue_3561.rs new file mode 100644 index 00000000000..8f6cd8f9fbc --- /dev/null +++ b/tests/source/issue_3561.rs @@ -0,0 +1,6 @@ +fn main() {;7 +} + +fn main() { + ;7 +} diff --git a/tests/source/skip_macro_invocations/all.rs b/tests/source/skip_macro_invocations/all.rs new file mode 100644 index 00000000000..d0437ee10fd --- /dev/null +++ b/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/tests/source/skip_macro_invocations/all_and_name.rs b/tests/source/skip_macro_invocations/all_and_name.rs new file mode 100644 index 00000000000..1f6722344fe --- /dev/null +++ b/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/tests/source/skip_macro_invocations/empty.rs b/tests/source/skip_macro_invocations/empty.rs new file mode 100644 index 00000000000..f3dd89dc4db --- /dev/null +++ b/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/tests/source/skip_macro_invocations/name.rs b/tests/source/skip_macro_invocations/name.rs new file mode 100644 index 00000000000..7fa5d3a6f71 --- /dev/null +++ b/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/tests/source/skip_macro_invocations/name_unknown.rs b/tests/source/skip_macro_invocations/name_unknown.rs new file mode 100644 index 00000000000..d5669532524 --- /dev/null +++ b/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/tests/source/skip_macro_invocations/names.rs b/tests/source/skip_macro_invocations/names.rs new file mode 100644 index 00000000000..a920381a455 --- /dev/null +++ b/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/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs new file mode 100644 index 00000000000..61296869a50 --- /dev/null +++ b/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/tests/source/skip_macro_invocations/path_qualified_match.rs b/tests/source/skip_macro_invocations/path_qualified_match.rs new file mode 100644 index 00000000000..9398918a9e1 --- /dev/null +++ b/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/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs b/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs new file mode 100644 index 00000000000..4e3eb542dbe --- /dev/null +++ b/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/tests/source/skip_macro_invocations/use_alias_examples.rs b/tests/source/skip_macro_invocations/use_alias_examples.rs new file mode 100644 index 00000000000..43cb8015de5 --- /dev/null +++ b/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/tests/source/tuple.rs b/tests/source/tuple.rs index 9a0f979fbca..5189a7454f3 100644 --- a/tests/source/tuple.rs +++ b/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/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs b/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs index 78b3ce146f2..56064e4a4cc 100644 --- a/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs +++ b/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/tests/target/cfg_if/detect/arch/x86.rs b/tests/target/cfg_if/detect/arch/x86.rs index 02d5eed1c29..47210cae2aa 100644 --- a/tests/target/cfg_if/detect/arch/x86.rs +++ b/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/tests/target/comments_unicode.rs b/tests/target/comments_unicode.rs new file mode 100644 index 00000000000..3e1b6b0a28f --- /dev/null +++ b/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/tests/target/configs/fn_args_layout/compressed.rs b/tests/target/configs/fn_params_layout/compressed.rs similarity index 92% rename from tests/target/configs/fn_args_layout/compressed.rs rename to tests/target/configs/fn_params_layout/compressed.rs index f189446e25d..ff32f0f1d58 100644 --- a/tests/target/configs/fn_args_layout/compressed.rs +++ b/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/tests/target/configs/fn_args_layout/tall.rs b/tests/target/configs/fn_params_layout/tall.rs similarity index 94% rename from tests/target/configs/fn_args_layout/tall.rs rename to tests/target/configs/fn_params_layout/tall.rs index 20f308973ac..25a86799af0 100644 --- a/tests/target/configs/fn_args_layout/tall.rs +++ b/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/tests/target/configs/fn_args_layout/vertical.rs b/tests/target/configs/fn_params_layout/vertical.rs similarity index 94% rename from tests/target/configs/fn_args_layout/vertical.rs rename to tests/target/configs/fn_params_layout/vertical.rs index 6c695a75df9..7a0e42415f3 100644 --- a/tests/target/configs/fn_args_layout/vertical.rs +++ b/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/tests/target/enum.rs b/tests/target/enum.rs index 9a25126b44e..70fc8ab376c 100644 --- a/tests/target/enum.rs +++ b/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/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 2c20ac5a752..f6a1a90c3fc 100644 --- a/tests/target/fn-custom-7.rs +++ b/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/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index 2eb2a973d24..506d9de3437 100644 --- a/tests/target/fn-custom.rs +++ b/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/tests/target/fn_args_layout-vertical.rs b/tests/target/fn_args_layout-vertical.rs index da0ac981d87..bfeca15c967 100644 --- a/tests/target/fn_args_layout-vertical.rs +++ b/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/tests/target/issue-2534/format_macro_matchers_false.rs b/tests/target/issue-2534/format_macro_matchers_false.rs new file mode 100644 index 00000000000..2038ed7f1d0 --- /dev/null +++ b/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/tests/target/issue-2534/format_macro_matchers_true.rs b/tests/target/issue-2534/format_macro_matchers_true.rs new file mode 100644 index 00000000000..01d939add4d --- /dev/null +++ b/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/tests/target/issue-3987/format_macro_bodies_false.rs b/tests/target/issue-3987/format_macro_bodies_false.rs new file mode 100644 index 00000000000..1352b762e45 --- /dev/null +++ b/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/tests/target/issue-3987/format_macro_bodies_true.rs b/tests/target/issue-3987/format_macro_bodies_true.rs new file mode 100644 index 00000000000..88d57159c85 --- /dev/null +++ b/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/tests/target/issue-4643.rs b/tests/target/issue-4643.rs new file mode 100644 index 00000000000..ef99e4db382 --- /dev/null +++ b/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 { + fn a(&self, x: A) -> i32; + fn b(&self, x: B) -> i32; + fn c(&self, x: C) -> i32; +} diff --git a/tests/target/issue-4689/one.rs b/tests/target/issue-4689/one.rs new file mode 100644 index 00000000000..7735e34f3b5 --- /dev/null +++ b/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(foo2: F) +where + F: Fn( + // this comment is deleted + ), +{ +} +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ) + fmt::Write, +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ), +{ +} +fn elaborate_bounds(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/tests/target/issue-4689/two.rs b/tests/target/issue-4689/two.rs new file mode 100644 index 00000000000..e3b5cd22810 --- /dev/null +++ b/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(foo2: F) +where + F: Fn( + // this comment is deleted + ), +{ +} +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ) + fmt::Write, +{ +} + +fn elaborate_bounds(mut mk_cand: F) +where + F: FnMut( + &mut ProbeContext, + ty::PolyTraitRefffffffffffffffffffffffffffffffff, + tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem, + ), +{ +} +fn elaborate_bounds(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/tests/target/issue-4791/issue_4928.rs b/tests/target/issue-4791/issue_4928.rs index 588656b535f..29f6bda9063 100644 --- a/tests/target/issue-4791/issue_4928.rs +++ b/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/tests/target/issue-5358.rs b/tests/target/issue-5358.rs new file mode 100644 index 00000000000..d4bf4909ad7 --- /dev/null +++ b/tests/target/issue-5358.rs @@ -0,0 +1,4 @@ +// Test /* comment */ inside trait generics does not get duplicated. +trait Test {} + +trait TestTwo {} diff --git a/tests/target/issue_1306.rs b/tests/target/issue_1306.rs new file mode 100644 index 00000000000..6bb514cdfe5 --- /dev/null +++ b/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/tests/target/issue_3033.rs b/tests/target/issue_3033.rs new file mode 100644 index 00000000000..e12249a6da6 --- /dev/null +++ b/tests/target/issue_3033.rs @@ -0,0 +1,2 @@ +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerBinding:: + BluetoothRemoteGATTServerMethods; diff --git a/tests/target/issue_3245.rs b/tests/target/issue_3245.rs new file mode 100644 index 00000000000..8f442f1181a --- /dev/null +++ b/tests/target/issue_3245.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + let y = 3; +} diff --git a/tests/target/issue_3561.rs b/tests/target/issue_3561.rs new file mode 100644 index 00000000000..846a14d86a5 --- /dev/null +++ b/tests/target/issue_3561.rs @@ -0,0 +1,7 @@ +fn main() { + 7 +} + +fn main() { + 7 +} diff --git a/tests/target/issue_4350.rs b/tests/target/issue_4350.rs new file mode 100644 index 00000000000..a94c5c32188 --- /dev/null +++ b/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/tests/target/issue_5668.rs b/tests/target/issue_5668.rs new file mode 100644 index 00000000000..bbd9a530b81 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/all.rs b/tests/target/skip_macro_invocations/all.rs new file mode 100644 index 00000000000..d0437ee10fd --- /dev/null +++ b/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/tests/target/skip_macro_invocations/all_and_name.rs b/tests/target/skip_macro_invocations/all_and_name.rs new file mode 100644 index 00000000000..1f6722344fe --- /dev/null +++ b/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/tests/target/skip_macro_invocations/empty.rs b/tests/target/skip_macro_invocations/empty.rs new file mode 100644 index 00000000000..4a398cc59c6 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/name.rs b/tests/target/skip_macro_invocations/name.rs new file mode 100644 index 00000000000..c4d577269c6 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/name_unknown.rs b/tests/target/skip_macro_invocations/name_unknown.rs new file mode 100644 index 00000000000..7ab1440395c --- /dev/null +++ b/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/tests/target/skip_macro_invocations/names.rs b/tests/target/skip_macro_invocations/names.rs new file mode 100644 index 00000000000..c6b41ff93d7 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs new file mode 100644 index 00000000000..6e372c72695 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/path_qualified_match.rs b/tests/target/skip_macro_invocations/path_qualified_match.rs new file mode 100644 index 00000000000..9398918a9e1 --- /dev/null +++ b/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/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs b/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs new file mode 100644 index 00000000000..aa57a2a655c --- /dev/null +++ b/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/tests/target/skip_macro_invocations/use_alias_examples.rs b/tests/target/skip_macro_invocations/use_alias_examples.rs new file mode 100644 index 00000000000..799dd8c08af --- /dev/null +++ b/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/tests/target/tuple.rs b/tests/target/tuple.rs index 68bb2f3bc28..24fcf8cfd7c 100644 --- a/tests/target/tuple.rs +++ b/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/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs index d61d4d7c216..6ccecc7e0bb 100644 --- a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs +++ b/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() {} From c6b822d85546f830f568bc4ff9b1d761d26964c1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 12:58:04 +1100 Subject: [PATCH 05/29] Rename `Cursor`/`CursorRef` as `TokenTreeCursor`/`RefTokenTreeCursor`. This makes it clear they return token trees, and makes for a nice comparison against `TokenCursor` which returns tokens. --- src/macros.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index d58f7547fef..7978d8cba95 100644 --- a/src/macros.rs +++ b/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::{ @@ -736,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 { @@ -768,7 +768,7 @@ impl MacroArgParser { &mut self, inner: Vec, delim: Delimiter, - iter: &mut Cursor, + iter: &mut TokenTreeCursor, ) -> Option<()> { let mut buffer = String::new(); let mut first = true; @@ -1121,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 { From 24f4ecec2595ab504994766d8cc60d2c11eaa369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 9 Feb 2023 10:16:00 +0000 Subject: [PATCH 06/29] Introduce `-Zterminal-urls` to use OSC8 for error codes Terminals supporting the OSC8 Hyperlink Extension can support inline anchors where the text is user defineable but clicking on it opens a browser to a specified URLs, just like `` does in HTML. https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda --- src/parse/session.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 6bfec79cd70..9014026b0aa 100644 --- a/src/parse/session.rs +++ b/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}, @@ -135,6 +135,7 @@ fn default_handler( None, false, false, + TerminalUrl::No, )) }; Handler::with_emitter( From af75a2f7f10001da3f9d5fbda2d9cce458b7959d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Nov 2022 11:55:16 +1100 Subject: [PATCH 07/29] Use `ThinVec` in various AST types. This commit changes the sequence parsers to produce `ThinVec`, which triggers numerous conversions. --- src/chains.rs | 4 +++- src/lib.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/chains.rs b/src/chains.rs index 39b8d687809..cbe523c6c3c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -74,6 +74,8 @@ use crate::utils::{ 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 { @@ -168,7 +170,7 @@ enum ChainItemKind { MethodCall( ast::PathSegment, Vec, - Vec>, + ThinVec>, ), StructField(symbol::Ident), TupleField(symbol::Ident, bool), diff --git a/src/lib.rs b/src/lib.rs index 0c27bcacfb8..b27405efdb7 100644 --- a/src/lib.rs +++ b/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. From 23007fc9e4ad5666c65e8a598e2942c8329def0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Jan 2023 14:13:27 +1100 Subject: [PATCH 08/29] Use `ThinVec` in `ast::Block`. --- src/closures.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/closures.rs b/src/closures.rs index 8fd0fcf8f5c..340113866c4 100644 --- a/src/closures.rs +++ b/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, From 01ed9ddf0ef7a754235b6c1f92689e6f048282d0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Jan 2023 15:39:22 +1100 Subject: [PATCH 09/29] Use `ThinVec` in a few more AST types. --- src/modules.rs | 13 +++++++------ src/parse/parser.rs | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/modules.rs b/src/modules.rs index 7a0d1736c59..af9a154a6ae 100644 --- a/src/modules.rs +++ b/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>; #[derive(Debug, Clone)] pub(crate) struct Module<'a> { ast_mod_kind: Option>, - pub(crate) items: Cow<'a, Vec>>, + pub(crate) items: Cow<'a, ThinVec>>, 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>, - mod_items: Cow<'a, Vec>>, + mod_items: Cow<'a, ThinVec>>, 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>, + items: ThinVec>, ) -> 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/parse/parser.rs b/src/parse/parser.rs index e0bd065518b..7ab042506bd 100644 --- a/src/parse/parser.rs +++ b/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>, Span), ParserError> { + ) -> Result<(ast::AttrVec, ThinVec>, 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) { From 8b7f8116d62e53cfd2b700155e6851c026529819 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 13 Oct 2022 10:13:02 +0100 Subject: [PATCH 10/29] errors: generate typed identifiers in each crate Instead of loading the Fluent resources for every crate in `rustc_error_messages`, each crate generates typed identifiers for its own diagnostics and creates a static which are pulled together in the `rustc_driver` crate and provided to the diagnostic emitter. Signed-off-by: David Wood --- src/parse/session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 9014026b0aa..a7a363d47ba 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -124,7 +124,7 @@ fn default_handler( silent_emitter() } else { let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); + rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES, false); Box::new(EmitterWriter::stderr( color_cfg, Some(source_map.clone()), From 386ea3770f39e41c8e3be7a05527484b11e23769 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 17 Oct 2022 14:11:26 +0100 Subject: [PATCH 11/29] various: translation resources from cg backend Extend `CodegenBackend` trait with a function returning the translation resources from the codegen backend, which can be added to the complete list of resources provided to the emitter. Signed-off-by: David Wood --- src/parse/session.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index a7a363d47ba..a64963db6a7 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -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_driver::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()), From a5ba6e025f9c37dc3b9f0943355974288f0c4da9 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 27 Feb 2023 13:07:44 +0000 Subject: [PATCH 12/29] Remove uses of `box_syntax` in rustc and tools --- tests/source/expr.rs | 11 ----------- tests/target/configs/combine_control_expr/false.rs | 6 ------ tests/target/configs/combine_control_expr/true.rs | 6 ------ tests/target/expr.rs | 14 -------------- 4 files changed, 37 deletions(-) diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 21f8a4a4366..879c551ea49 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -3,7 +3,6 @@ // Test expressions fn foo() -> bool { - let boxed: Box = box 5; let referenced = &5 ; let very_long_variable_name = ( a + first + simple + test ); @@ -132,12 +131,6 @@ fn qux() { } } -fn issue227() { - { - let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - fn issue184(source: &str) { for c in source.chars() { if index < 'a' { @@ -413,10 +406,6 @@ fn issue2704() { .concat(&requires1) .concat(&requires2) .distinct_total()); - let requires = requires.set(box requires0 - .concat(&requires1) - .concat(&requires2) - .distinct_total()); let requires = requires.set(requires0 .concat(&requires1) .concat(&requires2) diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs index 5ada9b1dd14..0ab82024937 100644 --- a/tests/target/configs/combine_control_expr/false.rs +++ b/tests/target/configs/combine_control_expr/false.rs @@ -108,12 +108,6 @@ fn main() { bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, )); - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - // Unary foo(!bar( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs index 52acd26492a..aa41e021fb7 100644 --- a/tests/target/configs/combine_control_expr/true.rs +++ b/tests/target/configs/combine_control_expr/true.rs @@ -96,12 +96,6 @@ fn main() { bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, )); - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - // Unary foo(!bar( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 84df802bc70..187a1dc976a 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -3,7 +3,6 @@ // Test expressions fn foo() -> bool { - let boxed: Box = box 5; let referenced = &5; let very_long_variable_name = (a + first + simple + test); @@ -179,13 +178,6 @@ fn qux() { } } -fn issue227() { - { - let handler = - box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - fn issue184(source: &str) { for c in source.chars() { if index < 'a' { @@ -454,12 +446,6 @@ fn issue2704() { .concat(&requires2) .distinct_total(), ); - let requires = requires.set( - box requires0 - .concat(&requires1) - .concat(&requires2) - .distinct_total(), - ); let requires = requires.set( requires0 .concat(&requires1) From 4e658cc01ef5190445016ea951e21a2d0ae02a33 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 27 Feb 2023 13:17:29 +0000 Subject: [PATCH 13/29] Remove `box_syntax` from AST and use in tools --- src/closures.rs | 2 -- src/expr.rs | 5 ----- src/matches.rs | 1 - src/utils.rs | 1 - 4 files changed, 9 deletions(-) diff --git a/src/closures.rs b/src/closures.rs index 340113866c4..c95e9a97b43 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -195,7 +195,6 @@ fn rewrite_closure_expr( | ast::ExprKind::Struct(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), @@ -441,7 +440,6 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr, version), diff --git a/src/expr.rs b/src/expr.rs index 3f0f217f890..7273402ec76 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -236,7 +236,6 @@ pub(crate) fn format_expr( ast::ExprKind::Yeet(Some(ref expr)) => { rewrite_unary_prefix(context, "do yeet ", &**expr, shape) } - ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => { rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape) } @@ -1299,7 +1298,6 @@ pub(crate) fn is_simple_expr(expr: &ast::Expr) -> bool { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Field(ref expr, _) | ast::ExprKind::Try(ref expr) @@ -1361,7 +1359,6 @@ pub(crate) fn can_be_overflowed_expr( // Handle unary-like expressions ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), @@ -1373,7 +1370,6 @@ pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Call(..) | ast::ExprKind::MacCall(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), @@ -2133,7 +2129,6 @@ pub(crate) fn is_method_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::MethodCall(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) => is_method_call(expr), diff --git a/src/matches.rs b/src/matches.rs index 85d9c5d2b9b..aac5e59b860 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -592,7 +592,6 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) - | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Index(ref expr, _) diff --git a/src/utils.rs b/src/utils.rs index 1e89f3ae75f..a26375ee643 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -492,7 +492,6 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Assign(..) | ast::ExprKind::AssignOp(..) | ast::ExprKind::Await(..) - | ast::ExprKind::Box(..) | ast::ExprKind::Break(..) | ast::ExprKind::Cast(..) | ast::ExprKind::Continue(..) From 3ef194c14cda52c36110a02d7b812371d7b99884 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Tue, 31 Jan 2023 22:13:25 +0100 Subject: [PATCH 14/29] Remove the `NodeId` of `ast::ExprKind::Async` --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 7273402ec76..ac96bedf2fe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -366,7 +366,7 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Async(capture_by, _node_id, ref block) => { + ast::ExprKind::Async(capture_by, ref block) => { let mover = if capture_by == ast::CaptureBy::Value { "move " } else { From 809dd77b8001f69bd5202f73d016f9ac8426b69e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 19 Mar 2023 21:32:34 +0400 Subject: [PATCH 15/29] rustc: Remove unused `Session` argument from some attribute functions --- src/attr.rs | 16 +--------------- src/parse/parser.rs | 5 ++--- src/reorder.rs | 4 ++-- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 5648e1254ed..22e45082a9f 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -2,7 +2,7 @@ use rustc_ast::ast; use rustc_ast::HasAttrs; -use rustc_span::{symbol::sym, Span, Symbol}; +use rustc_span::{symbol::sym, Span}; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; @@ -19,20 +19,6 @@ use crate::utils::{count_newlines, mk_sp}; mod doc_comment; -pub(crate) fn contains_name(attrs: &[ast::Attribute], name: Symbol) -> bool { - attrs.iter().any(|attr| attr.has_name(name)) -} - -pub(crate) fn first_attr_value_str_by_name( - attrs: &[ast::Attribute], - name: Symbol, -) -> Option { - attrs - .iter() - .find(|attr| attr.has_name(name)) - .and_then(|attr| attr.value_str()) -} - /// Returns attributes on the given statement. pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { stmt.attrs() diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 7ab042506bd..6bc53159b38 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -2,13 +2,12 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; -use rustc_ast::{ast, ptr}; +use rustc_ast::{ast, attr, 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; use crate::Input; @@ -93,7 +92,7 @@ pub(crate) enum ParserError { impl<'a> Parser<'a> { pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { - let path_sym = first_attr_value_str_by_name(attrs, sym::path)?; + let path_sym = attr::first_attr_value_str_by_name(attrs, sym::path)?; let path_str = path_sym.as_str(); // On windows, the base path might have the form diff --git a/src/reorder.rs b/src/reorder.rs index 9e4a668aa49..3bddf4c1b6a 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,7 +8,7 @@ use std::cmp::{Ord, Ordering}; -use rustc_ast::ast; +use rustc_ast::{ast, attr}; use rustc_span::{symbol::sym, Span}; use crate::config::{Config, GroupImportsTactic}; @@ -167,7 +167,7 @@ fn rewrite_reorderable_or_regroupable_items( } fn contains_macro_use_attr(item: &ast::Item) -> bool { - crate::attr::contains_name(&item.attrs, sym::macro_use) + attr::contains_name(&item.attrs, sym::macro_use) } /// Divides imports into three groups, corresponding to standard, external From c2890ec2d7f1cd7d8af262ffe9177094756f84b0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:37:47 +0000 Subject: [PATCH 16/29] rust-analyzer guided enum variant structification --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 25e8a024857..520bb527800 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1805,7 +1805,7 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ref ty, mutability, ref expr) => { + ast::ItemKind::Static(ast::Static(ref ty, mutability, ref expr)) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From ced3cd8d40b7dcb5756c246309598e309b4fdbcd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:50:04 +0000 Subject: [PATCH 17/29] rust-analyzer guided tuple field to named field --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 520bb527800..6cbe68ae398 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1805,7 +1805,7 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ast::Static(ref ty, mutability, ref expr)) => { + ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From 3ecb9ed53c3cc50f5e7ec6d03b2998bf69adea11 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 09:20:45 +0000 Subject: [PATCH 18/29] Split out ast::ItemKind::Const into its own struct --- src/items.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/items.rs b/src/items.rs index 6cbe68ae398..0dc8a4e937f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1808,7 +1808,7 @@ impl<'a> StaticParts<'a> { ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } - ast::ItemKind::Const(defaultness, ref ty, ref expr) => { + ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { (Some(defaultness), "const", ty, ast::Mutability::Not, expr) } _ => unreachable!(), @@ -1827,8 +1827,8 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr_opt) => { - (defaultness, ty, expr_opt) + ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { + (defaultness, ty, expr) } _ => unreachable!(), }; @@ -1846,7 +1846,7 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr) => (defaultness, ty, expr), + ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), _ => unreachable!(), }; StaticParts { From f1781396bf125b46b679d3bf9499c0b9278607f9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 12:34:05 +0000 Subject: [PATCH 19/29] box a bunch of large types --- src/items.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/items.rs b/src/items.rs index 0dc8a4e937f..43779cfaecd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1804,13 +1804,15 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { - (None, "static", ty, mutability, expr) - } - ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { - (Some(defaultness), "const", ty, ast::Mutability::Not, expr) - } + let (defaultness, prefix, ty, mutability, expr) = match &item.kind { + ast::ItemKind::Static(s) => (None, "static", &s.ty, s.mutability, &s.expr), + ast::ItemKind::Const(c) => ( + Some(c.defaultness), + "const", + &c.ty, + ast::Mutability::Not, + &c.expr, + ), _ => unreachable!(), }; StaticParts { @@ -1826,10 +1828,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { - (defaultness, ty, expr) - } + let (defaultness, ty, expr_opt) = match &ti.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { @@ -1845,8 +1845,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), + let (defaultness, ty, expr) = match &ii.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { From 84385bff42c9f823e83e64c3c9c61311feee608c Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Sun, 11 Sep 2022 00:37:49 -0700 Subject: [PATCH 20/29] offset_of --- src/expr.rs | 1 + src/utils.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/expr.rs b/src/expr.rs index ac96bedf2fe..b76e3a2a87c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,6 +345,7 @@ pub(crate) fn format_expr( // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + ast::ExprKind::OffsetOf(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) diff --git a/src/utils.rs b/src/utils.rs index a26375ee643..ca171657407 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -499,6 +499,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Field(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::OffsetOf(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) | ast::ExprKind::Range(..) From ecfdec44df08f118c641c4076238f07a7f437fe6 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 21 Apr 2023 01:44:17 -0700 Subject: [PATCH 21/29] minor tweaks --- src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index b76e3a2a87c..a0882eff707 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,7 +345,6 @@ pub(crate) fn format_expr( // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), - ast::ExprKind::OffsetOf(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) @@ -400,7 +399,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), - ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => { + ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) => { // These do not occur in the AST because macros aren't expanded. unreachable!() } From f4c9b4c26f7d28416031129f300b9a9bb5e68641 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 21 Apr 2023 08:59:30 -0700 Subject: [PATCH 22/29] rustfmt fmt --- src/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index a0882eff707..824e4219136 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -399,7 +399,9 @@ pub(crate) fn format_expr( } } ast::ExprKind::Underscore => Some("_".to_owned()), - ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) => { + ast::ExprKind::FormatArgs(..) + | ast::ExprKind::IncludedBytes(..) + | ast::ExprKind::OffsetOf(..) => { // These do not occur in the AST because macros aren't expanded. unreachable!() } From 6b9c151686baf6705b4bcfb6ce3db86bc817a9b3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Apr 2023 18:59:16 +0000 Subject: [PATCH 23/29] Tweak await span --- src/chains.rs | 4 ++-- src/expr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index cbe523c6c3c..0afce7cf659 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -232,7 +232,7 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } - ast::ExprKind::Await(ref nested) => { + ast::ExprKind::Await(ref nested, _) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } @@ -459,7 +459,7 @@ impl Chain { ast::ExprKind::MethodCall(ref call) => Some(Self::convert_try(&call.receiver, context)), ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(ref subexpr) => Some(Self::convert_try(subexpr, context)), + | ast::ExprKind::Await(ref subexpr, _) => Some(Self::convert_try(subexpr, context)), _ => None, } } diff --git a/src/expr.rs b/src/expr.rs index 824e4219136..5dc628adb0c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -218,7 +218,7 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), + | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( @@ -1889,7 +1889,7 @@ impl<'ast> RhsAssignKind<'ast> { ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_) + | ast::ExprKind::Await(_, _) ) } _ => false, From a74d2d7440003ada5c88fc75c4eb468335afa618 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 15 Mar 2023 07:10:59 +0800 Subject: [PATCH 24/29] fix tests --- tests/source/type-ascription.rs | 10 ++++----- .../configs/format_macro_bodies/true.rs | 8 ++----- .../configs/format_macro_matchers/false.rs | 8 ++----- .../configs/format_macro_matchers/true.rs | 8 ++----- tests/target/macros.rs | 22 ++++++++----------- tests/target/type-ascription.rs | 11 +++++----- tests/target/type.rs | 2 +- 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs index 4874094ccc4..fbdde272cb6 100644 --- a/tests/source/type-ascription.rs +++ b/tests/source/type-ascription.rs @@ -1,10 +1,10 @@ - +// #101728, we remove type ascription, so this test case is changed to `var as ty` fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - x : u32 - 1u32 / 10f32 : u32 + let _ = x as u32 - 1u32 / (10f32 as u32); } diff --git a/tests/target/configs/format_macro_bodies/true.rs b/tests/target/configs/format_macro_bodies/true.rs index 9dc2524c389..17ac1498c93 100644 --- a/tests/target/configs/format_macro_bodies/true.rs +++ b/tests/target/configs/format_macro_bodies/true.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_bodies: true macro_rules! foo { - ($a: ident : $b: ty) => { - $a(42): $b; - }; - ($a: ident $b: ident $c: ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/configs/format_macro_matchers/false.rs b/tests/target/configs/format_macro_matchers/false.rs index 3966d21be75..01ecac9879d 100644 --- a/tests/target/configs/format_macro_matchers/false.rs +++ b/tests/target/configs/format_macro_matchers/false.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_matchers: false macro_rules! foo { - ($a: ident : $b: ty) => { - $a(42): $b; - }; - ($a: ident $b: ident $c: ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/configs/format_macro_matchers/true.rs b/tests/target/configs/format_macro_matchers/true.rs index e113af96f26..fa0442e228a 100644 --- a/tests/target/configs/format_macro_matchers/true.rs +++ b/tests/target/configs/format_macro_matchers/true.rs @@ -1,10 +1,6 @@ // rustfmt-format_macro_matchers: true macro_rules! foo { - ($a:ident : $b:ty) => { - $a(42): $b; - }; - ($a:ident $b:ident $c:ident) => { - $a = $b + $c; - }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index e930b5037d9..7b4574349df 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -122,7 +122,7 @@ fn main() { 20, 21, 22); // #1092 - chain!(input, a: take!(max_size), || []); + chain!(input, a:take!(max_size), || []); // #2727 foo!("bar"); @@ -156,17 +156,13 @@ fn issue1178() { } fn issue1739() { - sql_function!( - add_rss_item, - add_rss_item_t, - ( - a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text - ) - ); + sql_function!(add_rss_item, + add_rss_item_t, + (a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text)); w.slice_mut(s![ .., @@ -232,7 +228,7 @@ fn issue_3174() { "debugMessage": debug.message, }) } else { - json!({ "errorKind": format!("{:?}", error.err_kind()) }) + json!({"errorKind": format!("{:?}", error.err_kind())}) }; } diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index a2f082ba4b4..99dc0336864 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,12 +1,13 @@ +// #101728, we remove type ascription, so this test case is changed to `var as ty` fn main() { let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) + as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - x: u32 - 1u32 / 10f32: u32 + let _ = x as u32 - 1u32 / (10f32 as u32); } diff --git a/tests/target/type.rs b/tests/target/type.rs index 38cf909c258..c789ecb055a 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -129,7 +129,7 @@ fn issue3117() { fn issue3139() { assert_eq!( to_json_value(&None::).unwrap(), - json!({ "test": None:: }) + json!( { "test": None :: } ) ); } From 9d20134a781b4b61b45276ab6f104c3dcbe9dc82 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 4 Apr 2023 11:41:53 +0800 Subject: [PATCH 25/29] remove rustfmt testcase for type ascription --- tests/source/type-ascription.rs | 10 ---------- tests/target/type-ascription.rs | 13 ------------- 2 files changed, 23 deletions(-) delete mode 100644 tests/source/type-ascription.rs delete mode 100644 tests/target/type-ascription.rs diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs deleted file mode 100644 index fbdde272cb6..00000000000 --- a/tests/source/type-ascription.rs +++ /dev/null @@ -1,10 +0,0 @@ -// #101728, we remove type ascription, so this test case is changed to `var as ty` -fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let _ = x as u32 - 1u32 / (10f32 as u32); -} diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs deleted file mode 100644 index 99dc0336864..00000000000 --- a/tests/target/type-ascription.rs +++ /dev/null @@ -1,13 +0,0 @@ -// #101728, we remove type ascription, so this test case is changed to `var as ty` -fn main() { - let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as SomeTrait; - - let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) - as AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let _ = x as u32 - 1u32 / (10f32 as u32); -} From 34a71f67d1e28fe0bf13593e26b682d097678875 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 29 Apr 2023 06:29:07 -0500 Subject: [PATCH 26/29] Make the BUG_REPORT_URL configurable by tools This greatly simplifies how hard it is to set a custom bug report url; previously tools had to copy the entire hook implementation. - Switch clippy to the new hook This also adds a `extra_info` callback so clippy can include its own version number, which differs from rustc's. - Call `install_ice_hook` in rustfmt --- src/bin/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bin/main.rs b/src/bin/main.rs index be64559e877..47846424b06 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,3 +1,5 @@ +#![feature(rustc_private)] + use anyhow::{format_err, Result}; use io::Error as IoError; @@ -19,7 +21,14 @@ use crate::rustfmt::{ FormatReportFormatterBuilder, Input, Session, Verbosity, }; +const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; + +// N.B. these crates are loaded from the sysroot, so they need extern crate. +extern crate rustc_driver; + fn main() { + rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| ()); + env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = make_opts(); From 8e330f9d5bb92b24afde750480b5d70d6c892da5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Apr 2023 06:02:49 +0000 Subject: [PATCH 27/29] Make tools happy --- src/types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types.rs b/src/types.rs index 01e2fb6e61e..9ebe38cc25f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -552,6 +552,8 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref .rewrite(context, shape.offset_left(8)?) .map(|s| format!("~const ?{}", s)), + rustc_ast::TraitBoundModifier::Negative + | rustc_ast::TraitBoundModifier::MaybeConstNegative => None, }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } From 8ed5d5de3d4e2cf94ddd00cee922d8533d23c1dd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Apr 2023 22:37:36 +0000 Subject: [PATCH 28/29] Rustfmt support for negative bounds, test --- src/types.rs | 8 ++++++-- tests/target/negative-bounds.rs | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/target/negative-bounds.rs diff --git a/src/types.rs b/src/types.rs index 9ebe38cc25f..f548388ed8b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -552,8 +552,12 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref .rewrite(context, shape.offset_left(8)?) .map(|s| format!("~const ?{}", s)), - rustc_ast::TraitBoundModifier::Negative - | rustc_ast::TraitBoundModifier::MaybeConstNegative => None, + ast::TraitBoundModifier::Negative => poly_trait_ref + .rewrite(context, shape.offset_left(1)?) + .map(|s| format!("!{}", s)), + ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref + .rewrite(context, shape.offset_left(8)?) + .map(|s| format!("~const !{}", s)), }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } diff --git a/tests/target/negative-bounds.rs b/tests/target/negative-bounds.rs new file mode 100644 index 00000000000..4fb35cccf66 --- /dev/null +++ b/tests/target/negative-bounds.rs @@ -0,0 +1,11 @@ +fn negative() +where + i32: !Copy, +{ +} + +fn maybe_const_negative() +where + i32: ~const !Copy, +{ +} From 0b17d7ea4605fcd3675c80069e0b5e82c4332b05 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Jun 2023 21:29:15 -0500 Subject: [PATCH 29/29] chore: address merge and bump toolchain --- config_proc_macro/src/attrs.rs | 7 ------- rust-toolchain | 2 +- src/macros.rs | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index 2c01b9a1321..d8de9aae088 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -64,13 +64,6 @@ fn is_attr_path(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 { match &attr.meta { syn::Meta::NameValue(syn::MetaNameValue { diff --git a/rust-toolchain b/rust-toolchain index 22283b3d620..03b909cd80c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-24" +channel = "nightly-2023-06-19" components = ["llvm-tools", "rustc-dev"] diff --git a/src/macros.rs b/src/macros.rs index 9f4beae7350..e9a298a2769 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1124,7 +1124,7 @@ struct MacroParser { } impl MacroParser { - const fn new(toks: Cursor) -> Self { + const fn new(toks: TokenTreeCursor) -> Self { Self { toks } }