From 75765f656ebae28dbbc6f93d36a1e851473aeec9 Mon Sep 17 00:00:00 2001
From: Ruby Lazuli <nipkraps@gmail.com>
Date: Sat, 22 May 2021 08:22:42 -0500
Subject: [PATCH 001/195] Allow `--edition 2021` to be passed to rustfmt

This was added to Configurations.md in #4618, but the option wasn't
actually made available. This should let people who are using Rust 2021
on nightly rustc run `cargo fmt` again.
---
 src/bin/main.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 56b07222212..92fe8b9c514 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -689,6 +689,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result<Edition> {
     match edition_str {
         "2015" => Ok(Edition::Edition2015),
         "2018" => Ok(Edition::Edition2018),
+        "2021" => Ok(Edition::Edition2021),
         _ => Err(format_err!("Invalid value for `--edition`")),
     }
 }

From 1ca3798d2c961c43b02e312e8aa0e4bfa3f1b37e Mon Sep 17 00:00:00 2001
From: Casey Rodarmor <casey@rodarmor.com>
Date: Sun, 9 May 2021 20:01:24 -0700
Subject: [PATCH 002/195] Improve pasta copyability of `merge_imports`
 deprecation message

Add double quotes around `Crate` so that it can be copied directly into a `Cargo.toml` file
---
 src/config/config_type.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/config/config_type.rs b/src/config/config_type.rs
index 2f567b25521..7fc4486ddcd 100644
--- a/src/config/config_type.rs
+++ b/src/config/config_type.rs
@@ -409,7 +409,7 @@ macro_rules! create_config {
                 if self.was_set().merge_imports() {
                     eprintln!(
                         "Warning: the `merge_imports` option is deprecated. \
-                        Use `imports_granularity=Crate` instead"
+                        Use `imports_granularity=\"Crate\"` instead"
                     );
                     if !self.was_set().imports_granularity() {
                         self.imports_granularity.2 = if self.merge_imports() {

From 486e774fbfbbe2be98cdd2ebdbfc3e8b92fc2a95 Mon Sep 17 00:00:00 2001
From: Michael Murphy <m.b.murphy15@gmail.com>
Date: Fri, 11 Jun 2021 02:39:28 +0100
Subject: [PATCH 003/195] Adjusting help message (#4865)

On stable, running with `--help|-h` shows information about `file-lines`
which is a nightly-only option. This commit removes all mention of
`file-lines` from the help message on stable.

There is room for improvement here; perhaps a new struct called, e.g.,
`StableOptions` could be added to complement the existing
`GetOptsOptions` struct. `StableOptions` could have a field for each
field in `GetOptsOptions`, with each field's value being a `bool` that
specifies whether or not the option exists on stable. Or is this adding
too much complexity?
---
 src/bin/main.rs | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 92fe8b9c514..4b4aa42d935 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -178,12 +178,15 @@ fn make_opts() -> Options {
     opts.optflag("v", "verbose", "Print verbose output");
     opts.optflag("q", "quiet", "Print less output");
     opts.optflag("V", "version", "Show version information");
-    opts.optflagopt(
-        "h",
-        "help",
-        "Show this message or help about a specific topic: `config` or `file-lines`",
-        "=TOPIC",
-    );
+    let help_topics = if is_nightly {
+        "`config` or `file-lines`"
+    } else {
+        "`config`"
+    };
+    let mut help_topic_msg = "Show this message or help about a specific topic: ".to_owned();
+    help_topic_msg.push_str(help_topics);
+
+    opts.optflagopt("h", "help", &help_topic_msg, "=TOPIC");
 
     opts
 }
@@ -437,7 +440,7 @@ fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
             return Ok(Operation::Help(HelpOp::None));
         } else if topic == Some("config".to_owned()) {
             return Ok(Operation::Help(HelpOp::Config));
-        } else if topic == Some("file-lines".to_owned()) {
+        } else if topic == Some("file-lines".to_owned()) && is_nightly() {
             return Ok(Operation::Help(HelpOp::FileLines));
         } else {
             return Err(OperationError::UnknownHelpTopic(topic.unwrap()));

From e634a6f9a8ad9435f2d9f6bbfb6a8eb018ee8e3f Mon Sep 17 00:00:00 2001
From: Michael Murphy <m.b.murphy15@gmail.com>
Date: Wed, 16 Jun 2021 04:33:34 +0100
Subject: [PATCH 004/195] Updating outdated links (#4869)

* Updating outdated links

Updating the links to the docs and source code for `ast.rs`. Seems like it was moved to a new crate at some point.

* Updating more outdated links

This time, the links to the `fmt-rfcs` repository, which is now owned by
`rust-dev-tools` (although GitHub was redirecting anyway).

* Update Contributing.md

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
---
 Contributing.md | 4 ++--
 README.md       | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Contributing.md b/Contributing.md
index 1b77dad11f0..a108195beb9 100644
--- a/Contributing.md
+++ b/Contributing.md
@@ -138,8 +138,8 @@ format.
 
 There are different nodes for every kind of item and expression in Rust. For
 more details see the source code in the compiler -
-[ast.rs](https://dxr.mozilla.org/rust/source/src/libsyntax/ast.rs) - and/or the
-[docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/index.html).
+[ast.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_ast/src/ast.rs) - and/or the
+[docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html).
 
 Many nodes in the AST (but not all, annoyingly) have a `Span`. A `Span` is a
 range in the source code, it can easily be converted to a snippet of source
diff --git a/README.md b/README.md
index 500a9f9a37c..9c7a1c4bc34 100644
--- a/README.md
+++ b/README.md
@@ -230,5 +230,5 @@ Apache License (Version 2.0).
 See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.
 
 [rust]: https://github.com/rust-lang/rust
-[fmt rfcs]: https://github.com/rust-lang-nursery/fmt-rfcs
-[style guide]: https://github.com/rust-lang-nursery/fmt-rfcs/blob/master/guide/guide.md
+[fmt rfcs]: https://github.com/rust-dev-tools/fmt-rfcs
+[style guide]: https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md

From b305d62e5b9e08c6f4540de0a349fbf6da3dc0e4 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <calebcartwright@users.noreply.github.com>
Date: Thu, 24 Jun 2021 18:22:28 -0500
Subject: [PATCH 005/195] fix: correct arm leading pipe check (#4880)

In the event a pattern starts with a leading pipe
the pattern span will contain, and begin with, the pipe.

This updates the process to see if a match arm contains
a leading pipe by leveraging this recent(ish) change to
the patterns in the AST, and avoids an indexing bug that
occurs when a pattern starts with a non-ascii char in the
old implementation.
---
 src/matches.rs                                  |  7 ++++---
 .../configs/match_arm_leading_pipes/preserve.rs |  8 ++++++++
 .../configs/match_arm_leading_pipes/preserve.rs |  8 ++++++++
 tests/target/issue_4868.rs                      | 17 +++++++++++++++++
 4 files changed, 37 insertions(+), 3 deletions(-)
 create mode 100644 tests/target/issue_4868.rs

diff --git a/src/matches.rs b/src/matches.rs
index f33fedce92d..140ec226c02 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -19,7 +19,7 @@ use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
 use crate::utils::{
     contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp,
-    mk_sp_lo_plus_one, semicolon_for_expr, trimmed_last_line_width, unicode_str_width,
+    semicolon_for_expr, trimmed_last_line_width, unicode_str_width,
 };
 
 /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`.
@@ -167,8 +167,9 @@ fn collect_beginning_verts(
     arms.iter()
         .map(|a| {
             context
-                .snippet_provider
-                .opt_span_before(mk_sp_lo_plus_one(a.pat.span.lo()), "|")
+                .snippet(a.pat.span)
+                .starts_with("|")
+                .then(|| a.pat.span().lo())
         })
         .collect()
 }
diff --git a/tests/source/configs/match_arm_leading_pipes/preserve.rs b/tests/source/configs/match_arm_leading_pipes/preserve.rs
index ea303e857de..5486877bde1 100644
--- a/tests/source/configs/match_arm_leading_pipes/preserve.rs
+++ b/tests/source/configs/match_arm_leading_pipes/preserve.rs
@@ -26,3 +26,11 @@ fn bar() {
         _ => {}
     }
 }
+
+fn f(x: NonAscii) -> bool {
+    match x {
+      // foo
+              |   Éfgh => true,
+        _ => false,
+    }
+}
\ No newline at end of file
diff --git a/tests/target/configs/match_arm_leading_pipes/preserve.rs b/tests/target/configs/match_arm_leading_pipes/preserve.rs
index 2beb1f5d813..4775575842a 100644
--- a/tests/target/configs/match_arm_leading_pipes/preserve.rs
+++ b/tests/target/configs/match_arm_leading_pipes/preserve.rs
@@ -25,3 +25,11 @@ fn bar() {
         _ => {}
     }
 }
+
+fn f(x: NonAscii) -> bool {
+    match x {
+        // foo
+        | Éfgh => true,
+        _ => false,
+    }
+}
diff --git a/tests/target/issue_4868.rs b/tests/target/issue_4868.rs
new file mode 100644
index 00000000000..763a82c3231
--- /dev/null
+++ b/tests/target/issue_4868.rs
@@ -0,0 +1,17 @@
+enum NonAscii {
+    Abcd,
+    Éfgh,
+}
+
+use NonAscii::*;
+
+fn f(x: NonAscii) -> bool {
+    match x {
+        Éfgh => true,
+        _ => false,
+    }
+}
+
+fn main() {
+    dbg!(f(Abcd));
+}

From 19733f19f18e2f2a1510667c078c7fc7739b3c54 Mon Sep 17 00:00:00 2001
From: Jethro Beekman <jethro@fortanix.com>
Date: Fri, 25 Jun 2021 16:17:43 +0200
Subject: [PATCH 006/195] Change line endings from CRLF to LF

---
 appveyor.yml | 110 +++++++++++++++++++++++++--------------------------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/appveyor.yml b/appveyor.yml
index 7bfe696009f..5ac99fd71f8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,55 +1,55 @@
-# This is based on https://github.com/japaric/rust-everywhere/blob/master/appveyor.yml
-# and modified (mainly removal of deployment) to suit rustfmt.
-
-environment:
-  global:
-    PROJECT_NAME: rustfmt
-  matrix:
-    # Stable channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: stable
-    # Beta channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: beta
-    # Nightly channel
-    - TARGET: i686-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: i686-pc-windows-msvc
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-msvc
-      CHANNEL: nightly
-
-# Install Rust and Cargo
-# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
-install:
-  - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
-  - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
-  - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
-  - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
-  - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y
-  - rustc -Vv
-  - cargo -V
-
-# ???
-build: false
-
-test_script:
-  - set CFG_RELEASE_CHANNEL=nightly
-  - set CFG_RELEASE=nightly
-  - cargo build --verbose
-  - cargo test
-  - cargo test -- --ignored
+# This is based on https://github.com/japaric/rust-everywhere/blob/master/appveyor.yml
+# and modified (mainly removal of deployment) to suit rustfmt.
+
+environment:
+  global:
+    PROJECT_NAME: rustfmt
+  matrix:
+    # Stable channel
+    # - TARGET: i686-pc-windows-gnu
+    #   CHANNEL: stable
+    # - TARGET: i686-pc-windows-msvc
+    #   CHANNEL: stable
+    # - TARGET: x86_64-pc-windows-gnu
+    #   CHANNEL: stable
+    # - TARGET: x86_64-pc-windows-msvc
+    #   CHANNEL: stable
+    # Beta channel
+    # - TARGET: i686-pc-windows-gnu
+    #   CHANNEL: beta
+    # - TARGET: i686-pc-windows-msvc
+    #   CHANNEL: beta
+    # - TARGET: x86_64-pc-windows-gnu
+    #   CHANNEL: beta
+    # - TARGET: x86_64-pc-windows-msvc
+    #   CHANNEL: beta
+    # Nightly channel
+    - TARGET: i686-pc-windows-gnu
+      CHANNEL: nightly
+    - TARGET: i686-pc-windows-msvc
+      CHANNEL: nightly
+    - TARGET: x86_64-pc-windows-gnu
+      CHANNEL: nightly
+    - TARGET: x86_64-pc-windows-msvc
+      CHANNEL: nightly
+
+# Install Rust and Cargo
+# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
+install:
+  - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
+  - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
+  - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
+  - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
+  - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y
+  - rustc -Vv
+  - cargo -V
+
+# ???
+build: false
+
+test_script:
+  - set CFG_RELEASE_CHANNEL=nightly
+  - set CFG_RELEASE=nightly
+  - cargo build --verbose
+  - cargo test
+  - cargo test -- --ignored

From 2cf280ed1ba84001aa4e14152ae37cea18ebcb1c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 4 Jul 2021 22:26:08 -0500
Subject: [PATCH 007/195] docs: clarify match_arm_blocks config documentation

---
 Configurations.md | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 9daa7065379..d2e5613eba9 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1475,7 +1475,9 @@ Copyright 2018 The Rust Project Developers.`, etc.:
 
 ## `match_arm_blocks`
 
-Wrap the body of arms in blocks when it does not fit on the same line with the pattern of arms
+Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator.
+
+The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body does not contain multiple statements nor line comments.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
@@ -1486,10 +1488,16 @@ Wrap the body of arms in blocks when it does not fit on the same line with the p
 ```rust
 fn main() {
     match lorem {
-        true => {
+        ipsum => {
             foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x)
         }
-        false => println!("{}", sit),
+        dolor => println!("{}", sit),
+        sit => foo(
+            "foooooooooooooooooooooooo",
+            "baaaaaaaaaaaaaaaaaaaaaaaarr",
+            "baaaaaaaaaaaaaaaaaaaazzzzzzzzzzzzz",
+            "qqqqqqqqquuuuuuuuuuuuuuuuuuuuuuuuuuxxx",
+        ),
     }
 }
 ```
@@ -1499,9 +1507,15 @@ fn main() {
 ```rust
 fn main() {
     match lorem {
-        true =>
+        lorem =>
             foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x),
-        false => println!("{}", sit),
+        ipsum => println!("{}", sit),
+        sit => foo(
+            "foooooooooooooooooooooooo",
+            "baaaaaaaaaaaaaaaaaaaaaaaarr",
+            "baaaaaaaaaaaaaaaaaaaazzzzzzzzzzzzz",
+            "qqqqqqqqquuuuuuuuuuuuuuuuuuuuuuuuuuxxx",
+        ),
     }
 }
 ```

From 4c2959fb12a6bd083003ec4371126211402e265d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sun, 18 Jul 2021 10:44:39 +0200
Subject: [PATCH 008/195] fix a bunch of clippy warnings

clippy::bind_instead_of_map
clippy::branches_sharing_code
clippy::collapsible_match
clippy::inconsistent_struct_constructor
clippy::int_plus_one
clippy::iter_count
clippy::iter_nth_zero
clippy::manual_range_contains
clippy::match_like_matches_macro
clippy::needless::collect
clippy::needless_question_mark
clippy::needless_return
clippy::op_ref
clippy::option_as_ref_deref
clippy::ptr_arg
clippy::redundant_clone
clippy::redundant_closure
clippy::redundant_static_lifetimes
clippy::search_is_some
clippy::#single_char_add_str
clippy::single_char_pattern
clippy::single_component_path_imports
clippy::single_match
clippy::skip_while_next
clippy::unnecessary_lazy_evaluations
clippy::unnecessary_unwrap
clippy::useless_conversion
clippy::useless_format
---
 src/attr.rs                     |  2 +-
 src/cargo-fmt/main.rs           |  4 ++--
 src/chains.rs                   |  5 +----
 src/closures.rs                 | 15 +++++--------
 src/comment.rs                  | 21 ++++++++----------
 src/config/file_lines.rs        |  4 ++--
 src/config/license.rs           |  1 -
 src/emitter/diff.rs             |  2 +-
 src/expr.rs                     | 30 +++++++++----------------
 src/formatting/newline_style.rs |  2 +-
 src/imports.rs                  | 30 ++++++++++---------------
 src/issues.rs                   | 14 +++---------
 src/items.rs                    | 26 +++++++++-------------
 src/lib.rs                      |  6 +----
 src/lists.rs                    | 11 ++++------
 src/macros.rs                   | 39 +++++++++++++++------------------
 src/missed_spans.rs             |  8 +++----
 src/overflow.rs                 | 28 ++++++++++-------------
 src/patterns.rs                 | 25 ++++++++++-----------
 src/rustfmt_diff.rs             |  7 ++----
 src/skip.rs                     |  6 ++---
 src/source_file.rs              |  2 +-
 src/string.rs                   |  4 ++--
 src/syntux/parser.rs            |  5 ++---
 src/types.rs                    | 15 ++++---------
 src/utils.rs                    |  5 ++---
 src/visitor.rs                  | 18 +++++++--------
 27 files changed, 130 insertions(+), 205 deletions(-)

diff --git a/src/attr.rs b/src/attr.rs
index c5ffb074ba5..315eb10a9db 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -183,7 +183,7 @@ fn format_derive(
     } else if let SeparatorTactic::Always = context.config.trailing_comma() {
         // Retain the trailing comma.
         result.push_str(&item_str);
-    } else if item_str.ends_with(",") {
+    } else if item_str.ends_with(',') {
         // Remove the trailing comma.
         result.push_str(&item_str[..item_str.len() - 1]);
     } else {
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 9062a2952ec..ba693e852ff 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -405,8 +405,8 @@ fn get_targets_recursive(
                 .packages
                 .iter()
                 .find(|p| p.name == dependency.name && p.source.is_none());
-            let manifest_path = if dependency_package.is_some() {
-                PathBuf::from(&dependency_package.unwrap().manifest_path)
+            let manifest_path = if let Some(dep_pkg) = dependency_package {
+                PathBuf::from(&dep_pkg.manifest_path)
             } else {
                 let mut package_manifest_path = PathBuf::from(&package.manifest_path);
                 package_manifest_path.pop();
diff --git a/src/chains.rs b/src/chains.rs
index 8053f0e8fec..614638ea2ab 100644
--- a/src/chains.rs
+++ b/src/chains.rs
@@ -231,10 +231,7 @@ impl ChainItem {
     }
 
     fn is_comment(&self) -> bool {
-        match self.kind {
-            ChainItemKind::Comment(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, ChainItemKind::Comment(..))
     }
 
     fn rewrite_method_call(
diff --git a/src/closures.rs b/src/closures.rs
index 3d65077ddc2..c9d46aef294 100644
--- a/src/closures.rs
+++ b/src/closures.rs
@@ -336,7 +336,7 @@ pub(crate) fn rewrite_last_closure(
 
         // We force to use block for the body of the closure for certain kinds of expressions.
         if is_block_closure_forced(context, body) {
-            return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then(
+            return rewrite_closure_with_block(body, &prefix, context, body_shape).map(
                 |body_str| {
                     match fn_decl.output {
                         ast::FnRetTy::Default(..) if body_str.lines().count() <= 7 => {
@@ -344,15 +344,15 @@ pub(crate) fn rewrite_last_closure(
                             // closure.  However, if the closure has a return type, then we must
                             // keep the blocks.
                             match rewrite_closure_expr(body, &prefix, context, shape) {
-                                Some(ref single_line_body_str)
+                                Some(single_line_body_str)
                                     if !single_line_body_str.contains('\n') =>
                                 {
-                                    Some(single_line_body_str.clone())
+                                    single_line_body_str
                                 }
-                                _ => Some(body_str),
+                                _ => body_str,
                             }
                         }
-                        _ => Some(body_str),
+                        _ => body_str,
                     }
                 },
             );
@@ -377,10 +377,7 @@ pub(crate) fn rewrite_last_closure(
 pub(crate) fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool {
     args.iter()
         .filter_map(OverflowableItem::to_expr)
-        .filter(|expr| match expr.kind {
-            ast::ExprKind::Closure(..) => true,
-            _ => false,
-        })
+        .filter(|expr| matches!(expr.kind, ast::ExprKind::Closure(..)))
         .count()
         > 1
 }
diff --git a/src/comment.rs b/src/comment.rs
index c71302fdd18..0f8118a408e 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -67,10 +67,7 @@ impl<'a> CommentStyle<'a> {
 
     /// Returns `true` if the commenting style is for documentation.
     pub(crate) fn is_doc_comment(&self) -> bool {
-        match *self {
-            CommentStyle::TripleSlash | CommentStyle::Doc => true,
-            _ => false,
-        }
+        matches!(*self, CommentStyle::TripleSlash | CommentStyle::Doc)
     }
 
     pub(crate) fn opener(&self) -> &'a str {
@@ -689,8 +686,8 @@ impl<'a> CommentRewrite<'a> {
 
         self.code_block_attr = None;
         self.item_block = None;
-        if line.starts_with("```") {
-            self.code_block_attr = Some(CodeBlockAttribute::new(&line[3..]))
+        if let Some(stripped) = line.strip_prefix("```") {
+            self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
         } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) {
             let ib = ItemizedBlock::new(&line);
             self.item_block = Some(ib);
@@ -948,8 +945,8 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
     {
         (&line[4..], true)
     } else if let CommentStyle::Custom(opener) = *style {
-        if line.starts_with(opener) {
-            (&line[opener.len()..], true)
+        if let Some(ref stripped) = line.strip_prefix(opener) {
+            (stripped, true)
         } else {
             (&line[opener.trim_end().len()..], false)
         }
@@ -968,8 +965,8 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
         || line.starts_with("**")
     {
         (&line[2..], line.chars().nth(1).unwrap() == ' ')
-    } else if line.starts_with('*') {
-        (&line[1..], false)
+    } else if let Some(stripped) = line.strip_prefix('*') {
+        (stripped, false)
     } else {
         (line, line.starts_with(' '))
     }
@@ -1682,8 +1679,8 @@ impl<'a> Iterator for CommentReducer<'a> {
 fn remove_comment_header(comment: &str) -> &str {
     if comment.starts_with("///") || comment.starts_with("//!") {
         &comment[3..]
-    } else if comment.starts_with("//") {
-        &comment[2..]
+    } else if let Some(ref stripped) = comment.strip_prefix("//") {
+        stripped
     } else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
         || comment.starts_with("/*!")
     {
diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs
index 22dd091cb51..4b799780d85 100644
--- a/src/config/file_lines.rs
+++ b/src/config/file_lines.rs
@@ -305,7 +305,7 @@ impl str::FromStr for FileLines {
         let mut m = HashMap::new();
         for js in v {
             let (s, r) = JsonSpan::into_tuple(js)?;
-            m.entry(s).or_insert_with(|| vec![]).push(r);
+            m.entry(s).or_insert_with(Vec::new).push(r);
         }
         Ok(FileLines::from_ranges(m))
     }
@@ -322,7 +322,7 @@ impl JsonSpan {
     fn into_tuple(self) -> Result<(FileName, Range), FileLinesError> {
         let (lo, hi) = self.range;
         let canonical = canonicalize_path_string(&self.file)
-            .ok_or_else(|| FileLinesError::CannotCanonicalize(self.file))?;
+            .ok_or(FileLinesError::CannotCanonicalize(self.file))?;
         Ok((canonical, Range::new(lo, hi)))
     }
 }
diff --git a/src/config/license.rs b/src/config/license.rs
index 121a1b1c151..c7feb502ea9 100644
--- a/src/config/license.rs
+++ b/src/config/license.rs
@@ -3,7 +3,6 @@ use std::fs::File;
 use std::io;
 use std::io::Read;
 
-use regex;
 use regex::Regex;
 
 #[derive(Debug)]
diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs
index 9be4fb28f99..2fbbfedb566 100644
--- a/src/emitter/diff.rs
+++ b/src/emitter/diff.rs
@@ -45,7 +45,7 @@ impl Emitter for DiffEmitter {
             return Ok(EmitterResult { has_diff: true });
         }
 
-        return Ok(EmitterResult { has_diff });
+        Ok(EmitterResult { has_diff })
     }
 }
 
diff --git a/src/expr.rs b/src/expr.rs
index bca9f77f959..6cfeb9977a9 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -263,15 +263,12 @@ pub(crate) fn format_expr(
             }
 
             fn needs_space_after_range(rhs: &ast::Expr) -> bool {
-                match rhs.kind {
-                    // Don't format `.. ..` into `....`, which is invalid.
-                    //
-                    // This check is unnecessary for `lhs`, because a range
-                    // starting from another range needs parentheses as `(x ..) ..`
-                    // (`x .. ..` is a range from `x` to `..`).
-                    ast::ExprKind::Range(None, _, _) => true,
-                    _ => false,
-                }
+                // Don't format `.. ..` into `....`, which is invalid.
+                //
+                // This check is unnecessary for `lhs`, because a range
+                // starting from another range needs parentheses as `(x ..) ..`
+                // (`x .. ..` is a range from `x` to `..`).
+                matches!(rhs.kind, ast::ExprKind::Range(None, _, _))
             }
 
             let default_sp_delim = |lhs: Option<&ast::Expr>, rhs: Option<&ast::Expr>| {
@@ -531,7 +528,7 @@ pub(crate) fn rewrite_block_with_visitor(
 
     let inner_attrs = attrs.map(inner_attributes);
     let label_str = rewrite_label(label);
-    visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces);
+    visitor.visit_block(block, inner_attrs.as_deref(), has_braces);
     let visitor_context = visitor.get_context();
     context
         .skipped_range
@@ -595,7 +592,7 @@ pub(crate) fn rewrite_cond(
                 String::from("\n") + &shape.indent.block_only().to_string(context.config);
             control_flow
                 .rewrite_cond(context, shape, &alt_block_sep)
-                .and_then(|rw| Some(rw.0))
+                .map(|rw| rw.0)
         }),
     }
 }
@@ -1157,18 +1154,11 @@ pub(crate) fn is_empty_block(
 }
 
 pub(crate) fn stmt_is_expr(stmt: &ast::Stmt) -> bool {
-    match stmt.kind {
-        ast::StmtKind::Expr(..) => true,
-        _ => false,
-    }
+    matches!(stmt.kind, ast::StmtKind::Expr(..))
 }
 
 pub(crate) fn is_unsafe_block(block: &ast::Block) -> bool {
-    if let ast::BlockCheckMode::Unsafe(..) = block.rules {
-        true
-    } else {
-        false
-    }
+    matches!(block.rules, ast::BlockCheckMode::Unsafe(..))
 }
 
 pub(crate) fn rewrite_literal(
diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs
index ac620094900..97c4fc16d6f 100644
--- a/src/formatting/newline_style.rs
+++ b/src/formatting/newline_style.rs
@@ -77,7 +77,7 @@ fn convert_to_windows_newlines(formatted_text: &String) -> String {
     transformed
 }
 
-fn convert_to_unix_newlines(formatted_text: &String) -> String {
+fn convert_to_unix_newlines(formatted_text: &str) -> String {
     formatted_text.replace(WINDOWS_NEWLINE, UNIX_NEWLINE)
 }
 
diff --git a/src/imports.rs b/src/imports.rs
index 0f635fe1ccb..64d78605f0c 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -374,7 +374,7 @@ impl UseTree {
             UseTreeKind::Nested(ref list) => {
                 // Extract comments between nested use items.
                 // This needs to be done before sorting use items.
-                let items: Vec<_> = itemize_list(
+                let items = itemize_list(
                     context.snippet_provider,
                     list.iter().map(|(tree, _)| tree),
                     "}",
@@ -385,8 +385,8 @@ impl UseTree {
                     context.snippet_provider.span_after(a.span, "{"),
                     a.span.hi(),
                     false,
-                )
-                .collect();
+                );
+
                 // in case of a global path and the nested list starts at the root,
                 // e.g., "::{foo, bar}"
                 if a.prefix.segments.len() == 1 && leading_modsep {
@@ -394,7 +394,7 @@ impl UseTree {
                 }
                 result.path.push(UseSegment::List(
                     list.iter()
-                        .zip(items.into_iter())
+                        .zip(items)
                         .map(|(t, list_item)| {
                             Self::from_ast(context, &t.0, Some(list_item), None, None, None)
                         })
@@ -466,11 +466,8 @@ impl UseTree {
 
         // Normalise foo::self as bar -> foo as bar.
         if let UseSegment::Slf(_) = last {
-            match self.path.last() {
-                Some(UseSegment::Ident(_, None)) => {
-                    aliased_self = true;
-                }
-                _ => {}
+            if let Some(UseSegment::Ident(_, None)) = self.path.last() {
+                aliased_self = true;
             }
         }
 
@@ -572,9 +569,8 @@ impl UseTree {
         match self.path.clone().last().unwrap() {
             UseSegment::List(list) => {
                 if list.len() == 1 && list[0].path.len() == 1 {
-                    match list[0].path[0] {
-                        UseSegment::Slf(..) => return vec![self],
-                        _ => (),
+                    if let UseSegment::Slf(..) = list[0].path[0] {
+                        return vec![self];
                     };
                 }
                 let prefix = &self.path[..self.path.len() - 1];
@@ -790,13 +786,9 @@ fn rewrite_nested_use_tree(
         }
     }
     let has_nested_list = use_tree_list.iter().any(|use_segment| {
-        use_segment
-            .path
-            .last()
-            .map_or(false, |last_segment| match last_segment {
-                UseSegment::List(..) => true,
-                _ => false,
-            })
+        use_segment.path.last().map_or(false, |last_segment| {
+            matches!(last_segment, UseSegment::List(..))
+        })
     });
 
     let remaining_width = if has_nested_list {
diff --git a/src/issues.rs b/src/issues.rs
index d369b75541e..33fb5522aea 100644
--- a/src/issues.rs
+++ b/src/issues.rs
@@ -126,11 +126,7 @@ impl BadIssueSeeker {
                     return Seeking::Number {
                         issue: Issue {
                             issue_type: IssueType::Todo,
-                            missing_number: if let ReportTactic::Unnumbered = self.report_todo {
-                                true
-                            } else {
-                                false
-                            },
+                            missing_number: matches!(self.report_todo, ReportTactic::Unnumbered),
                         },
                         part: NumberPart::OpenParen,
                     };
@@ -144,11 +140,7 @@ impl BadIssueSeeker {
                     return Seeking::Number {
                         issue: Issue {
                             issue_type: IssueType::Fixme,
-                            missing_number: if let ReportTactic::Unnumbered = self.report_fixme {
-                                true
-                            } else {
-                                false
-                            },
+                            missing_number: matches!(self.report_fixme, ReportTactic::Unnumbered),
                         },
                         part: NumberPart::OpenParen,
                     };
@@ -196,7 +188,7 @@ impl BadIssueSeeker {
                 }
             }
             NumberPart::Number => {
-                if c >= '0' && c <= '9' {
+                if ('0'..='9').contains(&c) {
                     part = NumberPart::CloseParen;
                 } else {
                     return IssueClassification::Bad(issue);
diff --git a/src/items.rs b/src/items.rs
index 420484c0ba1..0542358c6e7 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -741,7 +741,7 @@ pub(crate) fn format_impl(
                 // there is only one where-clause predicate
                 // recover the suppressed comma in single line where_clause formatting
                 if generics.where_clause.predicates.len() == 1 {
-                    result.push_str(",");
+                    result.push(',');
                 }
                 result.push_str(&format!("{}{{{}}}", sep, sep));
             } else {
@@ -1207,7 +1207,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
 
         let fits_single_line = !generic_bounds_str.contains('\n')
             && !where_str.contains('\n')
-            && generic_bounds_str.len() + where_str.len() + 1 <= shape.width;
+            && generic_bounds_str.len() + where_str.len() < shape.width;
         let space = if generic_bounds_str.is_empty() || where_str.is_empty() {
             Cow::from("")
         } else if fits_single_line {
@@ -1236,8 +1236,8 @@ pub(crate) fn format_trait_alias(
     let lhs = format!("{}trait {} =", vis_str, generics_str);
     // 1 = ";"
     let trait_alias_bounds = TraitAliasBounds {
-        generics,
         generic_bounds,
+        generics,
     };
     rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";")
 }
@@ -1993,7 +1993,7 @@ impl Rewrite for ast::Param {
             let num_attrs = self.attrs.len();
             (
                 mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()),
-                param_attrs_result.contains("\n"),
+                param_attrs_result.contains('\n'),
             )
         } else {
             (mk_sp(self.span.lo(), self.span.lo()), false)
@@ -3265,22 +3265,16 @@ pub(crate) fn rewrite_extern_crate(
 
 /// Returns `true` for `mod foo;`, false for `mod foo { .. }`.
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
-    match item.kind {
-        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) => false,
-        _ => true,
-    }
+    !matches!(
+        item.kind,
+        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _))
+    )
 }
 
 pub(crate) fn is_use_item(item: &ast::Item) -> bool {
-    match item.kind {
-        ast::ItemKind::Use(_) => true,
-        _ => false,
-    }
+    matches!(item.kind, ast::ItemKind::Use(_))
 }
 
 pub(crate) fn is_extern_crate(item: &ast::Item) -> bool {
-    match item.kind {
-        ast::ItemKind::ExternCrate(..) => true,
-        _ => false,
-    }
+    matches!(item.kind, ast::ItemKind::ExternCrate(..))
 }
diff --git a/src/lib.rs b/src/lib.rs
index ce8a45eea65..eb314e63de3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,7 +30,6 @@ use std::panic;
 use std::path::PathBuf;
 use std::rc::Rc;
 
-use ignore;
 use rustc_ast::ast;
 use rustc_span::{symbol, DUMMY_SP};
 use thiserror::Error;
@@ -149,10 +148,7 @@ pub enum ErrorKind {
 
 impl ErrorKind {
     fn is_comment(&self) -> bool {
-        match self {
-            ErrorKind::LostComment => true,
-            _ => false,
-        }
+        matches!(self, ErrorKind::LostComment)
     }
 }
 
diff --git a/src/lists.rs b/src/lists.rs
index ccf8f784c04..73e886c5563 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -194,10 +194,7 @@ impl ListItem {
     // Returns `true` if the item causes something to be written.
     fn is_substantial(&self) -> bool {
         fn empty(s: &Option<String>) -> bool {
-            match *s {
-                Some(ref s) if !s.is_empty() => false,
-                _ => true,
-            }
+            !matches!(*s, Some(ref s) if !s.is_empty())
         }
 
         !(empty(&self.pre_comment) && empty(&self.item) && empty(&self.post_comment))
@@ -618,8 +615,8 @@ pub(crate) fn extract_post_comment(
     let post_snippet = post_snippet[..comment_end].trim();
     let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') {
         post_snippet[1..].trim_matches(white_space)
-    } else if post_snippet.starts_with(separator) {
-        post_snippet[separator.len()..].trim_matches(white_space)
+    } else if let Some(stripped) = post_snippet.strip_prefix(separator) {
+        stripped.trim_matches(white_space)
     }
     // not comment or over two lines
     else if post_snippet.ends_with(',')
@@ -823,7 +820,7 @@ where
 pub(crate) fn total_item_width(item: &ListItem) -> usize {
     comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
         + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
-        + &item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
+        + item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
 }
 
 fn comment_len(comment: Option<&str>) -> usize {
diff --git a/src/macros.rs b/src/macros.rs
index bf4769b34aa..6c5e32716c0 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -179,10 +179,10 @@ fn return_macro_parse_failure_fallback(
         .lines()
         .last()
         .map(|closing_line| {
-            closing_line.trim().chars().all(|ch| match ch {
-                '}' | ')' | ']' => true,
-                _ => false,
-            })
+            closing_line
+                .trim()
+                .chars()
+                .all(|ch| matches!(ch, '}' | ')' | ']'))
         })
         .unwrap_or(false);
     if is_like_block_indent_style {
@@ -690,25 +690,22 @@ fn delim_token_to_str(
 
 impl MacroArgKind {
     fn starts_with_brace(&self) -> bool {
-        match *self {
+        matches!(
+            *self,
             MacroArgKind::Repeat(DelimToken::Brace, _, _, _)
-            | MacroArgKind::Delimited(DelimToken::Brace, _) => true,
-            _ => false,
-        }
+                | MacroArgKind::Delimited(DelimToken::Brace, _)
+        )
     }
 
     fn starts_with_dollar(&self) -> bool {
-        match *self {
-            MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..) => true,
-            _ => false,
-        }
+        matches!(
+            *self,
+            MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..)
+        )
     }
 
     fn ends_with_space(&self) -> bool {
-        match *self {
-            MacroArgKind::Separator(..) => true,
-            _ => false,
-        }
+        matches!(*self, MacroArgKind::Separator(..))
     }
 
     fn has_meta_var(&self) -> bool {
@@ -1162,10 +1159,10 @@ fn force_space_before(tok: &TokenKind) -> bool {
 }
 
 fn ident_like(tok: &Token) -> bool {
-    match tok.kind {
-        TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(_) => true,
-        _ => false,
-    }
+    matches!(
+        tok.kind,
+        TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(_)
+    )
 }
 
 fn next_space(tok: &TokenKind) -> SpaceState {
@@ -1399,7 +1396,7 @@ impl MacroBranch {
         // Undo our replacement of macro variables.
         // FIXME: this could be *much* more efficient.
         for (old, new) in &substs {
-            if old_body.find(new).is_some() {
+            if old_body.contains(new) {
                 debug!("rewrite_macro_def: bailing matching variable: `{}`", new);
                 return None;
             }
diff --git a/src/missed_spans.rs b/src/missed_spans.rs
index 17b11ed6cf4..263d840785a 100644
--- a/src/missed_spans.rs
+++ b/src/missed_spans.rs
@@ -230,8 +230,7 @@ impl<'a> FmtVisitor<'a> {
         let last_char = big_snippet
             .chars()
             .rev()
-            .skip_while(|rev_c| [' ', '\t'].contains(rev_c))
-            .next();
+            .find(|rev_c| ![' ', '\t'].contains(rev_c));
 
         let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c));
         let mut on_same_line = false;
@@ -262,7 +261,7 @@ impl<'a> FmtVisitor<'a> {
         let comment_shape = Shape::legacy(comment_width, comment_indent);
 
         if on_same_line {
-            match subslice.find("\n") {
+            match subslice.find('\n') {
                 None => {
                     self.push_str(subslice);
                 }
@@ -299,8 +298,7 @@ impl<'a> FmtVisitor<'a> {
             match snippet[status.line_start..]
                 .chars()
                 // skip trailing whitespaces
-                .skip_while(|c| *c == ' ' || *c == '\t')
-                .next()
+                .find(|c| !(*c == ' ' || *c == '\t'))
             {
                 Some('\n') | Some('\r') => {
                     if !is_last_comment_block(subslice) {
diff --git a/src/overflow.rs b/src/overflow.rs
index d670b0a41e8..e32213467a5 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -126,21 +126,19 @@ impl<'a> OverflowableItem<'a> {
             OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr),
             OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item {
                 ast::NestedMetaItem::Literal(..) => true,
-                ast::NestedMetaItem::MetaItem(ref meta_item) => match meta_item.kind {
-                    ast::MetaItemKind::Word => true,
-                    _ => false,
-                },
+                ast::NestedMetaItem::MetaItem(ref meta_item) => {
+                    matches!(meta_item.kind, ast::MetaItemKind::Word)
+                }
             },
             _ => false,
         }
     }
 
     pub(crate) fn is_expr(&self) -> bool {
-        match self {
-            OverflowableItem::Expr(..) => true,
-            OverflowableItem::MacroArg(MacroArg::Expr(..)) => true,
-            _ => false,
-        }
+        matches!(
+            self,
+            OverflowableItem::Expr(..) | OverflowableItem::MacroArg(MacroArg::Expr(..))
+        )
     }
 
     pub(crate) fn is_nested_call(&self) -> bool {
@@ -154,10 +152,7 @@ impl<'a> OverflowableItem<'a> {
     pub(crate) fn to_expr(&self) -> Option<&'a ast::Expr> {
         match self {
             OverflowableItem::Expr(expr) => Some(expr),
-            OverflowableItem::MacroArg(macro_arg) => match macro_arg {
-                MacroArg::Expr(ref expr) => Some(expr),
-                _ => None,
-            },
+            OverflowableItem::MacroArg(MacroArg::Expr(ref expr)) => Some(expr),
             _ => None,
         }
     }
@@ -178,10 +173,9 @@ impl<'a> OverflowableItem<'a> {
                     ast::NestedMetaItem::MetaItem(..) => true,
                 }
             }
-            OverflowableItem::SegmentParam(seg) => match seg {
-                SegmentParam::Type(ty) => can_be_overflowed_type(context, ty, len),
-                _ => false,
-            },
+            OverflowableItem::SegmentParam(SegmentParam::Type(ty)) => {
+                can_be_overflowed_type(context, ty, len)
+            }
             OverflowableItem::TuplePatField(pat) => can_be_overflowed_pat(context, pat, len),
             OverflowableItem::Ty(ty) => can_be_overflowed_type(context, ty, len),
             _ => false,
diff --git a/src/patterns.rs b/src/patterns.rs
index fa0ef260991..062e9cef9bb 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -238,7 +238,7 @@ impl Rewrite for Pat {
                         if let Some(rw) = p.rewrite(context, shape) {
                             rw
                         } else {
-                            format!("{}", context.snippet(p.span))
+                            context.snippet(p.span).to_string()
                         }
                     })
                     .collect();
@@ -310,23 +310,22 @@ fn rewrite_struct_pat(
         if fields_str.contains('\n') || fields_str.len() > one_line_width {
             // Add a missing trailing comma.
             if context.config.trailing_comma() == SeparatorTactic::Never {
-                fields_str.push_str(",");
+                fields_str.push(',');
             }
-            fields_str.push_str("\n");
+            fields_str.push('\n');
             fields_str.push_str(&nested_shape.indent.to_string(context.config));
-            fields_str.push_str("..");
         } else {
             if !fields_str.is_empty() {
                 // there are preceding struct fields being matched on
                 if tactic == DefinitiveListTactic::Vertical {
                     // if the tactic is Vertical, write_list already added a trailing ,
-                    fields_str.push_str(" ");
+                    fields_str.push(' ');
                 } else {
                     fields_str.push_str(", ");
                 }
             }
-            fields_str.push_str("..");
         }
+        fields_str.push_str("..");
     }
 
     // ast::Pat doesn't have attrs so use &[]
@@ -411,10 +410,7 @@ impl<'a> Spanned for TuplePatField<'a> {
 impl<'a> TuplePatField<'a> {
     fn is_dotdot(&self) -> bool {
         match self {
-            TuplePatField::Pat(pat) => match pat.kind {
-                ast::PatKind::Rest => true,
-                _ => false,
-            },
+            TuplePatField::Pat(pat) => matches!(pat.kind, ast::PatKind::Rest),
             TuplePatField::Dotdot(_) => true,
         }
     }
@@ -510,10 +506,11 @@ fn count_wildcard_suffix_len(
     )
     .collect();
 
-    for item in items.iter().rev().take_while(|i| match i.item {
-        Some(ref internal_string) if internal_string == "_" => true,
-        _ => false,
-    }) {
+    for item in items
+        .iter()
+        .rev()
+        .take_while(|i| matches!(i.item, Some(ref internal_string) if internal_string == "_"))
+    {
         suffix_len += 1;
 
         if item.has_comment() {
diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs
index fc2c7d06e26..a394ce07398 100644
--- a/src/rustfmt_diff.rs
+++ b/src/rustfmt_diff.rs
@@ -56,10 +56,7 @@ impl From<Vec<Mismatch>> for ModifiedLines {
         let chunks = mismatches.into_iter().map(|mismatch| {
             let lines = mismatch.lines.iter();
             let num_removed = lines
-                .filter(|line| match line {
-                    DiffLine::Resulting(_) => true,
-                    _ => false,
-                })
+                .filter(|line| matches!(line, DiffLine::Resulting(_)))
                 .count();
 
             let new_lines = mismatch.lines.into_iter().filter_map(|line| match line {
@@ -94,7 +91,7 @@ impl fmt::Display for ModifiedLines {
                 "{} {} {}",
                 chunk.line_number_orig,
                 chunk.lines_removed,
-                chunk.lines.iter().count()
+                chunk.lines.len()
             )?;
 
             for line in &chunk.lines {
diff --git a/src/skip.rs b/src/skip.rs
index 6c500635a95..0fdc097efc2 100644
--- a/src/skip.rs
+++ b/src/skip.rs
@@ -32,8 +32,8 @@ impl SkipContext {
     }
 }
 
-static RUSTFMT: &'static str = "rustfmt";
-static SKIP: &'static str = "skip";
+static RUSTFMT: &str = "rustfmt";
+static SKIP: &str = "skip";
 
 /// Say if you're playing with `rustfmt`'s skip attribute
 pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool {
@@ -46,7 +46,7 @@ pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool {
             segments[1].ident.to_string() == SKIP
                 && ["macros", "attributes"]
                     .iter()
-                    .any(|&n| n == &pprust::path_segment_to_string(&segments[2]))
+                    .any(|&n| n == pprust::path_segment_to_string(&segments[2]))
         }
         _ => false,
     }
diff --git a/src/source_file.rs b/src/source_file.rs
index 5a9a2cbd80c..853336004d8 100644
--- a/src/source_file.rs
+++ b/src/source_file.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::sync::Lrc;
 
 // Append a newline to the end of each file.
 pub(crate) fn append_newline(s: &mut String) {
-    s.push_str("\n");
+    s.push('\n');
 }
 
 #[cfg(test)]
diff --git a/src/string.rs b/src/string.rs
index 080c4f17788..0cb9d817ca2 100644
--- a/src/string.rs
+++ b/src/string.rs
@@ -57,7 +57,7 @@ impl<'a> StringFormat<'a> {
     /// This allows to fit more graphemes from the string on a line when
     /// SnippetState::EndWithLineFeed.
     fn max_width_without_indent(&self) -> Option<usize> {
-        Some(self.config.max_width().checked_sub(self.line_end.len())?)
+        self.config.max_width().checked_sub(self.line_end.len())
     }
 }
 
@@ -99,7 +99,7 @@ pub(crate) fn rewrite_string<'a>(
                 if is_new_line(grapheme) {
                     // take care of blank lines
                     result = trim_end_but_line_feed(fmt.trim_end, result);
-                    result.push_str("\n");
+                    result.push('\n');
                     if !is_bareline_ok && cur_start + i + 1 < graphemes.len() {
                         result.push_str(&indent_without_newline);
                         result.push_str(fmt.line_start);
diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index 0b94749f3c6..b5fe4335dd3 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -79,7 +79,7 @@ impl<'a> ParserBuilder<'a> {
                 rustc_span::FileName::Custom("stdin".to_owned()),
                 text,
             )
-            .map_err(|db| Some(db)),
+            .map_err(Some),
         }
     }
 }
@@ -196,8 +196,7 @@ impl<'a> Parser<'a> {
         mac: &'a ast::MacCall,
     ) -> Result<Vec<ast::Item>, &'static str> {
         let token_stream = mac.args.inner_tokens();
-        let mut parser =
-            rustc_parse::stream_to_parser(sess.inner(), token_stream.clone(), Some(""));
+        let mut parser = rustc_parse::stream_to_parser(sess.inner(), token_stream, Some(""));
 
         let mut items = vec![];
         let mut process_if_cfg = true;
diff --git a/src/types.rs b/src/types.rs
index 974c0c5990c..c6f89c31065 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -662,7 +662,7 @@ impl Rewrite for ast::Ty {
                 let mut_str = format_mutability(mt.mutbl);
                 let mut_len = mut_str.len();
                 let mut result = String::with_capacity(128);
-                result.push_str("&");
+                result.push('&');
                 let ref_hi = context.snippet_provider.span_after(self.span(), "&");
                 let mut cmnt_lo = ref_hi;
 
@@ -685,7 +685,7 @@ impl Rewrite for ast::Ty {
                     } else {
                         result.push_str(&lt_str);
                     }
-                    result.push_str(" ");
+                    result.push(' ');
                     cmnt_lo = lifetime.ident.span.hi();
                 }
 
@@ -1048,11 +1048,7 @@ fn join_bounds_inner(
                     true,
                 )
                 .map(|v| (v, trailing_span, extendable)),
-                _ => Some((
-                    String::from(strs) + &trailing_str,
-                    trailing_span,
-                    extendable,
-                )),
+                _ => Some((strs + &trailing_str, trailing_span, extendable)),
             }
         },
     )?;
@@ -1089,10 +1085,7 @@ fn rewrite_lifetime_param(
 ) -> Option<String> {
     let result = generic_params
         .iter()
-        .filter(|p| match p.kind {
-            ast::GenericParamKind::Lifetime => true,
-            _ => false,
-        })
+        .filter(|p| matches!(p.kind, ast::GenericParamKind::Lifetime))
         .map(|lt| lt.rewrite(context, shape))
         .collect::<Option<Vec<_>>>()?
         .join(", ");
diff --git a/src/utils.rs b/src/utils.rs
index 614cda5f911..06159a1b26e 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -191,7 +191,7 @@ pub(crate) fn outer_attributes(attrs: &[ast::Attribute]) -> Vec<ast::Attribute>
 
 #[inline]
 pub(crate) fn is_single_line(s: &str) -> bool {
-    s.chars().find(|&c| c == '\n').is_none()
+    !s.chars().any(|c| c == '\n')
 }
 
 #[inline]
@@ -260,8 +260,7 @@ fn is_skip(meta_item: &MetaItem) -> bool {
     match meta_item.kind {
         MetaItemKind::Word => {
             let path_str = pprust::path_to_string(&meta_item.path);
-            path_str == &*skip_annotation().as_str()
-                || path_str == &*depr_skip_annotation().as_str()
+            path_str == *skip_annotation().as_str() || path_str == *depr_skip_annotation().as_str()
         }
         MetaItemKind::List(ref l) => {
             meta_item.has_name(sym::cfg_attr) && l.len() == 2 && is_skip_nested(&l[1])
diff --git a/src/visitor.rs b/src/visitor.rs
index 079568630cf..3f251bf7c16 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -198,7 +198,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             let missing_span = self.next_span(hi);
             let snippet = self.snippet(missing_span);
             let len = CommentCodeSlices::new(snippet)
-                .nth(0)
+                .next()
                 .and_then(|(kind, _, s)| {
                     if kind == CodeCharKind::Normal {
                         s.rfind('\n')
@@ -293,7 +293,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     }
                     let span_in_between = mk_sp(last_hi, span.lo() + BytePos::from_usize(offset));
                     let snippet_in_between = self.snippet(span_in_between);
-                    let mut comment_on_same_line = !snippet_in_between.contains("\n");
+                    let mut comment_on_same_line = !snippet_in_between.contains('\n');
 
                     let mut comment_shape =
                         Shape::indented(self.block_indent, config).comment(config);
@@ -301,7 +301,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         self.push_str(" ");
                         // put the first line of the comment on the same line as the
                         // block's last line
-                        match sub_slice.find("\n") {
+                        match sub_slice.find('\n') {
                             None => {
                                 self.push_str(&sub_slice);
                             }
@@ -764,7 +764,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 let hi = self.snippet_provider.span_before(search_span, ";");
                 let target_span = mk_sp(mac.span().lo(), hi + BytePos(1));
                 let rewrite = rewrite.map(|rw| {
-                    if !rw.ends_with(";") {
+                    if !rw.ends_with(';') {
                         format!("{};", rw)
                     } else {
                         rw
@@ -921,7 +921,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         !is_skip_attr(segments)
     }
 
-    fn walk_mod_items(&mut self, items: &Vec<rustc_ast::ptr::P<ast::Item>>) {
+    fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
         self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
     }
 
@@ -953,10 +953,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             // break the Stability Guarantee
             // N.B. This could be updated to utilize the version gates.
             let include_next_empty = if stmts.len() > 1 {
-                match (&stmts[0].as_ast_node().kind, &stmts[1].as_ast_node().kind) {
-                    (ast::StmtKind::Item(_), ast::StmtKind::Empty) => true,
-                    _ => false,
-                }
+                matches!(
+                    (&stmts[0].as_ast_node().kind, &stmts[1].as_ast_node().kind),
+                    (ast::StmtKind::Item(_), ast::StmtKind::Empty)
+                )
             } else {
                 false
             };

From d42be80bf772688089b90a7f2c8651adc366a3c4 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 18 Jul 2021 12:14:23 -0500
Subject: [PATCH 009/195] chore: disable clippy::matches_like_macro lint

---
 Cargo.lock            | 24 +++++++++++++++---------
 src/cargo-fmt/main.rs |  1 +
 src/lib.rs            |  1 +
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0e12e81904c..03bb5598007 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -73,7 +73,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
 dependencies = [
  "backtrace-sys",
- "cfg-if",
+ "cfg-if 0.1.10",
  "libc",
  "rustc-demangle",
 ]
@@ -162,6 +162,12 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
 [[package]]
 name = "clap"
 version = "2.33.0"
@@ -207,7 +213,7 @@ version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
 dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
  "lazy_static",
 ]
 
@@ -218,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
 dependencies = [
  "autocfg",
- "cfg-if",
+ "cfg-if 0.1.10",
  "lazy_static",
 ]
 
@@ -245,7 +251,7 @@ version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
 dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
  "dirs-sys",
 ]
 
@@ -255,7 +261,7 @@ version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
 dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
  "libc",
  "redox_users",
  "winapi",
@@ -401,11 +407,11 @@ checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
 
 [[package]]
 name = "log"
-version = "0.4.8"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -426,7 +432,7 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
 dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
 ]
 
 [[package]]
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index ba693e852ff..90ffad927e2 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -1,6 +1,7 @@
 // Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/).
 
 #![deny(warnings)]
+#![allow(clippy::match_like_matches_macro)]
 
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, BTreeSet};
diff --git a/src/lib.rs b/src/lib.rs
index eb314e63de3..206d2f78290 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,7 @@
 #![deny(rust_2018_idioms)]
 #![warn(unreachable_pub)]
 #![recursion_limit = "256"]
+#![allow(clippy::match_like_matches_macro)]
 
 #[macro_use]
 extern crate derive_new;

From 0832137b9e72cf639d46f42d4801db8bc6d798e0 Mon Sep 17 00:00:00 2001
From: Elliot Bobrow <77182873+ebobrow@users.noreply.github.com>
Date: Mon, 19 Jul 2021 14:50:05 -0700
Subject: [PATCH 010/195] fix link in Contributing.md

---
 Contributing.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Contributing.md b/Contributing.md
index a108195beb9..e6dc6a22037 100644
--- a/Contributing.md
+++ b/Contributing.md
@@ -65,7 +65,7 @@ and get a better grasp on the execution flow.
 
 ## Hack!
 
-Here are some [good starting issues](https://github.com/rust-lang/rustfmt/issues?q=is%3Aopen+is%3Aissue+label%3Agood-first-issue).
+Here are some [good starting issues](https://github.com/rust-lang/rustfmt/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
 
 If you've found areas which need polish and don't have issues, please submit a
 PR, don't feel there needs to be an issue.

From 4236289b75ee55c78538c749512cdbeea5e1c332 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 25 Jul 2021 22:27:33 -0500
Subject: [PATCH 011/195] chore: bump toolchain

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index 7c9d02d933d..b0cd4464df8 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-05-13"
+channel = "nightly-2021-07-23"
 components = ["rustc-dev"]

From 778f03530f8fba92ae0d87644b8cef71d351a859 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 26 Jul 2021 21:17:15 -0500
Subject: [PATCH 012/195] ci: remove unnecessary cargo-make install on windows
 jobs

---
 .github/workflows/windows.yml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 08cb52eedae..c05e8d4896a 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -54,9 +54,6 @@ jobs:
       if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly'
       shell: bash
 
-    - name: cargo-make
-      run: cargo install --force cargo-make
-
     - name: build
       run: |
         rustc -Vv

From e7fa07036fa3e87f536fa3bedd3daad51dfeaf16 Mon Sep 17 00:00:00 2001
From: Outvi V <19144373+outloudvi@users.noreply.github.com>
Date: Thu, 22 Jul 2021 21:24:07 +0800
Subject: [PATCH 013/195] fix: make --edition 2021 visible in --help

---
 src/bin/main.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 4b4aa42d935..1bcc5c0dada 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -121,7 +121,7 @@ fn make_opts() -> Options {
          found reverts to the input file path",
         "[Path for the configuration file]",
     );
-    opts.optopt("", "edition", "Rust edition to use", "[2015|2018]");
+    opts.optopt("", "edition", "Rust edition to use", "[2015|2018|2021]");
     opts.optopt(
         "",
         "color",

From 0b21ea2161923a87f65932b6abb5e7a94003ec3a Mon Sep 17 00:00:00 2001
From: Ellen <supbscripter@gmail.com>
Date: Wed, 28 Apr 2021 20:44:40 +0100
Subject: [PATCH 014/195] Unyeet const param defaults

---
 src/types.rs                   | 12 +++++++++++-
 tests/source/issue-4816/lib.rs | 10 ++++++++++
 tests/target/issue-4816/lib.rs | 35 ++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue-4816/lib.rs
 create mode 100644 tests/target/issue-4816/lib.rs

diff --git a/src/types.rs b/src/types.rs
index c6f89c31065..1d3f4669fcd 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -571,13 +571,23 @@ impl Rewrite for ast::GenericParam {
         if let ast::GenericParamKind::Const {
             ref ty,
             kw_span: _,
-            default: _,
+            default,
         } = &self.kind
         {
             result.push_str("const ");
             result.push_str(rewrite_ident(context, self.ident));
             result.push_str(": ");
             result.push_str(&ty.rewrite(context, shape)?);
+            if let Some(default) = default {
+                let eq_str = match context.config.type_punctuation_density() {
+                    TypeDensity::Compressed => "=",
+                    TypeDensity::Wide => " = ",
+                };
+                result.push_str(eq_str);
+                let budget = shape.width.checked_sub(result.len())?;
+                let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?;
+                result.push_str(&rewrite);
+            }
         } else {
             result.push_str(rewrite_ident(context, self.ident));
         }
diff --git a/tests/source/issue-4816/lib.rs b/tests/source/issue-4816/lib.rs
new file mode 100644
index 00000000000..43d540c4a5d
--- /dev/null
+++ b/tests/source/issue-4816/lib.rs
@@ -0,0 +1,10 @@
+#![feature(const_generics_defaults)]
+struct Foo<const N: usize    =  1, const N2: usize =           2>;
+struct Bar<const N: usize, const N2: usize = {      N + 
+1 }>;
+struct Lots<const N1BlahFooUwU: usize = { 10 + 28 + 1872 / 10 * 3 },const N2SecondParamOhmyyy: usize = { N1BlahFooUwU / 2 + 10 * 2 },>;
+struct NamesRHard<const N: usize = { 1 + 1 + 1 + 1 + 1 + 1 }>;
+struct FooBar<
+    const LessThan100ButClose: usize = {1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1}
+>;
+struct FooBarrrrrrrr<const N: usize        =           {13478234326456456444323871+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+1+1+1 + 1},>;
diff --git a/tests/target/issue-4816/lib.rs b/tests/target/issue-4816/lib.rs
new file mode 100644
index 00000000000..246e775e1fe
--- /dev/null
+++ b/tests/target/issue-4816/lib.rs
@@ -0,0 +1,35 @@
+#![feature(const_generics_defaults)]
+struct Foo<const N: usize = 1, const N2: usize = 2>;
+struct Bar<const N: usize, const N2: usize = { N + 1 }>;
+struct Lots<
+    const N1BlahFooUwU: usize = { 10 + 28 + 1872 / 10 * 3 },
+    const N2SecondParamOhmyyy: usize = { N1BlahFooUwU / 2 + 10 * 2 },
+>;
+struct NamesRHard<const N: usize = { 1 + 1 + 1 + 1 + 1 + 1 }>;
+struct FooBar<
+    const LessThan100ButClose: usize = {
+        1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
+    },
+>;
+struct FooBarrrrrrrr<
+    const N: usize = {
+        13478234326456456444323871
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+            + 1
+    },
+>;

From 8c52aae10a099abf3f481a42bef60bc5db3aba47 Mon Sep 17 00:00:00 2001
From: klensy <klensy@users.noreply.github.com>
Date: Thu, 3 Jun 2021 05:28:20 +0300
Subject: [PATCH 015/195] Bump deps

* dirs-sys v0.3.4 -> v0.3.6 to drop a lot of deps
regex v1.3.1 -> v1.4.3 drops thread_local 0.3.6
bytecount v0.6.0 -> v0.6.2 replaces packed_simd with packed_simd_2
ignore v0.4.11 -> v0.4.17 drop crossbeam-channel v0.4.0

* itertools 8.0 -> 9.0
bump `ignore` version in Cargo.toml

* cargo_metadata 0.8 -> 0.12

* env_logger 0.6 -> 0.8
---
 Cargo.lock            | 380 ++++++++++++------------------------------
 Cargo.toml            |   8 +-
 src/cargo-fmt/main.rs |   2 +-
 3 files changed, 110 insertions(+), 280 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 03bb5598007..be134f3e975 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -35,21 +35,6 @@ version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
 
-[[package]]
-name = "arrayref"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
-
-[[package]]
-name = "arrayvec"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
-dependencies = [
- "nodrop",
-]
-
 [[package]]
 name = "atty"
 version = "0.2.13"
@@ -62,40 +47,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "0.1.7"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
-
-[[package]]
-name = "backtrace"
-version = "0.3.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
-dependencies = [
- "backtrace-sys",
- "cfg-if 0.1.10",
- "libc",
- "rustc-demangle",
-]
-
-[[package]]
-name = "backtrace-sys"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "base64"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
-dependencies = [
- "byteorder",
-]
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 [[package]]
 name = "bitflags"
@@ -103,17 +57,6 @@ version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
-[[package]]
-name = "blake2b_simd"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
-dependencies = [
- "arrayref",
- "arrayvec",
- "constant_time_eq",
-]
-
 [[package]]
 name = "bstr"
 version = "0.2.8"
@@ -125,37 +68,35 @@ dependencies = [
 
 [[package]]
 name = "bytecount"
-version = "0.6.0"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
+checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
 dependencies = [
- "packed_simd",
+ "packed_simd_2",
 ]
 
 [[package]]
-name = "byteorder"
-version = "1.3.2"
+name = "cargo-platform"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7"
+dependencies = [
+ "serde",
+]
 
 [[package]]
 name = "cargo_metadata"
-version = "0.8.2"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426"
+checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f"
 dependencies = [
+ "cargo-platform",
  "semver",
+ "semver-parser",
  "serde",
- "serde_derive",
  "serde_json",
 ]
 
-[[package]]
-name = "cc"
-version = "1.0.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c"
-
 [[package]]
 name = "cfg-if"
 version = "0.1.10"
@@ -183,48 +124,14 @@ dependencies = [
  "vec_map",
 ]
 
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "constant_time_eq"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
-dependencies = [
- "crossbeam-utils 0.7.0",
-]
-
 [[package]]
 name = "crossbeam-utils"
-version = "0.6.6"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
-dependencies = [
- "cfg-if 0.1.10",
- "lazy_static",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
 dependencies = [
  "autocfg",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "lazy_static",
 ]
 
@@ -257,11 +164,10 @@ dependencies = [
 
 [[package]]
 name = "dirs-sys"
-version = "0.3.4"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
+checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
 dependencies = [
- "cfg-if 0.1.10",
  "libc",
  "redox_users",
  "winapi",
@@ -275,9 +181,9 @@ checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 
 [[package]]
 name = "env_logger"
-version = "0.6.2"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
+checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
 dependencies = [
  "atty",
  "humantime",
@@ -286,40 +192,12 @@ dependencies = [
  "termcolor",
 ]
 
-[[package]]
-name = "failure"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
-dependencies = [
- "backtrace",
- "failure_derive",
-]
-
-[[package]]
-name = "failure_derive"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
 [[package]]
 name = "fnv"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
 [[package]]
 name = "getopts"
 version = "0.2.21"
@@ -330,10 +208,21 @@ dependencies = [
 ]
 
 [[package]]
-name = "globset"
-version = "0.4.4"
+name = "getrandom"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "globset"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -353,36 +242,33 @@ dependencies = [
 
 [[package]]
 name = "humantime"
-version = "1.3.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "ignore"
-version = "0.4.11"
+version = "0.4.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e"
+checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
 dependencies = [
- "crossbeam-channel",
+ "crossbeam-utils",
  "globset",
  "lazy_static",
  "log",
  "memchr",
  "regex",
  "same-file",
- "thread_local 1.0.1",
+ "thread_local",
  "walkdir",
  "winapi-util",
 ]
 
 [[package]]
 name = "itertools"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
 dependencies = [
  "either",
 ]
@@ -405,6 +291,12 @@ version = "0.2.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
 
+[[package]]
+name = "libm"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
+
 [[package]]
 name = "log"
 version = "0.4.14"
@@ -421,18 +313,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
 
 [[package]]
-name = "nodrop"
-version = "0.1.14"
+name = "packed_simd_2"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
-
-[[package]]
-name = "packed_simd"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
+checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
 dependencies = [
  "cfg-if 0.1.10",
+ "libm",
+]
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
 ]
 
 [[package]]
@@ -463,19 +359,13 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.6"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
+checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
 dependencies = [
  "unicode-xid",
 ]
 
-[[package]]
-name = "quick-error"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
-
 [[package]]
 name = "quote"
 version = "1.0.6"
@@ -485,96 +375,42 @@ dependencies = [
  "proc-macro2",
 ]
 
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-dependencies = [
- "cloudabi",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.4.2",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
 [[package]]
 name = "redox_syscall"
-version = "0.1.56"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
+checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+dependencies = [
+ "bitflags",
+]
 
 [[package]]
 name = "redox_users"
-version = "0.3.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
+checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
 dependencies = [
- "failure",
- "rand_os",
+ "getrandom",
  "redox_syscall",
- "rust-argon2",
 ]
 
 [[package]]
 name = "regex"
-version = "1.3.1"
+version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
+checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
 dependencies = [
  "aho-corasick",
  "memchr",
  "regex-syntax",
- "thread_local 0.3.6",
+ "thread_local",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.12"
+version = "0.6.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
-
-[[package]]
-name = "rust-argon2"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
-dependencies = [
- "base64",
- "blake2b_simd",
- "crossbeam-utils 0.6.6",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
 
 [[package]]
 name = "rustc-workspace-hack"
@@ -639,9 +475,9 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "0.9.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
 dependencies = [
  "semver-parser",
  "serde",
@@ -649,24 +485,27 @@ dependencies = [
 
 [[package]]
 name = "semver-parser"
-version = "0.7.0"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
+dependencies = [
+ "pest",
+]
 
 [[package]]
 name = "serde"
-version = "1.0.101"
+version = "1.0.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
+checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.101"
+version = "1.0.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
+checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -675,9 +514,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.41"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
+checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
 dependencies = [
  "itoa",
  "ryu",
@@ -716,9 +555,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.11"
+version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
+checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -736,18 +575,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "synstructure"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
-]
-
 [[package]]
 name = "term"
 version = "0.6.1"
@@ -796,15 +623,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-dependencies = [
- "lazy_static",
-]
-
 [[package]]
 name = "thread_local"
 version = "1.0.1"
@@ -823,6 +641,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
 [[package]]
 name = "unicode-segmentation"
 version = "1.3.0"
@@ -870,6 +694,12 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
 [[package]]
 name = "winapi"
 version = "0.3.8"
diff --git a/Cargo.toml b/Cargo.toml
index 3a04fb28f7c..e368f3eb1ec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ rustfmt-format-diff = []
 generic-simd = ["bytecount/generic-simd"]
 
 [dependencies]
-itertools = "0.8"
+itertools = "0.9"
 toml = "0.5"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
@@ -43,15 +43,15 @@ regex = "1.0"
 term = "0.6"
 diff = "0.1"
 log = "0.4.14"
-env_logger = "0.6"
+env_logger = "0.8"
 getopts = "0.2"
 derive-new = "0.5"
-cargo_metadata = "0.8"
+cargo_metadata = "0.12"
 bytecount = "0.6"
 unicode-width = "0.1.5"
 unicode_categories = "0.1.1"
 dirs = "2.0.1"
-ignore = "0.4.11"
+ignore = "0.4.17"
 annotate-snippets = { version = "0.8", features = ["color"] }
 structopt = "0.3"
 rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 90ffad927e2..f8cf698525b 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -528,7 +528,7 @@ fn get_cargo_metadata(
     if let Some(manifest_path) = manifest_path {
         cmd.manifest_path(manifest_path);
     }
-    cmd.other_options(&[String::from("--offline")]);
+    cmd.other_options(vec![String::from("--offline")]);
 
     match cmd.exec() {
         Ok(metadata) => Ok(metadata),

From 8cbee5604a069bf8426f0848fd4fd2c86cfff0fa Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 29 Jul 2021 21:15:56 -0500
Subject: [PATCH 016/195] ci: functionally delete appveyor

---
 appveyor.yml | 49 +------------------------------------------------
 1 file changed, 1 insertion(+), 48 deletions(-)

diff --git a/appveyor.yml b/appveyor.yml
index 5ac99fd71f8..b3dda091e0a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,55 +1,8 @@
-# This is based on https://github.com/japaric/rust-everywhere/blob/master/appveyor.yml
-# and modified (mainly removal of deployment) to suit rustfmt.
-
 environment:
   global:
     PROJECT_NAME: rustfmt
-  matrix:
-    # Stable channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: stable
-    # Beta channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: beta
-    # Nightly channel
-    - TARGET: i686-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: i686-pc-windows-msvc
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-msvc
-      CHANNEL: nightly
 
-# Install Rust and Cargo
-# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
-install:
-  - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
-  - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
-  - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
-  - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
-  - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y
-  - rustc -Vv
-  - cargo -V
-
-# ???
 build: false
 
 test_script:
-  - set CFG_RELEASE_CHANNEL=nightly
-  - set CFG_RELEASE=nightly
-  - cargo build --verbose
-  - cargo test
-  - cargo test -- --ignored
+  - echo Why does no one have access to delete me?

From fefb5427a2fb28459f91a776948fca0ab0f2d11c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Fri, 6 Aug 2021 21:26:27 -0500
Subject: [PATCH 017/195] fix: handle GAT types in impls with self bounds

---
 src/items.rs               | 82 ++++++++++++--------------------------
 src/visitor.rs             | 49 +++++++++--------------
 tests/source/issue_4911.rs |  6 +++
 tests/target/issue_4911.rs |  9 +++++
 4 files changed, 59 insertions(+), 87 deletions(-)
 create mode 100644 tests/source/issue_4911.rs
 create mode 100644 tests/target/issue_4911.rs

diff --git a/src/items.rs b/src/items.rs
index 0542358c6e7..1a56acc7de1 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1497,7 +1497,7 @@ fn format_tuple_struct(
     Some(result)
 }
 
-fn rewrite_type<R: Rewrite>(
+pub(crate) fn rewrite_type<R: Rewrite>(
     context: &RewriteContext<'_>,
     indent: Indent,
     ident: symbol::Ident,
@@ -1841,29 +1841,6 @@ fn rewrite_static(
         Some(format!("{}{};", prefix, ty_str))
     }
 }
-
-pub(crate) fn rewrite_type_alias(
-    ident: symbol::Ident,
-    ty_opt: Option<&ptr::P<ast::Ty>>,
-    generics: &ast::Generics,
-    generic_bounds_opt: Option<&ast::GenericBounds>,
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    vis: &ast::Visibility,
-    span: Span,
-) -> Option<String> {
-    rewrite_type(
-        context,
-        indent,
-        ident,
-        vis,
-        generics,
-        generic_bounds_opt,
-        ty_opt,
-        span,
-    )
-}
-
 struct OpaqueType<'a> {
     bounds: &'a ast::GenericBounds,
 }
@@ -1877,32 +1854,7 @@ impl<'a> Rewrite for OpaqueType<'a> {
     }
 }
 
-pub(crate) fn rewrite_opaque_impl_type(
-    context: &RewriteContext<'_>,
-    ident: symbol::Ident,
-    generics: &ast::Generics,
-    generic_bounds: &ast::GenericBounds,
-    indent: Indent,
-) -> Option<String> {
-    let ident_str = rewrite_ident(context, ident);
-    // 5 = "type "
-    let generics_shape = Shape::indented(indent, context.config).offset_left(5)?;
-    let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?;
-    let prefix = format!("type {} =", generics_str);
-    let rhs = OpaqueType {
-        bounds: generic_bounds,
-    };
-
-    rewrite_assign_rhs(
-        context,
-        &prefix,
-        &rhs,
-        Shape::indented(indent, context.config).sub_width(1)?,
-    )
-    .map(|s| s + ";")
-}
-
-pub(crate) fn rewrite_associated_impl_type(
+pub(crate) fn rewrite_impl_type(
     ident: symbol::Ident,
     vis: &ast::Visibility,
     defaultness: ast::Defaultness,
@@ -1912,7 +1864,25 @@ pub(crate) fn rewrite_associated_impl_type(
     indent: Indent,
     span: Span,
 ) -> Option<String> {
-    let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis, span)?;
+    // Opaque type
+    let result = if let Some(rustc_ast::ast::Ty {
+        kind: ast::TyKind::ImplTrait(_, ref bounds),
+        ..
+    }) = ty_opt.map(|t| &**t)
+    {
+        rewrite_type(
+            context,
+            indent,
+            ident,
+            &DEFAULT_VISIBILITY,
+            generics,
+            None,
+            Some(&OpaqueType { bounds }),
+            span,
+        )
+    } else {
+        rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
+    }?;
 
     match defaultness {
         ast::Defaultness::Default(..) => Some(format!("default {}", result)),
@@ -3164,14 +3134,14 @@ impl Rewrite for ast::ForeignItem {
             ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => {
                 let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
                     **ty_alias_kind;
-                rewrite_type_alias(
-                    self.ident,
-                    type_default.as_ref(),
-                    generics,
-                    Some(generic_bounds),
+                rewrite_type(
                     &context,
                     shape.indent,
+                    self.ident,
                     &self.vis,
+                    generics,
+                    Some(generic_bounds),
+                    type_default.as_ref(),
                     self.span,
                 )
             }
diff --git a/src/visitor.rs b/src/visitor.rs
index 3f251bf7c16..12a3281eda5 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -11,9 +11,9 @@ use crate::config::Version;
 use crate::config::{BraceStyle, Config};
 use crate::coverage::transform_missing_snippet;
 use crate::items::{
-    format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item,
-    rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type,
-    rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts,
+    format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
+    rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts,
+    StructParts,
 };
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
@@ -579,14 +579,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         **alias_kind;
                     match ty {
                         Some(ty) => {
-                            let rewrite = rewrite_type_alias(
-                                item.ident,
-                                Some(&*ty),
-                                generics,
-                                Some(generic_bounds),
+                            let rewrite = rewrite_type(
                                 &self.get_context(),
                                 self.block_indent,
+                                item.ident,
                                 &item.vis,
+                                generics,
+                                Some(generic_bounds),
+                                Some(&*ty),
                                 item.span,
                             );
                             self.push_rewrite(item.span, rewrite);
@@ -665,14 +665,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
                 let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
                     **ty_alias_kind;
-                let rewrite = rewrite_type_alias(
-                    ti.ident,
-                    type_default.as_ref(),
-                    generics,
-                    Some(generic_bounds),
+                let rewrite = rewrite_type(
                     &self.get_context(),
                     self.block_indent,
+                    ti.ident,
                     &ti.vis,
+                    generics,
+                    Some(generic_bounds),
+                    type_default.as_ref(),
                     ti.span,
                 );
                 self.push_rewrite(ti.span, rewrite);
@@ -715,8 +715,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
             ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
                 let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind;
-                let rewrite_associated = || {
-                    rewrite_associated_impl_type(
+                self.push_rewrite(
+                    ii.span,
+                    rewrite_impl_type(
                         ii.ident,
                         &ii.vis,
                         defaultness,
@@ -725,22 +726,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         &self.get_context(),
                         self.block_indent,
                         ii.span,
-                    )
-                };
-                let rewrite = match ty {
-                    None => rewrite_associated(),
-                    Some(ty) => match ty.kind {
-                        ast::TyKind::ImplTrait(_, ref bounds) => rewrite_opaque_impl_type(
-                            &self.get_context(),
-                            ii.ident,
-                            generics,
-                            bounds,
-                            self.block_indent,
-                        ),
-                        _ => rewrite_associated(),
-                    },
-                };
-                self.push_rewrite(ii.span, rewrite);
+                    ),
+                );
             }
             ast::AssocItemKind::MacCall(ref mac) => {
                 self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
diff --git a/tests/source/issue_4911.rs b/tests/source/issue_4911.rs
new file mode 100644
index 00000000000..21ef6c6c491
--- /dev/null
+++ b/tests/source/issue_4911.rs
@@ -0,0 +1,6 @@
+#![feature(generic_associated_types)]
+#![feature(min_type_alias_impl_trait)]
+
+impl SomeTrait for SomeType {
+    type SomeGAT<'a> where Self: 'a = impl SomeOtherTrait;
+}
\ No newline at end of file
diff --git a/tests/target/issue_4911.rs b/tests/target/issue_4911.rs
new file mode 100644
index 00000000000..890a62267ce
--- /dev/null
+++ b/tests/target/issue_4911.rs
@@ -0,0 +1,9 @@
+#![feature(generic_associated_types)]
+#![feature(min_type_alias_impl_trait)]
+
+impl SomeTrait for SomeType {
+    type SomeGAT<'a>
+    where
+        Self: 'a,
+    = impl SomeOtherTrait;
+}

From 5d8eb8d79ce01571e468df9a0dfad8b2730bdf58 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sat, 7 Aug 2021 20:24:14 -0500
Subject: [PATCH 018/195] fix: don't drop drop generic args on assoc ty
 constraints

---
 src/types.rs               | 125 ++++++++++++++++++++-----------------
 tests/target/issue_4943.rs |   8 +++
 2 files changed, 76 insertions(+), 57 deletions(-)
 create mode 100644 tests/target/issue_4943.rs

diff --git a/src/types.rs b/src/types.rs
index 1d3f4669fcd..9a0d31e51df 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -174,34 +174,41 @@ impl<'a> Rewrite for SegmentParam<'a> {
             SegmentParam::Const(const_) => const_.rewrite(context, shape),
             SegmentParam::LifeTime(lt) => lt.rewrite(context, shape),
             SegmentParam::Type(ty) => ty.rewrite(context, shape),
-            SegmentParam::Binding(assoc_ty_constraint) => {
-                let mut result = match assoc_ty_constraint.kind {
-                    ast::AssocTyConstraintKind::Bound { .. } => {
-                        format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident))
-                    }
-                    ast::AssocTyConstraintKind::Equality { .. } => {
-                        match context.config.type_punctuation_density() {
-                            TypeDensity::Wide => {
-                                format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident))
-                            }
-                            TypeDensity::Compressed => {
-                                format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident))
-                            }
-                        }
-                    }
-                };
-
-                let budget = shape.width.checked_sub(result.len())?;
-                let rewrite = assoc_ty_constraint
-                    .kind
-                    .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?;
-                result.push_str(&rewrite);
-                Some(result)
-            }
+            SegmentParam::Binding(atc) => atc.rewrite(context, shape),
         }
     }
 }
 
+impl Rewrite for ast::AssocTyConstraint {
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        use ast::AssocTyConstraintKind::{Bound, Equality};
+
+        let mut result = String::with_capacity(128);
+        result.push_str(rewrite_ident(context, self.ident));
+
+        if let Some(ref gen_args) = self.gen_args {
+            let budget = shape.width.checked_sub(result.len())?;
+            let shape = Shape::legacy(budget, shape.indent + result.len());
+            let gen_str = rewrite_generic_args(gen_args, context, shape, gen_args.span())?;
+            result.push_str(&gen_str);
+        }
+
+        let infix = match (&self.kind, context.config.type_punctuation_density()) {
+            (Bound { .. }, _) => ": ",
+            (Equality { .. }, TypeDensity::Wide) => " = ",
+            (Equality { .. }, TypeDensity::Compressed) => "=",
+        };
+        result.push_str(infix);
+
+        let budget = shape.width.checked_sub(result.len())?;
+        let shape = Shape::legacy(budget, shape.indent + result.len());
+        let rewrite = self.kind.rewrite(context, shape)?;
+        result.push_str(&rewrite);
+
+        Some(result)
+    }
+}
+
 impl Rewrite for ast::AssocTyConstraintKind {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match self {
@@ -240,21 +247,9 @@ fn rewrite_segment(
     };
 
     if let Some(ref args) = segment.args {
+        let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?;
         match **args {
             ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
-                let param_list = data
-                    .args
-                    .iter()
-                    .map(|x| match x {
-                        ast::AngleBracketedArg::Arg(generic_arg) => {
-                            SegmentParam::from_generic_arg(generic_arg)
-                        }
-                        ast::AngleBracketedArg::Constraint(constraint) => {
-                            SegmentParam::Binding(constraint)
-                        }
-                    })
-                    .collect::<Vec<_>>();
-
                 // HACK: squeeze out the span between the identifier and the parameters.
                 // The hack is requried so that we don't remove the separator inside macro calls.
                 // This does not work in the presence of comment, hoping that people are
@@ -270,33 +265,14 @@ fn rewrite_segment(
                 };
                 result.push_str(separator);
 
-                let generics_str = overflow::rewrite_with_angle_brackets(
-                    context,
-                    "",
-                    param_list.iter(),
-                    shape,
-                    mk_sp(*span_lo, span_hi),
-                )?;
-
                 // Update position of last bracket.
                 *span_lo = context
                     .snippet_provider
                     .span_after(mk_sp(*span_lo, span_hi), "<");
-
-                result.push_str(&generics_str)
-            }
-            ast::GenericArgs::Parenthesized(ref data) => {
-                result.push_str(&format_function_type(
-                    data.inputs.iter().map(|x| &**x),
-                    &data.output,
-                    false,
-                    data.span,
-                    context,
-                    shape,
-                )?);
             }
             _ => (),
         }
+        result.push_str(&generics_str)
     }
 
     Some(result)
@@ -489,6 +465,41 @@ impl Rewrite for ast::GenericArg {
     }
 }
 
+fn rewrite_generic_args(
+    gen_args: &ast::GenericArgs,
+    context: &RewriteContext<'_>,
+    shape: Shape,
+    span: Span,
+) -> Option<String> {
+    match gen_args {
+        ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
+            let args = data
+                .args
+                .iter()
+                .map(|x| match x {
+                    ast::AngleBracketedArg::Arg(generic_arg) => {
+                        SegmentParam::from_generic_arg(generic_arg)
+                    }
+                    ast::AngleBracketedArg::Constraint(constraint) => {
+                        SegmentParam::Binding(constraint)
+                    }
+                })
+                .collect::<Vec<_>>();
+
+            overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span)
+        }
+        ast::GenericArgs::Parenthesized(ref data) => format_function_type(
+            data.inputs.iter().map(|x| &**x),
+            &data.output,
+            false,
+            data.span,
+            context,
+            shape,
+        ),
+        _ => Some("".to_owned()),
+    }
+}
+
 fn rewrite_bounded_lifetime(
     lt: &ast::Lifetime,
     bounds: &[ast::GenericBound],
diff --git a/tests/target/issue_4943.rs b/tests/target/issue_4943.rs
new file mode 100644
index 00000000000..bc8f1a366da
--- /dev/null
+++ b/tests/target/issue_4943.rs
@@ -0,0 +1,8 @@
+impl SomeStruct {
+    fn process<T>(v: T) -> <Self as GAT>::R<T>
+    where
+        Self: GAT<R<T> = T>,
+    {
+        SomeStruct::do_something(v)
+    }
+}

From 1d6002ae3887536578e87b17935a83b94953a8d8 Mon Sep 17 00:00:00 2001
From: Nipunn Koorapati <nipunn1313@gmail.com>
Date: Sat, 7 Aug 2021 18:08:38 -0700
Subject: [PATCH 019/195] Enable triagebot assignment in rustfmt

---
 triagebot.toml | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 triagebot.toml

diff --git a/triagebot.toml b/triagebot.toml
new file mode 100644
index 00000000000..fa0824ac53c
--- /dev/null
+++ b/triagebot.toml
@@ -0,0 +1 @@
+[assign]

From 667a2da7af0ed32361f1ea195f7a42911a54f1a8 Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Sun, 31 May 2020 09:23:39 -0700
Subject: [PATCH 020/195] Fix stable toggle on gh pages configuration site

A demonstration of the fix is included in the PR associated with this
commit.
---
 docs/index.html | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 56d1917e2b6..1af43510398 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -155,7 +155,9 @@
                     head: val[0].text,
                     value: val,
                     stable: val.some((elem) => {
-                      return !!elem.text && elem.text.includes("**Stable**: Yes")
+                      return elem.type === "list" &&
+                        !!elem.raw &&
+                        elem.raw.includes("**Stable**: Yes");
                     }),
                     text: val.reduce((result, next) => {
                       return next.text != null
@@ -188,4 +190,4 @@
             }
         </script>
     </body>
-</html>
\ No newline at end of file
+</html>

From 6959d03a3aab11515acb5ca2f0e3e5940b451dee Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Sun, 31 May 2020 17:12:09 -0700
Subject: [PATCH 021/195] Show configs from different versions on github pages

See https://gushiermainecoon.htmlpasta.com/ for a demo of this change.

Part of #4178
---
 docs/index.html | 102 ++++++++++++++++++++++++++++++------------------
 1 file changed, 65 insertions(+), 37 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 1af43510398..49435e6ab36 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -5,6 +5,7 @@
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
       <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
       <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
+      <script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
       <style>
         @media (max-width: 767px) {
@@ -59,6 +60,14 @@
                   <label for="stable">stable: </label>
                   <input type="checkbox" id="stable" v-model="shouldStable">
               </div>
+              <div>
+                  <label for="version">version: </label>
+                  <select name="version" id="version" v-model="version">
+                    <option v-for="option in versionOptions" v-bind:value="option">
+                      {{ option }}
+                    </option>
+                  </select>
+              </div>
             </div>
             <div v-html="aboutHtml"></div>
             <div v-html="configurationAboutHtml"></div>
@@ -66,53 +75,72 @@
           </article>
         </div>
         <script>
-            const ConfigurationMdUrl = 'https://raw.githubusercontent.com/rust-lang/rustfmt/master/Configurations.md';
+            const MajorVersionBounds = {min: 1, max: 2};
+            const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
             const UrlHash = window.location.hash.replace(/^#/, '');
             new Vue({
               el: '#app',
-              data() {
-                const configurationDescriptions = [];
-                configurationDescriptions.links = {};
-                return {
-                  aboutHtml: '',
-                  configurationAboutHtml: '',
-                  searchCondition: UrlHash,
-                  configurationDescriptions,
-                  shouldStable: false
-                }
+              data: {
+                aboutHtml: '',
+                configurationAboutHtml: '',
+                configurationDescriptions: [],
+                searchCondition: UrlHash,
+                shouldStable: false,
+                version: 'master',
+                oldVersion: undefined,
+                versionOptions: ['master']
               },
-              computed: {
-                outputHtml() {
-                  const ast = this.configurationDescriptions
-                                  .filter(({ head, text, stable }) => {
+              asyncComputed: {
+                async outputHtml() {
+                  if (this.version !== this.oldVersion) {
+                    const ConfigurationMdUrl =
+                      `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.version}/Configurations.md`;
+                    const res = await axios.get(ConfigurationMdUrl);
+                    const {
+                      about,
+                      configurationAbout,
+                      configurationDescriptions
+                    } = parseMarkdownAst(res.data);
+                    this.aboutHtml = marked.parser(about);
+                    this.configurationAboutHtml = marked.parser(configurationAbout);
+                    this.configurationDescriptions = configurationDescriptions;
+                    this.oldVersion = this.version;
+                  }
 
-                                    if (
-                                      text.includes(this.searchCondition) === false &&
-                                      head.includes(this.searchCondition) === false
-                                    ) {
-                                      return false;
-                                    }
-                                    return (this.shouldStable)
-                                      ? stable === true
-                                      : true;
-                                  })
-                                  .reduce((stack, { value }) => {
-                                    return stack.concat(value);
-                                  }, []);
+                  const ast = this.configurationDescriptions
+                      .filter(({ head, text, stable }) => {
+                        if (text.includes(this.searchCondition) === false &&
+                          head.includes(this.searchCondition) === false) {
+                          return false;
+                        }
+                        return (this.shouldStable)
+                          ? stable === true
+                          : true;
+                      })
+                      .reduce((stack, { value }) => {
+                        return stack.concat(value);
+                      }, []);
                   ast.links = {};
                   return marked.parser(ast);
                 }
               },
               created: async function() {
-                const res = await axios.get(ConfigurationMdUrl);
-                const {
-                  about,
-                  configurationAbout,
-                  configurationDescriptions
-                } = parseMarkdownAst(res.data);
-                this.aboutHtml = marked.parser(about);
-                this.configurationAboutHtml = marked.parser(configurationAbout);
-                this.configurationDescriptions = configurationDescriptions;
+                const {data: tags} = await axios.get(RusfmtTagsUrl);
+                const reMajorVersion = /v(\d+)/;
+                const tagOptions = tags
+                  .map(tag => tag.name)
+                  .filter(tag => {
+                    const versionMatches = tag.match(reMajorVersion);
+                    if (!versionMatches || !versionMatches[1]) {
+                      return false;
+                    }
+                    const majorVersion = +versionMatches[1];
+                    // There are some superfluous version tags (e.g. a v8.1 tag), so we do some
+                    // sanity checking of the tags here.
+                    return majorVersion >= MajorVersionBounds.min &&
+                      majorVersion <= MajorVersionBounds.max;
+                  });
+                this.versionOptions = this.versionOptions.concat(tagOptions);
               },
               mounted() {
                 if (UrlHash === '') return;

From 916c238103b8a630fe514ab6b44814ef95387257 Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Sun, 31 May 2020 18:16:53 -0700
Subject: [PATCH 022/195] fixup! Show configs from different versions on github
 pages

---
 docs/index.html | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 49435e6ab36..ea2366863a7 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -75,7 +75,6 @@
           </article>
         </div>
         <script>
-            const MajorVersionBounds = {min: 1, max: 2};
             const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
             const UrlHash = window.location.hash.replace(/^#/, '');
             new Vue({
@@ -129,17 +128,7 @@
                 const reMajorVersion = /v(\d+)/;
                 const tagOptions = tags
                   .map(tag => tag.name)
-                  .filter(tag => {
-                    const versionMatches = tag.match(reMajorVersion);
-                    if (!versionMatches || !versionMatches[1]) {
-                      return false;
-                    }
-                    const majorVersion = +versionMatches[1];
-                    // There are some superfluous version tags (e.g. a v8.1 tag), so we do some
-                    // sanity checking of the tags here.
-                    return majorVersion >= MajorVersionBounds.min &&
-                      majorVersion <= MajorVersionBounds.max;
-                  });
+                  .filter(tag => tag.startsWith('v'));
                 this.versionOptions = this.versionOptions.concat(tagOptions);
               },
               mounted() {

From 1045c62ac141d98fa7c86deb36887a2a9f9b45f2 Mon Sep 17 00:00:00 2001
From: hafiz <20735482+ayazhafiz@users.noreply.github.com>
Date: Mon, 1 Jun 2020 09:29:16 -0500
Subject: [PATCH 023/195] Add github-style highlighting for code blocks (#4224)

---
 docs/index.html | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/docs/index.html b/docs/index.html
index ea2366863a7..cea224f40d7 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -3,9 +3,11 @@
     <head>
       <meta name="viewport" content="width=device-width">
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
+      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
       <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
       <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
       <script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
+      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
       <style>
         @media (max-width: 767px) {
@@ -120,7 +122,12 @@
                         return stack.concat(value);
                       }, []);
                   ast.links = {};
-                  return marked.parser(ast);
+
+                  return marked.parser(ast, {
+                    highlight(code, lang) {
+                      return hljs.highlight(lang ? lang : 'rust', code).value;
+                    }
+                  });
                 }
               },
               created: async function() {

From c5f1d9698e83fbbf59c97aa229804274daf4cc8c Mon Sep 17 00:00:00 2001
From: asrar <aszenz@gmail.com>
Date: Tue, 23 Jun 2020 08:00:45 +0530
Subject: [PATCH 024/195] Adds direct linking using header ids (#4272)

Separates out search and direct linking, uses header ids for direct linking and `?search=term` for filtering configurations.
Once the app mounts the page is scrolled to the current header set in the url hash.
---
 docs/index.html | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index cea224f40d7..c89c73d4cf7 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -79,13 +79,16 @@
         <script>
             const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
             const UrlHash = window.location.hash.replace(/^#/, '');
+            const queryParams = new URLSearchParams(window.location.search);
+            const searchParam = queryParams.get('search');
+            const searchTerm = null !== searchParam ? searchParam : '';
             new Vue({
               el: '#app',
               data: {
                 aboutHtml: '',
                 configurationAboutHtml: '',
                 configurationDescriptions: [],
-                searchCondition: UrlHash,
+                searchCondition: searchTerm,
                 shouldStable: false,
                 version: 'master',
                 oldVersion: undefined,
@@ -126,7 +129,9 @@
                   return marked.parser(ast, {
                     highlight(code, lang) {
                       return hljs.highlight(lang ? lang : 'rust', code).value;
-                    }
+                    },
+                    headerIds: true,
+                    headerPrefix: ''
                   });
                 }
               },

From 31c97ce0f067ddf5c01217cf172ef1ff260ca564 Mon Sep 17 00:00:00 2001
From: asrar <aszenz@gmail.com>
Date: Wed, 24 Jun 2020 05:12:40 +0530
Subject: [PATCH 025/195] Adds query param for version no (#4270)

* Adds query param for version no

This adds support for using a query parameter for selecting the version no

* Adds error handling to configuration request

Catch request exception in case fetching the configuration from the url fails, this can happen either if non existent version number is passed in or because of server issues.

* Makes version selection better

Covers a few common cases in which the version number can be specified.
---
 docs/index.html | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index c89c73d4cf7..c221c6db71f 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -82,6 +82,13 @@
             const queryParams = new URLSearchParams(window.location.search);
             const searchParam = queryParams.get('search');
             const searchTerm = null !== searchParam ? searchParam : '';
+            const versionParam = queryParams.get('version');
+            const parseVersionParam = (version) => {
+              if (version === 'master') return 'master';
+              if (version.startsWith('v')) return version;
+              return `v${version}`;
+            };
+            const versionNumber = null !== versionParam ? parseVersionParam(versionParam) : 'master';
             new Vue({
               el: '#app',
               data: {
@@ -90,7 +97,7 @@
                 configurationDescriptions: [],
                 searchCondition: searchTerm,
                 shouldStable: false,
-                version: 'master',
+                version: versionNumber,
                 oldVersion: undefined,
                 versionOptions: ['master']
               },
@@ -99,16 +106,20 @@
                   if (this.version !== this.oldVersion) {
                     const ConfigurationMdUrl =
                       `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.version}/Configurations.md`;
-                    const res = await axios.get(ConfigurationMdUrl);
-                    const {
-                      about,
-                      configurationAbout,
-                      configurationDescriptions
-                    } = parseMarkdownAst(res.data);
-                    this.aboutHtml = marked.parser(about);
-                    this.configurationAboutHtml = marked.parser(configurationAbout);
-                    this.configurationDescriptions = configurationDescriptions;
-                    this.oldVersion = this.version;
+                    try {
+                      const res = await axios.get(ConfigurationMdUrl);
+                      const {
+                        about,
+                        configurationAbout,
+                        configurationDescriptions
+                      } = parseMarkdownAst(res.data);
+                      this.aboutHtml = marked.parser(about);
+                      this.configurationAboutHtml = marked.parser(configurationAbout);
+                      this.configurationDescriptions = configurationDescriptions;
+                      this.oldVersion = this.version;
+                    } catch(error) {
+                        this.aboutHtml = "<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
+                    }
                   }
 
                   const ast = this.configurationDescriptions

From 3195d6c2b7fd2f958d823eb32bce0fb350bf6ec5 Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Thu, 2 Jul 2020 21:33:46 -0700
Subject: [PATCH 026/195] docs: Preserve updated query param content and add
 config option links

- Preserve search and version parameter updates in the url
- Render headings with an anchor to itself for easier linking to config
  options, variants, etc.

Demo: https://5efeb81ca3f0d.htmlsave.net/
---
 docs/index.html | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index c221c6db71f..40fafd44428 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -41,6 +41,15 @@
         .searchCondition > div {
           margin-right: 30px;
         }
+        .header-link {
+          position: relative;
+        }
+        .header-link:hover::before {
+          position: absolute;
+          left: -2em;
+          padding-right: 0.5em;
+          content: '\2002\00a7\2002';
+        }
       </style>
     </head>
     <body>
@@ -137,12 +146,27 @@
                       }, []);
                   ast.links = {};
 
+                  queryParams.set('version', this.version);
+                  queryParams.set('search', this.searchCondition);
+                  const curUrl = window.location.pathname +
+                    '?' + queryParams.toString() + window.location.hash;
+                  history.pushState(null, '', curUrl);
+
+                  const renderer = new marked.Renderer();
+                  renderer.heading = function(text, level) {
+                    const id = htmlToId(text);
+                    return `<h${level}>
+                              <a href="#${id}" name="${id}" class="header-link">${text}</a>
+                            </h${level}>`;
+                  };
+
                   return marked.parser(ast, {
                     highlight(code, lang) {
                       return hljs.highlight(lang ? lang : 'rust', code).value;
                     },
                     headerIds: true,
-                    headerPrefix: ''
+                    headerPrefix: '',
+                    renderer,
                   });
                 }
               },
@@ -156,13 +180,10 @@
               },
               mounted() {
                 if (UrlHash === '') return;
-                const interval = setInterval(() => {
-                  const target = document.querySelector(`#${UrlHash}`);
-                  if (target != null) {
-                    target.scrollIntoView(true);
-                    clearInterval(interval);
-                  }
-                }, 100);
+                const target = document.querySelector(`#${UrlHash}`);
+                if (target != null) {
+                  target.scrollIntoView(true);
+                }
               }
             });
             const extractDepthOnes = (ast) => {
@@ -228,6 +249,11 @@
                 configurationDescriptions
               };
             }
+            function htmlToId(text) {
+              const tmpl = document.createElement('template');
+              tmpl.innerHTML = text.trim();
+              return encodeURIComponent(CSS.escape(tmpl.content.textContent));
+            }
         </script>
     </body>
 </html>

From bf47fc17a3bbcf93f665ec2b19fbe794ead555af Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Wed, 15 Jul 2020 17:50:43 -0700
Subject: [PATCH 027/195] Ensure that doc url hash IDs are scrolled to on page
 load

I broke this a few weeks ago so I'll fix it

Demo: https://5f0fa445faca4aff5f580029--naughty-borg-09b903.netlify.app/?version=master&search=#brace_style
---
 docs/index.html | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 40fafd44428..1f299b91820 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -108,7 +108,8 @@
                 shouldStable: false,
                 version: versionNumber,
                 oldVersion: undefined,
-                versionOptions: ['master']
+                versionOptions: ['master'],
+                scrolledOnce: false,
               },
               asyncComputed: {
                 async outputHtml() {
@@ -156,11 +157,11 @@
                   renderer.heading = function(text, level) {
                     const id = htmlToId(text);
                     return `<h${level}>
-                              <a href="#${id}" name="${id}" class="header-link">${text}</a>
+                              <a id="${id}" href="#${id}" name="${id}" class="header-link">${text}</a>
                             </h${level}>`;
                   };
 
-                  return marked.parser(ast, {
+                  const html = marked.parser(ast, {
                     highlight(code, lang) {
                       return hljs.highlight(lang ? lang : 'rust', code).value;
                     },
@@ -168,6 +169,8 @@
                     headerPrefix: '',
                     renderer,
                   });
+                  document.dispatchEvent(new Event('htmlbuilt'));
+                  return html;
                 }
               },
               created: async function() {
@@ -178,12 +181,15 @@
                   .filter(tag => tag.startsWith('v'));
                 this.versionOptions = this.versionOptions.concat(tagOptions);
               },
-              mounted() {
+              updated: function() {
                 if (UrlHash === '') return;
-                const target = document.querySelector(`#${UrlHash}`);
-                if (target != null) {
-                  target.scrollIntoView(true);
-                }
+                this.$nextTick(() => {
+                  const target = document.querySelector(`#${UrlHash}`);
+                  if (target != null && !this.scrolledOnce) {
+                    target.scrollIntoView(true);
+                    this.scrolledOnce = true;
+                  }
+                });
               }
             });
             const extractDepthOnes = (ast) => {

From f5c782f321572e7eece7d42c51a049c1ae825b5a Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Wed, 15 Jul 2020 17:52:52 -0700
Subject: [PATCH 028/195] fixup! Ensure that doc url hash IDs are scrolled to
 on page load

---
 docs/index.html | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 1f299b91820..3cc0c45a759 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -161,7 +161,7 @@
                             </h${level}>`;
                   };
 
-                  const html = marked.parser(ast, {
+                  return marked.parser(ast, {
                     highlight(code, lang) {
                       return hljs.highlight(lang ? lang : 'rust', code).value;
                     },
@@ -169,8 +169,6 @@
                     headerPrefix: '',
                     renderer,
                   });
-                  document.dispatchEvent(new Event('htmlbuilt'));
-                  return html;
                 }
               },
               created: async function() {
@@ -181,7 +179,7 @@
                   .filter(tag => tag.startsWith('v'));
                 this.versionOptions = this.versionOptions.concat(tagOptions);
               },
-              updated: function() {
+              updated() {
                 if (UrlHash === '') return;
                 this.$nextTick(() => {
                   const target = document.querySelector(`#${UrlHash}`);

From 5c7ac69393a20e18bcc07f0d69383bc6254d1b40 Mon Sep 17 00:00:00 2001
From: Ayaz Hafiz <ayaz.hafiz.1@gmail.com>
Date: Wed, 15 Jul 2020 18:27:19 -0700
Subject: [PATCH 029/195] Warn when rate limit is on docs page

Demo: https://5f0fad2f06c62143ac519413--festive-golick-afb5e0.netlify.app
---
 docs/index.html | 58 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 3cc0c45a759..eb5ded4ac30 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -116,20 +116,22 @@
                   if (this.version !== this.oldVersion) {
                     const ConfigurationMdUrl =
                       `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.version}/Configurations.md`;
+                    let res;
                     try {
-                      const res = await axios.get(ConfigurationMdUrl);
-                      const {
-                        about,
-                        configurationAbout,
-                        configurationDescriptions
-                      } = parseMarkdownAst(res.data);
-                      this.aboutHtml = marked.parser(about);
-                      this.configurationAboutHtml = marked.parser(configurationAbout);
-                      this.configurationDescriptions = configurationDescriptions;
-                      this.oldVersion = this.version;
-                    } catch(error) {
-                        this.aboutHtml = "<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
+                      res = await axios.get(ConfigurationMdUrl).catch(e => { throw e });
+                    } catch(e) {
+                      this.handleReqFailure(e);
+                      return;
                     }
+                    const {
+                      about,
+                      configurationAbout,
+                      configurationDescriptions
+                    } = parseMarkdownAst(res.data);
+                    this.aboutHtml = marked.parser(about);
+                    this.configurationAboutHtml = marked.parser(configurationAbout);
+                    this.configurationDescriptions = configurationDescriptions;
+                    this.oldVersion = this.version;
                   }
 
                   const ast = this.configurationDescriptions
@@ -172,7 +174,13 @@
                 }
               },
               created: async function() {
-                const {data: tags} = await axios.get(RusfmtTagsUrl);
+                let tags;
+                try {
+                  tags = (await axios.get(RusfmtTagsUrl)).data;
+                } catch(e) {
+                  this.handleReqFailure(e);
+                  return;
+                }
                 const reMajorVersion = /v(\d+)/;
                 const tagOptions = tags
                   .map(tag => tag.name)
@@ -188,6 +196,30 @@
                     this.scrolledOnce = true;
                   }
                 });
+              },
+              methods: {
+                handleReqFailure(e) {
+                  if (e.response.status === 404) {
+                    this.aboutHtml =
+                      "<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
+                  } else if (
+                    e.response.status === 403 &&
+                    e.response.headers["X-RateLimit-Remaining"] === 0
+                  ) {
+                    const resetDate = new Date(
+                      e.response.headers['X-RateLimit-Reset'] * 1000
+                    ).toLocaleString();
+                    this.aboutHtml =
+                      `<p>You have hit the GitHub API rate limit; documentation cannot be updated.` +
+                      `<p>The rate limit will be reset at ${resetDate}.</p>`;
+                  } else {
+                    this.aboutHtml =
+                      `<p>Ecountered an error when fetching documentation data:</p>` +
+                      `<pre><code>${e.response.data}</code></pre>` +
+                      `<p>We would appreciate <a href="https://github.com/rust-lang/rustfmt/issues/new?template=bug_report.md">a bug report</a>.` +
+                      `<p>Try refreshing the page.</p>`;
+                  }
+                }
               }
             });
             const extractDepthOnes = (ast) => {

From 3c36a0c0b74c2e5cb4c27a53e596b5729a5b3c65 Mon Sep 17 00:00:00 2001
From: jdollar <dollarhidejoel@gmail.com>
Date: Sat, 3 Oct 2020 19:05:31 -0400
Subject: [PATCH 030/195] Exluding v0.8.1 and v0.7 from the config dropdown

Older tags of the repo don't have the configuration.md file
that the docs/index.html file uses to display configuration options.
Removing them from the list since they don't apply to the use case of the
documentation page.
---
 docs/index.html | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index eb5ded4ac30..bab4d2ec63b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -181,10 +181,12 @@
                   this.handleReqFailure(e);
                   return;
                 }
-                const reMajorVersion = /v(\d+)/;
+
+                const excludedTagVersions = new Set(['v0.7', 'v0.8.1']);
+
                 const tagOptions = tags
                   .map(tag => tag.name)
-                  .filter(tag => tag.startsWith('v'));
+                  .filter(tag => tag.startsWith('v') && !excludedTagVersions.has(tag));
                 this.versionOptions = this.versionOptions.concat(tagOptions);
               },
               updated() {

From 042c2ec369a61d52cef935cbb67ae9b81da03d0f Mon Sep 17 00:00:00 2001
From: gunadhya <6939749+gunadhya@users.noreply.github.com>
Date: Sat, 16 Jan 2021 01:34:11 +0530
Subject: [PATCH 031/195] Added Updated default version to Rustfmt docs config

---
 docs/index.html | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/docs/index.html b/docs/index.html
index bab4d2ec63b..f31c695f7ca 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -87,6 +87,7 @@
         </div>
         <script>
             const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
+            const RustfmtLatestUrl = 'https://api.github.com/repos/rust-lang/rustfmt/releases/latest';
             const UrlHash = window.location.hash.replace(/^#/, '');
             const queryParams = new URLSearchParams(window.location.search);
             const searchParam = queryParams.get('search');
@@ -112,6 +113,16 @@
                 scrolledOnce: false,
               },
               asyncComputed: {
+                async updateVersion() {
+                  let latest;
+                  try {
+                    latest = (await axios.get(RustfmtLatestUrl)).data;
+                  } catch(err) {
+                      console.log(err);
+                    return;
+                  }
+                  this.version = latest.name;
+                },
                 async outputHtml() {
                   if (this.version !== this.oldVersion) {
                     const ConfigurationMdUrl =

From ec86cfd6ba3412f7a12342a55093efebfac2b4c3 Mon Sep 17 00:00:00 2001
From: gunadhya <6939749+gunadhya@users.noreply.github.com>
Date: Fri, 22 Jan 2021 01:01:20 +0530
Subject: [PATCH 032/195] Fix redirect issue

Signed-off-by: gunadhya <6939749+gunadhya@users.noreply.github.com>
---
 docs/index.html | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/docs/index.html b/docs/index.html
index f31c695f7ca..bf4e455df21 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -121,7 +121,9 @@
                       console.log(err);
                     return;
                   }
-                  this.version = latest.name;
+                  if (versionParam == null) {
+                    this.version = latest.name;
+                  }
                 },
                 async outputHtml() {
                   if (this.version !== this.oldVersion) {

From f7872887e941c2c312bbf664515078df3867c41f Mon Sep 17 00:00:00 2001
From: David Bar-On <david.cdb004@gmail.com>
Date: Wed, 3 Mar 2021 11:25:59 +0200
Subject: [PATCH 033/195] Fix for version config option anchor

---
 docs/index.html | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index bf4e455df21..c3624bb9df1 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -72,8 +72,8 @@
                   <input type="checkbox" id="stable" v-model="shouldStable">
               </div>
               <div>
-                  <label for="version">version: </label>
-                  <select name="version" id="version" v-model="version">
+                  <label for="viewVersion">version: </label>
+                  <select name="viewVersion" id="viewVersion" v-model="viewVersion">
                     <option v-for="option in versionOptions" v-bind:value="option">
                       {{ option }}
                     </option>
@@ -107,8 +107,8 @@
                 configurationDescriptions: [],
                 searchCondition: searchTerm,
                 shouldStable: false,
-                version: versionNumber,
-                oldVersion: undefined,
+                viewVersion: versionNumber,
+                oldViewVersion: undefined,
                 versionOptions: ['master'],
                 scrolledOnce: false,
               },
@@ -122,13 +122,13 @@
                     return;
                   }
                   if (versionParam == null) {
-                    this.version = latest.name;
+                    this.viewVersion = latest.name;
                   }
                 },
                 async outputHtml() {
-                  if (this.version !== this.oldVersion) {
+                  if (this.viewVersion !== this.oldViewVersion) {
                     const ConfigurationMdUrl =
-                      `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.version}/Configurations.md`;
+                      `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.viewVersion}/Configurations.md`;
                     let res;
                     try {
                       res = await axios.get(ConfigurationMdUrl).catch(e => { throw e });
@@ -144,7 +144,7 @@
                     this.aboutHtml = marked.parser(about);
                     this.configurationAboutHtml = marked.parser(configurationAbout);
                     this.configurationDescriptions = configurationDescriptions;
-                    this.oldVersion = this.version;
+                    this.oldViewVersion = this.viewVersion;
                   }
 
                   const ast = this.configurationDescriptions
@@ -162,7 +162,7 @@
                       }, []);
                   ast.links = {};
 
-                  queryParams.set('version', this.version);
+                  queryParams.set('version', this.viewVersion);
                   queryParams.set('search', this.searchCondition);
                   const curUrl = window.location.pathname +
                     '?' + queryParams.toString() + window.location.hash;

From c8bd550c8dc9b68d41696e044213a032b3d476d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Fri, 20 Aug 2021 13:33:38 -0700
Subject: [PATCH 034/195] Add test for visibility on a trait item (currently
 wrong)

---
 tests/source/impls.rs | 8 ++++++++
 tests/source/trait.rs | 7 +++++++
 tests/target/impls.rs | 8 ++++++++
 tests/target/trait.rs | 7 +++++++
 4 files changed, 30 insertions(+)

diff --git a/tests/source/impls.rs b/tests/source/impls.rs
index fb8701989fa..dcd1f0cd5b0 100644
--- a/tests/source/impls.rs
+++ b/tests/source/impls.rs
@@ -13,6 +13,14 @@ pub impl Foo for Bar {
     // Comment 3
 }
 
+#[inherent]
+impl Visible for Bar {
+    pub const C: i32;
+    pub type T;
+    pub fn f();
+    pub fn g() {}
+}
+
 pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> {
     fn foo() { "hi" }    
 }
diff --git a/tests/source/trait.rs b/tests/source/trait.rs
index 80ee0188a6b..b6db9e1590d 100644
--- a/tests/source/trait.rs
+++ b/tests/source/trait.rs
@@ -174,3 +174,10 @@ Send
     + DDDDDDDD
     + DDDDDDDDD
     + EEEEEEE;
+
+trait Visible {
+    pub const C: i32;
+    pub type T;
+    pub fn f();
+    pub fn g() {}
+}
diff --git a/tests/target/impls.rs b/tests/target/impls.rs
index bf63f924a33..f5eebe3b394 100644
--- a/tests/target/impls.rs
+++ b/tests/target/impls.rs
@@ -21,6 +21,14 @@ pub impl Foo for Bar {
     // Comment 3
 }
 
+#[inherent]
+impl Visible for Bar {
+    pub const C: i32;
+    pub type T;
+    fn f();
+    pub fn g() {}
+}
+
 pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y>
 where
     X: Foo<'a, Z>,
diff --git a/tests/target/trait.rs b/tests/target/trait.rs
index 620046a71b2..0313d8d9b84 100644
--- a/tests/target/trait.rs
+++ b/tests/target/trait.rs
@@ -211,3 +211,10 @@ where
         + DDDDDDDD
         + DDDDDDDDD
         + EEEEEEE;
+
+trait Visible {
+    const C: i32;
+    pub type T;
+    fn f();
+    fn g() {}
+}

From fd6b025e8a5ab0bf0356030cab98575dca397f69 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Fri, 20 Aug 2021 13:41:27 -0700
Subject: [PATCH 035/195] Preserve visibility on trait items inside trait and
 impl

---
 src/items.rs          | 15 ++++++++-------
 src/visitor.rs        | 14 +++++---------
 tests/target/impls.rs |  2 +-
 tests/target/trait.rs |  6 +++---
 4 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index 1a56acc7de1..4fa7190c138 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -168,14 +168,14 @@ pub(crate) struct FnSig<'a> {
     constness: ast::Const,
     defaultness: ast::Defaultness,
     unsafety: ast::Unsafe,
-    visibility: ast::Visibility,
+    visibility: &'a ast::Visibility,
 }
 
 impl<'a> FnSig<'a> {
     pub(crate) fn from_method_sig(
         method_sig: &'a ast::FnSig,
         generics: &'a ast::Generics,
-        visibility: ast::Visibility,
+        visibility: &'a ast::Visibility,
     ) -> FnSig<'a> {
         FnSig {
             unsafety: method_sig.header.unsafety,
@@ -198,7 +198,7 @@ impl<'a> FnSig<'a> {
         match *fn_kind {
             visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt {
                 visit::FnCtxt::Assoc(..) => {
-                    let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis.clone());
+                    let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
                     fn_sig.defaultness = defaultness;
                     fn_sig
                 }
@@ -210,7 +210,7 @@ impl<'a> FnSig<'a> {
                     is_async: Cow::Borrowed(&fn_sig.header.asyncness),
                     defaultness,
                     unsafety: fn_sig.header.unsafety,
-                    visibility: vis.clone(),
+                    visibility: vis,
                 },
             },
             _ => unreachable!(),
@@ -317,6 +317,7 @@ impl<'a> FmtVisitor<'a> {
         indent: Indent,
         ident: symbol::Ident,
         sig: &ast::FnSig,
+        vis: &ast::Visibility,
         generics: &ast::Generics,
         span: Span,
     ) -> Option<String> {
@@ -328,7 +329,7 @@ impl<'a> FmtVisitor<'a> {
             &context,
             indent,
             ident,
-            &FnSig::from_method_sig(sig, generics, DEFAULT_VISIBILITY),
+            &FnSig::from_method_sig(sig, generics, vis),
             span,
             FnBraceStyle::None,
         )?;
@@ -1754,7 +1755,7 @@ impl<'a> StaticParts<'a> {
         };
         StaticParts {
             prefix: "const",
-            vis: &DEFAULT_VISIBILITY,
+            vis: &ti.vis,
             ident: ti.ident,
             ty,
             mutability: ast::Mutability::Not,
@@ -3110,7 +3111,7 @@ impl Rewrite for ast::ForeignItem {
                         context,
                         shape.indent,
                         self.ident,
-                        &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()),
+                        &FnSig::from_method_sig(&fn_sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
                     )
diff --git a/src/visitor.rs b/src/visitor.rs
index 12a3281eda5..c67ebe793fd 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -3,7 +3,7 @@ use std::rc::Rc;
 
 use rustc_ast::{ast, token::DelimToken, visit, AstLike};
 use rustc_data_structures::sync::Lrc;
-use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP};
+use rustc_span::{symbol, BytePos, Pos, Span};
 
 use crate::attr::*;
 use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices};
@@ -568,6 +568,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                             indent,
                             item.ident,
                             &fn_signature,
+                            &item.vis,
                             generics,
                             item.span,
                         );
@@ -641,14 +642,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
                 if let Some(ref body) = block {
                     let inner_attrs = inner_attributes(&ti.attrs);
-                    let vis = ast::Visibility {
-                        kind: ast::VisibilityKind::Inherited,
-                        span: DUMMY_SP,
-                        tokens: None,
-                    };
                     let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)),
                         generics,
                         &sig.decl,
                         ti.span,
@@ -658,7 +654,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 } else {
                     let indent = self.block_indent;
                     let rewrite =
-                        self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span);
+                        self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span);
                     self.push_rewrite(ti.span, rewrite);
                 }
             }
@@ -708,7 +704,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 } else {
                     let indent = self.block_indent;
                     let rewrite =
-                        self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span);
+                        self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
                     self.push_rewrite(ii.span, rewrite);
                 }
             }
diff --git a/tests/target/impls.rs b/tests/target/impls.rs
index f5eebe3b394..99e02990e41 100644
--- a/tests/target/impls.rs
+++ b/tests/target/impls.rs
@@ -25,7 +25,7 @@ pub impl Foo for Bar {
 impl Visible for Bar {
     pub const C: i32;
     pub type T;
-    fn f();
+    pub fn f();
     pub fn g() {}
 }
 
diff --git a/tests/target/trait.rs b/tests/target/trait.rs
index 0313d8d9b84..7f067991b26 100644
--- a/tests/target/trait.rs
+++ b/tests/target/trait.rs
@@ -213,8 +213,8 @@ where
         + EEEEEEE;
 
 trait Visible {
-    const C: i32;
+    pub const C: i32;
     pub type T;
-    fn f();
-    fn g() {}
+    pub fn f();
+    pub fn g() {}
 }

From e81c393663daab11238944cddfbd97541630f178 Mon Sep 17 00:00:00 2001
From: Ashvin Arsakularatne <ashvin.arsakularatne@gmail.com>
Date: Thu, 26 Aug 2021 00:21:29 +0530
Subject: [PATCH 036/195] fix: remove wrong reformatting of qualified paths in
 struct patterns

---
 src/patterns.rs              |  7 ++++---
 tests/target/issue-4908-2.rs | 20 ++++++++++++++++++++
 tests/target/issue-4908.rs   | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 3 deletions(-)
 create mode 100644 tests/target/issue-4908-2.rs
 create mode 100644 tests/target/issue-4908.rs

diff --git a/src/patterns.rs b/src/patterns.rs
index 062e9cef9bb..0c6a6f3e814 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -244,8 +244,8 @@ impl Rewrite for Pat {
                     .collect();
                 Some(format!("[{}]", rw.join(", ")))
             }
-            PatKind::Struct(_, ref path, ref fields, ellipsis) => {
-                rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
+            PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => {
+                rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape)
             }
             PatKind::MacCall(ref mac) => {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
@@ -258,6 +258,7 @@ impl Rewrite for Pat {
 }
 
 fn rewrite_struct_pat(
+    qself: &Option<ast::QSelf>,
     path: &ast::Path,
     fields: &[ast::PatField],
     ellipsis: bool,
@@ -267,7 +268,7 @@ fn rewrite_struct_pat(
 ) -> Option<String> {
     // 2 =  ` {`
     let path_shape = shape.sub_width(2)?;
-    let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;
+    let path_str = rewrite_path(context, PathContext::Expr, qself.as_ref(), path, path_shape)?;
 
     if fields.is_empty() && !ellipsis {
         return Some(format!("{} {{}}", path_str));
diff --git a/tests/target/issue-4908-2.rs b/tests/target/issue-4908-2.rs
new file mode 100644
index 00000000000..023b323cb27
--- /dev/null
+++ b/tests/target/issue-4908-2.rs
@@ -0,0 +1,20 @@
+#![feature(more_qualified_paths)]
+
+fn main() {
+    // destructure through a qualified path
+    let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
+}
+
+struct StructStruct {
+    br: i8,
+}
+
+struct Foo;
+
+trait A {
+    type Assoc;
+}
+
+impl A for Foo {
+    type Assoc = StructStruct;
+}
diff --git a/tests/target/issue-4908.rs b/tests/target/issue-4908.rs
new file mode 100644
index 00000000000..ac5357abe2a
--- /dev/null
+++ b/tests/target/issue-4908.rs
@@ -0,0 +1,34 @@
+#![feature(more_qualified_paths)]
+
+mod foo_bar {
+    pub enum Example {
+        Example1 {},
+        Example2 {},
+    }
+}
+
+fn main() {
+    foo!(crate::foo_bar::Example, Example1);
+
+    let i1 = foo_bar::Example::Example1 {};
+
+    assert_eq!(i1.foo_example(), 1);
+
+    let i2 = foo_bar::Example::Example2 {};
+
+    assert_eq!(i2.foo_example(), 2);
+}
+
+#[macro_export]
+macro_rules! foo {
+    ($struct:path, $variant:ident) => {
+        impl $struct {
+            pub fn foo_example(&self) -> i32 {
+                match self {
+                    <$struct>::$variant { .. } => 1,
+                    _ => 2,
+                }
+            }
+        }
+    };
+}

From ca9b050bbf786fc7f6ef56d82b1751a761efec44 Mon Sep 17 00:00:00 2001
From: Yusuke Tanaka <yusuktan@maguro.dev>
Date: Sat, 30 Jan 2021 14:50:28 +0900
Subject: [PATCH 037/195] Implement `One` option for imports_granularity
 (#4669)

This option merges all imports into a single `use` statement as long as
they have the same visibility.
---
 Configurations.md                       |  19 ++-
 src/config/options.rs                   |   2 +
 src/imports.rs                          | 146 +++++++++++++++++++++---
 src/reorder.rs                          |   1 +
 tests/source/imports_granularity_one.rs |  60 ++++++++++
 tests/target/imports_granularity_one.rs |  79 +++++++++++++
 6 files changed, 288 insertions(+), 19 deletions(-)
 create mode 100644 tests/source/imports_granularity_one.rs
 create mode 100644 tests/target/imports_granularity_one.rs

diff --git a/Configurations.md b/Configurations.md
index d2e5613eba9..469deccc56e 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1679,7 +1679,7 @@ pub enum Foo {}
 How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity.
 
 - **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`
+- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
 - **Stable**: No
 
 #### `Preserve` (default):
@@ -1733,6 +1733,23 @@ use qux::h;
 use qux::i;
 ```
 
+#### `One`:
+
+Merge all imports into a single `use` statement as long as they have the same visibility.
+
+```rust
+pub use foo::{x, y};
+use {
+    bar::{
+        a,
+        b::{self, f, g},
+        c,
+        d::e,
+    },
+    qux::{h, i},
+};
+```
+
 ## `merge_imports`
 
 This option is deprecated. Use `imports_granularity = "Crate"` instead.
diff --git a/src/config/options.rs b/src/config/options.rs
index 3b91021813c..db15ee97a40 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -125,6 +125,8 @@ pub enum ImportGranularity {
     Module,
     /// Use one `use` statement per imported item.
     Item,
+    /// Use one `use` statement including all items.
+    One,
 }
 
 #[config_type]
diff --git a/src/imports.rs b/src/imports.rs
index 64d78605f0c..5ac79936689 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -138,6 +138,29 @@ impl UseSegment {
         }
     }
 
+    // Check if self == other with their aliases removed.
+    fn equal_except_alias(&self, other: &Self) -> bool {
+        match (self, other) {
+            (UseSegment::Ident(ref s1, _), UseSegment::Ident(ref s2, _)) => s1 == s2,
+            (UseSegment::Slf(_), UseSegment::Slf(_))
+            | (UseSegment::Super(_), UseSegment::Super(_))
+            | (UseSegment::Crate(_), UseSegment::Crate(_))
+            | (UseSegment::Glob, UseSegment::Glob) => true,
+            (UseSegment::List(ref list1), UseSegment::List(ref list2)) => list1 == list2,
+            _ => false,
+        }
+    }
+
+    fn get_alias(&self) -> Option<&str> {
+        match self {
+            UseSegment::Ident(_, a)
+            | UseSegment::Slf(a)
+            | UseSegment::Super(a)
+            | UseSegment::Crate(a) => a.as_deref(),
+            _ => None,
+        }
+    }
+
     fn from_path_segment(
         context: &RewriteContext<'_>,
         path_seg: &ast::PathSegment,
@@ -558,6 +581,7 @@ impl UseTree {
                 SharedPrefix::Module => {
                     self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1]
                 }
+                SharedPrefix::One => true,
             }
         }
     }
@@ -598,7 +622,7 @@ impl UseTree {
     fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) {
         let mut prefix = 0;
         for (a, b) in self.path.iter().zip(other.path.iter()) {
-            if *a == *b {
+            if a.equal_except_alias(b) {
                 prefix += 1;
             } else {
                 break;
@@ -633,14 +657,20 @@ fn merge_rest(
             return Some(new_path);
         }
     } else if len == 1 {
-        let rest = if a.len() == len { &b[1..] } else { &a[1..] };
-        return Some(vec![
-            b[0].clone(),
-            UseSegment::List(vec![
-                UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP),
-                UseTree::from_path(rest.to_vec(), DUMMY_SP),
-            ]),
-        ]);
+        let (common, rest) = if a.len() == len {
+            (&a[0], &b[1..])
+        } else {
+            (&b[0], &a[1..])
+        };
+        let mut list = vec![UseTree::from_path(
+            vec![UseSegment::Slf(common.get_alias().map(ToString::to_string))],
+            DUMMY_SP,
+        )];
+        match rest {
+            [UseSegment::List(rest_list)] => list.extend(rest_list.clone()),
+            _ => list.push(UseTree::from_path(rest.to_vec(), DUMMY_SP)),
+        }
+        return Some(vec![b[0].clone(), UseSegment::List(list)]);
     } else {
         len -= 1;
     }
@@ -655,18 +685,54 @@ fn merge_rest(
 }
 
 fn merge_use_trees_inner(trees: &mut Vec<UseTree>, use_tree: UseTree, merge_by: SharedPrefix) {
-    let similar_trees = trees
-        .iter_mut()
-        .filter(|tree| tree.share_prefix(&use_tree, merge_by));
+    struct SimilarTree<'a> {
+        similarity: usize,
+        path_len: usize,
+        tree: &'a mut UseTree,
+    }
+
+    let similar_trees = trees.iter_mut().filter_map(|tree| {
+        if tree.share_prefix(&use_tree, merge_by) {
+            // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which
+            // tree `use_tree` should be merge.
+            // In other cases `similarity` won't be used, so set it to `0` as a dummy value.
+            let similarity = if merge_by == SharedPrefix::One {
+                tree.path
+                    .iter()
+                    .zip(&use_tree.path)
+                    .take_while(|(a, b)| a.equal_except_alias(b))
+                    .count()
+            } else {
+                0
+            };
+
+            let path_len = tree.path.len();
+            Some(SimilarTree {
+                similarity,
+                tree,
+                path_len,
+            })
+        } else {
+            None
+        }
+    });
+
     if use_tree.path.len() == 1 && merge_by == SharedPrefix::Crate {
-        if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) {
-            if tree.path.len() == 1 {
+        if let Some(tree) = similar_trees.min_by_key(|tree| tree.path_len) {
+            if tree.path_len == 1 {
                 return;
             }
         }
-    } else if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) {
-        if tree.path.len() > 1 {
-            tree.merge(&use_tree, merge_by);
+    } else if merge_by == SharedPrefix::One {
+        if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.similarity) {
+            if sim_tree.similarity > 0 {
+                sim_tree.tree.merge(&use_tree, merge_by);
+                return;
+            }
+        }
+    } else if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.path_len) {
+        if sim_tree.path_len > 1 {
+            sim_tree.tree.merge(&use_tree, merge_by);
             return;
         }
     }
@@ -880,6 +946,7 @@ impl Rewrite for UseTree {
 pub(crate) enum SharedPrefix {
     Crate,
     Module,
+    One,
 }
 
 #[cfg(test)]
@@ -904,7 +971,7 @@ mod test {
             }
 
             fn eat(&mut self, c: char) {
-                assert!(self.input.next().unwrap() == c);
+                assert_eq!(self.input.next().unwrap(), c);
             }
 
             fn push_segment(
@@ -1094,6 +1161,49 @@ mod test {
         );
     }
 
+    #[test]
+    fn test_use_tree_merge_one() {
+        test_merge!(One, ["a", "b"], ["{a, b}"]);
+
+        test_merge!(One, ["a::{aa, ab}", "b", "a"], ["{a::{self, aa, ab}, b}"]);
+
+        test_merge!(One, ["a as x", "b as y"], ["{a as x, b as y}"]);
+
+        test_merge!(
+            One,
+            ["a::{aa as xa, ab}", "b", "a"],
+            ["{a::{self, aa as xa, ab}, b}"]
+        );
+
+        test_merge!(
+            One,
+            ["a", "a::{aa, ab::{aba, abb}}"],
+            ["a::{self, aa, ab::{aba, abb}}"]
+        );
+
+        test_merge!(One, ["a", "b::{ba, *}"], ["{a, b::{ba, *}}"]);
+
+        test_merge!(One, ["a", "b", "a::aa"], ["{a::{self, aa}, b}"]);
+
+        test_merge!(
+            One,
+            ["a::aa::aaa", "a::ac::aca", "a::aa::*"],
+            ["a::{aa::{aaa, *}, ac::aca}"]
+        );
+
+        test_merge!(
+            One,
+            ["a", "b::{ba, bb}", "a::{aa::*, ab::aba}"],
+            ["{a::{self, aa::*, ab::aba}, b::{ba, bb}}"]
+        );
+
+        test_merge!(
+            One,
+            ["b", "a::ac::{aca, acb}", "a::{aa::*, ab}"],
+            ["{a::{aa::*, ab, ac::{aca, acb}}, b}"]
+        );
+    }
+
     #[test]
     fn test_flatten_use_trees() {
         assert_eq!(
diff --git a/src/reorder.rs b/src/reorder.rs
index ac65ff2c108..2c58350d4fe 100644
--- a/src/reorder.rs
+++ b/src/reorder.rs
@@ -113,6 +113,7 @@ fn rewrite_reorderable_or_regroupable_items(
                     merge_use_trees(normalized_items, SharedPrefix::Module)
                 }
                 ImportGranularity::Item => flatten_use_trees(normalized_items),
+                ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One),
                 ImportGranularity::Preserve => normalized_items,
             };
 
diff --git a/tests/source/imports_granularity_one.rs b/tests/source/imports_granularity_one.rs
new file mode 100644
index 00000000000..c21707df395
--- /dev/null
+++ b/tests/source/imports_granularity_one.rs
@@ -0,0 +1,60 @@
+// rustfmt-imports_granularity: One
+
+use b;
+use a::ac::{aca, acb};
+use a::{aa::*, ab};
+
+use a as x;
+use b::ba;
+use a::{aa, ab};
+
+use a::aa::aaa;
+use a::ab::aba as x;
+use a::aa::*;
+
+use a::aa;
+use a::ad::ada;
+#[cfg(test)]
+use a::{ab, ac::aca};
+use b;
+#[cfg(test)]
+use b::{
+    ba, bb,
+    bc::bca::{bcaa, bcab},
+};
+
+pub use a::aa;
+pub use a::ae;
+use a::{ab, ac, ad};
+use b::ba;
+pub use b::{bb, bc::bca};
+
+use a::aa::aaa;
+use a::ac::{aca, acb};
+use a::{aa::*, ab};
+use b::{
+    ba,
+    bb::{self, bba},
+};
+
+use crate::a;
+use crate::b::ba;
+use c::ca;
+
+use super::a;
+use c::ca;
+use super::b::ba;
+
+use crate::a;
+use super::b;
+use c::{self, ca};
+
+use a::{
+    // some comment
+    aa::{aaa, aab},
+    ab,
+    // another comment
+    ac::aca,
+};
+use b as x;
+use a::ad::ada;
diff --git a/tests/target/imports_granularity_one.rs b/tests/target/imports_granularity_one.rs
new file mode 100644
index 00000000000..78ec5e7325c
--- /dev/null
+++ b/tests/target/imports_granularity_one.rs
@@ -0,0 +1,79 @@
+// rustfmt-imports_granularity: One
+
+use {
+    a::{
+        aa::*,
+        ab,
+        ac::{aca, acb},
+    },
+    b,
+};
+
+use {
+    a::{self as x, aa, ab},
+    b::ba,
+};
+
+use a::{
+    aa::{aaa, *},
+    ab::aba as x,
+};
+
+#[cfg(test)]
+use a::{ab, ac::aca};
+#[cfg(test)]
+use b::{
+    ba, bb,
+    bc::bca::{bcaa, bcab},
+};
+use {
+    a::{aa, ad::ada},
+    b,
+};
+
+pub use {
+    a::{aa, ae},
+    b::{bb, bc::bca},
+};
+use {
+    a::{ab, ac, ad},
+    b::ba,
+};
+
+use {
+    a::{
+        aa::{aaa, *},
+        ab,
+        ac::{aca, acb},
+    },
+    b::{
+        ba,
+        bb::{self, bba},
+    },
+};
+
+use {
+    crate::{a, b::ba},
+    c::ca,
+};
+
+use {
+    super::{a, b::ba},
+    c::ca,
+};
+
+use {
+    super::b,
+    crate::a,
+    c::{self, ca},
+};
+
+use {
+    a::{
+        aa::{aaa, aab},
+        ab,
+        ac::aca,
+        ad::ada,
+    },
+    b as x,
+};

From c71c68c43fcc1499b7ee2237b718fcffc61961d2 Mon Sep 17 00:00:00 2001
From: Akiomi Kamakura <akiomik@gmail.com>
Date: Wed, 1 Sep 2021 20:15:16 +0900
Subject: [PATCH 038/195] Add <title> to docs

---
 docs/index.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/index.html b/docs/index.html
index c3624bb9df1..4fa932d4c76 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -2,6 +2,7 @@
 <html>
     <head>
       <meta name="viewport" content="width=device-width">
+      <title>Rustfmt</title>
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
       <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>

From d19f69cd7106d8e84d4e92dad4d94249128a9d35 Mon Sep 17 00:00:00 2001
From: Eric <e.lim0322@gmail.com>
Date: Mon, 30 Aug 2021 20:59:45 +1200
Subject: [PATCH 039/195] test: add missing source for #4943

---
 tests/source/issue_4943.rs | 9 +++++++++
 tests/target/issue_4943.rs | 2 ++
 2 files changed, 11 insertions(+)
 create mode 100644 tests/source/issue_4943.rs

diff --git a/tests/source/issue_4943.rs b/tests/source/issue_4943.rs
new file mode 100644
index 00000000000..0793b7b4fe1
--- /dev/null
+++ b/tests/source/issue_4943.rs
@@ -0,0 +1,9 @@
+#![feature(generic_associated_types)]
+
+impl SomeStruct {
+    fn process<T>(v: T) -> <Self as GAT>::R<T>
+    where Self: GAT<R<T> = T>
+    {
+        SomeStruct::do_something(v)
+    }
+}
diff --git a/tests/target/issue_4943.rs b/tests/target/issue_4943.rs
index bc8f1a366da..318f7ebed6e 100644
--- a/tests/target/issue_4943.rs
+++ b/tests/target/issue_4943.rs
@@ -1,3 +1,5 @@
+#![feature(generic_associated_types)]
+
 impl SomeStruct {
     fn process<T>(v: T) -> <Self as GAT>::R<T>
     where

From 33d1368674be78b5f058e1fb83d08e0d381ed2d6 Mon Sep 17 00:00:00 2001
From: Eric <e.lim0322@gmail.com>
Date: Mon, 30 Aug 2021 21:09:21 +1200
Subject: [PATCH 040/195] test: add test for #4257

---
 tests/source/issue_4257.rs | 13 +++++++++++++
 tests/target/issue_4257.rs | 18 ++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 tests/source/issue_4257.rs
 create mode 100644 tests/target/issue_4257.rs

diff --git a/tests/source/issue_4257.rs b/tests/source/issue_4257.rs
new file mode 100644
index 00000000000..2b887fadb62
--- /dev/null
+++ b/tests/source/issue_4257.rs
@@ -0,0 +1,13 @@
+#![feature(generic_associated_types)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+    type Type<'a> where T: 'a;
+    fn foo(x: &T) -> Self::Type<'_>;
+}
+impl<T> Trait<T> for () {
+    type Type<'a> where T: 'a = &'a T;
+    fn foo(x: &T) -> Self::Type<'_> {
+        x
+    }
+}
diff --git a/tests/target/issue_4257.rs b/tests/target/issue_4257.rs
new file mode 100644
index 00000000000..1ebaaf2b600
--- /dev/null
+++ b/tests/target/issue_4257.rs
@@ -0,0 +1,18 @@
+#![feature(generic_associated_types)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+    type Type<'a>
+    where
+        T: 'a;
+    fn foo(x: &T) -> Self::Type<'_>;
+}
+impl<T> Trait<T> for () {
+    type Type<'a>
+    where
+        T: 'a,
+    = &'a T;
+    fn foo(x: &T) -> Self::Type<'_> {
+        x
+    }
+}

From bfc60466bdbab90d578c6912083fe2e238e29166 Mon Sep 17 00:00:00 2001
From: Eric <e.lim0322@gmail.com>
Date: Mon, 30 Aug 2021 21:13:42 +1200
Subject: [PATCH 041/195] test: add test for #4954

---
 tests/source/issue_4954.rs | 5 +++++
 tests/target/issue_4954.rs | 7 +++++++
 2 files changed, 12 insertions(+)
 create mode 100644 tests/source/issue_4954.rs
 create mode 100644 tests/target/issue_4954.rs

diff --git a/tests/source/issue_4954.rs b/tests/source/issue_4954.rs
new file mode 100644
index 00000000000..8011c601b65
--- /dev/null
+++ b/tests/source/issue_4954.rs
@@ -0,0 +1,5 @@
+trait Foo {
+  type Arg<'a>;
+}
+
+struct Bar<T>(T) where for<'a> T: Foo<Arg<'a> = ()>;
diff --git a/tests/target/issue_4954.rs b/tests/target/issue_4954.rs
new file mode 100644
index 00000000000..aa5e79befe9
--- /dev/null
+++ b/tests/target/issue_4954.rs
@@ -0,0 +1,7 @@
+trait Foo {
+    type Arg<'a>;
+}
+
+struct Bar<T>(T)
+where
+    for<'a> T: Foo<Arg<'a> = ()>;

From ae5696a7c4c2edf642c37f06c526eb6bdf78c23b Mon Sep 17 00:00:00 2001
From: Eric <e.lim0322@gmail.com>
Date: Mon, 30 Aug 2021 21:17:43 +1200
Subject: [PATCH 042/195] test: add test for #4322

---
 tests/source/issue_4322.rs | 3 +++
 tests/target/issue_4322.rs | 5 +++++
 2 files changed, 8 insertions(+)
 create mode 100644 tests/source/issue_4322.rs
 create mode 100644 tests/target/issue_4322.rs

diff --git a/tests/source/issue_4322.rs b/tests/source/issue_4322.rs
new file mode 100644
index 00000000000..b28cc7cdd12
--- /dev/null
+++ b/tests/source/issue_4322.rs
@@ -0,0 +1,3 @@
+trait Bar {
+  type X<'a> where Self: 'a;
+}
diff --git a/tests/target/issue_4322.rs b/tests/target/issue_4322.rs
new file mode 100644
index 00000000000..0ec0547119f
--- /dev/null
+++ b/tests/target/issue_4322.rs
@@ -0,0 +1,5 @@
+trait Bar {
+    type X<'a>
+    where
+        Self: 'a;
+}

From 59063e8b407acf2d187ba12616f9f36d041eff8c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <calebcartwright@users.noreply.github.com>
Date: Thu, 16 Apr 2020 07:52:47 -0500
Subject: [PATCH 043/195] fix: newline width calc in combine w/ comments
 (#4123)

---
 src/comment.rs             |  2 +-
 tests/target/issue_4031.rs | 21 +++++++++++++++
 tests/target/issue_4110.rs | 55 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 tests/target/issue_4031.rs
 create mode 100644 tests/target/issue_4110.rs

diff --git a/src/comment.rs b/src/comment.rs
index 0f8118a408e..62b624acd49 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -184,7 +184,7 @@ pub(crate) fn combine_strs_with_missing_comments(
     let missing_comment = rewrite_missing_comment(span, shape, context)?;
 
     if missing_comment.is_empty() {
-        if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width {
+        if allow_extend && one_line_width <= shape.width {
             result.push_str(first_sep);
         } else if !prev_str.is_empty() {
             result.push_str(&indent.to_string_with_newline(config))
diff --git a/tests/target/issue_4031.rs b/tests/target/issue_4031.rs
new file mode 100644
index 00000000000..065d5395c7e
--- /dev/null
+++ b/tests/target/issue_4031.rs
@@ -0,0 +1,21 @@
+fn foo() {
+    with_woff2_glyf_table("tests/fonts/woff2/SFNT-TTF-Composite.woff2", |glyf| {
+        let actual = glyf
+            .records
+            .iter()
+            .map(|glyph| match glyph {
+                GlyfRecord::Parsed(
+                    found @ Glyph {
+                        data: GlyphData::Composite { .. },
+                        ..
+                    },
+                ) => Some(found),
+                _ => None,
+            })
+            .find(|candidate| candidate.is_some())
+            .unwrap()
+            .unwrap();
+
+        assert_eq!(*actual, expected)
+    });
+}
diff --git a/tests/target/issue_4110.rs b/tests/target/issue_4110.rs
new file mode 100644
index 00000000000..4a58c3946e1
--- /dev/null
+++ b/tests/target/issue_4110.rs
@@ -0,0 +1,55 @@
+fn bindings() {
+    let err = match (place_desc, explanation) {
+        (
+            Some(ref name),
+            BorrowExplanation::MustBeValidFor {
+                category:
+                    category @ (ConstraintCategory::Return
+                    | ConstraintCategory::CallArgument
+                    | ConstraintCategory::OpaqueType),
+                from_closure: false,
+                ref region_name,
+                span,
+                ..
+            },
+        ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+            .report_escaping_closure_capture(
+                borrow_spans,
+                borrow_span,
+                region_name,
+                category,
+                span,
+                &format!("`{}`", name),
+            ),
+        (
+            ref name,
+            BorrowExplanation::MustBeValidFor {
+                category: ConstraintCategory::Assignment,
+                from_closure: false,
+                region_name:
+                    RegionName {
+                        source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name),
+                        ..
+                    },
+                span,
+                ..
+            },
+        ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
+        (Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
+            location,
+            &name,
+            &borrow,
+            drop_span,
+            borrow_spans,
+            explanation,
+        ),
+        (None, explanation) => self.report_temporary_value_does_not_live_long_enough(
+            location,
+            &borrow,
+            drop_span,
+            borrow_spans,
+            proper_span,
+            explanation,
+        ),
+    };
+}

From a59cac29f4dcfd6e9aba03db07b33767809fcea0 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 6 Sep 2021 15:35:25 -0500
Subject: [PATCH 044/195] fix: use correct spans for params with attrs

---
 src/spanned.rs             |  2 +-
 tests/source/issue_4032.rs |  4 ++++
 tests/target/issue_4032.rs | 18 ++++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue_4032.rs
 create mode 100644 tests/target/issue_4032.rs

diff --git a/src/spanned.rs b/src/spanned.rs
index 7e3786b7cd9..8e6c75a3744 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -104,7 +104,7 @@ impl Spanned for ast::Arm {
 impl Spanned for ast::Param {
     fn span(&self) -> Span {
         if crate::items::is_named_param(self) {
-            mk_sp(self.pat.span.lo(), self.ty.span.hi())
+            mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi())
         } else {
             self.ty.span
         }
diff --git a/tests/source/issue_4032.rs b/tests/source/issue_4032.rs
new file mode 100644
index 00000000000..11ded074c34
--- /dev/null
+++ b/tests/source/issue_4032.rs
@@ -0,0 +1,4 @@
+fn a1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {}
+fn b1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {}
+fn a2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {}
+fn b2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {}
diff --git a/tests/target/issue_4032.rs b/tests/target/issue_4032.rs
new file mode 100644
index 00000000000..2e7e624ca6e
--- /dev/null
+++ b/tests/target/issue_4032.rs
@@ -0,0 +1,18 @@
+fn a1(
+    #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
+    a: u8,
+) {
+}
+fn b1(
+    #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
+    bb: u8,
+) {
+}
+fn a2(
+    #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8,
+) {
+}
+fn b2(
+    #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8,
+) {
+}

From c2f0e99d854d399880d05f546953659c2d170d54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Tue, 6 Oct 2020 03:44:48 +0200
Subject: [PATCH 045/195] try to write the parameter on a new line in case the
 attribute/parameter together are over max_width

---
 src/comment.rs | 14 ++++++++------
 src/items.rs   | 33 +++++++++++++++++++++++++++------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/src/comment.rs b/src/comment.rs
index 62b624acd49..42449d1060f 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -10,7 +10,8 @@ use crate::rewrite::RewriteContext;
 use crate::shape::{Indent, Shape};
 use crate::string::{rewrite_string, StringFormat};
 use crate::utils::{
-    count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, unicode_str_width,
+    count_newlines, first_line_width, last_line_width, trim_left_preserve_layout,
+    trimmed_last_line_width, unicode_str_width,
 };
 use crate::{ErrorKind, FormattingError};
 
@@ -171,11 +172,12 @@ pub(crate) fn combine_strs_with_missing_comments(
         String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128);
     result.push_str(prev_str);
     let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n');
-    let first_sep = if prev_str.is_empty() || next_str.is_empty() {
-        ""
-    } else {
-        " "
-    };
+    let first_sep =
+        if prev_str.is_empty() || next_str.is_empty() || trimmed_last_line_width(prev_str) == 0 {
+            ""
+        } else {
+            " "
+        };
     let mut one_line_width =
         last_line_width(prev_str) + first_line_width(next_str) + first_sep.len();
 
diff --git a/src/items.rs b/src/items.rs
index 4fa7190c138..6ba83b577ae 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1980,12 +1980,13 @@ impl Rewrite for ast::Param {
                 has_multiple_attr_lines,
             )
         } else if is_named_param(self) {
+            let param_name = &self
+                .pat
+                .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
             let mut result = combine_strs_with_missing_comments(
                 context,
                 &param_attrs_result,
-                &self
-                    .pat
-                    .rewrite(context, Shape::legacy(shape.width, shape.indent))?,
+                param_name,
                 span,
                 shape,
                 !has_multiple_attr_lines,
@@ -1999,10 +2000,30 @@ impl Rewrite for ast::Param {
                 result.push_str(&after_comment);
                 let overhead = last_line_width(&result);
                 let max_width = shape.width.checked_sub(overhead)?;
-                let ty_str = self
+                if let Some(ty_str) = self
                     .ty
-                    .rewrite(context, Shape::legacy(max_width, shape.indent))?;
-                result.push_str(&ty_str);
+                    .rewrite(context, Shape::legacy(max_width, shape.indent))
+                {
+                    result.push_str(&ty_str);
+                } else {
+                    result = combine_strs_with_missing_comments(
+                        context,
+                        &(param_attrs_result + &shape.to_string_with_newline(context.config)),
+                        param_name,
+                        span,
+                        shape,
+                        !has_multiple_attr_lines,
+                    )?;
+                    result.push_str(&before_comment);
+                    result.push_str(colon_spaces(context.config));
+                    result.push_str(&after_comment);
+                    let overhead = last_line_width(&result);
+                    let max_width = shape.width.checked_sub(overhead)?;
+                    let ty_str = self
+                        .ty
+                        .rewrite(context, Shape::legacy(max_width, shape.indent))?;
+                    result.push_str(&ty_str);
+                }
             }
 
             Some(result)

From 3d8cd57c2f166cb92204e95a5f4c73ab20fed4f2 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 6 Sep 2021 17:30:16 -0500
Subject: [PATCH 046/195] tests: add files for issue 4579

---
 tests/source/issue_4579.rs | 15 +++++++++++++++
 tests/target/issue_4579.rs | 16 ++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 tests/source/issue_4579.rs
 create mode 100644 tests/target/issue_4579.rs

diff --git a/tests/source/issue_4579.rs b/tests/source/issue_4579.rs
new file mode 100644
index 00000000000..73f345233ba
--- /dev/null
+++ b/tests/source/issue_4579.rs
@@ -0,0 +1,15 @@
+// rustfmt-hard_tabs: true
+
+#[macro_export]
+macro_rules! main {
+	() => {
+		#[spirv(fragment)]
+		pub fn main_fs(
+			mut out_color: ::spirv_std::storage_class::Output<Vec4>,
+			#[spirv(descriptor_set = 1)]iChannelResolution: ::spirv_std::storage_class::UniformConstant<
+				[::spirv_std::glam::Vec3A; 4],
+			>,
+		) {
+		}
+	};
+}
diff --git a/tests/target/issue_4579.rs b/tests/target/issue_4579.rs
new file mode 100644
index 00000000000..7b0a5f3a62e
--- /dev/null
+++ b/tests/target/issue_4579.rs
@@ -0,0 +1,16 @@
+// rustfmt-hard_tabs: true
+
+#[macro_export]
+macro_rules! main {
+	() => {
+		#[spirv(fragment)]
+		pub fn main_fs(
+			mut out_color: ::spirv_std::storage_class::Output<Vec4>,
+			#[spirv(descriptor_set = 1)]
+			iChannelResolution: ::spirv_std::storage_class::UniformConstant<
+				[::spirv_std::glam::Vec3A; 4],
+			>,
+		) {
+		}
+	};
+}

From 57548aa096f31d90b9606f882f5815a93b2570b3 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Tue, 7 Sep 2021 19:49:56 -0500
Subject: [PATCH 047/195] fix: resolve idempotency issue in extern body
 elements

---
 src/missed_spans.rs        | 20 ++++++++++++--------
 tests/source/issue_4963.rs |  5 +++++
 tests/target/issue_4963.rs |  9 +++++++++
 3 files changed, 26 insertions(+), 8 deletions(-)
 create mode 100644 tests/source/issue_4963.rs
 create mode 100644 tests/target/issue_4963.rs

diff --git a/src/missed_spans.rs b/src/missed_spans.rs
index 263d840785a..28edcb784b4 100644
--- a/src/missed_spans.rs
+++ b/src/missed_spans.rs
@@ -51,6 +51,14 @@ impl<'a> FmtVisitor<'a> {
     }
 
     pub(crate) fn format_missing_with_indent(&mut self, end: BytePos) {
+        self.format_missing_indent(end, true)
+    }
+
+    pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) {
+        self.format_missing_indent(end, false)
+    }
+
+    fn format_missing_indent(&mut self, end: BytePos, should_indent: bool) {
         let config = self.config;
         self.format_missing_inner(end, |this, last_snippet, snippet| {
             this.push_str(last_snippet.trim_end());
@@ -58,14 +66,10 @@ impl<'a> FmtVisitor<'a> {
                 // No new lines in the snippet.
                 this.push_str("\n");
             }
-            let indent = this.block_indent.to_string(config);
-            this.push_str(&indent);
-        })
-    }
-
-    pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) {
-        self.format_missing_inner(end, |this, last_snippet, _| {
-            this.push_str(last_snippet.trim_end());
+            if should_indent {
+                let indent = this.block_indent.to_string(config);
+                this.push_str(&indent);
+            }
         })
     }
 
diff --git a/tests/source/issue_4963.rs b/tests/source/issue_4963.rs
new file mode 100644
index 00000000000..32e1f6cd41b
--- /dev/null
+++ b/tests/source/issue_4963.rs
@@ -0,0 +1,5 @@
+mod test {
+    extern "C" {fn test();}
+}
+
+extern "C" {fn test();}
\ No newline at end of file
diff --git a/tests/target/issue_4963.rs b/tests/target/issue_4963.rs
new file mode 100644
index 00000000000..0c3c13579c1
--- /dev/null
+++ b/tests/target/issue_4963.rs
@@ -0,0 +1,9 @@
+mod test {
+    extern "C" {
+        fn test();
+    }
+}
+
+extern "C" {
+    fn test();
+}

From a80688329c7bf696245b5ed6f3eeda6a80ab3721 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 8 Sep 2021 18:59:49 -0500
Subject: [PATCH 048/195] fix: handle param doc comments for macro scenarios

---
 src/items.rs               |  9 ++++++---
 tests/target/issue_4936.rs | 10 ++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)
 create mode 100644 tests/target/issue_4936.rs

diff --git a/src/items.rs b/src/items.rs
index 6ba83b577ae..e8eb1c5dfbb 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1960,14 +1960,17 @@ impl Rewrite for ast::Param {
         let param_attrs_result = self
             .attrs
             .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
-        let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() {
+        // N.B. Doc comments aren't typically valid syntax, but could appear
+        // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936
+        let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() {
             let num_attrs = self.attrs.len();
             (
                 mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()),
                 param_attrs_result.contains('\n'),
+                self.attrs.iter().any(|a| a.is_doc_comment()),
             )
         } else {
-            (mk_sp(self.span.lo(), self.span.lo()), false)
+            (mk_sp(self.span.lo(), self.span.lo()), false, false)
         };
 
         if let Some(ref explicit_self) = self.to_self() {
@@ -1989,7 +1992,7 @@ impl Rewrite for ast::Param {
                 param_name,
                 span,
                 shape,
-                !has_multiple_attr_lines,
+                !has_multiple_attr_lines && !has_doc_comments,
             )?;
 
             if !is_empty_infer(&*self.ty, self.pat.span) {
diff --git a/tests/target/issue_4936.rs b/tests/target/issue_4936.rs
new file mode 100644
index 00000000000..c19e505fd03
--- /dev/null
+++ b/tests/target/issue_4936.rs
@@ -0,0 +1,10 @@
+#[discard_params_doc]
+trait Trait {
+    fn foo(
+        &self,
+        /// some docs
+        bar: String,
+        /// another docs
+        baz: i32,
+    );
+}

From b10ab51fed62f54010a786e3f7d018700464b786 Mon Sep 17 00:00:00 2001
From: Nipunn Koorapati <nipunn1313@gmail.com>
Date: Sat, 7 Aug 2021 18:00:51 -0700
Subject: [PATCH 049/195] rustfmt doc code blocks with multiple comma-separated
 attributes

Added test covering this. Chose to treat the code block
as rust if and only if all of the comma-separated attributes
are rust-valid. Chose to allow/preserve whitespace around commas

Fixes #3158
---
 src/comment.rs             | 52 ++++++++++++---------------
 tests/source/issue-3158.rs | 74 ++++++++++++++++++++++++++++++++++++++
 tests/target/issue-3158.rs | 74 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+), 29 deletions(-)
 create mode 100644 tests/source/issue-3158.rs
 create mode 100644 tests/target/issue-3158.rs

diff --git a/src/comment.rs b/src/comment.rs
index 42449d1060f..60825424858 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -394,28 +394,26 @@ fn identify_comment(
     }
 }
 
-/// Attributes for code blocks in rustdoc.
-/// See https://doc.rust-lang.org/rustdoc/print.html#attributes
+/// Enum indicating if the code block contains rust based on attributes
 enum CodeBlockAttribute {
     Rust,
-    Ignore,
-    Text,
-    ShouldPanic,
-    NoRun,
-    CompileFail,
+    NotRust,
 }
 
 impl CodeBlockAttribute {
-    fn new(attribute: &str) -> CodeBlockAttribute {
-        match attribute {
-            "rust" | "" => CodeBlockAttribute::Rust,
-            "ignore" => CodeBlockAttribute::Ignore,
-            "text" => CodeBlockAttribute::Text,
-            "should_panic" => CodeBlockAttribute::ShouldPanic,
-            "no_run" => CodeBlockAttribute::NoRun,
-            "compile_fail" => CodeBlockAttribute::CompileFail,
-            _ => CodeBlockAttribute::Text,
+    /// Parse comma separated attributes list. Return rust only if all
+    /// attributes are valid rust attributes
+    /// See https://doc.rust-lang.org/rustdoc/print.html#attributes
+    fn new(attributes: &str) -> CodeBlockAttribute {
+        for attribute in attributes.split(",") {
+            match attribute.trim() {
+                "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
+                | "edition2021" => (),
+                "ignore" | "compile_fail" | "text" => return CodeBlockAttribute::NotRust,
+                _ => return CodeBlockAttribute::NotRust,
+            }
         }
+        CodeBlockAttribute::Rust
     }
 }
 
@@ -649,25 +647,21 @@ impl<'a> CommentRewrite<'a> {
         } else if self.code_block_attr.is_some() {
             if line.starts_with("```") {
                 let code_block = match self.code_block_attr.as_ref().unwrap() {
-                    CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => {
-                        trim_custom_comment_prefix(&self.code_block_buffer)
-                    }
-                    _ if self.code_block_buffer.is_empty() => String::new(),
-                    _ => {
+                    CodeBlockAttribute::Rust
+                        if self.fmt.config.format_code_in_doc_comments()
+                            && !self.code_block_buffer.is_empty() =>
+                    {
                         let mut config = self.fmt.config.clone();
                         config.set().wrap_comments(false);
-                        if config.format_code_in_doc_comments() {
-                            if let Some(s) =
-                                crate::format_code_block(&self.code_block_buffer, &config, false)
-                            {
-                                trim_custom_comment_prefix(&s.snippet)
-                            } else {
-                                trim_custom_comment_prefix(&self.code_block_buffer)
-                            }
+                        if let Some(s) =
+                            crate::format_code_block(&self.code_block_buffer, &config, false)
+                        {
+                            trim_custom_comment_prefix(&s.snippet)
                         } else {
                             trim_custom_comment_prefix(&self.code_block_buffer)
                         }
                     }
+                    _ => trim_custom_comment_prefix(&self.code_block_buffer),
                 };
                 if !code_block.is_empty() {
                     self.result.push_str(&self.comment_line_separator);
diff --git a/tests/source/issue-3158.rs b/tests/source/issue-3158.rs
new file mode 100644
index 00000000000..315073db6af
--- /dev/null
+++ b/tests/source/issue-3158.rs
@@ -0,0 +1,74 @@
+// rustfmt-format_code_in_doc_comments: true
+
+/// Should format
+/// ```rust
+/// assert!( false );
+/// ```
+///
+/// Should format
+/// ```rust,should_panic
+/// assert!( false );
+/// ```
+///
+/// Should format
+/// ```rust,should_panic,edition2018
+/// assert!( false );
+/// ```
+///
+/// Should format
+/// ```rust , should_panic , edition2018
+/// assert!( false );
+/// ```
+///
+/// Should not format
+/// ```ignore
+/// assert!( false );
+/// ```
+///
+/// Should not format (not all are rust)
+/// ```rust,ignore
+/// assert!( false );
+/// ```
+///
+/// Should not format (rust compile_fail)
+/// ```compile_fail
+/// assert!( false );
+/// ```
+///
+/// Should not format (rust compile_fail)
+/// ```rust,compile_fail
+/// assert!( false );
+/// ```
+///
+/// Various unspecified ones that should format
+/// ```
+/// assert!( false );
+/// ```
+///
+/// ```,
+/// assert!( false );
+/// ```
+///
+/// ```,,,,,
+/// assert!( false );
+/// ```
+///
+/// ```,,,  rust  ,,
+/// assert!( false );
+/// ```
+///
+/// Should not format
+/// ```,,,  rust  ,  ignore,
+/// assert!( false );
+/// ```
+///
+/// Few empty ones
+/// ```
+/// ```
+///
+/// ```rust
+/// ```
+///
+/// ```ignore
+/// ```
+fn foo() {}
diff --git a/tests/target/issue-3158.rs b/tests/target/issue-3158.rs
new file mode 100644
index 00000000000..4bbbdc1d039
--- /dev/null
+++ b/tests/target/issue-3158.rs
@@ -0,0 +1,74 @@
+// rustfmt-format_code_in_doc_comments: true
+
+/// Should format
+/// ```rust
+/// assert!(false);
+/// ```
+///
+/// Should format
+/// ```rust,should_panic
+/// assert!(false);
+/// ```
+///
+/// Should format
+/// ```rust,should_panic,edition2018
+/// assert!(false);
+/// ```
+///
+/// Should format
+/// ```rust , should_panic , edition2018
+/// assert!(false);
+/// ```
+///
+/// Should not format
+/// ```ignore
+/// assert!( false );
+/// ```
+///
+/// Should not format (not all are rust)
+/// ```rust,ignore
+/// assert!( false );
+/// ```
+///
+/// Should not format (rust compile_fail)
+/// ```compile_fail
+/// assert!( false );
+/// ```
+///
+/// Should not format (rust compile_fail)
+/// ```rust,compile_fail
+/// assert!( false );
+/// ```
+///
+/// Various unspecified ones that should format
+/// ```
+/// assert!(false);
+/// ```
+///
+/// ```,
+/// assert!(false);
+/// ```
+///
+/// ```,,,,,
+/// assert!(false);
+/// ```
+///
+/// ```,,,  rust  ,,
+/// assert!(false);
+/// ```
+///
+/// Should not format
+/// ```,,,  rust  ,  ignore,
+/// assert!( false );
+/// ```
+///
+/// Few empty ones
+/// ```
+/// ```
+///
+/// ```rust
+/// ```
+///
+/// ```ignore
+/// ```
+fn foo() {}

From 67a59f6ee35c3cfd75e2aab5a8475608e167840b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= <lnicola@dend.ro>
Date: Fri, 8 Nov 2019 23:50:18 +0200
Subject: [PATCH 050/195] opts: rephrase wording for --all and -p

---
 src/cargo-fmt/main.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index f8cf698525b..f1125fa0bda 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -36,7 +36,7 @@ pub struct Opts {
     #[structopt(long = "version")]
     version: bool,
 
-    /// Specify package to format (only usable in workspaces)
+    /// Specify package to format
     #[structopt(short = "p", long = "package", value_name = "package")]
     packages: Vec<String>,
 
@@ -53,7 +53,7 @@ pub struct Opts {
     #[structopt(name = "rustfmt_options", raw(true))]
     rustfmt_options: Vec<String>,
 
-    /// Format all packages (only usable in workspaces)
+    /// Format all packages, and also their local path-based dependencies
     #[structopt(long = "all")]
     format_all: bool,
 }

From d4ffd1efa4c83084f05f6e83585ae0a70450bcfd Mon Sep 17 00:00:00 2001
From: Seiichi Uchida <seuchida@gmail.com>
Date: Fri, 10 Jul 2020 11:23:12 +0900
Subject: [PATCH 051/195] Support @generated marker to skip code formatting

This is a copy of #4296 with these changes:
* file is not reopened again to find if the file is generated
* first five lines are scanned for `@generated` marker instead of one
* no attempt is made to only search for marker in comments

`@generated` marker is used by certain tools to understand that the
file is generated, so it should be treated differently than a file
written by a human:
* linters should not be invoked on these files,
* diffs in these files are less important,
* and these files should not be reformatted.

This PR proposes builtin support for `@generated` marker.

I have not found a standard for a generated file marker, but:
* Facebook [uses `@generated` marker](https://tinyurl.com/fb-generated)
* Phabricator tool which was spawned from Facebook internal tool
  [also understands `@generated` marker](https://git.io/JnVHa)
* Cargo inserts `@generated` marker into [generated Cargo.lock files](https://git.io/JnVHP)

My personal story is that rust-protobuf project which I maintain
was broken twice because of incompatibilities/bugs in rustfmt marker
handling: [one](https://github.com/stepancheg/rust-protobuf/issues/493),
[two](https://github.com/stepancheg/rust-protobuf/issues/551).
(Also, rust-protobuf started generating `@generated` marker
[6 years ago](https://git.io/JnV5h)).

While rustfmt AST markers are useful to apply to a certain AST
elements, disable whole-file-at-once all-tools-at-once text level
marker might be easier to use and more reliable for generated code.
---
 Configurations.md                                    | 9 +++++++++
 src/config/mod.rs                                    | 2 ++
 src/formatting.rs                                    | 9 ++++++++-
 src/formatting/generated.rs                          | 7 +++++++
 src/syntux/session.rs                                | 6 ++++++
 src/test/mod.rs                                      | 2 +-
 tests/source/configs/format_generated_files/false.rs | 8 ++++++++
 tests/source/configs/format_generated_files/true.rs  | 8 ++++++++
 tests/target/configs/format_generated_files/false.rs | 8 ++++++++
 tests/target/configs/format_generated_files/true.rs  | 6 ++++++
 10 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 src/formatting/generated.rs
 create mode 100644 tests/source/configs/format_generated_files/false.rs
 create mode 100644 tests/source/configs/format_generated_files/true.rs
 create mode 100644 tests/target/configs/format_generated_files/false.rs
 create mode 100644 tests/target/configs/format_generated_files/true.rs

diff --git a/Configurations.md b/Configurations.md
index 469deccc56e..84e8c3f7db6 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -924,6 +924,15 @@ fn add_one(x: i32) -> i32 {
 }
 ```
 
+## `format_generated_files`
+
+Format generated files. A file is considered generated
+if any of the first five lines contains `@generated` marker.
+
+- **Default value**: `false`
+- **Possible values**: `true`, `false`
+- **Stable**: No
+
 ## `format_macro_matchers`
 
 Format the metavariable matching patterns in macros.
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 8c04363b1fd..3d6e32fdb60 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -136,6 +136,7 @@ create_config! {
     inline_attribute_width: usize, 0, false,
         "Write an item and its attribute on the same line \
         if their combined width is below a threshold";
+    format_generated_files: bool, false, false, "Format generated files";
 
     // Options that can change the source code beyond whitespace/blocks (somewhat linty things)
     merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@@ -604,6 +605,7 @@ blank_lines_lower_bound = 0
 edition = "2015"
 version = "One"
 inline_attribute_width = 0
+format_generated_files = false
 merge_derives = true
 use_try_shorthand = false
 use_field_init_shorthand = false
diff --git a/src/formatting.rs b/src/formatting.rs
index e0403574eeb..9ef47b887ca 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -10,6 +10,7 @@ use rustc_span::Span;
 use self::newline_style::apply_newline_style;
 use crate::comment::{CharClasses, FullCodeCharKind};
 use crate::config::{Config, FileName, Verbosity};
+use crate::formatting::generated::is_generated_file;
 use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
 use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
@@ -18,6 +19,7 @@ use crate::utils::count_newlines;
 use crate::visitor::FmtVisitor;
 use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
 
+mod generated;
 mod newline_style;
 
 // A map of the files of a crate, with their new content
@@ -103,7 +105,12 @@ fn format_project<T: FormatHandler>(
     context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
-        let should_ignore = !input_is_stdin && context.ignore_file(&path);
+        let source_file = context.parse_session.span_to_file_contents(module.span);
+        let src = source_file.src.as_ref().expect("SourceFile without src");
+
+        let should_ignore = (!input_is_stdin && context.ignore_file(&path))
+            || (!config.format_generated_files() && is_generated_file(src));
+
         if (config.skip_children() && path != main_file) || should_ignore {
             continue;
         }
diff --git a/src/formatting/generated.rs b/src/formatting/generated.rs
new file mode 100644
index 00000000000..58f43f17ee1
--- /dev/null
+++ b/src/formatting/generated.rs
@@ -0,0 +1,7 @@
+/// Returns `true` if the given span is a part of generated files.
+pub(super) fn is_generated_file(original_snippet: &str) -> bool {
+    original_snippet
+        .lines()
+        .take(5) // looking for marker only in the beginning of the file
+        .any(|line| line.contains("@generated"))
+}
diff --git a/src/syntux/session.rs b/src/syntux/session.rs
index 870f0acfe39..94257e1ce7f 100644
--- a/src/syntux/session.rs
+++ b/src/syntux/session.rs
@@ -175,6 +175,12 @@ impl ParseSess {
         self.parse_sess.source_map().span_to_filename(span).into()
     }
 
+    pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> {
+        self.parse_sess
+            .source_map()
+            .lookup_source_file(span.data().lo)
+    }
+
     pub(crate) fn span_to_first_line_string(&self, span: Span) -> String {
         let file_lines = self.parse_sess.source_map().span_to_lines(span).ok();
 
diff --git a/src/test/mod.rs b/src/test/mod.rs
index cb52346a13a..ece1b91bfd7 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -694,7 +694,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap<String, String> {
     reader
         .lines()
         .map(|line| line.expect("failed getting line"))
-        .take_while(|line| line_regex.is_match(line))
+        .filter(|line| line_regex.is_match(line))
         .filter_map(|line| {
             regex.captures_iter(&line).next().map(|capture| {
                 (
diff --git a/tests/source/configs/format_generated_files/false.rs b/tests/source/configs/format_generated_files/false.rs
new file mode 100644
index 00000000000..dec1e00d117
--- /dev/null
+++ b/tests/source/configs/format_generated_files/false.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: false
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/source/configs/format_generated_files/true.rs b/tests/source/configs/format_generated_files/true.rs
new file mode 100644
index 00000000000..a25ddc25a6a
--- /dev/null
+++ b/tests/source/configs/format_generated_files/true.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: true
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/target/configs/format_generated_files/false.rs b/tests/target/configs/format_generated_files/false.rs
new file mode 100644
index 00000000000..dec1e00d117
--- /dev/null
+++ b/tests/target/configs/format_generated_files/false.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: false
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/target/configs/format_generated_files/true.rs b/tests/target/configs/format_generated_files/true.rs
new file mode 100644
index 00000000000..5fea7e8b341
--- /dev/null
+++ b/tests/target/configs/format_generated_files/true.rs
@@ -0,0 +1,6 @@
+// @generated
+// rustfmt-format_generated_files: true
+
+fn main() {
+    println!("hello, world");
+}

From 9d65b7dcd19557bca9aa4b175efa14a35db6d713 Mon Sep 17 00:00:00 2001
From: Arjen Laarhoven <arjen@laarhoven.info>
Date: Thu, 15 Jul 2021 19:55:52 +0200
Subject: [PATCH 052/195] feat: upper- or lowercase hexadecimal literals

---
 Configurations.md                    |  7 ++++++
 src/config/mod.rs                    |  3 +++
 src/config/options.rs                | 11 ++++++++++
 src/expr.rs                          | 33 +++++++++++++++++++++++++++-
 tests/source/hex_literal_lower.rs    |  5 +++++
 tests/source/hex_literal_upper.rs    |  5 +++++
 tests/target/hex_literal_lower.rs    |  5 +++++
 tests/target/hex_literal_preserve.rs |  5 +++++
 tests/target/hex_literal_upper.rs    |  5 +++++
 9 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/hex_literal_lower.rs
 create mode 100644 tests/source/hex_literal_upper.rs
 create mode 100644 tests/target/hex_literal_lower.rs
 create mode 100644 tests/target/hex_literal_preserve.rs
 create mode 100644 tests/target/hex_literal_upper.rs

diff --git a/Configurations.md b/Configurations.md
index 84e8c3f7db6..b8f8f305396 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1056,6 +1056,13 @@ fn lorem() -> usize {
 
 See also: [`tab_spaces`](#tab_spaces).
 
+## `hex_literal_case`
+
+Control the case of the letters in hexadecimal literal values
+
+- **Default value**: `Preserve`
+- **Possible values**: `Upper`, `Lower`
+- **Stable**: No
 
 ## `hide_parse_errors`
 
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 3d6e32fdb60..c6cee8ed227 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -69,6 +69,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";
+    hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
+        "Format hexadecimal integer literals";
 
     // Single line expressions and items
     empty_item_single_line: bool, true, false,
@@ -570,6 +572,7 @@ license_template_path = ""
 format_strings = false
 format_macro_matchers = false
 format_macro_bodies = true
+hex_literal_case = "Preserve"
 empty_item_single_line = true
 struct_lit_single_line = true
 fn_single_line = false
diff --git a/src/config/options.rs b/src/config/options.rs
index db15ee97a40..e92f8e8a531 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -129,6 +129,17 @@ pub enum ImportGranularity {
     One,
 }
 
+/// Controls how rustfmt should handle case in hexadecimal literals.
+#[config_type]
+pub enum HexLiteralCase {
+    /// Leave the literal as-is
+    Preserve,
+    /// Ensure all literals use uppercase lettering
+    Upper,
+    /// Ensure all literals use lowercase lettering
+    Lower,
+}
+
 #[config_type]
 pub enum ReportTactic {
     Always,
diff --git a/src/expr.rs b/src/expr.rs
index 6cfeb9977a9..01cc388c186 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -13,7 +13,7 @@ use crate::comment::{
     rewrite_missing_comment, CharClasses, FindUncommented,
 };
 use crate::config::lists::*;
-use crate::config::{Config, ControlBraceStyle, IndentStyle, Version};
+use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, Version};
 use crate::lists::{
     definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
     struct_lit_tactic, write_list, ListFormatting, Separator,
@@ -1168,6 +1168,7 @@ pub(crate) fn rewrite_literal(
 ) -> Option<String> {
     match l.kind {
         ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape),
+        ast::LitKind::Int(..) => rewrite_int_lit(context, l, shape),
         _ => wrap_str(
             context.snippet(l.span).to_owned(),
             context.config.max_width(),
@@ -1202,6 +1203,36 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
     )
 }
 
+fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option<String> {
+    let span = lit.span;
+    let symbol = lit.token.symbol.as_str();
+
+    if symbol.starts_with("0x") {
+        let hex_lit = match context.config.hex_literal_case() {
+            HexLiteralCase::Preserve => None,
+            HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()),
+            HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()),
+        };
+        if let Some(hex_lit) = hex_lit {
+            return wrap_str(
+                format!(
+                    "0x{}{}",
+                    hex_lit,
+                    lit.token.suffix.map_or(String::new(), |s| s.to_string())
+                ),
+                context.config.max_width(),
+                shape,
+            );
+        }
+    }
+
+    wrap_str(
+        context.snippet(span).to_owned(),
+        context.config.max_width(),
+        shape,
+    )
+}
+
 fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option<SeparatorTactic> {
     if context.inside_macro() {
         if span_ends_with_comma(context, span) {
diff --git a/tests/source/hex_literal_lower.rs b/tests/source/hex_literal_lower.rs
new file mode 100644
index 00000000000..ce307b3aa52
--- /dev/null
+++ b/tests/source/hex_literal_lower.rs
@@ -0,0 +1,5 @@
+// rustfmt-hex_literal_case: Lower
+fn main() {
+    let h1 = 0xCAFE_5EA7;
+    let h2 = 0xCAFE_F00Du32;
+}
diff --git a/tests/source/hex_literal_upper.rs b/tests/source/hex_literal_upper.rs
new file mode 100644
index 00000000000..b1092ad71ba
--- /dev/null
+++ b/tests/source/hex_literal_upper.rs
@@ -0,0 +1,5 @@
+// rustfmt-hex_literal_case: Upper
+fn main() {
+    let h1 = 0xCaFE_5ea7;
+    let h2 = 0xCAFE_F00Du32;
+}
diff --git a/tests/target/hex_literal_lower.rs b/tests/target/hex_literal_lower.rs
new file mode 100644
index 00000000000..5c27fded167
--- /dev/null
+++ b/tests/target/hex_literal_lower.rs
@@ -0,0 +1,5 @@
+// rustfmt-hex_literal_case: Lower
+fn main() {
+    let h1 = 0xcafe_5ea7;
+    let h2 = 0xcafe_f00du32;
+}
diff --git a/tests/target/hex_literal_preserve.rs b/tests/target/hex_literal_preserve.rs
new file mode 100644
index 00000000000..e8774d0bb24
--- /dev/null
+++ b/tests/target/hex_literal_preserve.rs
@@ -0,0 +1,5 @@
+// rustfmt-hex_literal_case: Preserve
+fn main() {
+    let h1 = 0xcAfE_5Ea7;
+    let h2 = 0xCaFe_F00du32;
+}
diff --git a/tests/target/hex_literal_upper.rs b/tests/target/hex_literal_upper.rs
new file mode 100644
index 00000000000..48bb93d2c1c
--- /dev/null
+++ b/tests/target/hex_literal_upper.rs
@@ -0,0 +1,5 @@
+// rustfmt-hex_literal_case: Upper
+fn main() {
+    let h1 = 0xCAFE_5EA7;
+    let h2 = 0xCAFE_F00Du32;
+}

From 17cb2b147e11c9ad274b316026b1001fbd7007d4 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <calebcartwright@users.noreply.github.com>
Date: Sat, 26 Oct 2019 21:07:04 -0500
Subject: [PATCH 053/195] feat: add --check flag to cargo fmt (#3890)

---
 src/cargo-fmt/main.rs | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index f1125fa0bda..89ce454ac4d 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -56,6 +56,10 @@ pub struct Opts {
     /// Format all packages, and also their local path-based dependencies
     #[structopt(long = "all")]
     format_all: bool,
+
+    /// Run rustfmt in check mode
+    #[structopt(long = "check")]
+    check: bool,
 }
 
 fn main() {
@@ -104,6 +108,12 @@ fn execute() -> i32 {
 
     let strategy = CargoFmtStrategy::from_opts(&opts);
     let mut rustfmt_args = opts.rustfmt_options;
+    if opts.check {
+        let check_flag = String::from("--check");
+        if !rustfmt_args.contains(&check_flag) {
+            rustfmt_args.push(check_flag);
+        }
+    }
     if let Some(message_format) = opts.message_format {
         if let Err(msg) = convert_message_format_to_rustfmt_args(&message_format, &mut rustfmt_args)
         {
@@ -553,6 +563,7 @@ mod cargo_fmt_tests {
         assert_eq!(false, o.quiet);
         assert_eq!(false, o.verbose);
         assert_eq!(false, o.version);
+        assert_eq!(false, o.check);
         assert_eq!(empty, o.packages);
         assert_eq!(empty, o.rustfmt_options);
         assert_eq!(false, o.format_all);
@@ -571,6 +582,7 @@ mod cargo_fmt_tests {
             "p2",
             "--message-format",
             "short",
+            "--check",
             "--",
             "--edition",
             "2018",
@@ -578,6 +590,7 @@ mod cargo_fmt_tests {
         assert_eq!(true, o.quiet);
         assert_eq!(false, o.verbose);
         assert_eq!(false, o.version);
+        assert_eq!(true, o.check);
         assert_eq!(vec!["p1", "p2"], o.packages);
         assert_eq!(vec!["--edition", "2018"], o.rustfmt_options);
         assert_eq!(false, o.format_all);
@@ -606,12 +619,12 @@ mod cargo_fmt_tests {
     fn mandatory_separator() {
         assert!(
             Opts::clap()
-                .get_matches_from_safe(&["test", "--check"])
+                .get_matches_from_safe(&["test", "--emit"])
                 .is_err()
         );
         assert!(
             !Opts::clap()
-                .get_matches_from_safe(&["test", "--", "--check"])
+                .get_matches_from_safe(&["test", "--", "--emit"])
                 .is_err()
         );
     }

From 7aa69e5bc87f32fdcbf037abce2d575335480b9a Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 16 Sep 2021 21:25:09 -0500
Subject: [PATCH 054/195] refactor: use iter workaround for contains() gap

---
 src/cargo-fmt/main.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 89ce454ac4d..147b19d7a48 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -109,9 +109,9 @@ fn execute() -> i32 {
     let strategy = CargoFmtStrategy::from_opts(&opts);
     let mut rustfmt_args = opts.rustfmt_options;
     if opts.check {
-        let check_flag = String::from("--check");
-        if !rustfmt_args.contains(&check_flag) {
-            rustfmt_args.push(check_flag);
+        let check_flag = "--check";
+        if !rustfmt_args.iter().any(|o| o == check_flag) {
+            rustfmt_args.push(check_flag.to_owned());
         }
     }
     if let Some(message_format) = opts.message_format {

From dd445aba080cd337300644c77137fedcad482623 Mon Sep 17 00:00:00 2001
From: Ulyssa <git@ulyssa.dev>
Date: Wed, 15 Sep 2021 08:58:23 -0700
Subject: [PATCH 055/195] Trailing comma on match block goes missing when guard
 is on its own line

---
 src/matches.rs                             |  1 +
 tests/source/match-block-trailing-comma.rs |  8 ++++++++
 tests/target/match-block-trailing-comma.rs | 10 ++++++++++
 3 files changed, 19 insertions(+)

diff --git a/src/matches.rs b/src/matches.rs
index 140ec226c02..5a6ed0ec06e 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -409,6 +409,7 @@ fn rewrite_match_body(
             }
             result.push_str(&nested_indent_str);
             result.push_str(&body_str);
+            result.push_str(&comma);
             return Some(result);
         }
 
diff --git a/tests/source/match-block-trailing-comma.rs b/tests/source/match-block-trailing-comma.rs
index e9daac13bf9..baa05b79c16 100644
--- a/tests/source/match-block-trailing-comma.rs
+++ b/tests/source/match-block-trailing-comma.rs
@@ -8,6 +8,14 @@ fn foo() {
             "line1";
             "line2"
         }
+        ThisIsA::Guard if true => {
+            "line1";
+            "line2"
+        }
+        ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) if true => {
+            "line1";
+            "line2"
+        }
         b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
               bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb),
     }
diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs
index 44d1f289f8e..5ab433a2e6c 100644
--- a/tests/target/match-block-trailing-comma.rs
+++ b/tests/target/match-block-trailing-comma.rs
@@ -8,6 +8,16 @@ fn foo() {
             "line1";
             "line2"
         },
+        ThisIsA::Guard if true => {
+            "line1";
+            "line2"
+        },
+        ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine)
+            if true =>
+        {
+            "line1";
+            "line2"
+        },
         b => (
             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
             bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,

From 74df7b3265702949105161b36aee8b0975907210 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 19 Sep 2021 22:15:50 -0500
Subject: [PATCH 056/195] deps: update cargo_metadata to include 'path'

---
 Cargo.lock | 44 ++++++++++++++------------------------------
 Cargo.toml |  2 +-
 2 files changed, 15 insertions(+), 31 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index be134f3e975..7263f047477 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -75,6 +75,15 @@ dependencies = [
  "packed_simd_2",
 ]
 
+[[package]]
+name = "camino"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "cargo-platform"
 version = "0.1.1"
@@ -86,13 +95,13 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.12.3"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f"
+checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
 dependencies = [
+ "camino",
  "cargo-platform",
  "semver",
- "semver-parser",
  "serde",
  "serde_json",
 ]
@@ -322,15 +331,6 @@ dependencies = [
  "libm",
 ]
 
-[[package]]
-name = "pest"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
-dependencies = [
- "ucd-trie",
-]
-
 [[package]]
 name = "proc-macro-error"
 version = "0.4.11"
@@ -475,23 +475,13 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "0.11.0"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
 dependencies = [
- "semver-parser",
  "serde",
 ]
 
-[[package]]
-name = "semver-parser"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
-dependencies = [
- "pest",
-]
-
 [[package]]
 name = "serde"
 version = "1.0.126"
@@ -641,12 +631,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "ucd-trie"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
-
 [[package]]
 name = "unicode-segmentation"
 version = "1.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index e368f3eb1ec..970b13eab35 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -46,7 +46,7 @@ log = "0.4.14"
 env_logger = "0.8"
 getopts = "0.2"
 derive-new = "0.5"
-cargo_metadata = "0.12"
+cargo_metadata = "0.14"
 bytecount = "0.6"
 unicode-width = "0.1.5"
 unicode_categories = "0.1.1"

From 7f6229b9aada69389be4ead0ecbec8aed5892a24 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Sep 2021 18:58:38 -0500
Subject: [PATCH 057/195] tests: restructure and extend cargo-fmt tests

---
 .gitignore                                    |   1 +
 src/cargo-fmt/test/message_format.rs          |  80 ++++++++++
 src/cargo-fmt/test/mod.rs                     | 137 ++++++++++++++++++
 src/cargo-fmt/test/targets.rs                 | 134 +++++++++++++++++
 .../divergent-crate-dir-names/Cargo.toml      |  13 ++
 .../dependency-dir-name/Cargo.toml            |  10 ++
 .../dependency-dir-name/src/lib.rs            |   7 +
 .../subdep-dir-name/Cargo.toml                |   7 +
 .../subdep-dir-name/src/lib.rs                |   7 +
 .../divergent-crate-dir-names/src/main.rs     |   3 +
 .../workspaces/path-dep-above/e/Cargo.toml    |   6 +
 .../workspaces/path-dep-above/e/src/main.rs   |   1 +
 .../workspaces/path-dep-above/ws/Cargo.toml   |   5 +
 .../workspaces/path-dep-above/ws/a/Cargo.toml |   6 +
 .../path-dep-above/ws/a/d/Cargo.toml          |   7 +
 .../path-dep-above/ws/a/d/f/Cargo.toml        |   4 +
 .../path-dep-above/ws/a/d/f/src/lib.rs        |   1 +
 .../path-dep-above/ws/a/d/src/lib.rs          |   1 +
 .../path-dep-above/ws/a/src/main.rs           |   1 +
 .../workspaces/path-dep-above/ws/b/Cargo.toml |   6 +
 .../path-dep-above/ws/b/src/main.rs           |   1 +
 .../workspaces/path-dep-above/ws/c/Cargo.toml |   4 +
 .../workspaces/path-dep-above/ws/c/src/lib.rs |   1 +
 23 files changed, 443 insertions(+)
 create mode 100644 src/cargo-fmt/test/message_format.rs
 create mode 100644 src/cargo-fmt/test/mod.rs
 create mode 100644 src/cargo-fmt/test/targets.rs
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs
 create mode 100644 tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml
 create mode 100644 tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs

diff --git a/.gitignore b/.gitignore
index 37adf8751ca..71cf88f79e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 # Generated by Cargo
 # will have compiled files and executables
 /target
+tests/cargo-fmt/**/target
 
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
 # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
diff --git a/src/cargo-fmt/test/message_format.rs b/src/cargo-fmt/test/message_format.rs
new file mode 100644
index 00000000000..bf44924f13c
--- /dev/null
+++ b/src/cargo-fmt/test/message_format.rs
@@ -0,0 +1,80 @@
+use super::*;
+
+#[test]
+fn invalid_message_format() {
+    assert_eq!(
+        convert_message_format_to_rustfmt_args("awesome", &mut vec![]),
+        Err(String::from(
+            "invalid --message-format value: awesome. Allowed values are: short|json|human"
+        )),
+    );
+}
+
+#[test]
+fn json_message_format_and_check_arg() {
+    let mut args = vec![String::from("--check")];
+    assert_eq!(
+        convert_message_format_to_rustfmt_args("json", &mut args),
+        Err(String::from(
+            "cannot include --check arg when --message-format is set to json"
+        )),
+    );
+}
+
+#[test]
+fn json_message_format_and_emit_arg() {
+    let mut args = vec![String::from("--emit"), String::from("checkstyle")];
+    assert_eq!(
+        convert_message_format_to_rustfmt_args("json", &mut args),
+        Err(String::from(
+            "cannot include --emit arg when --message-format is set to json"
+        )),
+    );
+}
+
+#[test]
+fn json_message_format() {
+    let mut args = vec![String::from("--edition"), String::from("2018")];
+    assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok());
+    assert_eq!(
+        args,
+        vec![
+            String::from("--edition"),
+            String::from("2018"),
+            String::from("--emit"),
+            String::from("json")
+        ]
+    );
+}
+
+#[test]
+fn human_message_format() {
+    let exp_args = vec![String::from("--emit"), String::from("json")];
+    let mut act_args = exp_args.clone();
+    assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok());
+    assert_eq!(act_args, exp_args);
+}
+
+#[test]
+fn short_message_format() {
+    let mut args = vec![String::from("--check")];
+    assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
+    assert_eq!(args, vec![String::from("--check"), String::from("-l")]);
+}
+
+#[test]
+fn short_message_format_included_short_list_files_flag() {
+    let mut args = vec![String::from("--check"), String::from("-l")];
+    assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
+    assert_eq!(args, vec![String::from("--check"), String::from("-l")]);
+}
+
+#[test]
+fn short_message_format_included_long_list_files_flag() {
+    let mut args = vec![String::from("--check"), String::from("--files-with-diff")];
+    assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
+    assert_eq!(
+        args,
+        vec![String::from("--check"), String::from("--files-with-diff")]
+    );
+}
diff --git a/src/cargo-fmt/test/mod.rs b/src/cargo-fmt/test/mod.rs
new file mode 100644
index 00000000000..360503632c7
--- /dev/null
+++ b/src/cargo-fmt/test/mod.rs
@@ -0,0 +1,137 @@
+use super::*;
+
+mod message_format;
+mod targets;
+
+#[test]
+fn default_options() {
+    let empty: Vec<String> = vec![];
+    let o = Opts::from_iter(&empty);
+    assert_eq!(false, o.quiet);
+    assert_eq!(false, o.verbose);
+    assert_eq!(false, o.version);
+    assert_eq!(false, o.check);
+    assert_eq!(empty, o.packages);
+    assert_eq!(empty, o.rustfmt_options);
+    assert_eq!(false, o.format_all);
+    assert_eq!(None, o.manifest_path);
+    assert_eq!(None, o.message_format);
+}
+
+#[test]
+fn good_options() {
+    let o = Opts::from_iter(&[
+        "test",
+        "-q",
+        "-p",
+        "p1",
+        "-p",
+        "p2",
+        "--message-format",
+        "short",
+        "--check",
+        "--",
+        "--edition",
+        "2018",
+    ]);
+    assert_eq!(true, o.quiet);
+    assert_eq!(false, o.verbose);
+    assert_eq!(false, o.version);
+    assert_eq!(true, o.check);
+    assert_eq!(vec!["p1", "p2"], o.packages);
+    assert_eq!(vec!["--edition", "2018"], o.rustfmt_options);
+    assert_eq!(false, o.format_all);
+    assert_eq!(Some(String::from("short")), o.message_format);
+}
+
+#[test]
+fn unexpected_option() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "unexpected"])
+            .is_err()
+    );
+}
+
+#[test]
+fn unexpected_flag() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "--flag"])
+            .is_err()
+    );
+}
+
+#[test]
+fn mandatory_separator() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "--emit"])
+            .is_err()
+    );
+    assert!(
+        !Opts::clap()
+            .get_matches_from_safe(&["test", "--", "--emit"])
+            .is_err()
+    );
+}
+
+#[test]
+fn multiple_packages_one_by_one() {
+    let o = Opts::from_iter(&[
+        "test",
+        "-p",
+        "package1",
+        "--package",
+        "package2",
+        "-p",
+        "package3",
+    ]);
+    assert_eq!(3, o.packages.len());
+}
+
+#[test]
+fn multiple_packages_grouped() {
+    let o = Opts::from_iter(&[
+        "test",
+        "--package",
+        "package1",
+        "package2",
+        "-p",
+        "package3",
+        "package4",
+    ]);
+    assert_eq!(4, o.packages.len());
+}
+
+#[test]
+fn empty_packages_1() {
+    assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err());
+}
+
+#[test]
+fn empty_packages_2() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "-p", "--", "--check"])
+            .is_err()
+    );
+}
+
+#[test]
+fn empty_packages_3() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "-p", "--verbose"])
+            .is_err()
+    );
+}
+
+#[test]
+fn empty_packages_4() {
+    assert!(
+        Opts::clap()
+            .get_matches_from_safe(&["test", "-p", "--check"])
+            .is_err()
+    );
+}
diff --git a/src/cargo-fmt/test/targets.rs b/src/cargo-fmt/test/targets.rs
new file mode 100644
index 00000000000..b7e7fabdf71
--- /dev/null
+++ b/src/cargo-fmt/test/targets.rs
@@ -0,0 +1,134 @@
+use super::*;
+
+struct ExpTarget {
+    path: &'static str,
+    edition: &'static str,
+    kind: &'static str,
+}
+
+mod all_targets {
+    use super::*;
+
+    fn assert_correct_targets_loaded(
+        manifest_suffix: &str,
+        source_root: &str,
+        exp_targets: &[ExpTarget],
+        exp_num_targets: usize,
+    ) {
+        let root_path = Path::new("tests/cargo-fmt/source").join(source_root);
+        let get_path = |exp: &str| PathBuf::from(&root_path).join(exp).canonicalize().unwrap();
+        let manifest_path = Path::new(&root_path).join(manifest_suffix);
+        let targets = get_targets(&CargoFmtStrategy::All, Some(manifest_path.as_path()))
+            .expect("Targets should have been loaded");
+
+        assert_eq!(targets.len(), exp_num_targets);
+
+        for target in exp_targets {
+            assert!(targets.contains(&Target {
+                path: get_path(target.path),
+                edition: target.edition.to_owned(),
+                kind: target.kind.to_owned(),
+            }));
+        }
+    }
+
+    mod different_crate_and_dir_names {
+        use super::*;
+
+        fn assert_correct_targets_loaded(manifest_suffix: &str) {
+            let exp_targets = vec![
+                ExpTarget {
+                    path: "dependency-dir-name/subdep-dir-name/src/lib.rs",
+                    edition: "2018",
+                    kind: "lib",
+                },
+                ExpTarget {
+                    path: "dependency-dir-name/src/lib.rs",
+                    edition: "2018",
+                    kind: "lib",
+                },
+                ExpTarget {
+                    path: "src/main.rs",
+                    edition: "2018",
+                    kind: "main",
+                },
+            ];
+            super::assert_correct_targets_loaded(
+                manifest_suffix,
+                "divergent-crate-dir-names",
+                &exp_targets,
+                3,
+            );
+        }
+
+        #[test]
+        fn correct_targets_from_root() {
+            assert_correct_targets_loaded("Cargo.toml");
+        }
+
+        #[test]
+        fn correct_targets_from_sub_local_dep() {
+            assert_correct_targets_loaded("dependency-dir-name/Cargo.toml");
+        }
+    }
+
+    mod workspaces {
+        use super::*;
+
+        fn assert_correct_targets_loaded(manifest_suffix: &str) {
+            let exp_targets = vec![
+                ExpTarget {
+                    path: "ws/a/src/main.rs",
+                    edition: "2018",
+                    kind: "bin",
+                },
+                ExpTarget {
+                    path: "ws/b/src/main.rs",
+                    edition: "2018",
+                    kind: "bin",
+                },
+                ExpTarget {
+                    path: "ws/c/src/lib.rs",
+                    edition: "2018",
+                    kind: "lib",
+                },
+                ExpTarget {
+                    path: "ws/a/d/src/lib.rs",
+                    edition: "2018",
+                    kind: "lib",
+                },
+                ExpTarget {
+                    path: "e/src/main.rs",
+                    edition: "2018",
+                    kind: "main",
+                },
+                ExpTarget {
+                    path: "ws/a/d/f/src/lib.rs",
+                    edition: "2018",
+                    kind: "lib",
+                },
+            ];
+            super::assert_correct_targets_loaded(
+                manifest_suffix,
+                "workspaces/path-dep-above",
+                &exp_targets,
+                6,
+            );
+        }
+
+        #[test]
+        fn includes_outside_workspace_deps() {
+            assert_correct_targets_loaded("ws/Cargo.toml");
+        }
+
+        #[test]
+        fn includes_workspace_from_dep_above() {
+            assert_correct_targets_loaded("e/Cargo.toml");
+        }
+
+        #[test]
+        fn includes_all_packages_from_workspace_subdir() {
+            assert_correct_targets_loaded("ws/a/d/f/Cargo.toml");
+        }
+    }
+}
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml b/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml
new file mode 100644
index 00000000000..315364a6457
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "cargo-fmt-test"
+version = "0.1.0"
+authors = ["calebcartwright"]
+edition = "2018"
+
+[dependencies]
+indexmap = "1.0.2"
+
+[workspace]
+members = [
+  "dependency-dir-name",
+]
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml
new file mode 100644
index 00000000000..4493882bf40
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "dependency-crate-name"
+version = "0.1.0"
+authors = ["calebcartwright"]
+edition = "2018"
+
+[dependencies]
+subdep-crate-name = { path = "subdep-dir-name" }
+indexmap = "1.0.2"
+rusty-hook = "0.8.4"
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs
new file mode 100644
index 00000000000..e93b18d725b
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs
@@ -0,0 +1,7 @@
+#[cfg(test)]
+mod tests {
+#[test]
+fn it_works() {
+    assert_eq!(2 + 2, 4);
+}
+}
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml
new file mode 100644
index 00000000000..7dad09f4077
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "subdep-crate-name"
+version = "0.1.0"
+authors = ["calebcartwright"]
+edition = "2018"
+
+[dependencies]
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs
new file mode 100644
index 00000000000..1c08c1c4fd3
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs
@@ -0,0 +1,7 @@
+#[cfg(test)]
+mod tests {
+#[test]
+fn sub_test_that_works() {
+    assert_eq!(3 + 3, 6);
+}
+ }
diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs b/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs
new file mode 100644
index 00000000000..f5c339a8dd1
--- /dev/null
+++ b/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+println!("Hello, world!");
+}
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml
new file mode 100644
index 00000000000..df1886c82be
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "e"
+version = "0.1.0"
+edition = "2018"
+[dependencies]
+c = { path = "../ws/c" }
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs
new file mode 100644
index 00000000000..1c26a3895f3
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs
@@ -0,0 +1 @@
+struct E{   }
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml
new file mode 100644
index 00000000000..202739b613b
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+members = [
+    "a",
+    "b"
+] 
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml
new file mode 100644
index 00000000000..712a113448f
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "a"
+version = "0.1.0"
+edition = "2018"
+[dependencies]
+d = { path = "./d" }
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml
new file mode 100644
index 00000000000..fb0f06fe5fc
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "d"
+version = "0.1.0"
+edition = "2018"
+[dependencies]
+e = { path = "../../../e" }
+f = { path = "f" }
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml
new file mode 100644
index 00000000000..5c4fa561788
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "f"
+version = "0.1.0"
+edition = "2018"
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs
new file mode 100644
index 00000000000..c655c4d5e1a
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs
@@ -0,0 +1 @@
+struct F{   }
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs
new file mode 100644
index 00000000000..04e6e4cb940
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs
@@ -0,0 +1 @@
+struct D{   }
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs
new file mode 100644
index 00000000000..04e6e4cb940
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs
@@ -0,0 +1 @@
+struct D{   }
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml
new file mode 100644
index 00000000000..47a24ff4f27
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "b"
+version = "0.1.0"
+edition = "2018"
+[dependencies]
+c = { path = "../c" }
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs
new file mode 100644
index 00000000000..4833bbc69b4
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs
@@ -0,0 +1 @@
+struct B{   }
\ No newline at end of file
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml
new file mode 100644
index 00000000000..49fa6c395eb
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "c"
+version = "0.1.0"
+edition = "2018"
diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs
new file mode 100644
index 00000000000..1245ac91d60
--- /dev/null
+++ b/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs
@@ -0,0 +1 @@
+struct C{   }
\ No newline at end of file

From 4b9d637f5846b92f2c17b98985c47dea795064d2 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Sep 2021 19:09:16 -0500
Subject: [PATCH 058/195] refactor: simplify local dep lookups

---
 src/cargo-fmt/main.rs | 280 ++++--------------------------------------
 1 file changed, 26 insertions(+), 254 deletions(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 147b19d7a48..1d423ac3491 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -17,6 +17,10 @@ use std::str;
 
 use structopt::StructOpt;
 
+#[path = "test/mod.rs"]
+#[cfg(test)]
+mod cargo_fmt_tests;
+
 #[derive(StructOpt, Debug)]
 #[structopt(
     bin_name = "cargo fmt",
@@ -356,7 +360,7 @@ fn get_targets_root_only(
     manifest_path: Option<&Path>,
     targets: &mut BTreeSet<Target>,
 ) -> Result<(), io::Error> {
-    let metadata = get_cargo_metadata(manifest_path, false)?;
+    let metadata = get_cargo_metadata(manifest_path)?;
     let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?;
     let (in_workspace_root, current_dir_manifest) = if let Some(target_manifest) = manifest_path {
         (
@@ -400,34 +404,29 @@ fn get_targets_recursive(
     mut targets: &mut BTreeSet<Target>,
     visited: &mut BTreeSet<String>,
 ) -> Result<(), io::Error> {
-    let metadata = get_cargo_metadata(manifest_path, false)?;
-    let metadata_with_deps = get_cargo_metadata(manifest_path, true)?;
-
-    for package in metadata.packages {
+    let metadata = get_cargo_metadata(manifest_path)?;
+    for package in &metadata.packages {
         add_targets(&package.targets, &mut targets);
 
-        // Look for local dependencies.
-        for dependency in package.dependencies {
-            if dependency.source.is_some() || visited.contains(&dependency.name) {
+        // Look for local dependencies using information available since cargo v1.51
+        // It's theoretically possible someone could use a newer version of rustfmt with
+        // a much older version of `cargo`, but we don't try to explicitly support that scenario.
+        // If someone reports an issue with path-based deps not being formatted, be sure to
+        // confirm their version of `cargo` (not `cargo-fmt`) is >= v1.51
+        // https://github.com/rust-lang/cargo/pull/8994
+        for dependency in &package.dependencies {
+            if dependency.path.is_none() || visited.contains(&dependency.name) {
                 continue;
             }
 
-            let dependency_package = metadata_with_deps
-                .packages
-                .iter()
-                .find(|p| p.name == dependency.name && p.source.is_none());
-            let manifest_path = if let Some(dep_pkg) = dependency_package {
-                PathBuf::from(&dep_pkg.manifest_path)
-            } else {
-                let mut package_manifest_path = PathBuf::from(&package.manifest_path);
-                package_manifest_path.pop();
-                package_manifest_path.push(&dependency.name);
-                package_manifest_path.push("Cargo.toml");
-                package_manifest_path
-            };
-
-            if manifest_path.exists() {
-                visited.insert(dependency.name);
+            let manifest_path = PathBuf::from(dependency.path.as_ref().unwrap()).join("Cargo.toml");
+            if manifest_path.exists()
+                && !metadata
+                    .packages
+                    .iter()
+                    .any(|p| p.manifest_path.eq(&manifest_path))
+            {
+                visited.insert(dependency.name.to_owned());
                 get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
             }
         }
@@ -441,8 +440,7 @@ fn get_targets_with_hitlist(
     hitlist: &[String],
     targets: &mut BTreeSet<Target>,
 ) -> Result<(), io::Error> {
-    let metadata = get_cargo_metadata(manifest_path, false)?;
-
+    let metadata = get_cargo_metadata(manifest_path)?;
     let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist);
 
     for package in metadata.packages {
@@ -527,14 +525,9 @@ fn run_rustfmt(
         .unwrap_or(SUCCESS))
 }
 
-fn get_cargo_metadata(
-    manifest_path: Option<&Path>,
-    include_deps: bool,
-) -> Result<cargo_metadata::Metadata, io::Error> {
+fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
     let mut cmd = cargo_metadata::MetadataCommand::new();
-    if !include_deps {
-        cmd.no_deps();
-    }
+    cmd.no_deps();
     if let Some(manifest_path) = manifest_path {
         cmd.manifest_path(manifest_path);
     }
@@ -551,224 +544,3 @@ fn get_cargo_metadata(
         }
     }
 }
-
-#[cfg(test)]
-mod cargo_fmt_tests {
-    use super::*;
-
-    #[test]
-    fn default_options() {
-        let empty: Vec<String> = vec![];
-        let o = Opts::from_iter(&empty);
-        assert_eq!(false, o.quiet);
-        assert_eq!(false, o.verbose);
-        assert_eq!(false, o.version);
-        assert_eq!(false, o.check);
-        assert_eq!(empty, o.packages);
-        assert_eq!(empty, o.rustfmt_options);
-        assert_eq!(false, o.format_all);
-        assert_eq!(None, o.manifest_path);
-        assert_eq!(None, o.message_format);
-    }
-
-    #[test]
-    fn good_options() {
-        let o = Opts::from_iter(&[
-            "test",
-            "-q",
-            "-p",
-            "p1",
-            "-p",
-            "p2",
-            "--message-format",
-            "short",
-            "--check",
-            "--",
-            "--edition",
-            "2018",
-        ]);
-        assert_eq!(true, o.quiet);
-        assert_eq!(false, o.verbose);
-        assert_eq!(false, o.version);
-        assert_eq!(true, o.check);
-        assert_eq!(vec!["p1", "p2"], o.packages);
-        assert_eq!(vec!["--edition", "2018"], o.rustfmt_options);
-        assert_eq!(false, o.format_all);
-        assert_eq!(Some(String::from("short")), o.message_format);
-    }
-
-    #[test]
-    fn unexpected_option() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "unexpected"])
-                .is_err()
-        );
-    }
-
-    #[test]
-    fn unexpected_flag() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "--flag"])
-                .is_err()
-        );
-    }
-
-    #[test]
-    fn mandatory_separator() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "--emit"])
-                .is_err()
-        );
-        assert!(
-            !Opts::clap()
-                .get_matches_from_safe(&["test", "--", "--emit"])
-                .is_err()
-        );
-    }
-
-    #[test]
-    fn multiple_packages_one_by_one() {
-        let o = Opts::from_iter(&[
-            "test",
-            "-p",
-            "package1",
-            "--package",
-            "package2",
-            "-p",
-            "package3",
-        ]);
-        assert_eq!(3, o.packages.len());
-    }
-
-    #[test]
-    fn multiple_packages_grouped() {
-        let o = Opts::from_iter(&[
-            "test",
-            "--package",
-            "package1",
-            "package2",
-            "-p",
-            "package3",
-            "package4",
-        ]);
-        assert_eq!(4, o.packages.len());
-    }
-
-    #[test]
-    fn empty_packages_1() {
-        assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err());
-    }
-
-    #[test]
-    fn empty_packages_2() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "--", "--check"])
-                .is_err()
-        );
-    }
-
-    #[test]
-    fn empty_packages_3() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "--verbose"])
-                .is_err()
-        );
-    }
-
-    #[test]
-    fn empty_packages_4() {
-        assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "--check"])
-                .is_err()
-        );
-    }
-
-    mod convert_message_format_to_rustfmt_args_tests {
-        use super::*;
-
-        #[test]
-        fn invalid_message_format() {
-            assert_eq!(
-                convert_message_format_to_rustfmt_args("awesome", &mut vec![]),
-                Err(String::from(
-                    "invalid --message-format value: awesome. Allowed values are: short|json|human"
-                )),
-            );
-        }
-
-        #[test]
-        fn json_message_format_and_check_arg() {
-            let mut args = vec![String::from("--check")];
-            assert_eq!(
-                convert_message_format_to_rustfmt_args("json", &mut args),
-                Err(String::from(
-                    "cannot include --check arg when --message-format is set to json"
-                )),
-            );
-        }
-
-        #[test]
-        fn json_message_format_and_emit_arg() {
-            let mut args = vec![String::from("--emit"), String::from("checkstyle")];
-            assert_eq!(
-                convert_message_format_to_rustfmt_args("json", &mut args),
-                Err(String::from(
-                    "cannot include --emit arg when --message-format is set to json"
-                )),
-            );
-        }
-
-        #[test]
-        fn json_message_format() {
-            let mut args = vec![String::from("--edition"), String::from("2018")];
-            assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok());
-            assert_eq!(
-                args,
-                vec![
-                    String::from("--edition"),
-                    String::from("2018"),
-                    String::from("--emit"),
-                    String::from("json")
-                ]
-            );
-        }
-
-        #[test]
-        fn human_message_format() {
-            let exp_args = vec![String::from("--emit"), String::from("json")];
-            let mut act_args = exp_args.clone();
-            assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok());
-            assert_eq!(act_args, exp_args);
-        }
-
-        #[test]
-        fn short_message_format() {
-            let mut args = vec![String::from("--check")];
-            assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
-            assert_eq!(args, vec![String::from("--check"), String::from("-l")]);
-        }
-
-        #[test]
-        fn short_message_format_included_short_list_files_flag() {
-            let mut args = vec![String::from("--check"), String::from("-l")];
-            assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
-            assert_eq!(args, vec![String::from("--check"), String::from("-l")]);
-        }
-
-        #[test]
-        fn short_message_format_included_long_list_files_flag() {
-            let mut args = vec![String::from("--check"), String::from("--files-with-diff")];
-            assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok());
-            assert_eq!(
-                args,
-                vec![String::from("--check"), String::from("--files-with-diff")]
-            );
-        }
-    }
-}

From cb144c35e7d7151bb4b6ccd9b30a4141959166d1 Mon Sep 17 00:00:00 2001
From: Lucas Kent <rubickent@gmail.com>
Date: Fri, 10 Sep 2021 17:50:40 +1000
Subject: [PATCH 059/195] In Configurations.md demonstrate both cases for noop
 selections

---
 Configurations.md | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/Configurations.md b/Configurations.md
index b8f8f305396..ff83f02f87b 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1684,6 +1684,9 @@ pub enum Foo {}
 #### `false`:
 
 ```rust
+#[derive(Eq, PartialEq, Debug, Copy, Clone)]
+pub enum Bar {}
+
 #[derive(Eq, PartialEq)]
 #[derive(Debug)]
 #[derive(Copy, Clone)]
@@ -1857,6 +1860,9 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments.
 #![doc = "Example documentation"]
 
 #[doc = "Example item documentation"]
+pub enum Bar {}
+
+/// Example item documentation
 pub enum Foo {}
 ```
 
@@ -1971,6 +1977,8 @@ fn main() {
 #### `false`:
 ```rust
 fn main() {
+    (foo());
+
     ((((foo()))));
 }
 ```
@@ -1996,6 +2004,14 @@ impl Iterator for Dummy {
 
     type Item = i32;
 }
+
+impl Iterator for Dummy {
+    type Item = i32;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
 ```
 
 #### `true`
@@ -2552,7 +2568,8 @@ fn main() {
     let x = 1;
     let y = 2;
     let z = 3;
-    let a = Foo { x: x, y: y, z: z };
+    let a = Foo { x, y, z };
+    let b = Foo { x: x, y: y, z: z };
 }
 ```
 
@@ -2721,6 +2738,8 @@ Replace uses of the try! macro by the ? shorthand
 
 ```rust
 fn main() {
+    let lorem = ipsum.map(|dolor| dolor.sit())?;
+
     let lorem = try!(ipsum.map(|dolor| dolor.sit()));
 }
 ```
@@ -2792,6 +2811,12 @@ Break comments to fit on the line
 #### `false` (default):
 
 ```rust
+// Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+// sed do eiusmod tempor incididunt ut labore et dolore
+// magna aliqua. Ut enim ad minim veniam, quis nostrud
+// exercitation ullamco laboris nisi ut aliquip ex ea
+// commodo consequat.
+
 // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
 ```
 

From a5138b34d5f2644d916e906a3d460856a1b1a42a Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Mon, 27 Sep 2021 16:55:23 -0400
Subject: [PATCH 060/195] Prevent removal of qualified path for tuple struct
 inside macro

fixes 5005

This was very similar to 4964 and the fix was to extract and pass along
the qself of the ``PatKind::TupleStruct``
---
 src/patterns.rs                            | 5 +++--
 tests/target/issue-5005/minimum_example.rs | 9 +++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)
 create mode 100644 tests/target/issue-5005/minimum_example.rs

diff --git a/src/patterns.rs b/src/patterns.rs
index 0c6a6f3e814..4c6a2d5d75b 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -226,8 +226,9 @@ impl Rewrite for Pat {
             PatKind::Path(ref q_self, ref path) => {
                 rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
             }
-            PatKind::TupleStruct(_, ref path, ref pat_vec) => {
-                let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?;
+            PatKind::TupleStruct(ref q_self, ref path, ref pat_vec) => {
+                let path_str =
+                    rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)?;
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
             PatKind::Lit(ref expr) => expr.rewrite(context, shape),
diff --git a/tests/target/issue-5005/minimum_example.rs b/tests/target/issue-5005/minimum_example.rs
new file mode 100644
index 00000000000..11cc645fa53
--- /dev/null
+++ b/tests/target/issue-5005/minimum_example.rs
@@ -0,0 +1,9 @@
+#![feature(more_qualified_paths)]
+macro_rules! show {
+    ($ty:ty, $ex:expr) => {
+        match $ex {
+            <$ty>::A(_val) => println!("got a"), // formatting should not remove <$ty>::
+            <$ty>::B => println!("got b"),
+        }
+    };
+}

From e3203ef5e6902e0bbb7b62ebd34b3d53cb5d28b8 Mon Sep 17 00:00:00 2001
From: Ulyssa <git@ulyssa.dev>
Date: Mon, 20 Sep 2021 16:29:28 -0700
Subject: [PATCH 061/195] Add tests for binop_separator = Back

---
 tests/source/binop-separator-back/bitwise.rs  | 14 ++++++++
 tests/source/binop-separator-back/comp.rs     | 23 +++++++++++++
 tests/source/binop-separator-back/logic.rs    |  7 ++++
 tests/source/binop-separator-back/math.rs     |  7 ++++
 tests/source/binop-separator-back/patterns.rs |  9 +++++
 tests/source/binop-separator-back/range.rs    |  7 ++++
 tests/target/binop-separator-back/bitwise.rs  | 18 ++++++++++
 tests/target/binop-separator-back/comp.rs     | 33 +++++++++++++++++++
 tests/target/binop-separator-back/logic.rs    | 10 ++++++
 tests/target/binop-separator-back/math.rs     | 23 +++++++++++++
 tests/target/binop-separator-back/patterns.rs | 11 +++++++
 tests/target/binop-separator-back/range.rs    |  9 +++++
 12 files changed, 171 insertions(+)
 create mode 100644 tests/source/binop-separator-back/bitwise.rs
 create mode 100644 tests/source/binop-separator-back/comp.rs
 create mode 100644 tests/source/binop-separator-back/logic.rs
 create mode 100644 tests/source/binop-separator-back/math.rs
 create mode 100644 tests/source/binop-separator-back/patterns.rs
 create mode 100644 tests/source/binop-separator-back/range.rs
 create mode 100644 tests/target/binop-separator-back/bitwise.rs
 create mode 100644 tests/target/binop-separator-back/comp.rs
 create mode 100644 tests/target/binop-separator-back/logic.rs
 create mode 100644 tests/target/binop-separator-back/math.rs
 create mode 100644 tests/target/binop-separator-back/patterns.rs
 create mode 100644 tests/target/binop-separator-back/range.rs

diff --git a/tests/source/binop-separator-back/bitwise.rs b/tests/source/binop-separator-back/bitwise.rs
new file mode 100644
index 00000000000..3804bf3215b
--- /dev/null
+++ b/tests/source/binop-separator-back/bitwise.rs
@@ -0,0 +1,14 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ & abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ << abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+}
diff --git a/tests/source/binop-separator-back/comp.rs b/tests/source/binop-separator-back/comp.rs
new file mode 100644
index 00000000000..50a27127445
--- /dev/null
+++ b/tests/source/binop-separator-back/comp.rs
@@ -0,0 +1,23 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ < abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ > abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ == abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+}
diff --git a/tests/source/binop-separator-back/logic.rs b/tests/source/binop-separator-back/logic.rs
new file mode 100644
index 00000000000..8c297e5a675
--- /dev/null
+++ b/tests/source/binop-separator-back/logic.rs
@@ -0,0 +1,7 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ && abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ || abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {
+        //
+    }
+}
diff --git a/tests/source/binop-separator-back/math.rs b/tests/source/binop-separator-back/math.rs
new file mode 100644
index 00000000000..3af4aad1605
--- /dev/null
+++ b/tests/source/binop-separator-back/math.rs
@@ -0,0 +1,7 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+}
diff --git a/tests/source/binop-separator-back/patterns.rs b/tests/source/binop-separator-back/patterns.rs
new file mode 100644
index 00000000000..a8c3b5cdd9b
--- /dev/null
+++ b/tests/source/binop-separator-back/patterns.rs
@@ -0,0 +1,9 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    match val {
+    ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine | ThisIsA::SecondValueSeparatedByAPipe | ThisIsA::ThirdValueSeparatedByAPipe => {
+    //
+    }
+    }
+}
diff --git a/tests/source/binop-separator-back/range.rs b/tests/source/binop-separator-back/range.rs
new file mode 100644
index 00000000000..bdd3de9922b
--- /dev/null
+++ b/tests/source/binop-separator-back/range.rs
@@ -0,0 +1,7 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+}
diff --git a/tests/target/binop-separator-back/bitwise.rs b/tests/target/binop-separator-back/bitwise.rs
new file mode 100644
index 00000000000..ce32c05ef70
--- /dev/null
+++ b/tests/target/binop-separator-back/bitwise.rs
@@ -0,0 +1,18 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ &
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ |
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <<
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >>
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+}
diff --git a/tests/target/binop-separator-back/comp.rs b/tests/target/binop-separator-back/comp.rs
new file mode 100644
index 00000000000..efd837bcfe3
--- /dev/null
+++ b/tests/target/binop-separator-back/comp.rs
@@ -0,0 +1,33 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <=
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >=
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ==
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+}
diff --git a/tests/target/binop-separator-back/logic.rs b/tests/target/binop-separator-back/logic.rs
new file mode 100644
index 00000000000..5f69fd5f55e
--- /dev/null
+++ b/tests/target/binop-separator-back/logic.rs
@@ -0,0 +1,10 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ &&
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ||
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+    {
+        //
+    }
+}
diff --git a/tests/target/binop-separator-back/math.rs b/tests/target/binop-separator-back/math.rs
new file mode 100644
index 00000000000..7a3f27e733b
--- /dev/null
+++ b/tests/target/binop-separator-back/math.rs
@@ -0,0 +1,23 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ *
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ /
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ *
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ *
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ /
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ /
+            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+}
diff --git a/tests/target/binop-separator-back/patterns.rs b/tests/target/binop-separator-back/patterns.rs
new file mode 100644
index 00000000000..2e59713526a
--- /dev/null
+++ b/tests/target/binop-separator-back/patterns.rs
@@ -0,0 +1,11 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    match val {
+        ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine |
+        ThisIsA::SecondValueSeparatedByAPipe |
+        ThisIsA::ThirdValueSeparatedByAPipe => {
+            //
+        }
+    }
+}
diff --git a/tests/target/binop-separator-back/range.rs b/tests/target/binop-separator-back/range.rs
new file mode 100644
index 00000000000..19e5a81cd9c
--- /dev/null
+++ b/tests/target/binop-separator-back/range.rs
@@ -0,0 +1,9 @@
+// rustfmt-binop_separator: Back
+
+fn main() {
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+
+    let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..=
+        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;
+}

From f0f449d6edda5a40057fc82ea02cc9abeae4d012 Mon Sep 17 00:00:00 2001
From: Patrick Walton <pcwalton@mimiga.net>
Date: Fri, 17 Sep 2021 18:56:30 -0700
Subject: [PATCH 062/195] Wrap long array and slice patterns.

Closes #4530.
---
 src/overflow.rs            |  4 +++-
 src/patterns.rs            | 12 +++++++++++-
 tests/source/issue-4530.rs |  4 ++++
 tests/target/issue-4530.rs |  9 +++++++++
 4 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 tests/source/issue-4530.rs
 create mode 100644 tests/target/issue-4530.rs

diff --git a/src/overflow.rs b/src/overflow.rs
index e32213467a5..ac24181c780 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -77,6 +77,7 @@ pub(crate) enum OverflowableItem<'a> {
     FieldDef(&'a ast::FieldDef),
     TuplePatField(&'a TuplePatField<'a>),
     Ty(&'a ast::Ty),
+    Pat(&'a ast::Pat),
 }
 
 impl<'a> Rewrite for OverflowableItem<'a> {
@@ -116,6 +117,7 @@ impl<'a> OverflowableItem<'a> {
             OverflowableItem::FieldDef(sf) => f(*sf),
             OverflowableItem::TuplePatField(pat) => f(*pat),
             OverflowableItem::Ty(ty) => f(*ty),
+            OverflowableItem::Pat(pat) => f(*pat),
         }
     }
 
@@ -232,7 +234,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types {
     }
 }
 
-impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty);
+impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty, Pat);
 impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]);
 
 pub(crate) fn into_overflowable_list<'a, T>(
diff --git a/src/patterns.rs b/src/patterns.rs
index 4c6a2d5d75b..34987b1d59e 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -4,6 +4,7 @@ use rustc_span::{BytePos, Span};
 
 use crate::comment::{combine_strs_with_missing_comments, FindUncommented};
 use crate::config::lists::*;
+use crate::config::Version;
 use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field};
 use crate::lists::{
     definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
@@ -232,7 +233,7 @@ impl Rewrite for Pat {
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
             PatKind::Lit(ref expr) => expr.rewrite(context, shape),
-            PatKind::Slice(ref slice_pat) => {
+            PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => {
                 let rw: Vec<String> = slice_pat
                     .iter()
                     .map(|p| {
@@ -245,6 +246,15 @@ impl Rewrite for Pat {
                     .collect();
                 Some(format!("[{}]", rw.join(", ")))
             }
+            PatKind::Slice(ref slice_pat) => overflow::rewrite_with_square_brackets(
+                context,
+                "",
+                slice_pat.iter(),
+                shape,
+                self.span,
+                None,
+                None,
+            ),
             PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => {
                 rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape)
             }
diff --git a/tests/source/issue-4530.rs b/tests/source/issue-4530.rs
new file mode 100644
index 00000000000..9d2882abb3c
--- /dev/null
+++ b/tests/source/issue-4530.rs
@@ -0,0 +1,4 @@
+// rustfmt-version: Two
+fn main() {
+    let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] = panic!();
+}
diff --git a/tests/target/issue-4530.rs b/tests/target/issue-4530.rs
new file mode 100644
index 00000000000..296dc559a93
--- /dev/null
+++ b/tests/target/issue-4530.rs
@@ -0,0 +1,9 @@
+// rustfmt-version: Two
+fn main() {
+    let [
+        aaaaaaaaaaaaaaaaaaaaaaaaaa,
+        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
+        cccccccccccccccccccccccccc,
+        ddddddddddddddddddddddddd,
+    ] = panic!();
+}

From 40f4993c67ff54e413da17496769407ab85f3924 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Thu, 23 Sep 2021 22:43:03 -0400
Subject: [PATCH 063/195] Update derive attibute span to start after opening
 '('

Fixes 4984

When parsing derive attributes we're only concerned about the traits
and comments listed between the opening and closing parentheses.

Derive attribute spans currently start at the '#'.

    Span starts here
    |
    v
    #[derive(...)]

After this update the derive spans start after the opening '('.

    Span starts here
             |
             V
    #[derive(...)]
---
 src/attr.rs                                  |  5 +++-
 tests/source/issue-4984/minimum_example.rs   |  2 ++
 tests/source/issue-4984/multi_line_derive.rs | 20 +++++++++++++++
 tests/target/issue-4984/minimum_example.rs   |  2 ++
 tests/target/issue-4984/multi_line_derive.rs | 26 ++++++++++++++++++++
 5 files changed, 54 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue-4984/minimum_example.rs
 create mode 100644 tests/source/issue-4984/multi_line_derive.rs
 create mode 100644 tests/target/issue-4984/minimum_example.rs
 create mode 100644 tests/target/issue-4984/multi_line_derive.rs

diff --git a/src/attr.rs b/src/attr.rs
index 315eb10a9db..a5982820e3d 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -13,6 +13,7 @@ use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting,
 use crate::overflow;
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::Shape;
+use crate::source_map::SpanUtils;
 use crate::types::{rewrite_path, PathContext};
 use crate::utils::{count_newlines, mk_sp};
 
@@ -116,7 +117,9 @@ fn format_derive(
                 |span| span.lo(),
                 |span| span.hi(),
                 |span| Some(context.snippet(*span).to_owned()),
-                attr.span.lo(),
+                // We update derive attribute spans to start after the opening '('
+                // This helps us focus parsing to just what's inside #[derive(...)]
+                context.snippet_provider.span_after(attr.span, "("),
                 attr.span.hi(),
                 false,
             );
diff --git a/tests/source/issue-4984/minimum_example.rs b/tests/source/issue-4984/minimum_example.rs
new file mode 100644
index 00000000000..677f8737716
--- /dev/null
+++ b/tests/source/issue-4984/minimum_example.rs
@@ -0,0 +1,2 @@
+#[derive(/*Debug, */Clone)]
+struct Foo;
diff --git a/tests/source/issue-4984/multi_line_derive.rs b/tests/source/issue-4984/multi_line_derive.rs
new file mode 100644
index 00000000000..73921dd1735
--- /dev/null
+++ b/tests/source/issue-4984/multi_line_derive.rs
@@ -0,0 +1,20 @@
+#[derive(
+/* ---------- Some really important comment that just had to go inside the derive --------- */
+Debug, Clone, Eq, PartialEq,
+)]
+struct Foo {
+    a: i32,
+    b: T,
+}
+
+#[derive(
+/*
+    Some really important comment that just had to go inside the derive.
+    Also had to be put over multiple lines
+*/
+Debug, Clone, Eq, PartialEq,
+)]
+struct Bar {
+    a: i32,
+    b: T,
+}
diff --git a/tests/target/issue-4984/minimum_example.rs b/tests/target/issue-4984/minimum_example.rs
new file mode 100644
index 00000000000..f0599c5d694
--- /dev/null
+++ b/tests/target/issue-4984/minimum_example.rs
@@ -0,0 +1,2 @@
+#[derive(/*Debug, */ Clone)]
+struct Foo;
diff --git a/tests/target/issue-4984/multi_line_derive.rs b/tests/target/issue-4984/multi_line_derive.rs
new file mode 100644
index 00000000000..5fbd9784adc
--- /dev/null
+++ b/tests/target/issue-4984/multi_line_derive.rs
@@ -0,0 +1,26 @@
+#[derive(
+    /* ---------- Some really important comment that just had to go inside the derive --------- */
+    Debug,
+    Clone,
+    Eq,
+    PartialEq,
+)]
+struct Foo {
+    a: i32,
+    b: T,
+}
+
+#[derive(
+    /*
+        Some really important comment that just had to go inside the derive.
+        Also had to be put over multiple lines
+    */
+    Debug,
+    Clone,
+    Eq,
+    PartialEq,
+)]
+struct Bar {
+    a: i32,
+    b: T,
+}

From 365a2f8f6e710f67d6485fe9004bb3f64da977bc Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Wed, 29 Sep 2021 14:18:54 -0400
Subject: [PATCH 064/195] Add additional test cases for issue 4984

---
 tests/source/issue-4984/multiple_comments_within.rs |  8 ++++++++
 tests/target/issue-4984/multiple_comments_within.rs | 11 +++++++++++
 tests/target/issue-4984/should_not_change.rs        |  5 +++++
 3 files changed, 24 insertions(+)
 create mode 100644 tests/source/issue-4984/multiple_comments_within.rs
 create mode 100644 tests/target/issue-4984/multiple_comments_within.rs
 create mode 100644 tests/target/issue-4984/should_not_change.rs

diff --git a/tests/source/issue-4984/multiple_comments_within.rs b/tests/source/issue-4984/multiple_comments_within.rs
new file mode 100644
index 00000000000..eb474a723d0
--- /dev/null
+++ b/tests/source/issue-4984/multiple_comments_within.rs
@@ -0,0 +1,8 @@
+#[derive(
+/* ---------- Some really important comment that just had to go inside the derive --------- */
+Debug, Clone,/* Another comment */Eq, PartialEq,
+)]
+struct Foo {
+    a: i32,
+    b: T,
+}
diff --git a/tests/target/issue-4984/multiple_comments_within.rs b/tests/target/issue-4984/multiple_comments_within.rs
new file mode 100644
index 00000000000..d2924f0d0f2
--- /dev/null
+++ b/tests/target/issue-4984/multiple_comments_within.rs
@@ -0,0 +1,11 @@
+#[derive(
+    /* ---------- Some really important comment that just had to go inside the derive --------- */
+    Debug,
+    Clone,
+    /* Another comment */ Eq,
+    PartialEq,
+)]
+struct Foo {
+    a: i32,
+    b: T,
+}
diff --git a/tests/target/issue-4984/should_not_change.rs b/tests/target/issue-4984/should_not_change.rs
new file mode 100644
index 00000000000..e46ee511084
--- /dev/null
+++ b/tests/target/issue-4984/should_not_change.rs
@@ -0,0 +1,5 @@
+#[derive(Clone, Debug, Eq, PartialEq)]
+struct Foo;
+
+#[derive(Clone)]
+struct Bar;

From 8b58cce673d6ae4fbc1f3a8d28859bc100a72ed8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= <emilio@crisal.io>
Date: Sat, 16 May 2020 22:20:51 +0200
Subject: [PATCH 065/195] Stabilize match_block_trailing_comma. (#4145)

Servo has used this since forever, and it'd be useful to be able to use
rustfmt stable there so that we can use the same rustfmt version in
both Firefox and Servo.

Feel free to close this if there's any reason it shouldn't be done.
---
 Configurations.md | 2 +-
 src/config/mod.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index ff83f02f87b..06db897a42e 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1626,7 +1626,7 @@ Put a trailing comma after a block based match arm (non-block arms are not affec
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3380)
+- **Stable**: Yes
 
 #### `false` (default):
 
diff --git a/src/config/mod.rs b/src/config/mod.rs
index c6cee8ed227..398a1814d8d 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -127,7 +127,7 @@ create_config! {
         "Add trailing semicolon after break, continue and return";
     trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false,
         "How to handle trailing commas for lists";
-    match_block_trailing_comma: bool, false, false,
+    match_block_trailing_comma: bool, false, true,
         "Put a trailing comma after a block based match arm (non-block arms are not affected)";
     blank_lines_upper_bound: usize, 1, false,
         "Maximum number of blank lines which can be put between items";

From d41805704d4a07ac77e0bc59ea5c91cdb69dea26 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Mon, 11 Oct 2021 18:30:35 -0400
Subject: [PATCH 066/195] Prevent structs with ".." from being rewritten with
 alignment

 rustfmt should only support rewriting a struct in an expression
 position with alignment (non-default behavior) when there is no rest
 (with or without a base) and all of the fields are non-shorthand.
---
 src/expr.rs                                   | 11 ++--
 .../source/issue-4926/deeply_nested_struct.rs | 35 ++++++++++++
 ...ply_nested_struct_with_long_field_names.rs | 43 +++++++++++++++
 .../deeply_nested_struct_with_many_fields.rs  | 44 +++++++++++++++
 tests/source/issue-4926/enum_struct_field.rs  | 35 ++++++++++++
 tests/source/issue-4926/minimum_example.rs    | 10 ++++
 .../struct_with_long_field_names.rs           | 21 ++++++++
 .../issue-4926/struct_with_many_fields.rs     | 21 ++++++++
 .../target/issue-4926/deeply_nested_struct.rs | 38 +++++++++++++
 ...ply_nested_struct_with_long_field_names.rs | 44 +++++++++++++++
 .../deeply_nested_struct_with_many_fields.rs  | 54 +++++++++++++++++++
 tests/target/issue-4926/enum_struct_field.rs  | 41 ++++++++++++++
 tests/target/issue-4926/minimum_example.rs    | 10 ++++
 .../struct_with_long_field_names.rs           | 24 +++++++++
 .../issue-4926/struct_with_many_fields.rs     | 34 ++++++++++++
 15 files changed, 458 insertions(+), 7 deletions(-)
 create mode 100644 tests/source/issue-4926/deeply_nested_struct.rs
 create mode 100644 tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs
 create mode 100644 tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs
 create mode 100644 tests/source/issue-4926/enum_struct_field.rs
 create mode 100644 tests/source/issue-4926/minimum_example.rs
 create mode 100644 tests/source/issue-4926/struct_with_long_field_names.rs
 create mode 100644 tests/source/issue-4926/struct_with_many_fields.rs
 create mode 100644 tests/target/issue-4926/deeply_nested_struct.rs
 create mode 100644 tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs
 create mode 100644 tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs
 create mode 100644 tests/target/issue-4926/enum_struct_field.rs
 create mode 100644 tests/target/issue-4926/minimum_example.rs
 create mode 100644 tests/target/issue-4926/struct_with_long_field_names.rs
 create mode 100644 tests/target/issue-4926/struct_with_many_fields.rs

diff --git a/src/expr.rs b/src/expr.rs
index 01cc388c186..3a54426b0dd 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1528,12 +1528,12 @@ fn rewrite_struct_lit<'a>(
     let path_shape = shape.sub_width(2)?;
     let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;
 
-    let has_base = match struct_rest {
+    let has_base_or_rest = match struct_rest {
         ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
         ast::StructRest::Rest(_) if fields.is_empty() => {
             return Some(format!("{} {{ .. }}", path_str));
         }
-        ast::StructRest::Base(_) => true,
+        ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true,
         _ => false,
     };
 
@@ -1542,7 +1542,7 @@ fn rewrite_struct_lit<'a>(
 
     let one_line_width = h_shape.map_or(0, |shape| shape.width);
     let body_lo = context.snippet_provider.span_after(span, "{");
-    let fields_str = if struct_lit_can_be_aligned(fields, has_base)
+    let fields_str = if struct_lit_can_be_aligned(fields, has_base_or_rest)
         && context.config.struct_field_align_threshold() > 0
     {
         rewrite_with_alignment(
@@ -1614,10 +1614,7 @@ fn rewrite_struct_lit<'a>(
             nested_shape,
             tactic,
             context,
-            force_no_trailing_comma
-                || has_base
-                || !context.use_block_indent()
-                || matches!(struct_rest, ast::StructRest::Rest(_)),
+            force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(),
         );
 
         write_list(&item_vec, &fmt)?
diff --git a/tests/source/issue-4926/deeply_nested_struct.rs b/tests/source/issue-4926/deeply_nested_struct.rs
new file mode 100644
index 00000000000..e55e41bd1a5
--- /dev/null
+++ b/tests/source/issue-4926/deeply_nested_struct.rs
@@ -0,0 +1,35 @@
+
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X { a: 1_000, b: 1_000, .. }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
\ No newline at end of file
diff --git a/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs b/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs
new file mode 100644
index 00000000000..516699fa2b8
--- /dev/null
+++ b/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs
@@ -0,0 +1,43 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    really_really_long_field_a: i32,
+    really_really_really_long_field_b: i32,
+    really_really_really_really_long_field_c: i32,
+    really_really_really_really_really_long_field_d: i32,
+    really_really_really_really_really_really_long_field_e: i32,
+    f: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X {
+                                        really_really_long_field_a: 10,
+                                        really_really_really_long_field_b: 10,
+                                        really_really_really_really_long_field_c: 10,
+                                        really_really_really_really_really_long_field_d: 10,
+                                        really_really_really_really_really_really_long_field_e: 10, ..
+                                    }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
diff --git a/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs b/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs
new file mode 100644
index 00000000000..38fd6f02cf0
--- /dev/null
+++ b/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs
@@ -0,0 +1,44 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: i32,
+    j: i32,
+    k: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X {
+                                        a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, ..
+                                    }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
diff --git a/tests/source/issue-4926/enum_struct_field.rs b/tests/source/issue-4926/enum_struct_field.rs
new file mode 100644
index 00000000000..336378537df
--- /dev/null
+++ b/tests/source/issue-4926/enum_struct_field.rs
@@ -0,0 +1,35 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-enum_discrim_align_threshold: 30
+// rustfmt-imports_layout: HorizontalVertical
+
+#[derive(Default)]
+struct InnerStructA { bbbbbbbbb: i32, cccccccc: i32 }
+
+enum SomeEnumNamedD {
+    E(InnerStructA),
+    F {
+        ggggggggggggggggggggggggg: bool,
+        h: bool,
+    }
+}
+
+impl SomeEnumNamedD {
+    fn f_variant() -> Self {
+        Self::F { ggggggggggggggggggggggggg: true, h: true }
+    }
+}
+
+fn main() {
+    let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant();
+    let something_we_care_about = matches!(
+        kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk,
+        SomeEnumNamedD::F {
+            ggggggggggggggggggggggggg: true,
+            ..
+        }
+    );
+
+    if something_we_care_about {
+        println!("Yup it happened");
+    }
+}
diff --git a/tests/source/issue-4926/minimum_example.rs b/tests/source/issue-4926/minimum_example.rs
new file mode 100644
index 00000000000..2c3045dea48
--- /dev/null
+++ b/tests/source/issue-4926/minimum_example.rs
@@ -0,0 +1,10 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X { a: i32, b: i32 }
+
+fn test(x: X) {
+    let y = matches!(x, X {
+        a: 1,
+        ..
+    });
+}
diff --git a/tests/source/issue-4926/struct_with_long_field_names.rs b/tests/source/issue-4926/struct_with_long_field_names.rs
new file mode 100644
index 00000000000..b8a37f0714e
--- /dev/null
+++ b/tests/source/issue-4926/struct_with_long_field_names.rs
@@ -0,0 +1,21 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    really_really_long_field_a: i32,
+    really_really_really_long_field_b: i32,
+    really_really_really_really_long_field_c: i32,
+    really_really_really_really_really_long_field_d: i32,
+    really_really_really_really_really_really_long_field_e: i32,
+    f: i32,
+}
+
+fn test(x: X) {
+    let y = matches!(x, X {
+        really_really_long_field_a: 10,
+        really_really_really_long_field_b: 10,
+        really_really_really_really_long_field_c: 10,
+        really_really_really_really_really_long_field_d: 10,
+        really_really_really_really_really_really_long_field_e: 10,
+        ..
+    });
+}
diff --git a/tests/source/issue-4926/struct_with_many_fields.rs b/tests/source/issue-4926/struct_with_many_fields.rs
new file mode 100644
index 00000000000..4adfd3b3062
--- /dev/null
+++ b/tests/source/issue-4926/struct_with_many_fields.rs
@@ -0,0 +1,21 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: i32,
+    j: i32,
+    k: i32,
+}
+
+fn test(x: X) {
+    let y = matches!(x, X {
+        a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, ..
+    });
+}
\ No newline at end of file
diff --git a/tests/target/issue-4926/deeply_nested_struct.rs b/tests/target/issue-4926/deeply_nested_struct.rs
new file mode 100644
index 00000000000..072cf2f6674
--- /dev/null
+++ b/tests/target/issue-4926/deeply_nested_struct.rs
@@ -0,0 +1,38 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X {
+                                        a: 1_000,
+                                        b: 1_000,
+                                        ..
+                                    }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
diff --git a/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs b/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs
new file mode 100644
index 00000000000..c7bc7f7296d
--- /dev/null
+++ b/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs
@@ -0,0 +1,44 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    really_really_long_field_a: i32,
+    really_really_really_long_field_b: i32,
+    really_really_really_really_long_field_c: i32,
+    really_really_really_really_really_long_field_d: i32,
+    really_really_really_really_really_really_long_field_e: i32,
+    f: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X {
+                                        really_really_long_field_a: 10,
+                                        really_really_really_long_field_b: 10,
+                                        really_really_really_really_long_field_c: 10,
+                                        really_really_really_really_really_long_field_d: 10,
+                                        really_really_really_really_really_really_long_field_e: 10,
+                                        ..
+                                    }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
diff --git a/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs b/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs
new file mode 100644
index 00000000000..69793162519
--- /dev/null
+++ b/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs
@@ -0,0 +1,54 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: i32,
+    j: i32,
+    k: i32,
+}
+
+fn test(x: X) {
+    let d = {
+        let e = {
+            let f = {
+                let g = {
+                    let h = {
+                        let i = {
+                            let j = {
+                                matches!(
+                                    x,
+                                    X {
+                                        a: 1_000,
+                                        b: 1_000,
+                                        c: 1_000,
+                                        d: 1_000,
+                                        e: 1_000,
+                                        f: 1_000,
+                                        g: 1_000,
+                                        h: 1_000,
+                                        i: 1_000,
+                                        j: 1_000,
+                                        ..
+                                    }
+                                )
+                            };
+                            j
+                        };
+                        i
+                    };
+                    h
+                };
+                g
+            };
+            f
+        };
+        e
+    };
+}
diff --git a/tests/target/issue-4926/enum_struct_field.rs b/tests/target/issue-4926/enum_struct_field.rs
new file mode 100644
index 00000000000..2471df84653
--- /dev/null
+++ b/tests/target/issue-4926/enum_struct_field.rs
@@ -0,0 +1,41 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-enum_discrim_align_threshold: 30
+// rustfmt-imports_layout: HorizontalVertical
+
+#[derive(Default)]
+struct InnerStructA {
+    bbbbbbbbb: i32,
+    cccccccc:  i32,
+}
+
+enum SomeEnumNamedD {
+    E(InnerStructA),
+    F {
+        ggggggggggggggggggggggggg: bool,
+        h:                         bool,
+    },
+}
+
+impl SomeEnumNamedD {
+    fn f_variant() -> Self {
+        Self::F {
+            ggggggggggggggggggggggggg: true,
+            h:                         true,
+        }
+    }
+}
+
+fn main() {
+    let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant();
+    let something_we_care_about = matches!(
+        kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk,
+        SomeEnumNamedD::F {
+            ggggggggggggggggggggggggg: true,
+            ..
+        }
+    );
+
+    if something_we_care_about {
+        println!("Yup it happened");
+    }
+}
diff --git a/tests/target/issue-4926/minimum_example.rs b/tests/target/issue-4926/minimum_example.rs
new file mode 100644
index 00000000000..06e18427465
--- /dev/null
+++ b/tests/target/issue-4926/minimum_example.rs
@@ -0,0 +1,10 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+}
+
+fn test(x: X) {
+    let y = matches!(x, X { a: 1, .. });
+}
diff --git a/tests/target/issue-4926/struct_with_long_field_names.rs b/tests/target/issue-4926/struct_with_long_field_names.rs
new file mode 100644
index 00000000000..ac4674ab5d5
--- /dev/null
+++ b/tests/target/issue-4926/struct_with_long_field_names.rs
@@ -0,0 +1,24 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    really_really_long_field_a: i32,
+    really_really_really_long_field_b: i32,
+    really_really_really_really_long_field_c: i32,
+    really_really_really_really_really_long_field_d: i32,
+    really_really_really_really_really_really_long_field_e: i32,
+    f: i32,
+}
+
+fn test(x: X) {
+    let y = matches!(
+        x,
+        X {
+            really_really_long_field_a: 10,
+            really_really_really_long_field_b: 10,
+            really_really_really_really_long_field_c: 10,
+            really_really_really_really_really_long_field_d: 10,
+            really_really_really_really_really_really_long_field_e: 10,
+            ..
+        }
+    );
+}
diff --git a/tests/target/issue-4926/struct_with_many_fields.rs b/tests/target/issue-4926/struct_with_many_fields.rs
new file mode 100644
index 00000000000..96dfe14bf7d
--- /dev/null
+++ b/tests/target/issue-4926/struct_with_many_fields.rs
@@ -0,0 +1,34 @@
+// rustfmt-struct_field_align_threshold: 30
+
+struct X {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: i32,
+    j: i32,
+    k: i32,
+}
+
+fn test(x: X) {
+    let y = matches!(
+        x,
+        X {
+            a: 1_000,
+            b: 1_000,
+            c: 1_000,
+            d: 1_000,
+            e: 1_000,
+            f: 1_000,
+            g: 1_000,
+            h: 1_000,
+            i: 1_000,
+            j: 1_000,
+            ..
+        }
+    );
+}

From f7c4a44149b4e3a683f5506929050f2b50117328 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Tue, 5 Oct 2021 01:24:10 -0400
Subject: [PATCH 067/195] Adjust non-empty tuple struct span to start before
 fields

Resolves 5011

Tuple structs with visibility modifiers and comments before the first
field were incorrectly formatted. Comments would duplicate part of the
visibility modifier and struct name.

When trying to parse the tuple fields the ``items::Context`` searches
for the opening '(', but because the visibility modifier introduces
another '(' -- for example ``pub(crate)`` -- the parsing gets messed up.

Now the span is adjusted to start after the struct identifier, or after
any generics. Adjusting the span in this way ensures that the
``items::Contex`` will correctly find the tuple fields.
---
 src/items.rs               |  7 ++++++-
 tests/source/issue-5011.rs | 12 ++++++++++++
 tests/target/issue-5011.rs |  8 ++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue-5011.rs
 create mode 100644 tests/target/issue-5011.rs

diff --git a/src/items.rs b/src/items.rs
index e8eb1c5dfbb..471a365e470 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1469,12 +1469,17 @@ fn format_tuple_struct(
         format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")");
     } else {
         let shape = Shape::indented(offset, context.config).sub_width(1)?;
+        let lo = if let Some(generics) = struct_parts.generics {
+            generics.span.hi()
+        } else {
+            struct_parts.ident.span.hi()
+        };
         result = overflow::rewrite_with_parens(
             context,
             &result,
             fields.iter(),
             shape,
-            span,
+            mk_sp(lo, span.hi()),
             context.config.fn_call_width(),
             None,
         )?;
diff --git a/tests/source/issue-5011.rs b/tests/source/issue-5011.rs
new file mode 100644
index 00000000000..b48292164e4
--- /dev/null
+++ b/tests/source/issue-5011.rs
@@ -0,0 +1,12 @@
+pub(crate) struct ASlash(
+    // hello
+    i32
+);
+
+pub(crate) struct AStar(
+    /* hello */
+    i32
+);
+
+pub(crate) struct BStar(/* hello */ i32);
+
diff --git a/tests/target/issue-5011.rs b/tests/target/issue-5011.rs
new file mode 100644
index 00000000000..9ad4a1929bd
--- /dev/null
+++ b/tests/target/issue-5011.rs
@@ -0,0 +1,8 @@
+pub(crate) struct ASlash(
+    // hello
+    i32,
+);
+
+pub(crate) struct AStar(/* hello */ i32);
+
+pub(crate) struct BStar(/* hello */ i32);

From f2fb3c9659e072d7df6315906f1adbd06c3bc9e3 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Wed, 6 Oct 2021 13:09:24 -0400
Subject: [PATCH 068/195] Update connector search in
 ControlFlow::rewrite_pat_expr for for loops

Resolves 5009

For loops represented by a ControlFlow object use " in" as their connector.
rustfmt searches for the first uncommented occurrence of the word "in" within the
current span and adjusts it's starting point to look for comments right after that.
visually this looks like this:

    rustfmt starts looking for comments here
            |
            V
    for x in /* ... */ 0..1 {}

This works well in most cases, however when the pattern also contains
the word "in", this leads to issues.

    rustfmt starts looking for comments here
          |
          V
    for in_here in /* ... */ 0..1 {}
        -------
        pattern

In order to correctly identify the connector, the new approach first
updates the span to start after the pattern and then searches for the
first uncommented occurrence of "in".
---
 src/expr.rs                                   |  2 +-
 tests/target/issue-5009/1_minimum_example.rs  |  4 +++
 .../2_many_in_connectors_in_pattern.rs        |  3 ++
 ...sted_for_loop_with_connector_in_pattern.rs |  5 +++
 .../4_nested_for_loop_with_if_elseif_else.rs  | 13 ++++++++
 ...r_loop_with_connector_in_if_elseif_else.rs | 15 +++++++++
 ...sted_for_loop_with_connector_in_pattern.rs | 32 +++++++++++++++++++
 7 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 tests/target/issue-5009/1_minimum_example.rs
 create mode 100644 tests/target/issue-5009/2_many_in_connectors_in_pattern.rs
 create mode 100644 tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs
 create mode 100644 tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs
 create mode 100644 tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs
 create mode 100644 tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs

diff --git a/src/expr.rs b/src/expr.rs
index 3a54426b0dd..f40f80e4253 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -822,7 +822,7 @@ impl<'a> ControlFlow<'a> {
             let pat_string = pat.rewrite(context, pat_shape)?;
             let comments_lo = context
                 .snippet_provider
-                .span_after(self.span, self.connector.trim());
+                .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim());
             let comments_span = mk_sp(comments_lo, expr.span.lo());
             return rewrite_assign_rhs_with_comments(
                 context,
diff --git a/tests/target/issue-5009/1_minimum_example.rs b/tests/target/issue-5009/1_minimum_example.rs
new file mode 100644
index 00000000000..55836f4bf52
--- /dev/null
+++ b/tests/target/issue-5009/1_minimum_example.rs
@@ -0,0 +1,4 @@
+fn main() {
+    // the "in" inside the pattern produced invalid syntax
+    for variable_in_here /* ... */ in 0..1 {}
+}
diff --git a/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs b/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs
new file mode 100644
index 00000000000..d83590c6852
--- /dev/null
+++ b/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs
@@ -0,0 +1,3 @@
+fn main() {
+    for in_in_in_in_in_in_in_in /* ... */ in 0..1 {}
+}
diff --git a/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs b/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs
new file mode 100644
index 00000000000..9c800723939
--- /dev/null
+++ b/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs
@@ -0,0 +1,5 @@
+fn main() {
+    for variable_in_x /* ... */ in 0..1 {
+        for variable_in_y /* ... */ in 0..1 {}
+    }
+}
diff --git a/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs b/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs
new file mode 100644
index 00000000000..a716d0d3082
--- /dev/null
+++ b/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs
@@ -0,0 +1,13 @@
+fn main() {
+    for variable_in_x /* ... */ in 0..1 {
+        for variable_in_y /* ... */ in 0..1 {
+            if false {
+
+            } else if false {
+
+            } else {
+
+            }
+        }
+    }
+}
diff --git a/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs b/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs
new file mode 100644
index 00000000000..41ea46d4cb9
--- /dev/null
+++ b/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs
@@ -0,0 +1,15 @@
+fn main() {
+    let in_ = false;
+
+    for variable_in_x /* ... */ in 0..1 {
+        for variable_in_y /* ... */ in 0..1 {
+            if in_ {
+
+            } else if in_ {
+
+            } else {
+
+            }
+        }
+    }
+}
diff --git a/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs b/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs
new file mode 100644
index 00000000000..789e54f7e5f
--- /dev/null
+++ b/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs
@@ -0,0 +1,32 @@
+fn main() {
+    for variable_in_a /* ... */ in 0..1 {
+        for variable_in_b /* ... */ in 0..1 {
+            for variable_in_c /* ... */ in 0..1 {
+                for variable_in_d /* ... */ in 0..1 {
+                    for variable_in_e /* ... */ in 0..1 {
+                        for variable_in_f /* ... */ in 0..1 {
+                            for variable_in_g /* ... */ in 0..1 {
+                                for variable_in_h /* ... */ in 0..1 {
+                                    for variable_in_i /* ... */ in 0..1 {
+                                        for variable_in_j /* ... */ in 0..1 {
+                                            for variable_in_k /* ... */ in 0..1 {
+                                                for variable_in_l /* ... */ in 0..1 {
+                                                    for variable_in_m /* ... */ in 0..1 {
+                                                        for variable_in_n /* ... */ in 0..1 {
+                                                            for variable_in_o /* ... */ in 0..1 {
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

From c9c1932be3299b40eab63106deeb5d5ad2283b61 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 13 Oct 2021 21:22:34 -0500
Subject: [PATCH 069/195] feat: stabilize disable_all_formatting

---
 Configurations.md | 6 ++++--
 src/config/mod.rs | 2 +-
 src/test/mod.rs   | 5 -----
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 06db897a42e..7a77dbe154b 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -521,11 +521,13 @@ fn main() {
 
 ## `disable_all_formatting`
 
-Don't reformat anything
+Don't reformat anything.
+
+Note that this option may be soft-deprecated in the future once the [ignore](#ignore) option is stabilized. Nightly toolchain users are encouraged to use [ignore](#ignore) instead when possible.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3388)
+- **Stable**: Yes
 
 ## `edition`
 
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 398a1814d8d..c5419d860c9 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -155,7 +155,7 @@ create_config! {
         "Require a specific version of rustfmt";
     unstable_features: bool, false, false,
             "Enables unstable features. Only available on nightly channel";
-    disable_all_formatting: bool, false, false, "Don't reformat anything";
+    disable_all_formatting: bool, false, true, "Don't reformat anything";
     skip_children: bool, false, false, "Don't reformat out of line modules";
     hide_parse_errors: bool, false, false, "Hide errors from the parser";
     error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width";
diff --git a/src/test/mod.rs b/src/test/mod.rs
index ece1b91bfd7..48d61289a9b 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -469,11 +469,6 @@ fn stdin_works_with_modified_lines() {
 #[test]
 fn stdin_disable_all_formatting_test() {
     init_log();
-    match option_env!("CFG_RELEASE_CHANNEL") {
-        None | Some("nightly") => {}
-        // These tests require nightly.
-        _ => return,
-    }
     let input = String::from("fn main() { println!(\"This should not be formatted.\"); }");
     let mut child = Command::new(rustfmt().to_str().unwrap())
         .stdin(Stdio::piped())

From 0cff306b61922ed5f460a4f6cbd4134498a3c42f Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 13 Oct 2021 21:41:50 -0500
Subject: [PATCH 070/195] ci: fix release asset upload job

---
 .github/workflows/upload-assets.yml | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml
index 9a5fd0dd1d3..f4dd3944453 100644
--- a/.github/workflows/upload-assets.yml
+++ b/.github/workflows/upload-assets.yml
@@ -1,8 +1,10 @@
 name: upload
 
 on:
+  push:
   release:
     types: [created]
+  workflow_dispatch:
 
 jobs:
   build-release:
@@ -14,42 +16,40 @@ jobs:
           - build: linux-x86_64
             os: ubuntu-latest
             rust: nightly
+            target: x86_64-unknown-linux-gnu
           - build: macos-x86_64
             os: macos-latest
             rust: nightly
+            target: x86_64-apple-darwin
           - build: windows-x86_64-gnu
             os: windows-latest
             rust: nightly-x86_64-gnu
+            target: x86_64-pc-windows-gnu
           - build: windows-x86_64-msvc
             os: windows-latest
             rust: nightly-x86_64-msvc
+            target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v2
 
-      - name: Install Rust
-        uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: ${{ matrix.rust }}
-          override: true
+        # Run build
+      - 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 ${{ matrix.target }}
 
       - name: Add mingw64 to path for x86_64-gnu
         run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH
         if: matrix.rust == 'nightly-x86_64-gnu'
         shell: bash
 
-      - name: Install cargo-make
-        uses: actions-rs/cargo@v1
-        with:
-          command: install
-          args: --force cargo-make
-
       - name: Build release binaries
         uses: actions-rs/cargo@v1
         with:
-          command: make
-          args: release
+          command: build
+          args: --release
 
       - name: Build archive
         shell: bash
@@ -70,6 +70,7 @@ jobs:
           fi
 
       - name: Upload Release Asset
+        if: github.event_name == 'release'
         uses: actions/upload-release-asset@v1
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

From 5f4811ed7bc600e0cbe40c962e8933adb9baaddf Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Thu, 14 Oct 2021 17:16:28 -0400
Subject: [PATCH 071/195] Handle DefinitiveListTactic::SpecialMacro when
 writing pre-comments

Resolves 4615

Previously only Vertical and Mixed enum variants of DefinitiveListTactic
were considered when rewriting pre-comments for inner items in
lists::write_list.

Because we failed to considering the SpecialMacro variant we ended up in
a scenario where a ListItem with a pre_comment and a pre_comment_style
of ListItemCommentStyle::DifferentLine was written on the same line as the
list item itself.

Now we apply the same pre-comment formatting to SpecialMacro, Vertical,
and Mixed variants of DefinitiveListTactic.
---
 src/lists.rs                               | 46 +++++++++++-----------
 tests/source/issue-4615/minimum_example.rs |  4 ++
 tests/target/issue-4615/minimum_example.rs |  5 +++
 3 files changed, 33 insertions(+), 22 deletions(-)
 create mode 100644 tests/source/issue-4615/minimum_example.rs
 create mode 100644 tests/target/issue-4615/minimum_example.rs

diff --git a/src/lists.rs b/src/lists.rs
index 73e886c5563..f0c2ae1499f 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -367,29 +367,31 @@ where
             result.push_str(&comment);
 
             if !inner_item.is_empty() {
-                if tactic == DefinitiveListTactic::Vertical || tactic == DefinitiveListTactic::Mixed
-                {
-                    // We cannot keep pre-comments on the same line if the comment if normalized.
-                    let keep_comment = if formatting.config.normalize_comments()
-                        || item.pre_comment_style == ListItemCommentStyle::DifferentLine
-                    {
-                        false
-                    } else {
-                        // We will try to keep the comment on the same line with the item here.
-                        // 1 = ` `
-                        let total_width = total_item_width(item) + item_sep_len + 1;
-                        total_width <= formatting.shape.width
-                    };
-                    if keep_comment {
-                        result.push(' ');
-                    } else {
-                        result.push('\n');
-                        result.push_str(indent_str);
-                        // This is the width of the item (without comments).
-                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+                match tactic {
+                    DefinitiveListTactic::SpecialMacro(_)
+                    | DefinitiveListTactic::Vertical
+                    | DefinitiveListTactic::Mixed => {
+                        // We cannot keep pre-comments on the same line if the comment is normalized
+                        let keep_comment = if formatting.config.normalize_comments()
+                            || item.pre_comment_style == ListItemCommentStyle::DifferentLine
+                        {
+                            false
+                        } else {
+                            // We will try to keep the comment on the same line with the item here.
+                            // 1 = ` `
+                            let total_width = total_item_width(item) + item_sep_len + 1;
+                            total_width <= formatting.shape.width
+                        };
+                        if keep_comment {
+                            result.push(' ');
+                        } else {
+                            result.push('\n');
+                            result.push_str(indent_str);
+                            // This is the width of the item (without comments).
+                            line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+                        }
                     }
-                } else {
-                    result.push(' ');
+                    _ => result.push(' '),
                 }
             }
             item_max_width = None;
diff --git a/tests/source/issue-4615/minimum_example.rs b/tests/source/issue-4615/minimum_example.rs
new file mode 100644
index 00000000000..89af5d1239d
--- /dev/null
+++ b/tests/source/issue-4615/minimum_example.rs
@@ -0,0 +1,4 @@
+info!(//debug
+    "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}",
+    self.name, function_code, data, crc, output_cmd
+);
diff --git a/tests/target/issue-4615/minimum_example.rs b/tests/target/issue-4615/minimum_example.rs
new file mode 100644
index 00000000000..223b89b812d
--- /dev/null
+++ b/tests/target/issue-4615/minimum_example.rs
@@ -0,0 +1,5 @@
+info!(
+    //debug
+    "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}",
+    self.name, function_code, data, crc, output_cmd
+);

From 1ae5c35f8d2a0d2ce5d914a479839dc0f3eb70f9 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <ytmimi@horizonmedia.com>
Date: Mon, 18 Oct 2021 20:48:58 -0400
Subject: [PATCH 072/195] Replace match expression with match! macro

This is a follow up to 5f4811ed7bc600e0cbe40c962e8933adb9baaddf

The matches! macro expresses the condition more succinctly and avoids
the extra level of indentation introduced with the match arm body.
---
 src/lists.rs | 46 ++++++++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/src/lists.rs b/src/lists.rs
index f0c2ae1499f..c04b4787616 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -367,31 +367,29 @@ where
             result.push_str(&comment);
 
             if !inner_item.is_empty() {
-                match tactic {
-                    DefinitiveListTactic::SpecialMacro(_)
-                    | DefinitiveListTactic::Vertical
-                    | DefinitiveListTactic::Mixed => {
-                        // We cannot keep pre-comments on the same line if the comment is normalized
-                        let keep_comment = if formatting.config.normalize_comments()
-                            || item.pre_comment_style == ListItemCommentStyle::DifferentLine
-                        {
-                            false
-                        } else {
-                            // We will try to keep the comment on the same line with the item here.
-                            // 1 = ` `
-                            let total_width = total_item_width(item) + item_sep_len + 1;
-                            total_width <= formatting.shape.width
-                        };
-                        if keep_comment {
-                            result.push(' ');
-                        } else {
-                            result.push('\n');
-                            result.push_str(indent_str);
-                            // This is the width of the item (without comments).
-                            line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
-                        }
+                use DefinitiveListTactic::*;
+                if matches!(tactic, Vertical | Mixed | SpecialMacro(_)) {
+                    // We cannot keep pre-comments on the same line if the comment is normalized.
+                    let keep_comment = if formatting.config.normalize_comments()
+                        || item.pre_comment_style == ListItemCommentStyle::DifferentLine
+                    {
+                        false
+                    } else {
+                        // We will try to keep the comment on the same line with the item here.
+                        // 1 = ` `
+                        let total_width = total_item_width(item) + item_sep_len + 1;
+                        total_width <= formatting.shape.width
+                    };
+                    if keep_comment {
+                        result.push(' ');
+                    } else {
+                        result.push('\n');
+                        result.push_str(indent_str);
+                        // This is the width of the item (without comments).
+                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
                     }
-                    _ => result.push(' '),
+                } else {
+                    result.push(' ')
                 }
             }
             item_max_width = None;

From 5f79583c3c83aa3b8a832e4effacb9141de4c2aa Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Tue, 19 Oct 2021 23:13:06 -0500
Subject: [PATCH 073/195] chore: bump toolchain, fix conflict

---
 Cargo.lock     | 6 ------
 rust-toolchain | 2 +-
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8e4f9098965..7263f047477 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -118,12 +118,6 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
 [[package]]
 name = "clap"
 version = "2.33.0"
diff --git a/rust-toolchain b/rust-toolchain
index b0cd4464df8..b19ecbdb07c 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-07-23"
+channel = "nightly-2021-10-20"
 components = ["rustc-dev"]

From efa8f5521d3813cc897ba29ea0ef98c7aef66bb6 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 20 Oct 2021 00:00:30 -0500
Subject: [PATCH 074/195] chore: bump version and changelog

---
 CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 Cargo.lock   |  2 +-
 Cargo.toml   |  2 +-
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 68354b6ceaf..b59438dc4fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,73 @@
 
 ## [Unreleased]
 
+## [1.4.38] 2021-10-20
+
+### Changed
+
+- Switched from `rustc-ap-*` crates to `rustc_private` for consumption model of rustc internals
+- `annotate-snippets` updated to v0.8 [PR #4762](https://github.com/rust-lang/rustfmt/pull/4762)
+- Greatly improved the performance of `cargo fmt` in large workspaces utilizing the `--all` flag by updating to a newer version of `cargo_metadata` that leverages updated `cargo` output from v1.51+ [PR #4997](https://github.com/rust-lang/rustfmt/pull/4997)
+- Improved formatting of long slice patterns [#4530](https://github.com/rust-lang/rustfmt/issues/4530)
+  - **Note you must have `version = Two` in your configuration to take advantage of the new formatting**
+- Stabilized `match_block_trailing_comma` configuration option [#3380](https://github.com/rust-lang/rustfmt/issues/3380) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma)
+- Stabilized `disable_all_formatting` configuration option [#5026](https://github.com/rust-lang/rustfmt/pull/5026) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting)
+- Various improvements to the configuration documentation website [https://rust-lang.github.io/rustfmt/?version=v1.4.38]([https://rust-lang.github.io/rustfmt/?version=v1.4.38])
+- Addressed various clippy and rustc warnings
+
+
+### Fixed
+
+- Resolved issue where specious whitespace would be inserted when a block style comment was terminated within string literal processing [#4312](https://github.com/rust-lang/rustfmt/issues/4312)
+- Nested out-of-line mods are again parsed and formatted [#4874](https://github.com/rust-lang/rustfmt/issues/4874)
+- Accepts `2021` for edition value from rustfmt command line [PR #4847](https://github.com/rust-lang/rustfmt/pull/4847)
+- Unstable command line options are no longer displayed in `--help` text on stable [PR #4798](https://github.com/rust-lang/rustfmt/issues/4798)
+- Stopped panicking on patterns in match arms which start with non-ascii characters [#4868](https://github.com/rust-lang/rustfmt/issues/4868)
+- Stopped stripping defaults on const params [#4816](https://github.com/rust-lang/rustfmt/issues/4816)
+- Fixed issue with dropped content with GAT aliases with self bounds in impls [#4911](https://github.com/rust-lang/rustfmt/issues/4911)
+- Stopped removing generic args on associated type constraints [#4943](https://github.com/rust-lang/rustfmt/issues/4943)
+- Stopped dropping visibility on certain trait and impl items [#4960](https://github.com/rust-lang/rustfmt/issues/4960)
+- Fixed dropping of qualified paths in struct patterns [#4908](https://github.com/rust-lang/rustfmt/issues/4908) and [#5005](https://github.com/rust-lang/rustfmt/issues/5005)
+- Fixed bug in line width calculation that was causing specious formatting of certain patterns [#4031](https://github.com/rust-lang/rustfmt/issues/4031)
+  - **Note that this bug fix may cause observable formatting changes in cases where code had been formatted with prior versions of rustfmt that contained the bug**
+- Fixed bug where rustfmt would drop parameter attributes if they were too long in certain cases [#4579](https://github.com/rust-lang/rustfmt/issues/4579)
+- Resolved idempotency issue with extern body elements [#4963](https://github.com/rust-lang/rustfmt/issues/4963)
+- rustfmt will now handle doc-style comments on function parameters, since they could appear with certain macro usage patterns even though it's generally invalid syntax [#4936](https://github.com/rust-lang/rustfmt/issues/4936)
+- Fixed bug in `match_block_trailing_comma` where commas were not added to the blocks of bodies whose arm had a guard that did not fit on the same line as the pattern [#4998](https://github.com/rust-lang/rustfmt/pull/4998)
+- Fixed bug in cases where derive attributes started with a block style comment [#4984](https://github.com/rust-lang/rustfmt/issues/4984)
+- Fixed issue where the struct rest could be lost when `struct_field_align_threshold` was enabled [#4926](https://github.com/rust-lang/rustfmt/issues/4926)
+- Handles cases where certain control flow type expressions have comments between patterns/keywords and the pattern ident contains the keyword [#5009](https://github.com/rust-lang/rustfmt/issues/5009)
+- Handles tuple structs that have explicit visibilities and start with a block style comment [#5011](https://github.com/rust-lang/rustfmt/issues/5011)
+- Handles leading line-style comments in certain types of macro calls [#4615](https://github.com/rust-lang/rustfmt/issues/4615)
+
+
+### Added
+- Granular width heuristic options made available for user control [PR #4782](https://github.com/rust-lang/rustfmt/pull/4782). This includes the following:
+  - [`array_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#array_width)
+  - [`attr_fn_like_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#attr_fn_like_width)
+  - [`chain_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#chain_width)
+  - [`fn_call_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#fn_call_width)
+  - [`single_line_if_else_max_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#single_line_if_else_max_width)
+  - [`struct_lit_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_lit_width)
+  - [`struct_variant_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_variant_width)
+
+Note this hit the rustup distributions prior to the v1.4.38 release as part of an out-of-cycle updates, but is listed in this version because the feature was not in the other v1.4.37 releases. See also the `use_small_heuristics` section on the configuration site for more information
+[https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics)
+
+- New `One` variant added to `imports_granularity` configuration option which can be used to reformat all imports into a single use statement [#4669](https://github.com/rust-lang/rustfmt/issues/4669)
+- rustfmt will now skip files that are annotated with `@generated` at the top of the file [#3958](https://github.com/rust-lang/rustfmt/issues/3958)
+- New configuration option `hex_literal_case` that allows user to control the casing utilized for hex literals [PR #4903](https://github.com/rust-lang/rustfmt/pull/4903)
+
+See the section on the configuration site for more information
+https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#hex_literal_case
+
+- `cargo fmt` now directly supports the `--check` flag, which means it's now possible to run `cargo fmt --check` instead of the more verbose `cargo fmt -- --check` [#3888](https://github.com/rust-lang/rustfmt/issues/3888)
+
+### Install/Download Options
+- **rustup (nightly)** - *pending*
+- **GitHub Release Binaries** - [Release v1.4.38](https://github.com/rust-lang/rustfmt/releases/tag/v1.4.38)
+- **Build from source** - [Tag v1.4.38](https://github.com/rust-lang/rustfmt/tree/v1.4.38), see instructions for how to [install rustfmt from source][install-from-source]
+
 ## [1.4.37] 2021-04-03
 
 ### Changed
diff --git a/Cargo.lock b/Cargo.lock
index 7263f047477..2ef83ddd1ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -429,7 +429,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.37"
+version = "1.4.38"
 dependencies = [
  "annotate-snippets",
  "anyhow",
diff --git a/Cargo.toml b/Cargo.toml
index d282766e00b..8d9c4a7fb20 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "rustfmt-nightly"
-version = "1.4.37"
+version = "1.4.38"
 description = "Tool to find and fix Rust formatting issues"
 repository = "https://github.com/rust-lang/rustfmt"
 readme = "README.md"

From 599b2fd9c47f913c6c3540b4805528d8bacd3d7e Mon Sep 17 00:00:00 2001
From: Martinez <Heliozoa@users.noreply.github.com>
Date: Sat, 23 Oct 2021 19:01:48 +0300
Subject: [PATCH 075/195] Add One option to group_imports (#4966)

* Add Together option to group_imports

* Rename option to One

* Rename files from Together to One
---
 Configurations.md                             | 19 ++++++++++++++++++-
 src/config/options.rs                         |  2 ++
 src/reorder.rs                                |  4 +++-
 .../group_imports/One-merge_imports.rs        | 17 +++++++++++++++++
 .../configs/group_imports/One-nested.rs       |  7 +++++++
 .../configs/group_imports/One-no_reorder.rs   | 16 ++++++++++++++++
 tests/source/configs/group_imports/One.rs     | 15 +++++++++++++++
 .../group_imports/One-merge_imports.rs        | 14 ++++++++++++++
 .../configs/group_imports/One-nested.rs       |  6 ++++++
 .../configs/group_imports/One-no_reorder.rs   | 12 ++++++++++++
 tests/target/configs/group_imports/One.rs     | 11 +++++++++++
 11 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 tests/source/configs/group_imports/One-merge_imports.rs
 create mode 100644 tests/source/configs/group_imports/One-nested.rs
 create mode 100644 tests/source/configs/group_imports/One-no_reorder.rs
 create mode 100644 tests/source/configs/group_imports/One.rs
 create mode 100644 tests/target/configs/group_imports/One-merge_imports.rs
 create mode 100644 tests/target/configs/group_imports/One-nested.rs
 create mode 100644 tests/target/configs/group_imports/One-no_reorder.rs
 create mode 100644 tests/target/configs/group_imports/One.rs

diff --git a/Configurations.md b/Configurations.md
index 7a77dbe154b..13826883d2f 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2062,7 +2062,7 @@ use sit;
 Controls the strategy for how imports are grouped together.
 
 - **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `StdExternalCrate`
+- **Possible values**: `Preserve`, `StdExternalCrate`, `One`
 - **Stable**: No
 
 #### `Preserve` (default):
@@ -2108,6 +2108,23 @@ use super::update::convert_publish_payload;
 use crate::models::Event;
 ```
 
+#### `One`:
+
+Discard existing import groups, and create a single group for everything
+
+```rust
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
+```
+
 ## `reorder_modules`
 
 Reorder `mod` declarations alphabetically in group.
diff --git a/src/config/options.rs b/src/config/options.rs
index e92f8e8a531..a17d48349c0 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -112,6 +112,8 @@ pub enum GroupImportsTactic {
     ///  2. other imports
     ///  3. `self` / `crate` / `super` imports
     StdExternalCrate,
+    /// Discard existing groups, and create a single group for everything
+    One,
 }
 
 #[config_type]
diff --git a/src/reorder.rs b/src/reorder.rs
index 2c58350d4fe..0732c8ee700 100644
--- a/src/reorder.rs
+++ b/src/reorder.rs
@@ -118,7 +118,9 @@ fn rewrite_reorderable_or_regroupable_items(
             };
 
             let mut regrouped_items = match context.config.group_imports() {
-                GroupImportsTactic::Preserve => vec![normalized_items],
+                GroupImportsTactic::Preserve | GroupImportsTactic::One => {
+                    vec![normalized_items]
+                }
                 GroupImportsTactic::StdExternalCrate => group_imports(normalized_items),
             };
 
diff --git a/tests/source/configs/group_imports/One-merge_imports.rs b/tests/source/configs/group_imports/One-merge_imports.rs
new file mode 100644
index 00000000000..157d3857908
--- /dev/null
+++ b/tests/source/configs/group_imports/One-merge_imports.rs
@@ -0,0 +1,17 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+use alloc::vec::Vec;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/tests/source/configs/group_imports/One-nested.rs b/tests/source/configs/group_imports/One-nested.rs
new file mode 100644
index 00000000000..109bd07e1ee
--- /dev/null
+++ b/tests/source/configs/group_imports/One-nested.rs
@@ -0,0 +1,7 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+
+    use std::path;
+    use crate::foo::bar2;
+}
diff --git a/tests/source/configs/group_imports/One-no_reorder.rs b/tests/source/configs/group_imports/One-no_reorder.rs
new file mode 100644
index 00000000000..f82f62c7f5b
--- /dev/null
+++ b/tests/source/configs/group_imports/One-no_reorder.rs
@@ -0,0 +1,16 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/tests/source/configs/group_imports/One.rs b/tests/source/configs/group_imports/One.rs
new file mode 100644
index 00000000000..5ab7a950805
--- /dev/null
+++ b/tests/source/configs/group_imports/One.rs
@@ -0,0 +1,15 @@
+// rustfmt-group_imports: One
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/tests/target/configs/group_imports/One-merge_imports.rs b/tests/target/configs/group_imports/One-merge_imports.rs
new file mode 100644
index 00000000000..52e0e1c5ac2
--- /dev/null
+++ b/tests/target/configs/group_imports/One-merge_imports.rs
@@ -0,0 +1,14 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use super::{
+    schema::{Context, Payload},
+    update::convert_publish_payload,
+};
+use crate::models::Event;
+use alloc::{alloc::Layout, vec::Vec};
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
diff --git a/tests/target/configs/group_imports/One-nested.rs b/tests/target/configs/group_imports/One-nested.rs
new file mode 100644
index 00000000000..5b648548260
--- /dev/null
+++ b/tests/target/configs/group_imports/One-nested.rs
@@ -0,0 +1,6 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+    use crate::foo::bar2;
+    use std::path;
+}
diff --git a/tests/target/configs/group_imports/One-no_reorder.rs b/tests/target/configs/group_imports/One-no_reorder.rs
new file mode 100644
index 00000000000..015e841d014
--- /dev/null
+++ b/tests/target/configs/group_imports/One-no_reorder.rs
@@ -0,0 +1,12 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+use std::sync::Arc;
+use broker::database::PooledConnection;
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/tests/target/configs/group_imports/One.rs b/tests/target/configs/group_imports/One.rs
new file mode 100644
index 00000000000..3094c7ae115
--- /dev/null
+++ b/tests/target/configs/group_imports/One.rs
@@ -0,0 +1,11 @@
+// rustfmt-group_imports: One
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;

From d454e8106024fcb517d8fc20d4bdd2c54229695a Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sat, 23 Oct 2021 17:18:47 -0400
Subject: [PATCH 076/195] Add rustdoc CI check

Resolves 5038

rust-lang/rust builds now document rustfmt (rust-lang/rust#87119). The
build process is updated with doc checks to ensure that rustfmt doesn't
introduce warnings.

Warnings are treated as hard errors in rust-lang/rust and won't show
until bors tests the changes (refs rust-lang/rust#90087).
---
 .github/workflows/rustdoc_check.yml | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 .github/workflows/rustdoc_check.yml

diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml
new file mode 100644
index 00000000000..ca96d30f586
--- /dev/null
+++ b/.github/workflows/rustdoc_check.yml
@@ -0,0 +1,25 @@
+name: rustdoc check
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+
+jobs:
+  rustdoc_check:
+    runs-on: ubuntu-latest
+    name: rustdoc check
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+
+    - 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: document rustfmt
+      env:
+        RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings
+      run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro

From c493ee4828ab8e94ed175ec781afe7351bf89784 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sat, 23 Oct 2021 23:07:57 +0200
Subject: [PATCH 077/195] fix clippy::needless_borrow

---
 src/attr.rs               |  4 ++--
 src/attr/doc_comment.rs   |  2 +-
 src/cargo-fmt/main.rs     |  6 +++---
 src/chains.rs             |  4 ++--
 src/comment.rs            | 14 +++++++-------
 src/emitter/checkstyle.rs |  4 ++--
 src/emitter/diff.rs       |  2 +-
 src/expr.rs               | 12 ++++++------
 src/formatting.rs         |  4 ++--
 src/imports.rs            |  4 ++--
 src/items.rs              | 30 +++++++++++++++---------------
 src/lib.rs                |  4 ++--
 src/lists.rs              |  4 ++--
 src/macros.rs             | 16 ++++++++--------
 src/matches.rs            | 10 +++++-----
 src/modules.rs            |  4 ++--
 src/overflow.rs           |  2 +-
 src/pairs.rs              | 16 ++++++++--------
 src/patterns.rs           |  2 +-
 src/syntux/parser.rs      |  2 +-
 src/syntux/session.rs     |  2 +-
 src/test/mod.rs           |  4 ++--
 src/types.rs              |  4 ++--
 src/utils.rs              |  6 +++---
 src/visitor.rs            | 20 ++++++++++----------
 25 files changed, 91 insertions(+), 91 deletions(-)

diff --git a/src/attr.rs b/src/attr.rs
index a5982820e3d..76b66e9da80 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -451,7 +451,7 @@ impl Rewrite for [ast::Attribute] {
                         if next.is_doc_comment() {
                             let snippet = context.snippet(missing_span);
                             let (_, mlb) = has_newlines_before_after_comment(snippet);
-                            result.push_str(&mlb);
+                            result.push_str(mlb);
                         }
                     }
                     result.push('\n');
@@ -484,7 +484,7 @@ impl Rewrite for [ast::Attribute] {
                     if next.is_doc_comment() {
                         let snippet = context.snippet(missing_span);
                         let (_, mlb) = has_newlines_before_after_comment(snippet);
-                        result.push_str(&mlb);
+                        result.push_str(mlb);
                     }
                 }
                 result.push('\n');
diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs
index c3dcb84c948..f653a12a8af 100644
--- a/src/attr/doc_comment.rs
+++ b/src/attr/doc_comment.rs
@@ -77,7 +77,7 @@ mod tests {
     ) {
         assert_eq!(
             expected_comment,
-            format!("{}", DocCommentFormatter::new(&literal, style))
+            format!("{}", DocCommentFormatter::new(literal, style))
         );
     }
 }
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 1d423ac3491..759b21218c3 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -401,12 +401,12 @@ fn get_targets_root_only(
 
 fn get_targets_recursive(
     manifest_path: Option<&Path>,
-    mut targets: &mut BTreeSet<Target>,
+    targets: &mut BTreeSet<Target>,
     visited: &mut BTreeSet<String>,
 ) -> Result<(), io::Error> {
     let metadata = get_cargo_metadata(manifest_path)?;
     for package in &metadata.packages {
-        add_targets(&package.targets, &mut targets);
+        add_targets(&package.targets, targets);
 
         // Look for local dependencies using information available since cargo v1.51
         // It's theoretically possible someone could use a newer version of rustfmt with
@@ -427,7 +427,7 @@ fn get_targets_recursive(
                     .any(|p| p.manifest_path.eq(&manifest_path))
             {
                 visited.insert(dependency.name.to_owned());
-                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
+                get_targets_recursive(Some(&manifest_path), targets, visited)?;
             }
         }
     }
diff --git a/src/chains.rs b/src/chains.rs
index 614638ea2ab..e26e24ec55a 100644
--- a/src/chains.rs
+++ b/src/chains.rs
@@ -568,7 +568,7 @@ impl<'a> ChainFormatterShared<'a> {
         } else {
             self.rewrites
                 .iter()
-                .map(|rw| utils::unicode_str_width(&rw))
+                .map(|rw| utils::unicode_str_width(rw))
                 .sum()
         } + last.tries;
         let one_line_budget = if self.child_count == 1 {
@@ -673,7 +673,7 @@ impl<'a> ChainFormatterShared<'a> {
                 ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector),
                 _ => result.push_str(&connector),
             }
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
         }
 
         Some(result)
diff --git a/src/comment.rs b/src/comment.rs
index dc4f4516252..a3cd0359e6b 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -563,7 +563,7 @@ impl<'a> CommentRewrite<'a> {
             result.push_str(line);
             result.push_str(match iter.peek() {
                 Some(next_line) if next_line.is_empty() => sep.trim_end(),
-                Some(..) => &sep,
+                Some(..) => sep,
                 None => "",
             });
         }
@@ -622,7 +622,7 @@ impl<'a> CommentRewrite<'a> {
         let is_last = i == count_newlines(orig);
 
         if let Some(ref mut ib) = self.item_block {
-            if ib.add_line(&line) {
+            if ib.add_line(line) {
                 return false;
             }
             self.is_prev_line_multi_line = false;
@@ -684,8 +684,8 @@ impl<'a> CommentRewrite<'a> {
         self.item_block = None;
         if let Some(stripped) = line.strip_prefix("```") {
             self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
-        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) {
-            let ib = ItemizedBlock::new(&line);
+        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) {
+            let ib = ItemizedBlock::new(line);
             self.item_block = Some(ib);
             return false;
         }
@@ -941,7 +941,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
     {
         (&line[4..], true)
     } else if let CommentStyle::Custom(opener) = *style {
-        if let Some(ref stripped) = line.strip_prefix(opener) {
+        if let Some(stripped) = line.strip_prefix(opener) {
             (stripped, true)
         } else {
             (&line[opener.trim_end().len()..], false)
@@ -1570,7 +1570,7 @@ pub(crate) fn recover_comment_removed(
                 context.parse_sess.span_to_filename(span),
                 vec![FormattingError::from_span(
                     span,
-                    &context.parse_sess,
+                    context.parse_sess,
                     ErrorKind::LostComment,
                 )],
             );
@@ -1675,7 +1675,7 @@ impl<'a> Iterator for CommentReducer<'a> {
 fn remove_comment_header(comment: &str) -> &str {
     if comment.starts_with("///") || comment.starts_with("//!") {
         &comment[3..]
-    } else if let Some(ref stripped) = comment.strip_prefix("//") {
+    } else if let Some(stripped) = comment.strip_prefix("//") {
         stripped
     } else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
         || comment.starts_with("/*!")
diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs
index 4448214f3ff..76f2527db3d 100644
--- a/src/emitter/checkstyle.rs
+++ b/src/emitter/checkstyle.rs
@@ -121,7 +121,7 @@ mod tests {
             format!(r#"<file name="{}">"#, bin_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Hello, world!");"#),
+                XmlEscaped(r#"    println!("Hello, world!");"#),
             ),
             String::from("</file>"),
         ];
@@ -129,7 +129,7 @@ mod tests {
             format!(r#"<file name="{}">"#, lib_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Greetings!");"#),
+                XmlEscaped(r#"    println!("Greetings!");"#),
             ),
             String::from("</file>"),
         ];
diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs
index 2fbbfedb566..7264ad8bbf3 100644
--- a/src/emitter/diff.rs
+++ b/src/emitter/diff.rs
@@ -23,7 +23,7 @@ impl Emitter for DiffEmitter {
         }: FormattedFile<'_>,
     ) -> Result<EmitterResult, io::Error> {
         const CONTEXT_SIZE: usize = 3;
-        let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE);
+        let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
         let has_diff = !mismatch.is_empty();
 
         if has_diff {
diff --git a/src/expr.rs b/src/expr.rs
index 7f1dd363f93..c67c14b1985 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -257,7 +257,7 @@ pub(crate) fn format_expr(
                         }
                         _ => false,
                     },
-                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr),
+                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
                     _ => false,
                 }
             }
@@ -423,7 +423,7 @@ fn rewrite_empty_block(
     prefix: &str,
     shape: Shape,
 ) -> Option<String> {
-    if block_has_statements(&block) {
+    if block_has_statements(block) {
         return None;
     }
 
@@ -1148,7 +1148,7 @@ pub(crate) fn is_empty_block(
     block: &ast::Block,
     attrs: Option<&[ast::Attribute]>,
 ) -> bool {
-    !block_has_statements(&block)
+    !block_has_statements(block)
         && !block_contains_comment(context, block)
         && attrs.map_or(true, |a| inner_attributes(a).is_empty())
 }
@@ -1621,7 +1621,7 @@ fn rewrite_struct_lit<'a>(
     };
 
     let fields_str =
-        wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?;
+        wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
     Some(format!("{} {{{}}}", path_str, fields_str))
 
     // FIXME if context.config.indent_style() == Visual, but we run out
@@ -1888,7 +1888,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     shape: Shape,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
-    let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') {
+    let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
         shape.indent.width()
     } else {
         0
@@ -1947,7 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
 
     if contains_comment {
         let rhs = rhs.trim_start();
-        combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend)
+        combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
     } else {
         Some(lhs + &rhs)
     }
diff --git a/src/formatting.rs b/src/formatting.rs
index 9ef47b887ca..7d0facb8f12 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -155,7 +155,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
         let snippet_provider = self.parse_session.snippet_provider(module.span);
         let mut visitor = FmtVisitor::from_parse_sess(
             &self.parse_session,
-            &self.config,
+            self.config,
             &snippet_provider,
             self.report.clone(),
         );
@@ -180,7 +180,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
             &mut visitor.buffer,
             &path,
             &visitor.skipped_range.borrow(),
-            &self.config,
+            self.config,
             &self.report,
         );
 
diff --git a/src/imports.rs b/src/imports.rs
index 5ac79936689..40e0d06f99d 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -275,7 +275,7 @@ impl UseTree {
         shape: Shape,
     ) -> Option<String> {
         let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
-            crate::utils::format_visibility(context, &vis)
+            crate::utils::format_visibility(context, vis)
         });
         let use_str = self
             .rewrite(context, shape.offset_left(vis.len())?)
@@ -929,7 +929,7 @@ impl Rewrite for UseTree {
     fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
         let mut result = String::with_capacity(256);
         let mut iter = self.path.iter().peekable();
-        while let Some(ref segment) = iter.next() {
+        while let Some(segment) = iter.next() {
             let segment_str = segment.rewrite(context, shape)?;
             result.push_str(&segment_str);
             if iter.peek().is_some() {
diff --git a/src/items.rs b/src/items.rs
index 1cb1a2701c3..1c7899b3ac3 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -226,7 +226,7 @@ impl<'a> FnSig<'a> {
     fn to_str(&self, context: &RewriteContext<'_>) -> String {
         let mut result = String::with_capacity(128);
         // Vis defaultness constness unsafety abi.
-        result.push_str(&*format_visibility(context, &self.visibility));
+        result.push_str(&*format_visibility(context, self.visibility));
         result.push_str(format_defaultness(self.defaultness));
         result.push_str(format_constness(self.constness));
         result.push_str(format_async(&self.is_async));
@@ -1220,7 +1220,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
         } else if fits_single_line {
             Cow::from(" ")
         } else {
-            shape.indent.to_string_with_newline(&context.config)
+            shape.indent.to_string_with_newline(context.config)
         };
 
         Some(format!("{}{}{}", generic_bounds_str, space, where_str))
@@ -1238,7 +1238,7 @@ pub(crate) fn format_trait_alias(
     let alias = rewrite_ident(context, ident);
     // 6 = "trait ", 2 = " ="
     let g_shape = shape.offset_left(6)?.sub_width(2)?;
-    let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
+    let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
     let vis_str = format_visibility(context, vis);
     let lhs = format!("{}trait {} =", vis_str, generics_str);
     // 1 = ";"
@@ -1386,7 +1386,7 @@ fn format_empty_struct_or_tuple(
     closer: &str,
 ) {
     // 3 = " {}" or "();"
-    let used_width = last_line_used_width(&result, offset.width()) + 3;
+    let used_width = last_line_used_width(result, offset.width()) + 3;
     if used_width > context.config.max_width() {
         result.push_str(&offset.to_string_with_newline(context.config))
     }
@@ -2066,7 +2066,7 @@ fn rewrite_explicit_self(
                     )?;
                     Some(combine_strs_with_missing_comments(
                         context,
-                        &param_attrs,
+                        param_attrs,
                         &format!("&{} {}self", lifetime_str, mut_str),
                         span,
                         shape,
@@ -2075,7 +2075,7 @@ fn rewrite_explicit_self(
                 }
                 None => Some(combine_strs_with_missing_comments(
                     context,
-                    &param_attrs,
+                    param_attrs,
                     &format!("&{}self", mut_str),
                     span,
                     shape,
@@ -2091,7 +2091,7 @@ fn rewrite_explicit_self(
 
             Some(combine_strs_with_missing_comments(
                 context,
-                &param_attrs,
+                param_attrs,
                 &format!("{}self: {}", format_mutability(mutability), type_str),
                 span,
                 shape,
@@ -2100,7 +2100,7 @@ fn rewrite_explicit_self(
         }
         ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
             context,
-            &param_attrs,
+            param_attrs,
             &format!("{}self", format_mutability(mutability)),
             span,
             shape,
@@ -2226,7 +2226,7 @@ fn rewrite_fn_base(
     }
 
     // Skip `pub(crate)`.
-    let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
+    let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
     // A conservative estimation, the goal is to be over all parens in generics
     let params_start = fn_sig
         .generics
@@ -2984,7 +2984,7 @@ fn format_header(
     let mut result = String::with_capacity(128);
     let shape = Shape::indented(offset, context.config);
 
-    result.push_str(&format_visibility(context, vis).trim());
+    result.push_str(format_visibility(context, vis).trim());
 
     // Check for a missing comment between the visibility and the item name.
     let after_vis = vis.span.hi();
@@ -3005,7 +3005,7 @@ fn format_header(
         }
     }
 
-    result.push_str(&rewrite_ident(context, ident));
+    result.push_str(rewrite_ident(context, ident));
 
     result
 }
@@ -3133,7 +3133,7 @@ impl Rewrite for ast::ForeignItem {
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, self.ident, fn_sig, &self.vis, Some(body)),
                         generics,
                         &fn_sig.decl,
                         self.span,
@@ -3146,7 +3146,7 @@ impl Rewrite for ast::ForeignItem {
                         context,
                         shape.indent,
                         self.ident,
-                        &FnSig::from_method_sig(&fn_sig, generics, &self.vis),
+                        &FnSig::from_method_sig(fn_sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
                     )
@@ -3171,7 +3171,7 @@ impl Rewrite for ast::ForeignItem {
                 let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
                     **ty_alias_kind;
                 rewrite_type(
-                    &context,
+                    context,
                     shape.indent,
                     self.ident,
                     &self.vis,
@@ -3229,7 +3229,7 @@ fn rewrite_attrs(
     combine_strs_with_missing_comments(
         context,
         &attrs_str,
-        &item_str,
+        item_str,
         missed_span,
         shape,
         allow_extend,
diff --git a/src/lib.rs b/src/lib.rs
index 47a7b9d4dbe..792a1080f0e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -283,7 +283,7 @@ impl FormatReport {
         writeln!(
             t,
             "{}",
-            FormatReportFormatterBuilder::new(&self)
+            FormatReportFormatterBuilder::new(self)
                 .enable_colors(true)
                 .build()
         )?;
@@ -297,7 +297,7 @@ impl FormatReport {
 impl fmt::Display for FormatReport {
     // Prints all the formatting errors.
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?;
+        write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?;
         Ok(())
     }
 }
diff --git a/src/lists.rs b/src/lists.rs
index c04b4787616..d341ec8e6b0 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -386,7 +386,7 @@ where
                         result.push('\n');
                         result.push_str(indent_str);
                         // This is the width of the item (without comments).
-                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s));
                     }
                 } else {
                     result.push(' ')
@@ -820,7 +820,7 @@ where
 pub(crate) fn total_item_width(item: &ListItem) -> usize {
     comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
         + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
-        + item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
+        + item.item.as_ref().map_or(0, |s| unicode_str_width(s))
 }
 
 fn comment_len(comment: Option<&str>) -> usize {
diff --git a/src/macros.rs b/src/macros.rs
index 927187dfd8a..ef747638e33 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -186,7 +186,7 @@ fn return_macro_parse_failure_fallback(
         })
         .unwrap_or(false);
     if is_like_block_indent_style {
-        return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
+        return trim_left_preserve_layout(context.snippet(span), indent, context.config);
     }
 
     context.skipped_range.borrow_mut().push((
@@ -437,7 +437,7 @@ fn rewrite_macro_inner(
             // the `macro_name!` and `{ /* macro_body */ }` but skip modifying
             // anything in between the braces (for now).
             let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
-            match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
+            match trim_left_preserve_layout(snippet, shape.indent, context.config) {
                 Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
                 None => Some(format!("{} {}", macro_name, snippet)),
             }
@@ -901,7 +901,7 @@ impl MacroArgParser {
                     break;
                 }
                 TokenTree::Token(ref t) => {
-                    buffer.push_str(&pprust::token_to_string(&t));
+                    buffer.push_str(&pprust::token_to_string(t));
                 }
                 _ => return None,
             }
@@ -1045,7 +1045,7 @@ fn wrap_macro_args_inner(
     let mut iter = args.iter().peekable();
     let indent_str = shape.indent.to_string_with_newline(context.config);
 
-    while let Some(ref arg) = iter.next() {
+    while let Some(arg) = iter.next() {
         result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
 
         if use_multiple_lines
@@ -1055,7 +1055,7 @@ fn wrap_macro_args_inner(
                 result.pop();
             }
             result.push_str(&indent_str);
-        } else if let Some(ref next_arg) = iter.peek() {
+        } else if let Some(next_arg) = iter.peek() {
             let space_before_dollar =
                 !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
             let space_before_brace = next_arg.kind.starts_with_brace();
@@ -1370,7 +1370,7 @@ impl MacroBranch {
                     {
                         s += &indent_str;
                     }
-                    (s + l + "\n", indent_next_line(kind, &l, &config))
+                    (s + l + "\n", indent_next_line(kind, l, &config))
                 },
             )
             .0;
@@ -1514,11 +1514,11 @@ fn rewrite_macro_with_items(
             MacroArg::Item(item) => item,
             _ => return None,
         };
-        visitor.visit_item(&item);
+        visitor.visit_item(item);
     }
 
     let mut result = String::with_capacity(256);
-    result.push_str(&macro_name);
+    result.push_str(macro_name);
     result.push_str(opener);
     result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
     result.push_str(visitor.buffer.trim());
diff --git a/src/matches.rs b/src/matches.rs
index 5a6ed0ec06e..25b953ef425 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -319,7 +319,7 @@ fn flatten_arm_body<'a>(
     let can_extend =
         |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr);
 
-    if let Some(ref block) = block_can_be_flattened(context, body) {
+    if let Some(block) = block_can_be_flattened(context, body) {
         if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
             if let ast::ExprKind::Block(..) = expr.kind {
                 flatten_arm_body(context, expr, None)
@@ -393,7 +393,7 @@ fn rewrite_match_body(
         if comment_str.is_empty() {
             String::new()
         } else {
-            rewrite_comment(comment_str, false, shape, &context.config)?
+            rewrite_comment(comment_str, false, shape, context.config)?
         }
     };
 
@@ -408,8 +408,8 @@ fn rewrite_match_body(
                 result.push_str(&arrow_comment);
             }
             result.push_str(&nested_indent_str);
-            result.push_str(&body_str);
-            result.push_str(&comma);
+            result.push_str(body_str);
+            result.push_str(comma);
             return Some(result);
         }
 
@@ -451,7 +451,7 @@ fn rewrite_match_body(
             result.push_str(&arrow_comment);
         }
         result.push_str(&block_sep);
-        result.push_str(&body_str);
+        result.push_str(body_str);
         result.push_str(&body_suffix);
         Some(result)
     };
diff --git a/src/modules.rs b/src/modules.rs
index ded34d9032f..b0c1604a602 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -290,7 +290,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 };
                 self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
             }
-            SubModKind::Internal(ref item) => {
+            SubModKind::Internal(item) => {
                 self.push_inline_mod_directory(item.ident, &item.attrs);
                 self.visit_sub_mod_after_directory_update(sub_mod, None)
             }
@@ -317,7 +317,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
             (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
-                self.visit_mod_from_ast(&items)
+                self.visit_mod_from_ast(items)
             }
             (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
             (_, _) => Ok(()),
diff --git a/src/overflow.rs b/src/overflow.rs
index ac24181c780..3475f5c378c 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -394,7 +394,7 @@ impl<'a> Context<'a> {
     ) -> Option<String> {
         let last_item = self.last_item()?;
         let rewrite = match last_item {
-            OverflowableItem::Expr(ref expr) => {
+            OverflowableItem::Expr(expr) => {
                 match expr.kind {
                     // When overflowing the closure which consists of a single control flow
                     // expression, force to use block if its condition uses multi line.
diff --git a/src/pairs.rs b/src/pairs.rs
index 0f3d5e8f878..d1c75126ea4 100644
--- a/src/pairs.rs
+++ b/src/pairs.rs
@@ -55,11 +55,11 @@ fn rewrite_pairs_one_line<T: Rewrite>(
 
     for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
         if let Some(rewrite) = rewrite {
-            if !is_single_line(&rewrite) || result.len() > shape.width {
+            if !is_single_line(rewrite) || result.len() > shape.width {
                 return None;
             }
 
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
             result.push(' ');
             result.push_str(s);
             result.push(' ');
@@ -94,18 +94,18 @@ fn rewrite_pairs_multiline<T: Rewrite>(
     shape: Shape,
     context: &RewriteContext<'_>,
 ) -> Option<String> {
-    let rhs_offset = shape.rhs_overhead(&context.config);
+    let rhs_offset = shape.rhs_overhead(context.config);
     let nested_shape = (match context.config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(0),
         IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
     })
-    .with_max_width(&context.config)
+    .with_max_width(context.config)
     .sub_width(rhs_offset)?;
 
     let indent_str = nested_shape.indent.to_string_with_newline(context.config);
     let mut result = String::new();
 
-    result.push_str(&list.list[0].1.as_ref()?);
+    result.push_str(list.list[0].1.as_ref()?);
 
     for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
         // The following test checks if we should keep two subexprs on the same
@@ -144,7 +144,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             }
         }
 
-        result.push_str(&default_rw.as_ref()?);
+        result.push_str(default_rw.as_ref()?);
     }
     Some(result)
 }
@@ -264,12 +264,12 @@ impl FlattenPair for ast::Expr {
                 return node.rewrite(context, shape);
             }
             let nested_overhead = sep + 1;
-            let rhs_offset = shape.rhs_overhead(&context.config);
+            let rhs_offset = shape.rhs_overhead(context.config);
             let nested_shape = (match context.config.indent_style() {
                 IndentStyle::Visual => shape.visual_indent(0),
                 IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
             })
-            .with_max_width(&context.config)
+            .with_max_width(context.config)
             .sub_width(rhs_offset)?;
             let default_shape = match context.config.binop_separator() {
                 SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
diff --git a/src/patterns.rs b/src/patterns.rs
index ba8d8024a97..2676c647355 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -482,7 +482,7 @@ fn rewrite_tuple_pat(
     let path_str = path_str.unwrap_or_default();
 
     overflow::rewrite_with_parens(
-        &context,
+        context,
         &path_str,
         pat_vec.iter(),
         shape,
diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index b5fe4335dd3..14b92238cfa 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -112,7 +112,7 @@ impl<'a> Parser<'a> {
         span: Span,
     ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(sess.inner(), &path, Some(span));
+            let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok(result) => Some(result),
                 Err(mut e) => {
diff --git a/src/syntux/session.rs b/src/syntux/session.rs
index 946c076d9f2..cdb4893d443 100644
--- a/src/syntux/session.rs
+++ b/src/syntux/session.rs
@@ -164,7 +164,7 @@ impl ParseSess {
     }
 
     pub(crate) fn ignore_file(&self, path: &FileName) -> bool {
-        self.ignore_path_set.as_ref().is_match(&path)
+        self.ignore_path_set.as_ref().is_match(path)
     }
 
     pub(crate) fn set_silent_emitter(&mut self) {
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 48d61289a9b..e2620508c34 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -535,9 +535,9 @@ fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<Format
 
         debug!("Testing '{}'...", file_name.display());
 
-        match idempotent_check(&file_name, &opt_config) {
+        match idempotent_check(&file_name, opt_config) {
             Ok(ref report) if report.has_warnings() => {
-                print!("{}", FormatReportFormatterBuilder::new(&report).build());
+                print!("{}", FormatReportFormatterBuilder::new(report).build());
                 fails += 1;
             }
             Ok(report) => reports.push(report),
diff --git a/src/types.rs b/src/types.rs
index 62c05ba078c..9ea90c5e46d 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -728,7 +728,7 @@ impl Rewrite for ast::Ty {
                     result = combine_strs_with_missing_comments(
                         context,
                         result.trim_end(),
-                        &mt.ty.rewrite(&context, shape)?,
+                        &mt.ty.rewrite(context, shape)?,
                         before_ty_span,
                         shape,
                         true,
@@ -738,7 +738,7 @@ impl Rewrite for ast::Ty {
                     let budget = shape.width.checked_sub(used_width)?;
                     let ty_str = mt
                         .ty
-                        .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?;
+                        .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
                     result.push_str(&ty_str);
                 }
 
diff --git a/src/utils.rs b/src/utils.rs
index 29e1e070d41..3a8713c5bdb 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -42,7 +42,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool {
         (
             VisibilityKind::Restricted { path: p, .. },
             VisibilityKind::Restricted { path: q, .. },
-        ) => pprust::path_to_string(&p) == pprust::path_to_string(&q),
+        ) => pprust::path_to_string(p) == pprust::path_to_string(q),
         (VisibilityKind::Public, VisibilityKind::Public)
         | (VisibilityKind::Inherited, VisibilityKind::Inherited)
         | (
@@ -689,7 +689,7 @@ mod test {
     #[test]
     fn test_remove_trailing_white_spaces() {
         let s = "    r#\"\n        test\n    \"#";
-        assert_eq!(remove_trailing_white_spaces(&s), s);
+        assert_eq!(remove_trailing_white_spaces(s), s);
     }
 
     #[test]
@@ -698,7 +698,7 @@ mod test {
         let config = Config::default();
         let indent = Indent::new(4, 0);
         assert_eq!(
-            trim_left_preserve_layout(&s, indent, &config),
+            trim_left_preserve_layout(s, indent, &config),
             Some("aaa\n    bbb\n    ccc".to_string())
         );
     }
diff --git a/src/visitor.rs b/src/visitor.rs
index d854d90b40b..c37e1cb1011 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -164,7 +164,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                 } else {
                     let shape = self.shape();
-                    let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
+                    let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape));
                     self.push_rewrite(stmt.span(), rewrite)
                 }
             }
@@ -273,9 +273,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         let comment_snippet = self.snippet(span);
 
-        let align_to_right = if unindent_comment && contains_comment(&comment_snippet) {
+        let align_to_right = if unindent_comment && contains_comment(comment_snippet) {
             let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or("");
-            last_line_width(first_lines) > last_line_width(&comment_snippet)
+            last_line_width(first_lines) > last_line_width(comment_snippet)
         } else {
             false
         };
@@ -439,7 +439,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let filtered_attrs;
         let mut attrs = &item.attrs;
         let skip_context_saved = self.skip_context.clone();
-        self.skip_context.update_with_attrs(&attrs);
+        self.skip_context.update_with_attrs(attrs);
 
         let should_visit_node_again = match item.kind {
             // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
@@ -488,12 +488,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
                 ast::ItemKind::Impl { .. } => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::Trait(..) => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
@@ -552,7 +552,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                             visit::FnKind::Fn(
                                 fn_ctxt,
                                 item.ident,
-                                &fn_signature,
+                                fn_signature,
                                 &item.vis,
                                 Some(body),
                             ),
@@ -567,7 +567,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         let rewrite = self.rewrite_required_fn(
                             indent,
                             item.ident,
-                            &fn_signature,
+                            fn_signature,
                             &item.vis,
                             generics,
                             item.span,
@@ -718,7 +718,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         &ii.vis,
                         defaultness,
                         ty.as_ref(),
-                        &generics,
+                        generics,
                         &self.get_context(),
                         self.block_indent,
                         ii.span,
@@ -905,7 +905,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     }
 
     fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
-        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
+        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
     }
 
     fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {

From 0b8ffac0297a46d7d2d2f8328cbc49de7e7144f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sat, 23 Oct 2021 23:21:52 +0200
Subject: [PATCH 078/195] fix a bunch of the other clippy warnings that look
 interesting

---
 src/comment.rs  | 4 ++--
 src/expr.rs     | 6 +++---
 src/matches.rs  | 2 +-
 src/modules.rs  | 2 +-
 src/patterns.rs | 6 +++---
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/comment.rs b/src/comment.rs
index a3cd0359e6b..7b76c232937 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -405,7 +405,7 @@ impl CodeBlockAttribute {
     /// attributes are valid rust attributes
     /// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>
     fn new(attributes: &str) -> CodeBlockAttribute {
-        for attribute in attributes.split(",") {
+        for attribute in attributes.split(',') {
             match attribute.trim() {
                 "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
                 | "edition2021" => (),
@@ -1384,7 +1384,7 @@ impl<'a> Iterator for LineClasses<'a> {
             None => unreachable!(),
         };
 
-        while let Some((kind, c)) = self.base.next() {
+        for (kind, c) in self.base.by_ref() {
             // needed to set the kind of the ending character on the last line
             self.kind = kind;
             if c == '\n' {
diff --git a/src/expr.rs b/src/expr.rs
index c67c14b1985..1ca01f9db9a 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1207,11 +1207,11 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
     let span = lit.span;
     let symbol = lit.token.symbol.as_str();
 
-    if symbol.starts_with("0x") {
+    if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
         let hex_lit = match context.config.hex_literal_case() {
             HexLiteralCase::Preserve => None,
-            HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()),
-            HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()),
+            HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()),
+            HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()),
         };
         if let Some(hex_lit) = hex_lit {
             return wrap_str(
diff --git a/src/matches.rs b/src/matches.rs
index 25b953ef425..22d23fc1cdb 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -168,7 +168,7 @@ fn collect_beginning_verts(
         .map(|a| {
             context
                 .snippet(a.pat.span)
-                .starts_with("|")
+                .starts_with('|')
                 .then(|| a.pat.span().lo())
         })
         .collect()
diff --git a/src/modules.rs b/src/modules.rs
index b0c1604a602..88d434d759d 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -197,7 +197,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
     /// Visit modules from AST.
     fn visit_mod_from_ast(
         &mut self,
-        items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>,
+        items: &'ast [rustc_ast::ptr::P<ast::Item>],
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(item) {
diff --git a/src/patterns.rs b/src/patterns.rs
index 2676c647355..a80d63201f9 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -456,11 +456,11 @@ fn rewrite_tuple_pat(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<String> {
-    let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect();
-
-    if pat_vec.is_empty() {
+    if pats.is_empty() {
         return Some(format!("{}()", path_str.unwrap_or_default()));
     }
+    let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
+
     let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
     let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
     {

From 8b766f35bcf0b2c2dcd82bd4e4ec82af49c16367 Mon Sep 17 00:00:00 2001
From: Seiichi Uchida <seuchida@gmail.com>
Date: Mon, 11 May 2020 09:50:41 +0900
Subject: [PATCH 079/195] Remove legacy-rustfmt.toml (#4169)

---
 legacy-rustfmt.toml | 2 --
 1 file changed, 2 deletions(-)
 delete mode 100644 legacy-rustfmt.toml

diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml
deleted file mode 100644
index f976fa68e4c..00000000000
--- a/legacy-rustfmt.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-indent_style = "Visual"
-combine_control_expr = false

From bc46af97423cef7484a806e8282c545d7607889e Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Tue, 19 Oct 2021 01:14:51 -0400
Subject: [PATCH 080/195] Retain trailing comments in module when using
 rustfmt::skip attribute

Resolves 5033

Trailing comments at the end of the root Module were removed because the
module span did not extend until the end of the file.

The root Module's span now encompasses the entire file, which ensures
that no comments are lost when using ``#![rustfmt::skip]``
---
 src/modules.rs                             |  6 ++++--
 tests/target/issue-5033/minimum_example.rs |  8 ++++++++
 tests/target/issue-5033/nested_modules.rs  | 11 +++++++++++
 3 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 tests/target/issue-5033/minimum_example.rs
 create mode 100644 tests/target/issue-5033/nested_modules.rs

diff --git a/src/modules.rs b/src/modules.rs
index 88d434d759d..9e75f41ae36 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -16,7 +16,7 @@ use crate::syntux::parser::{
     Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
 };
 use crate::syntux::session::ParseSess;
-use crate::utils::contains_skip;
+use crate::utils::{contains_skip, mk_sp};
 
 mod visitor;
 
@@ -135,10 +135,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             self.visit_mod_from_ast(&krate.items)?;
         }
 
+        let snippet_provider = self.parse_sess.snippet_provider(krate.span);
+
         self.file_map.insert(
             root_filename,
             Module::new(
-                krate.span,
+                mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
                 None,
                 Cow::Borrowed(&krate.items),
                 Cow::Borrowed(&krate.attrs),
diff --git a/tests/target/issue-5033/minimum_example.rs b/tests/target/issue-5033/minimum_example.rs
new file mode 100644
index 00000000000..0e7df41deb2
--- /dev/null
+++ b/tests/target/issue-5033/minimum_example.rs
@@ -0,0 +1,8 @@
+// leading comment
+
+#![rustfmt::skip]
+fn main() {
+    println!("main"); // commented
+}
+
+// post comment
diff --git a/tests/target/issue-5033/nested_modules.rs b/tests/target/issue-5033/nested_modules.rs
new file mode 100644
index 00000000000..7a11133b60b
--- /dev/null
+++ b/tests/target/issue-5033/nested_modules.rs
@@ -0,0 +1,11 @@
+#![rustfmt::skip]
+
+mod a {
+    mod b {
+
+    }
+
+    // trailing comment b
+}
+
+// trailing comment a

From ed5a0250d3f9401046253ebaf25105f2be7749f2 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sat, 30 Oct 2021 10:10:08 -0500
Subject: [PATCH 081/195] refactor: minor parser cleanup

---
 src/syntux/parser.rs | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index 14b92238cfa..d1bb2f80004 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -125,18 +125,12 @@ impl<'a> Parser<'a> {
             }
         }));
         match result {
-            Ok(Some(m)) => {
-                if !sess.has_errors() {
-                    return Ok(m);
-                }
-
-                if sess.can_reset_errors() {
-                    sess.reset_errors();
-                    return Ok(m);
-                }
-                Err(ParserError::ParseError)
+            Ok(Some(m)) if !sess.has_errors() => Ok(m),
+            Ok(Some(m)) if sess.can_reset_errors() => {
+                sess.reset_errors();
+                Ok(m)
             }
-            Ok(None) => Err(ParserError::ParseError),
+            Ok(_) => Err(ParserError::ParseError),
             Err(..) if path.exists() => Err(ParserError::ParseError),
             Err(_) => Err(ParserError::ParsePanicError),
         }

From 54b1e0bb15934bedad7c3df4626b291bfe742522 Mon Sep 17 00:00:00 2001
From: enterprisey <danielhglus@gmail.com>
Date: Thu, 14 Nov 2019 09:44:59 -0500
Subject: [PATCH 082/195] README grammar fix (#3926)

Remove comma splice
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 9c7a1c4bc34..62e8ea60891 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ cargo +nightly fmt
 
 ## Limitations
 
-Rustfmt tries to work on as much Rust code as possible, sometimes, the code
+Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
 doesn't even need to compile! As we approach a 1.0 release we are also looking
 to limit areas of instability; in particular, post-1.0, the formatting of most
 code should not change as Rustfmt improves. However, there are some things that

From a24ed3c322b9b9a6b7dc9f3f18e4142d3adabf46 Mon Sep 17 00:00:00 2001
From: chansuke <chansuke@georepublic.de>
Date: Wed, 25 Nov 2020 19:31:02 +0900
Subject: [PATCH 083/195] Fix MSRV

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 62e8ea60891..eb39468d4d1 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,7 @@ rustfmt to exit with an error code if the input is not formatted correctly.
 It will also print any found differences. (Older versions of Rustfmt don't
 support `--check`, use `--write-mode diff`).
 
-A minimal Travis setup could look like this (requires Rust 1.24.0 or greater):
+A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):
 
 ```yaml
 language: rust

From a4d7011c18eeae7fbb11286822b9519dc9a9325f Mon Sep 17 00:00:00 2001
From: Jonathan <30177086+MonliH@users.noreply.github.com>
Date: Sun, 11 Oct 2020 16:28:45 +0000
Subject: [PATCH 084/195] Document RUSTFMT environment variable (#4464)

* Document RUSTFMT env var

* Move documentation up

* Apply suggestions from code review

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>

* Fix accedental removal

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
# Conflicts:
#	README.md
---
 README.md | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/README.md b/README.md
index eb39468d4d1..b3d21e6fb87 100644
--- a/README.md
+++ b/README.md
@@ -102,6 +102,25 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all
 binary and library targets of your crate.
 
 You can run `rustfmt --help` for information about available arguments.
+The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both
+single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).
+Please see `cargo fmt --help` for usage information.
+
+You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT` 
+environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`)
+
+### Running `rustfmt` directly
+
+To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some
+examples follow:
+
+- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place
+- `rustfmt` will read a code from stdin and write formatting to stdout
+  - `echo "fn     main() {}" | rustfmt` would emit "fn main() {}".
+
+For more information, including arguments and emit options, see `rustfmt --help`.
+
+### Verifying code is formatted
 
 When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not
 make any formatting changes to the input, and `1` if Rustfmt would make changes.

From 5ce82e15133501cdfa96d58370e9b4c3873546b1 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Fri, 8 Oct 2021 19:22:12 -0400
Subject: [PATCH 085/195] Prevent trailing whitespace in where clause bound
 predicate

resolves 5012
resolves 4850

This behavior was noticed when using the ``trailing_comma = "Never"``
configuration option (5012).

This behavior was also noticed when using default configurations (4850).

rustfmt would add a trailing space to where clause bounds that had an
empty right hand side.

Now no trailing space is added to the end of these where clause bounds.
---
 src/expr.rs                                      | 3 +++
 tests/target/issue-5012/trailing_comma_always.rs | 8 ++++++++
 tests/target/issue-5012/trailing_comma_never.rs  | 8 ++++++++
 tests/target/issue_4850.rs                       | 4 ++++
 4 files changed, 23 insertions(+)
 create mode 100644 tests/target/issue-5012/trailing_comma_always.rs
 create mode 100644 tests/target/issue-5012/trailing_comma_never.rs
 create mode 100644 tests/target/issue_4850.rs

diff --git a/src/expr.rs b/src/expr.rs
index 1ca01f9db9a..58942e442de 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1962,6 +1962,9 @@ fn choose_rhs<R: Rewrite>(
     has_rhs_comment: bool,
 ) -> Option<String> {
     match orig_rhs {
+        Some(ref new_str) if new_str.is_empty() => {
+            return Some(String::new());
+        }
         Some(ref new_str)
             if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
         {
diff --git a/tests/target/issue-5012/trailing_comma_always.rs b/tests/target/issue-5012/trailing_comma_always.rs
new file mode 100644
index 00000000000..ff9c40fbbd8
--- /dev/null
+++ b/tests/target/issue-5012/trailing_comma_always.rs
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Always
+
+pub struct Matrix<T, const R: usize, const C: usize,>
+where
+    [T; R * C]:,
+{
+    contents: [T; R * C],
+}
diff --git a/tests/target/issue-5012/trailing_comma_never.rs b/tests/target/issue-5012/trailing_comma_never.rs
new file mode 100644
index 00000000000..2fac8eae52b
--- /dev/null
+++ b/tests/target/issue-5012/trailing_comma_never.rs
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Never
+
+pub struct Matrix<T, const R: usize, const C: usize>
+where
+    [T; R * C]:
+{
+    contents: [T; R * C]
+}
diff --git a/tests/target/issue_4850.rs b/tests/target/issue_4850.rs
new file mode 100644
index 00000000000..7d4da9022fe
--- /dev/null
+++ b/tests/target/issue_4850.rs
@@ -0,0 +1,4 @@
+impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where
+    [(); this_is_a_long_const_function_name()]:
+{
+}

From c1eab154c9139a281d17c5ae70151bac4fcbf60f Mon Sep 17 00:00:00 2001
From: Peter Hall <peterjoel@gmail.com>
Date: Wed, 7 Oct 2020 12:55:01 +0100
Subject: [PATCH 086/195] Use a custom env var for log settings intead of
 default RUST_LOG

# Conflicts:
#	src/rustfmt/main.rs
---
 Contributing.md         | 2 +-
 src/bin/main.rs         | 2 +-
 src/format-diff/main.rs | 2 +-
 src/git-rustfmt/main.rs | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Contributing.md b/Contributing.md
index e6dc6a22037..3073996019e 100644
--- a/Contributing.md
+++ b/Contributing.md
@@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file
 ## Debugging
 
 Some `rewrite_*` methods use the `debug!` macro for printing useful information.
-These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`.
+These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
 These traces can be helpful in understanding which part of the code was used
 and get a better grasp on the execution flow.
 
diff --git a/src/bin/main.rs b/src/bin/main.rs
index 1bcc5c0dada..9d2e97c9479 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -20,7 +20,7 @@ use crate::rustfmt::{
 };
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = make_opts();
 
     let exit_code = match execute(&opts) {
diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs
index c751932273b..655aeda42bf 100644
--- a/src/format-diff/main.rs
+++ b/src/format-diff/main.rs
@@ -64,7 +64,7 @@ pub struct Opts {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = Opts::from_args();
     if let Err(e) = run(opts) {
         println!("{}", e);
diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs
index 16f5d1dd4f2..579778edbe7 100644
--- a/src/git-rustfmt/main.rs
+++ b/src/git-rustfmt/main.rs
@@ -170,7 +170,7 @@ impl Config {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
 
     let opts = make_opts();
     let matches = opts

From bd86077c58b0460a17ae071edbca9e6bba0aa6b1 Mon Sep 17 00:00:00 2001
From: r00ster <r00ster91@protonmail.com>
Date: Mon, 1 Nov 2021 19:53:35 +0100
Subject: [PATCH 087/195]  Remove grave accent that shouldn't be there

---
 src/config/options.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/config/options.rs b/src/config/options.rs
index a17d48349c0..bce9e5d07f2 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -20,7 +20,7 @@ pub enum NewlineStyle {
     Windows,
     /// Force CR (`\n).
     Unix,
-    /// `\r\n` in Windows, `\n`` on other platforms.
+    /// `\r\n` in Windows, `\n` on other platforms.
     Native,
 }
 

From e75c4d7ee9a48b8599a3a61d3b79ccbe0a18d77e Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 3 Nov 2021 21:10:01 -0500
Subject: [PATCH 088/195] ci: drop appveyor

---
 appveyor.yml | 8 --------
 1 file changed, 8 deletions(-)
 delete mode 100644 appveyor.yml

diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index b3dda091e0a..00000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-environment:
-  global:
-    PROJECT_NAME: rustfmt
-
-build: false
-
-test_script:
-  - echo Why does no one have access to delete me?

From a5f85058ac2e3f330bd48dd8de26bf429fc28c30 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 4 Nov 2021 18:00:22 -0500
Subject: [PATCH 089/195] fix: handle external mods imported via
 external->inline load hierarchy

---
 src/modules.rs                               |  4 +-
 src/test/mod_resolver.rs                     | 42 ++++++++++++++------
 tests/mod-resolver/issue-5063/foo.rs         |  2 +
 tests/mod-resolver/issue-5063/foo/bar/baz.rs |  1 +
 tests/mod-resolver/issue-5063/main.rs        |  5 +++
 5 files changed, 41 insertions(+), 13 deletions(-)
 create mode 100644 tests/mod-resolver/issue-5063/foo.rs
 create mode 100644 tests/mod-resolver/issue-5063/foo/bar/baz.rs
 create mode 100644 tests/mod-resolver/issue-5063/main.rs

diff --git a/src/modules.rs b/src/modules.rs
index 9e75f41ae36..b1f229d9daa 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -321,7 +321,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
                 self.visit_mod_from_ast(items)
             }
-            (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
+                self.visit_mod_outside_ast(items)
+            }
             (_, _) => Ok(()),
         }
     }
diff --git a/src/test/mod_resolver.rs b/src/test/mod_resolver.rs
index e0b55e3efb2..ae4a0d0fccb 100644
--- a/src/test/mod_resolver.rs
+++ b/src/test/mod_resolver.rs
@@ -5,21 +5,39 @@ use super::read_config;
 
 use crate::{FileName, Input, Session};
 
-#[test]
-fn nested_out_of_line_mods_loaded() {
-    // See also https://github.com/rust-lang/rustfmt/issues/4874
-    let filename = "tests/mod-resolver/issue-4874/main.rs";
-    let input_file = PathBuf::from(filename);
+fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) {
+    let input_file = PathBuf::from(input_file_name);
     let config = read_config(&input_file);
     let mut session = Session::<io::Stdout>::new(config, None);
     let report = session
-        .format(Input::File(filename.into()))
+        .format(Input::File(input_file_name.into()))
         .expect("Should not have had any execution errors");
     let errors_by_file = &report.internal.borrow().0;
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/bar/baz.rs",
-    ))));
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/foo/qux.rs",
-    ))));
+    for exp_file in exp_misformatted_files {
+        assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file))));
+    }
+}
+
+#[test]
+fn nested_out_of_line_mods_loaded() {
+    // See also https://github.com/rust-lang/rustfmt/issues/4874
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-4874/main.rs",
+        &[
+            "tests/mod-resolver/issue-4874/bar/baz.rs",
+            "tests/mod-resolver/issue-4874/foo/qux.rs",
+        ],
+    );
+}
+
+#[test]
+fn out_of_line_nested_inline_within_out_of_line() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5063
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-5063/main.rs",
+        &[
+            "tests/mod-resolver/issue-5063/foo/bar/baz.rs",
+            "tests/mod-resolver/issue-5063/foo.rs",
+        ],
+    );
 }
diff --git a/tests/mod-resolver/issue-5063/foo.rs b/tests/mod-resolver/issue-5063/foo.rs
new file mode 100644
index 00000000000..d56974773fb
--- /dev/null
+++ b/tests/mod-resolver/issue-5063/foo.rs
@@ -0,0 +1,2 @@
+mod bar {
+        mod baz;}
\ No newline at end of file
diff --git a/tests/mod-resolver/issue-5063/foo/bar/baz.rs b/tests/mod-resolver/issue-5063/foo/bar/baz.rs
new file mode 100644
index 00000000000..3519b0ee59c
--- /dev/null
+++ b/tests/mod-resolver/issue-5063/foo/bar/baz.rs
@@ -0,0 +1 @@
+fn    baz()    {       }
\ No newline at end of file
diff --git a/tests/mod-resolver/issue-5063/main.rs b/tests/mod-resolver/issue-5063/main.rs
new file mode 100644
index 00000000000..41c81c7bb43
--- /dev/null
+++ b/tests/mod-resolver/issue-5063/main.rs
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Hello, world!");
+}
+
+mod foo;
\ No newline at end of file

From 9027db984be06dc99fd88264e9dbe84541547f08 Mon Sep 17 00:00:00 2001
From: Dmitry Murzin <diraria@yandex.ru>
Date: Sat, 6 Jun 2020 17:19:50 +0300
Subject: [PATCH 090/195] Update IntelliJ Integration (#4238)

---
 intellij.md | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/intellij.md b/intellij.md
index 7aea6222b8b..6a711c0171a 100644
--- a/intellij.md
+++ b/intellij.md
@@ -3,19 +3,28 @@
 ## Installation
 
 - Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/).
-  CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535))
-  
-- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin"
-  ![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png)
+  CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE.
 
-- Press "Install" on the rust plugin
-  ![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png)
+- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace
+  ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png)
+
+- Press "Install" on the Rust plugin
+  ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png)
   
 - Restart CLion/IntelliJ
 
 ## Configuration
 
-- Open the settings window (File -> Settings) and search for "reformat"
+### Run Rustfmt on save
+
+- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
+  ![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
+
+- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
+
+### Bind shortcut to "Reformat File with Rustfmt" action
+
+- Open the settings window (File → Settings) and search for "reformat"
   ![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png)
 - Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut
 

From 4d50e7c7606efca32bd937a4c60772a616fdbc33 Mon Sep 17 00:00:00 2001
From: mujpao <mujpao@gmail.com>
Date: Mon, 1 Nov 2021 23:13:30 -0700
Subject: [PATCH 091/195] Put empty trait braces on same line if possible

---
 src/items.rs                                  | 15 ++++--
 tests/source/empty-item-single-line-false.rs  | 46 +++++++++++++++++++
 .../item-brace-style-always-next-line.rs      | 35 ++++++++++++++
 tests/target/empty-item-single-line-false.rs  | 41 +++++++++++++++++
 .../item-brace-style-always-next-line.rs      | 29 ++++++++++++
 5 files changed, 163 insertions(+), 3 deletions(-)
 create mode 100644 tests/source/empty-item-single-line-false.rs
 create mode 100644 tests/target/empty-item-single-line-false.rs

diff --git a/src/items.rs b/src/items.rs
index 1c7899b3ac3..e37a1b69658 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1122,12 +1122,24 @@ pub(crate) fn format_trait(
             }
         }
 
+        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+        let snippet = context.snippet(block_span);
+        let open_pos = snippet.find_uncommented("{")? + 1;
+
         match context.config.brace_style() {
             _ if last_line_contains_single_line_comment(&result)
                 || last_line_width(&result) + 2 > context.budget(offset.width()) =>
             {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
+            _ if context.config.empty_item_single_line()
+                && trait_items.is_empty()
+                && !result.contains('\n')
+                && !contains_comment(&snippet[open_pos..]) =>
+            {
+                result.push_str(" {}");
+                return Some(result);
+            }
             BraceStyle::AlwaysNextLine => {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
@@ -1144,9 +1156,6 @@ pub(crate) fn format_trait(
         }
         result.push('{');
 
-        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
-        let snippet = context.snippet(block_span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
         let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
 
         if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
diff --git a/tests/source/empty-item-single-line-false.rs b/tests/source/empty-item-single-line-false.rs
new file mode 100644
index 00000000000..20c5bc83b46
--- /dev/null
+++ b/tests/source/empty-item-single-line-false.rs
@@ -0,0 +1,46 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+
+}
+
+struct Struct
+{
+
+}
+
+enum Enum
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
diff --git a/tests/source/item-brace-style-always-next-line.rs b/tests/source/item-brace-style-always-next-line.rs
index 38094d67a77..0fb6405120a 100644
--- a/tests/source/item-brace-style-always-next-line.rs
+++ b/tests/source/item-brace-style-always-next-line.rs
@@ -27,3 +27,38 @@ mod M {
 
     struct D<T> where T: Copy {}
 }
+
+
+fn function()
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
diff --git a/tests/target/empty-item-single-line-false.rs b/tests/target/empty-item-single-line-false.rs
new file mode 100644
index 00000000000..bf7f70e7c43
--- /dev/null
+++ b/tests/target/empty-item-single-line-false.rs
@@ -0,0 +1,41 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+}
+
+struct Struct {}
+
+enum Enum {}
+
+trait Trait
+{
+}
+
+impl<T> Trait for T
+{
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}
diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs
index 531ac598683..4935fac04f1 100644
--- a/tests/target/item-brace-style-always-next-line.rs
+++ b/tests/target/item-brace-style-always-next-line.rs
@@ -40,3 +40,32 @@ mod M
     where
         T: Copy, {}
 }
+
+fn function() {}
+
+trait Trait {}
+
+impl<T> Trait for T {}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}

From 19c5c74951db8673aa3e3edba8393ce90346f96f Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sat, 6 Nov 2021 12:59:06 -0500
Subject: [PATCH 092/195] refactor: dedupe & simplify ty alias formatting

---
 src/items.rs   | 166 ++++++++++++++++++++++---------------------------
 src/visitor.rs |  81 +++++++-----------------
 2 files changed, 97 insertions(+), 150 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index e37a1b69658..13d8a416a1e 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1185,18 +1185,6 @@ pub(crate) fn format_trait(
     }
 }
 
-struct OpaqueTypeBounds<'a> {
-    generic_bounds: &'a ast::GenericBounds,
-}
-
-impl<'a> Rewrite for OpaqueTypeBounds<'a> {
-    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        self.generic_bounds
-            .rewrite(context, shape)
-            .map(|s| format!("impl {}", s))
-    }
-}
-
 pub(crate) struct TraitAliasBounds<'a> {
     generic_bounds: &'a ast::GenericBounds,
     generics: &'a ast::Generics,
@@ -1518,17 +1506,79 @@ fn format_tuple_struct(
     Some(result)
 }
 
-pub(crate) fn rewrite_type<R: Rewrite>(
-    context: &RewriteContext<'_>,
+pub(crate) enum ItemVisitorKind<'a> {
+    Item(&'a ast::Item),
+    AssocTraitItem(&'a ast::AssocItem),
+    AssocImplItem(&'a ast::AssocItem),
+    ForeignItem(&'a ast::ForeignItem),
+}
+
+struct TyAliasRewriteInfo<'c, 'g>(
+    &'c RewriteContext<'c>,
+    Indent,
+    &'g ast::Generics,
+    symbol::Ident,
+    Span,
+);
+
+pub(crate) fn rewrite_type_alias<'a, 'b>(
+    ty_alias_kind: &ast::TyAliasKind,
+    context: &RewriteContext<'a>,
     indent: Indent,
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    generics: &ast::Generics,
-    generic_bounds_opt: Option<&ast::GenericBounds>,
-    rhs: Option<&R>,
+    visitor_kind: &ItemVisitorKind<'b>,
     span: Span,
+) -> Option<String> {
+    use ItemVisitorKind::*;
+
+    let ast::TyAliasKind(defaultness, ref generics, ref generic_bounds, ref ty) = *ty_alias_kind;
+    let ty_opt = ty.as_ref().map(|t| &**t);
+    let (ident, vis) = match visitor_kind {
+        Item(i) => (i.ident, &i.vis),
+        AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
+        ForeignItem(i) => (i.ident, &i.vis),
+    };
+    let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
+
+    // Type Aliases are formatted slightly differently depending on the context
+    // in which they appear, whether they are opaque, and whether they are associated.
+    // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
+    // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
+    match (visitor_kind, ty_opt) {
+        (Item(_), None) => {
+            let op_ty = OpaqueType { generic_bounds };
+            rewrite_ty(rw_info, Some(generic_bounds), Some(&op_ty), vis)
+        }
+        (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(generic_bounds), Some(&*ty), vis),
+        (AssocImplItem(_), _) => {
+            let result = if let Some(ast::Ty {
+                kind: ast::TyKind::ImplTrait(_, ref generic_bounds),
+                ..
+            }) = ty_opt
+            {
+                let op_ty = OpaqueType { generic_bounds };
+                rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
+            } else {
+                rewrite_ty(rw_info, None, ty.as_ref(), vis)
+            }?;
+            match defaultness {
+                ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+                _ => Some(result),
+            }
+        }
+        (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
+            rewrite_ty(rw_info, Some(generic_bounds), ty.as_ref(), vis)
+        }
+    }
+}
+
+fn rewrite_ty<R: Rewrite>(
+    rw_info: &TyAliasRewriteInfo<'_, '_>,
+    generic_bounds_opt: Option<&ast::GenericBounds>,
+    rhs: Option<&R>,
+    vis: &ast::Visibility,
 ) -> Option<String> {
     let mut result = String::with_capacity(128);
+    let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1616,28 +1666,6 @@ pub(crate) fn rewrite_type<R: Rewrite>(
     }
 }
 
-pub(crate) fn rewrite_opaque_type(
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    ident: symbol::Ident,
-    generic_bounds: &ast::GenericBounds,
-    generics: &ast::Generics,
-    vis: &ast::Visibility,
-    span: Span,
-) -> Option<String> {
-    let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
-    rewrite_type(
-        context,
-        indent,
-        ident,
-        vis,
-        generics,
-        Some(generic_bounds),
-        Some(&opaque_type_bounds),
-        span,
-    )
-}
-
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
     (
         if config.space_before_colon() { " " } else { "" },
@@ -1863,54 +1891,18 @@ fn rewrite_static(
     }
 }
 struct OpaqueType<'a> {
-    bounds: &'a ast::GenericBounds,
+    generic_bounds: &'a ast::GenericBounds,
 }
 
 impl<'a> Rewrite for OpaqueType<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         let shape = shape.offset_left(5)?; // `impl `
-        self.bounds
+        self.generic_bounds
             .rewrite(context, shape)
             .map(|s| format!("impl {}", s))
     }
 }
 
-pub(crate) fn rewrite_impl_type(
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    defaultness: ast::Defaultness,
-    ty_opt: Option<&ptr::P<ast::Ty>>,
-    generics: &ast::Generics,
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    span: Span,
-) -> Option<String> {
-    // Opaque type
-    let result = if let Some(rustc_ast::ast::Ty {
-        kind: ast::TyKind::ImplTrait(_, ref bounds),
-        ..
-    }) = ty_opt.map(|t| &**t)
-    {
-        rewrite_type(
-            context,
-            indent,
-            ident,
-            &DEFAULT_VISIBILITY,
-            generics,
-            None,
-            Some(&OpaqueType { bounds }),
-            span,
-        )
-    } else {
-        rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
-    }?;
-
-    match defaultness {
-        ast::Defaultness::Default(..) => Some(format!("default {}", result)),
-        _ => Some(result),
-    }
-}
-
 impl Rewrite for ast::FnRetTy {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match *self {
@@ -3176,19 +3168,9 @@ impl Rewrite for ast::ForeignItem {
                 // 1 = ;
                 rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
             }
-            ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                rewrite_type(
-                    context,
-                    shape.indent,
-                    self.ident,
-                    &self.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    self.span,
-                )
+            ast::ForeignItemKind::TyAlias(ref ty_alias) => {
+                let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
+                rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Item)
diff --git a/src/visitor.rs b/src/visitor.rs
index c37e1cb1011..f385245248d 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -12,8 +12,7 @@ use crate::config::{BraceStyle, Config};
 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,
-    rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts,
-    StructParts,
+    rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
 };
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
@@ -576,35 +575,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     }
                 }
                 ast::ItemKind::TyAlias(ref alias_kind) => {
-                    let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) =
-                        **alias_kind;
-                    match ty {
-                        Some(ty) => {
-                            let rewrite = rewrite_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                &item.vis,
-                                generics,
-                                Some(generic_bounds),
-                                Some(&*ty),
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                        None => {
-                            let rewrite = rewrite_opaque_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                generic_bounds,
-                                generics,
-                                &item.vis,
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                    }
+                    use ItemVisitorKind::Item;
+                    self.visit_ty_alias_kind(alias_kind, &Item(&item), item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
@@ -627,6 +599,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         self.skip_context = skip_context_saved;
     }
 
+    fn visit_ty_alias_kind(
+        &mut self,
+        ty_kind: &ast::TyAliasKind,
+        visitor_kind: &ItemVisitorKind<'_>,
+        span: Span,
+    ) {
+        let rewrite = rewrite_type_alias(
+            ty_kind,
+            &self.get_context(),
+            self.block_indent,
+            visitor_kind,
+            span,
+        );
+        self.push_rewrite(span, rewrite);
+    }
+
     pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
         skip_out_of_file_lines_range_visitor!(self, ti.span);
 
@@ -659,19 +647,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 }
             }
             ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                let rewrite = rewrite_type(
-                    &self.get_context(),
-                    self.block_indent,
-                    ti.ident,
-                    &ti.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    ti.span,
-                );
-                self.push_rewrite(ti.span, rewrite);
+                use ItemVisitorKind::AssocTraitItem;
+                self.visit_ty_alias_kind(ty_alias_kind, &AssocTraitItem(&ti), ti.span);
             }
             ast::AssocItemKind::MacCall(ref mac) => {
                 self.visit_mac(mac, Some(ti.ident), MacroPosition::Item);
@@ -710,20 +687,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             }
             ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
             ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind;
-                self.push_rewrite(
-                    ii.span,
-                    rewrite_impl_type(
-                        ii.ident,
-                        &ii.vis,
-                        defaultness,
-                        ty.as_ref(),
-                        generics,
-                        &self.get_context(),
-                        self.block_indent,
-                        ii.span,
-                    ),
-                );
+                use ItemVisitorKind::AssocImplItem;
+                self.visit_ty_alias_kind(ty_alias_kind, &AssocImplItem(&ii), ii.span);
             }
             ast::AssocItemKind::MacCall(ref mac) => {
                 self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);

From e4472d3b07b2c34b27688303745d4cc0e74da9a5 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sat, 6 Nov 2021 17:12:25 -0500
Subject: [PATCH 093/195] refactor: dedupe associated item visitation

---
 src/visitor.rs | 90 ++++++++++++++++++++------------------------------
 1 file changed, 35 insertions(+), 55 deletions(-)

diff --git a/src/visitor.rs b/src/visitor.rs
index f385245248d..25b0085b3ef 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -615,85 +615,65 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         self.push_rewrite(span, rewrite);
     }
 
-    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ti.span);
+    fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+        use ItemVisitorKind::*;
+        // TODO(calebcartwright): Not sure the skip spans are correct
+        let (ai, skip_span, assoc_ctxt) = match visitor_kind {
+            AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+            AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
+            _ => unreachable!(),
+        };
+        skip_out_of_file_lines_range_visitor!(self, ai.span);
 
-        if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span());
+        if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
+            self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
             return;
         }
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
-        match ti.kind {
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)),
-            ast::AssocItemKind::Fn(ref fn_kind) => {
+        match (&ai.kind, visitor_kind) {
+            (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
+                self.visit_static(&StaticParts::from_trait_item(&ai))
+            }
+            (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
+                self.visit_static(&StaticParts::from_impl_item(&ai))
+            }
+            (ast::AssocItemKind::Fn(ref fn_kind), _) => {
                 let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
                 if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ti.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait);
+                    let inner_attrs = inner_attributes(&ai.attrs);
+                    let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
                         generics,
                         &sig.decl,
-                        ti.span,
+                        ai.span,
                         defaultness,
                         Some(&inner_attrs),
                     );
                 } else {
                     let indent = self.block_indent;
                     let rewrite =
-                        self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span);
-                    self.push_rewrite(ti.span, rewrite);
+                        self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
+                    self.push_rewrite(ai.span, rewrite);
                 }
             }
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                use ItemVisitorKind::AssocTraitItem;
-                self.visit_ty_alias_kind(ty_alias_kind, &AssocTraitItem(&ti), ti.span);
+            (ast::AssocItemKind::TyAlias(ref ty_alias_kind), _) => {
+                self.visit_ty_alias_kind(ty_alias_kind, visitor_kind, ai.span);
             }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ti.ident), MacroPosition::Item);
+            (ast::AssocItemKind::MacCall(ref mac), _) => {
+                self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
             }
+            _ => unreachable!(),
         }
     }
 
+    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
+        self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+    }
+
     pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ii.span);
-
-        if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span);
-            return;
-        }
-
-        match ii.kind {
-            ast::AssocItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ii.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl);
-                    self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)),
-                        generics,
-                        &sig.decl,
-                        ii.span,
-                        defaultness,
-                        Some(&inner_attrs),
-                    );
-                } else {
-                    let indent = self.block_indent;
-                    let rewrite =
-                        self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
-                    self.push_rewrite(ii.span, rewrite);
-                }
-            }
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                use ItemVisitorKind::AssocImplItem;
-                self.visit_ty_alias_kind(ty_alias_kind, &AssocImplItem(&ii), ii.span);
-            }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
-            }
-        }
+        self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
     }
 
     fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {

From 31bc54a9a8d556ddb124dc177ea82569250651d1 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 7 Nov 2021 19:06:24 -0600
Subject: [PATCH 094/195] chore: bump toolchain

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index b19ecbdb07c..1d2cad66751 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-10-20"
+channel = "nightly-2021-11-08"
 components = ["rustc-dev"]

From e6d1bf5acba29a8944f3bd537bcefb5e5972e5f1 Mon Sep 17 00:00:00 2001
From: Wu Yu Wei <wusyong9104@gmail.com>
Date: Tue, 31 Mar 2020 14:36:12 +0800
Subject: [PATCH 095/195] Link tracking issues in Configurations.md (#4096)

# Conflicts:
#	Configurations.md
---
 Configurations.md | 94 +++++++++++++++++++++++------------------------
 1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 13826883d2f..4a281251f22 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -47,7 +47,7 @@ Where to put a binary operator when a binary expression goes multiline.
 
 - **Default value**: `"Front"`
 - **Possible values**: `"Front"`, `"Back"`
-- **Stable**: No (tracking issue: #3368)
+- **Stable**: No (tracking issue: [#3368](https://github.com/rust-lang/rustfmt/issues/3368))
 
 #### `"Front"` (default):
 
@@ -88,7 +88,7 @@ them, additional blank lines are inserted.
 
 - **Default value**: `0`
 - **Possible values**: *unsigned integer*
-- **Stable**: No (tracking issue: #3382)
+- **Stable**: No (tracking issue: [#3382](https://github.com/rust-lang/rustfmt/issues/3382))
 
 ### Example
 Original Code (rustfmt will not change it with the default value of `0`):
@@ -128,7 +128,7 @@ lines are found, they are trimmed down to match this integer.
 
 - **Default value**: `1`
 - **Possible values**: any non-negative integer
-- **Stable**: No (tracking issue: #3381)
+- **Stable**: No (tracking issue: [#3381](https://github.com/rust-lang/rustfmt/issues/3381))
 
 ### Example
 Original Code:
@@ -186,7 +186,7 @@ Brace style for items
 
 - **Default value**: `"SameLineWhere"`
 - **Possible values**: `"AlwaysNextLine"`, `"PreferSameLine"`, `"SameLineWhere"`
-- **Stable**: No (tracking issue: #3376)
+- **Stable**: No (tracking issue: [#3376](https://github.com/rust-lang/rustfmt/issues/3376))
 
 ### Functions
 
@@ -313,7 +313,7 @@ Whether to use colored output or not.
 
 - **Default value**: `"Auto"`
 - **Possible values**: "Auto", "Always", "Never"
-- **Stable**: No (tracking issue: #3385)
+- **Stable**: No (tracking issue: [#3385](https://github.com/rust-lang/rustfmt/issues/3385))
 
 ## `combine_control_expr`
 
@@ -321,7 +321,7 @@ Combine control expressions with function calls.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3369)
+- **Stable**: No (tracking issue: [#3369](https://github.com/rust-lang/rustfmt/issues/3369))
 
 #### `true` (default):
 
@@ -429,7 +429,7 @@ Maximum length of comments. No effect unless`wrap_comments = true`.
 
 - **Default value**: `80`
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3349)
+- **Stable**: No (tracking issue: [#3349](https://github.com/rust-lang/rustfmt/issues/3349))
 
 **Note:** A value of `0` results in [`wrap_comments`](#wrap_comments) being applied regardless of a line's width.
 
@@ -452,7 +452,7 @@ Replace strings of _ wildcards by a single .. in tuple patterns
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3384)
+- **Stable**: No (tracking issue: [#3384](https://github.com/rust-lang/rustfmt/issues/3384))
 
 #### `false` (default):
 
@@ -477,7 +477,7 @@ Brace style for control flow constructs
 
 - **Default value**: `"AlwaysSameLine"`
 - **Possible values**: `"AlwaysNextLine"`, `"AlwaysSameLine"`, `"ClosingNextLine"`
-- **Stable**: No (tracking issue: #3377)
+- **Stable**: No (tracking issue: [#3377](https://github.com/rust-lang/rustfmt/issues/3377))
 
 #### `"AlwaysSameLine"` (default):
 
@@ -551,7 +551,7 @@ Put empty-body functions and impls on a single line
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3356)
+- **Stable**: No (tracking issue: [#3356](https://github.com/rust-lang/rustfmt/issues/3356))
 
 #### `true` (default):
 
@@ -584,7 +584,7 @@ doesn't get ignored when aligning.
 
 - **Default value** : 0
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3372)
+- **Stable**: No (tracking issue: [#3372](https://github.com/rust-lang/rustfmt/issues/3372))
 
 #### `0` (default):
 
@@ -630,7 +630,7 @@ using a shorter name.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3391)
+- **Stable**: No (tracking issue: [#3391](https://github.com/rust-lang/rustfmt/issues/3391))
 
 See also [`max_width`](#max_width).
 
@@ -641,7 +641,7 @@ trailing whitespaces.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3392)
+- **Stable**: No (tracking issue: [#3392](https://github.com/rust-lang/rustfmt/issues/3392))
 
 ## `fn_args_layout`
 
@@ -771,7 +771,7 @@ Put single-expression functions on a single line
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3358)
+- **Stable**: No (tracking issue: [#3358](https://github.com/rust-lang/rustfmt/issues/3358))
 
 #### `false` (default):
 
@@ -832,7 +832,7 @@ Force multiline closure and match arm bodies to be wrapped in a block
 
 - **Default value**: `false`
 - **Possible values**: `false`, `true`
-- **Stable**: No (tracking issue: #3374)
+- **Stable**: No (tracking issue: [#3374](https://github.com/rust-lang/rustfmt/issues/3374))
 
 #### `false` (default):
 
@@ -881,7 +881,7 @@ Format code snippet included in doc comments.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3348)
+- **Stable**: No (tracking issue: [#3348](https://github.com/rust-lang/rustfmt/issues/3348))
 
 #### `false` (default):
 
@@ -941,7 +941,7 @@ Format the metavariable matching patterns in macros.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3354)
+- **Stable**: No (tracking issue: [#3354](https://github.com/rust-lang/rustfmt/issues/3354))
 
 #### `false` (default):
 
@@ -978,7 +978,7 @@ Format the bodies of macros.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3355)
+- **Stable**: No (tracking issue: [#3355](https://github.com/rust-lang/rustfmt/issues/3355))
 
 #### `true` (default):
 
@@ -1011,7 +1011,7 @@ Format string literals where necessary
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3353)
+- **Stable**: No (tracking issue: [#3353](https://github.com/rust-lang/rustfmt/issues/3353))
 
 #### `false` (default):
 
@@ -1072,7 +1072,7 @@ Do not show parse errors if the parser failed to parse files.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3390)
+- **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390))
 
 ## `ignore`
 
@@ -1081,7 +1081,7 @@ The pattern format is the same as [.gitignore](https://git-scm.com/docs/gitignor
 
 - **Default value**: format every file
 - **Possible values**: See an example below
-- **Stable**: No (tracking issue: #3395)
+- **Stable**: No (tracking issue: [#3395](https://github.com/rust-lang/rustfmt/issues/3395))
 
 ### Example
 
@@ -1114,7 +1114,7 @@ Indent style of imports
 
 - **Default Value**: `"Block"`
 - **Possible values**: `"Block"`, `"Visual"`
-- **Stable**: No (tracking issue: #3360)
+- **Stable**: No (tracking issue: [#3360](https://github.com/rust-lang/rustfmt/issues/3360))
 
 #### `"Block"` (default):
 
@@ -1140,7 +1140,7 @@ Item layout inside a imports block
 
 - **Default value**: "Mixed"
 - **Possible values**: "Horizontal", "HorizontalVertical", "Mixed", "Vertical"
-- **Stable**: No (tracking issue: #3361)
+- **Stable**: No (tracking issue: [#3361](https://github.com/rust-lang/rustfmt/issues/3361))
 
 #### `"Mixed"` (default):
 
@@ -1203,7 +1203,7 @@ Indent on expressions or items.
 
 - **Default value**: `"Block"`
 - **Possible values**: `"Block"`, `"Visual"`
-- **Stable**: No (tracking issue: #3346)
+- **Stable**: No (tracking issue: [#3346](https://github.com/rust-lang/rustfmt/issues/3346))
 
 ### Array
 
@@ -1456,7 +1456,7 @@ Write an item and its attribute on the same line if their combined width is belo
 
 - **Default value**: 0
 - **Possible values**: any positive integer
-- **Stable**: No (tracking issue: #3343)
+- **Stable**: No (tracking issue: [#3343](https://github.com/rust-lang/rustfmt/issues/3343))
 
 ### Example
 
@@ -1477,7 +1477,7 @@ Check whether beginnings of files match a license template.
 
 - **Default value**: `""`
 - **Possible values**: path to a license template file
-- **Stable**: No (tracking issue: #3352)
+- **Stable**: No (tracking issue: [#3352](https://github.com/rust-lang/rustfmt/issues/3352))
 
 A license template is a plain text file which is matched literally against the
 beginning of each source file, except for `{}`-delimited blocks, which are
@@ -1499,7 +1499,7 @@ The Style Guide requires that bodies are block wrapped by default if a line brea
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3373)
+- **Stable**: No (tracking issue: [#3373](https://github.com/rust-lang/rustfmt/issues/3373))
 
 #### `true` (default):
 
@@ -1826,7 +1826,7 @@ Convert /* */ comments to // comments where possible
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3350)
+- **Stable**: No (tracking issue: [#3350](https://github.com/rust-lang/rustfmt/issues/3350))
 
 #### `false` (default):
 
@@ -1854,7 +1854,7 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3351)
+- **Stable**: No (tracking issue: [#3351](https://github.com/rust-lang/rustfmt/issues/3351))
 
 #### `false` (default):
 
@@ -1885,7 +1885,7 @@ instead of being indented on a new line.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3370)
+- **Stable**: No (tracking issue: [#3370](https://github.com/rust-lang/rustfmt/issues/3370))
 
 #### `false` (default):
 
@@ -1992,7 +1992,7 @@ Reorder impl items. `type` and `const` are put first, then macros and methods.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3363)
+- **Stable**: No (tracking issue: [#3363](https://github.com/rust-lang/rustfmt/issues/3363))
 
 #### `false` (default)
 
@@ -2166,7 +2166,7 @@ Report `FIXME` items in comments.
 
 - **Default value**: `"Never"`
 - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: #3394)
+- **Stable**: No (tracking issue: [#3394](https://github.com/rust-lang/rustfmt/issues/3394))
 
 Warns about any comments containing `FIXME` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
@@ -2181,7 +2181,7 @@ Report `TODO` items in comments.
 
 - **Default value**: `"Never"`
 - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: #3393)
+- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393))
 
 Warns about any comments containing `TODO` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
@@ -2196,7 +2196,7 @@ specific version of rustfmt is used in your CI, use this option.
 
 - **Default value**: `CARGO_PKG_VERSION`
 - **Possible values**: any published version (e.g. `"0.3.8"`)
-- **Stable**: No (tracking issue: #3386)
+- **Stable**: No (tracking issue: [#3386](https://github.com/rust-lang/rustfmt/issues/3386))
 
 ## `skip_children`
 
@@ -2204,7 +2204,7 @@ Don't reformat out of line modules
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3389)
+- **Stable**: No (tracking issue: [#3389](https://github.com/rust-lang/rustfmt/issues/3386))
 
 ## `single_line_if_else_max_width`
 
@@ -2224,7 +2224,7 @@ Leave a space after the colon.
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3366)
+- **Stable**: No (tracking issue: [#3366](https://github.com/rust-lang/rustfmt/issues/3366))
 
 #### `true` (default):
 
@@ -2256,7 +2256,7 @@ Leave a space before the colon.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3365)
+- **Stable**: No (tracking issue: [#3365](https://github.com/rust-lang/rustfmt/issues/3365))
 
 #### `false` (default):
 
@@ -2288,7 +2288,7 @@ Put spaces around the .., ..=, and ... range operators
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3367)
+- **Stable**: No (tracking issue: [#3367](https://github.com/rust-lang/rustfmt/issues/3367))
 
 #### `false` (default):
 
@@ -2344,7 +2344,7 @@ The maximum diff of width between struct fields to be aligned with each other.
 
 - **Default value** : 0
 - **Possible values**: any non-negative integer
-- **Stable**: No (tracking issue: #3371)
+- **Stable**: No (tracking issue: [#3371](https://github.com/rust-lang/rustfmt/issues/3371))
 
 #### `0` (default):
 
@@ -2372,7 +2372,7 @@ Put small struct literals on a single line
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3357)
+- **Stable**: No (tracking issue: [#3357](https://github.com/rust-lang/rustfmt/issues/3357))
 
 #### `true` (default):
 
@@ -2460,7 +2460,7 @@ How to handle trailing commas for lists
 
 - **Default value**: `"Vertical"`
 - **Possible values**: `"Always"`, `"Never"`, `"Vertical"`
-- **Stable**: No (tracking issue: #3379)
+- **Stable**: No (tracking issue: [#3379](https://github.com/rust-lang/rustfmt/issues/3379))
 
 #### `"Vertical"` (default):
 
@@ -2518,7 +2518,7 @@ Add trailing semicolon after break, continue and return
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3378)
+- **Stable**: No (tracking issue: [#3378](https://github.com/rust-lang/rustfmt/issues/3378))
 
 #### `true` (default):
 ```rust
@@ -2540,7 +2540,7 @@ Determines if `+` or `=` are wrapped in spaces in the punctuation of types
 
 - **Default value**: `"Wide"`
 - **Possible values**: `"Compressed"`, `"Wide"`
-- **Stable**: No (tracking issue: #3364)
+- **Stable**: No (tracking issue: [#3364](https://github.com/rust-lang/rustfmt/issues/3364))
 
 #### `"Wide"` (default):
 
@@ -2564,7 +2564,7 @@ Enable unstable features on the unstable channel.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3387)
+- **Stable**: No (tracking issue: [#3387](https://github.com/rust-lang/rustfmt/issues/3387))
 
 ## `use_field_init_shorthand`
 
@@ -2779,7 +2779,7 @@ version number.
 
 - **Default value**: `One`
 - **Possible values**: `One`, `Two`
-- **Stable**: No (tracking issue: #3383)
+- **Stable**: No (tracking issue: [#3383](https://github.com/rust-lang/rustfmt/issues/3383))
 
 ### Example
 
@@ -2793,7 +2793,7 @@ Forces the `where` clause to be laid out on a single line.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3359)
+- **Stable**: No (tracking issue: [#3359](https://github.com/rust-lang/rustfmt/issues/3359))
 
 #### `false` (default):
 
@@ -2825,7 +2825,7 @@ Break comments to fit on the line
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3347)
+- **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347))
 
 #### `false` (default):
 

From eee8f0419dca910187350ac38fe9694b8b7919b9 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 17 Nov 2021 12:51:37 -0600
Subject: [PATCH 096/195] refactor: cleanup duplicative Impl handling code

---
 src/items.rs   | 503 +++++++++++++++++++++++--------------------------
 src/visitor.rs |   4 +-
 2 files changed, 237 insertions(+), 270 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index 50121a8b6b5..849e6c06218 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -579,6 +579,25 @@ impl<'a> FmtVisitor<'a> {
 
     fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
         if self.get_context().config.reorder_impl_items() {
+            type TyOpt = Option<ptr::P<ast::Ty>>;
+            use crate::ast::AssocItemKind::*;
+            let is_type = |ty: &TyOpt| {
+                ty.as_ref()
+                    .map_or(true, |t| !matches!(t.kind, ast::TyKind::ImplTrait(..)))
+            };
+            let is_opaque = |ty: &TyOpt| !is_type(ty);
+            let both_type = |left: &TyOpt, right: &TyOpt| is_type(left) && is_type(right);
+            let both_opaque = |left: &TyOpt, right: &TyOpt| is_opaque(left) && is_opaque(right);
+            let need_empty_line = |a: &ast::AssocItemKind, b: &ast::AssocItemKind| match (a, b) {
+                (TyAlias(lty), TyAlias(rty))
+                    if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
+                {
+                    false
+                }
+                (Const(..), Const(..)) => false,
+                _ => true,
+            };
+
             // Create visitor for each items, then reorder them.
             let mut buffer = vec![];
             for item in items {
@@ -587,50 +606,6 @@ impl<'a> FmtVisitor<'a> {
                 self.buffer.clear();
             }
 
-            fn is_type(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
-                if let Some(lty) = ty {
-                    if let ast::TyKind::ImplTrait(..) = lty.kind {
-                        return false;
-                    }
-                }
-                true
-            }
-
-            fn is_opaque(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
-                !is_type(ty)
-            }
-
-            fn both_type(
-                a: &Option<rustc_ast::ptr::P<ast::Ty>>,
-                b: &Option<rustc_ast::ptr::P<ast::Ty>>,
-            ) -> bool {
-                is_type(a) && is_type(b)
-            }
-
-            fn both_opaque(
-                a: &Option<rustc_ast::ptr::P<ast::Ty>>,
-                b: &Option<rustc_ast::ptr::P<ast::Ty>>,
-            ) -> bool {
-                is_opaque(a) && is_opaque(b)
-            }
-
-            // In rustc-ap-v638 the `OpaqueTy` AssocItemKind variant was removed but
-            // we still need to differentiate to maintain sorting order.
-
-            // type -> opaque -> const -> macro -> method
-            use crate::ast::AssocItemKind::*;
-            fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
-                match (a, b) {
-                    (TyAlias(lty), TyAlias(rty))
-                        if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
-                    {
-                        false
-                    }
-                    (Const(..), Const(..)) => false,
-                    _ => true,
-                }
-            }
-
             buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
                 (TyAlias(lty), TyAlias(rty))
                     if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
@@ -676,136 +651,133 @@ impl<'a> FmtVisitor<'a> {
 pub(crate) fn format_impl(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    iimpl: &ast::Impl,
     offset: Indent,
 ) -> Option<String> {
-    if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::Impl {
-            ref generics,
-            ref self_ty,
-            ref items,
-            ..
-        } = **impl_kind;
-        let mut result = String::with_capacity(128);
-        let ref_and_type = format_impl_ref_and_type(context, item, offset)?;
-        let sep = offset.to_string_with_newline(context.config);
-        result.push_str(&ref_and_type);
+    let ast::Impl {
+        generics,
+        self_ty,
+        items,
+        ..
+    } = iimpl;
+    let mut result = String::with_capacity(128);
+    let ref_and_type = format_impl_ref_and_type(context, item, iimpl, offset)?;
+    let sep = offset.to_string_with_newline(context.config);
+    result.push_str(&ref_and_type);
 
-        let where_budget = if result.contains('\n') {
-            context.config.max_width()
-        } else {
-            context.budget(last_line_width(&result))
-        };
-
-        let mut option = WhereClauseOption::snuggled(&ref_and_type);
-        let snippet = context.snippet(item.span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
-        if !contains_comment(&snippet[open_pos..])
-            && items.is_empty()
-            && generics.where_clause.predicates.len() == 1
-            && !result.contains('\n')
-        {
-            option.suppress_comma();
-            option.snuggle();
-            option.allow_single_line();
-        }
-
-        let missing_span = mk_sp(self_ty.span.hi(), item.span.hi());
-        let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
-        let where_clause_str = rewrite_where_clause(
-            context,
-            &generics.where_clause,
-            context.config.brace_style(),
-            Shape::legacy(where_budget, offset.block_only()),
-            false,
-            "{",
-            where_span_end,
-            self_ty.span.hi(),
-            option,
-        )?;
-
-        // If there is no where-clause, we may have missing comments between the trait name and
-        // the opening brace.
-        if generics.where_clause.predicates.is_empty() {
-            if let Some(hi) = where_span_end {
-                match recover_missing_comment_in_span(
-                    mk_sp(self_ty.span.hi(), hi),
-                    Shape::indented(offset, context.config),
-                    context,
-                    last_line_width(&result),
-                ) {
-                    Some(ref missing_comment) if !missing_comment.is_empty() => {
-                        result.push_str(missing_comment);
-                    }
-                    _ => (),
-                }
-            }
-        }
-
-        if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
-            result.push_str(&where_clause_str);
-            if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
-                // if the where_clause contains extra comments AND
-                // there is only one where-clause predicate
-                // recover the suppressed comma in single line where_clause formatting
-                if generics.where_clause.predicates.len() == 1 {
-                    result.push(',');
-                }
-                result.push_str(&format!("{}{{{}}}", sep, sep));
-            } else {
-                result.push_str(" {}");
-            }
-            return Some(result);
-        }
-
-        result.push_str(&where_clause_str);
-
-        let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
-        match context.config.brace_style() {
-            _ if need_newline => result.push_str(&sep),
-            BraceStyle::AlwaysNextLine => result.push_str(&sep),
-            BraceStyle::PreferSameLine => result.push(' '),
-            BraceStyle::SameLineWhere => {
-                if !where_clause_str.is_empty() {
-                    result.push_str(&sep);
-                } else {
-                    result.push(' ');
-                }
-            }
-        }
-
-        result.push('{');
-        // this is an impl body snippet(impl SampleImpl { /* here */ })
-        let lo = max(self_ty.span.hi(), generics.where_clause.span.hi());
-        let snippet = context.snippet(mk_sp(lo, item.span.hi()));
-        let open_pos = snippet.find_uncommented("{")? + 1;
-
-        if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
-            let mut visitor = FmtVisitor::from_context(context);
-            let item_indent = offset.block_only().block_indent(context.config);
-            visitor.block_indent = item_indent;
-            visitor.last_pos = lo + BytePos(open_pos as u32);
-
-            visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
-            visitor.visit_impl_items(items);
-
-            visitor.format_missing(item.span.hi() - BytePos(1));
-
-            let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
-            let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
-
-            result.push_str(&inner_indent_str);
-            result.push_str(visitor.buffer.trim());
-            result.push_str(&outer_indent_str);
-        } else if need_newline || !context.config.empty_item_single_line() {
-            result.push_str(&sep);
-        }
-
-        result.push('}');
-
-        Some(result)
+    let where_budget = if result.contains('\n') {
+        context.config.max_width()
     } else {
-        unreachable!();
+        context.budget(last_line_width(&result))
+    };
+
+    let mut option = WhereClauseOption::snuggled(&ref_and_type);
+    let snippet = context.snippet(item.span);
+    let open_pos = snippet.find_uncommented("{")? + 1;
+    if !contains_comment(&snippet[open_pos..])
+        && items.is_empty()
+        && generics.where_clause.predicates.len() == 1
+        && !result.contains('\n')
+    {
+        option.suppress_comma();
+        option.snuggle();
+        option.allow_single_line();
     }
+
+    let missing_span = mk_sp(self_ty.span.hi(), item.span.hi());
+    let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
+    let where_clause_str = rewrite_where_clause(
+        context,
+        &generics.where_clause,
+        context.config.brace_style(),
+        Shape::legacy(where_budget, offset.block_only()),
+        false,
+        "{",
+        where_span_end,
+        self_ty.span.hi(),
+        option,
+    )?;
+
+    // If there is no where-clause, we may have missing comments between the trait name and
+    // the opening brace.
+    if generics.where_clause.predicates.is_empty() {
+        if let Some(hi) = where_span_end {
+            match recover_missing_comment_in_span(
+                mk_sp(self_ty.span.hi(), hi),
+                Shape::indented(offset, context.config),
+                context,
+                last_line_width(&result),
+            ) {
+                Some(ref missing_comment) if !missing_comment.is_empty() => {
+                    result.push_str(missing_comment);
+                }
+                _ => (),
+            }
+        }
+    }
+
+    if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
+        result.push_str(&where_clause_str);
+        if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
+            // if the where_clause contains extra comments AND
+            // there is only one where-clause predicate
+            // recover the suppressed comma in single line where_clause formatting
+            if generics.where_clause.predicates.len() == 1 {
+                result.push(',');
+            }
+            result.push_str(&format!("{}{{{}}}", sep, sep));
+        } else {
+            result.push_str(" {}");
+        }
+        return Some(result);
+    }
+
+    result.push_str(&where_clause_str);
+
+    let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
+    match context.config.brace_style() {
+        _ if need_newline => result.push_str(&sep),
+        BraceStyle::AlwaysNextLine => result.push_str(&sep),
+        BraceStyle::PreferSameLine => result.push(' '),
+        BraceStyle::SameLineWhere => {
+            if !where_clause_str.is_empty() {
+                result.push_str(&sep);
+            } else {
+                result.push(' ');
+            }
+        }
+    }
+
+    result.push('{');
+    // this is an impl body snippet(impl SampleImpl { /* here */ })
+    let lo = max(self_ty.span.hi(), generics.where_clause.span.hi());
+    let snippet = context.snippet(mk_sp(lo, item.span.hi()));
+    let open_pos = snippet.find_uncommented("{")? + 1;
+
+    if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
+        let mut visitor = FmtVisitor::from_context(context);
+        let item_indent = offset.block_only().block_indent(context.config);
+        visitor.block_indent = item_indent;
+        visitor.last_pos = lo + BytePos(open_pos as u32);
+
+        visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
+        visitor.visit_impl_items(items);
+
+        visitor.format_missing(item.span.hi() - BytePos(1));
+
+        let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
+        let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
+
+        result.push_str(&inner_indent_str);
+        result.push_str(visitor.buffer.trim());
+        result.push_str(&outer_indent_str);
+    } else if need_newline || !context.config.empty_item_single_line() {
+        result.push_str(&sep);
+    }
+
+    result.push('}');
+
+    Some(result)
 }
 
 fn is_impl_single_line(
@@ -830,111 +802,106 @@ fn is_impl_single_line(
 fn format_impl_ref_and_type(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    iimpl: &ast::Impl,
     offset: Indent,
 ) -> Option<String> {
-    if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::Impl {
-            unsafety,
-            polarity,
-            defaultness,
-            constness,
-            ref generics,
-            of_trait: ref trait_ref,
-            ref self_ty,
-            ..
-        } = **impl_kind;
-        let mut result = String::with_capacity(128);
+    let ast::Impl {
+        unsafety,
+        polarity,
+        defaultness,
+        constness,
+        ref generics,
+        of_trait: ref trait_ref,
+        ref self_ty,
+        ..
+    } = *iimpl;
+    let mut result = String::with_capacity(128);
 
-        result.push_str(&format_visibility(context, &item.vis));
-        result.push_str(format_defaultness(defaultness));
-        result.push_str(format_unsafety(unsafety));
+    result.push_str(&format_visibility(context, &item.vis));
+    result.push_str(format_defaultness(defaultness));
+    result.push_str(format_unsafety(unsafety));
 
-        let shape = if context.config.version() == Version::Two {
-            Shape::indented(offset + last_line_width(&result), context.config)
-        } else {
-            generics_shape_from_config(
-                context.config,
-                Shape::indented(offset + last_line_width(&result), context.config),
-                0,
-            )?
-        };
-        let generics_str = rewrite_generics(context, "impl", generics, shape)?;
-        result.push_str(&generics_str);
-        result.push_str(format_constness_right(constness));
-
-        let polarity_str = match polarity {
-            ast::ImplPolarity::Negative(_) => "!",
-            ast::ImplPolarity::Positive => "",
-        };
-
-        let polarity_overhead;
-        let trait_ref_overhead;
-        if let Some(ref trait_ref) = *trait_ref {
-            let result_len = last_line_width(&result);
-            result.push_str(&rewrite_trait_ref(
-                context,
-                trait_ref,
-                offset,
-                polarity_str,
-                result_len,
-            )?);
-            polarity_overhead = 0; // already written
-            trait_ref_overhead = " for".len();
-        } else {
-            polarity_overhead = polarity_str.len();
-            trait_ref_overhead = 0;
-        }
-
-        // Try to put the self type in a single line.
-        let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
-            // If there is no where-clause adapt budget for type formatting to take space and curly
-            // brace into account.
-            match context.config.brace_style() {
-                BraceStyle::AlwaysNextLine => 0,
-                _ => 2,
-            }
-        } else {
-            0
-        };
-        let used_space = last_line_width(&result)
-            + polarity_overhead
-            + trait_ref_overhead
-            + curly_brace_overhead;
-        // 1 = space before the type.
-        let budget = context.budget(used_space + 1);
-        if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
-            if !self_ty_str.contains('\n') {
-                if trait_ref.is_some() {
-                    result.push_str(" for ");
-                } else {
-                    result.push(' ');
-                    result.push_str(polarity_str);
-                }
-                result.push_str(&self_ty_str);
-                return Some(result);
-            }
-        }
-
-        // Couldn't fit the self type on a single line, put it on a new line.
-        result.push('\n');
-        // Add indentation of one additional tab.
-        let new_line_offset = offset.block_indent(context.config);
-        result.push_str(&new_line_offset.to_string(context.config));
-        if trait_ref.is_some() {
-            result.push_str("for ");
-        } else {
-            result.push_str(polarity_str);
-        }
-        let budget = context.budget(last_line_width(&result) + polarity_overhead);
-        let type_offset = match context.config.indent_style() {
-            IndentStyle::Visual => new_line_offset + trait_ref_overhead,
-            IndentStyle::Block => new_line_offset,
-        };
-        result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
-        Some(result)
+    let shape = if context.config.version() == Version::Two {
+        Shape::indented(offset + last_line_width(&result), context.config)
     } else {
-        unreachable!();
+        generics_shape_from_config(
+            context.config,
+            Shape::indented(offset + last_line_width(&result), context.config),
+            0,
+        )?
+    };
+    let generics_str = rewrite_generics(context, "impl", generics, shape)?;
+    result.push_str(&generics_str);
+    result.push_str(format_constness_right(constness));
+
+    let polarity_str = match polarity {
+        ast::ImplPolarity::Negative(_) => "!",
+        ast::ImplPolarity::Positive => "",
+    };
+
+    let polarity_overhead;
+    let trait_ref_overhead;
+    if let Some(ref trait_ref) = *trait_ref {
+        let result_len = last_line_width(&result);
+        result.push_str(&rewrite_trait_ref(
+            context,
+            trait_ref,
+            offset,
+            polarity_str,
+            result_len,
+        )?);
+        polarity_overhead = 0; // already written
+        trait_ref_overhead = " for".len();
+    } else {
+        polarity_overhead = polarity_str.len();
+        trait_ref_overhead = 0;
     }
+
+    // Try to put the self type in a single line.
+    let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
+        // If there is no where-clause adapt budget for type formatting to take space and curly
+        // brace into account.
+        match context.config.brace_style() {
+            BraceStyle::AlwaysNextLine => 0,
+            _ => 2,
+        }
+    } else {
+        0
+    };
+    let used_space =
+        last_line_width(&result) + polarity_overhead + trait_ref_overhead + curly_brace_overhead;
+    // 1 = space before the type.
+    let budget = context.budget(used_space + 1);
+    if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
+        if !self_ty_str.contains('\n') {
+            if trait_ref.is_some() {
+                result.push_str(" for ");
+            } else {
+                result.push(' ');
+                result.push_str(polarity_str);
+            }
+            result.push_str(&self_ty_str);
+            return Some(result);
+        }
+    }
+
+    // Couldn't fit the self type on a single line, put it on a new line.
+    result.push('\n');
+    // Add indentation of one additional tab.
+    let new_line_offset = offset.block_indent(context.config);
+    result.push_str(&new_line_offset.to_string(context.config));
+    if trait_ref.is_some() {
+        result.push_str("for ");
+    } else {
+        result.push_str(polarity_str);
+    }
+    let budget = context.budget(last_line_width(&result) + polarity_overhead);
+    let type_offset = match context.config.indent_style() {
+        IndentStyle::Visual => new_line_offset + trait_ref_overhead,
+        IndentStyle::Block => new_line_offset,
+    };
+    result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
+    Some(result)
 }
 
 fn rewrite_trait_ref(
diff --git a/src/visitor.rs b/src/visitor.rs
index 527042d098a..e4a7be742ab 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -485,9 +485,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         if should_visit_node_again {
             match item.kind {
                 ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
-                ast::ItemKind::Impl { .. } => {
+                ast::ItemKind::Impl(ref iimpl) => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_impl(ctx, item, iimpl, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::Trait(..) => {

From 0023abfb2c826d8a9ff74146ece513b22b86fdce Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 18 Nov 2021 12:38:34 -0600
Subject: [PATCH 097/195] tests: add cases for type alias issues

---
 tests/source/issue_4823.rs |  5 +++++
 tests/source/issue_5027.rs |  7 +++++++
 tests/source/issue_5086.rs |  2 ++
 tests/target/issue_4823.rs |  5 +++++
 tests/target/issue_5027.rs | 17 +++++++++++++++++
 tests/target/issue_5086.rs |  2 ++
 6 files changed, 38 insertions(+)
 create mode 100644 tests/source/issue_4823.rs
 create mode 100644 tests/source/issue_5027.rs
 create mode 100644 tests/source/issue_5086.rs
 create mode 100644 tests/target/issue_4823.rs
 create mode 100644 tests/target/issue_5027.rs
 create mode 100644 tests/target/issue_5086.rs

diff --git a/tests/source/issue_4823.rs b/tests/source/issue_4823.rs
new file mode 100644
index 00000000000..a008dd3d838
--- /dev/null
+++ b/tests/source/issue_4823.rs
@@ -0,0 +1,5 @@
+macro_rules! m {
+() => {
+type Type;
+};
+}
diff --git a/tests/source/issue_5027.rs b/tests/source/issue_5027.rs
new file mode 100644
index 00000000000..67beeb23b71
--- /dev/null
+++ b/tests/source/issue_5027.rs
@@ -0,0 +1,7 @@
+// rustfmt-version: Two
+
+pub type Iter<'a, D> =                 impl       DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;
+
+trait FOo {pub type Iter<'a, D> = impl        DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;}
+
+impl Bar {pub type Iter<'a, D> = impl             DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;}
\ No newline at end of file
diff --git a/tests/source/issue_5086.rs b/tests/source/issue_5086.rs
new file mode 100644
index 00000000000..1644c9d2ccb
--- /dev/null
+++ b/tests/source/issue_5086.rs
@@ -0,0 +1,2 @@
+#[cfg(any())]
+    type   Type :   Bound ;
\ No newline at end of file
diff --git a/tests/target/issue_4823.rs b/tests/target/issue_4823.rs
new file mode 100644
index 00000000000..de17467c0ef
--- /dev/null
+++ b/tests/target/issue_4823.rs
@@ -0,0 +1,5 @@
+macro_rules! m {
+    () => {
+        type Type;
+    };
+}
diff --git a/tests/target/issue_5027.rs b/tests/target/issue_5027.rs
new file mode 100644
index 00000000000..26d771720b6
--- /dev/null
+++ b/tests/target/issue_5027.rs
@@ -0,0 +1,17 @@
+// rustfmt-version: Two
+
+pub type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+    + ExactSizeIterator
+    + 'a;
+
+trait FOo {
+    pub type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+        + ExactSizeIterator
+        + 'a;
+}
+
+impl Bar {
+    type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
+        + ExactSizeIterator
+        + 'a;
+}
diff --git a/tests/target/issue_5086.rs b/tests/target/issue_5086.rs
new file mode 100644
index 00000000000..7a0be06f791
--- /dev/null
+++ b/tests/target/issue_5086.rs
@@ -0,0 +1,2 @@
+#[cfg(any())]
+type Type: Bound;

From 2c442ccf25a98c9e8f0a972d94f10ef44b7b09bf Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 18 Nov 2021 12:39:38 -0600
Subject: [PATCH 098/195] fix: correct some type alias issues

---
 src/items.rs | 49 ++++++++++++++++++++++++-------------------------
 src/types.rs |  8 ++++++++
 2 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index 849e6c06218..63c32e012df 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -28,6 +28,7 @@ use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt::Stmt;
+use crate::types::opaque_ty;
 use crate::utils::*;
 use crate::vertical::rewrite_with_alignment;
 use crate::visitor::FmtVisitor;
@@ -581,13 +582,10 @@ impl<'a> FmtVisitor<'a> {
         if self.get_context().config.reorder_impl_items() {
             type TyOpt = Option<ptr::P<ast::Ty>>;
             use crate::ast::AssocItemKind::*;
-            let is_type = |ty: &TyOpt| {
-                ty.as_ref()
-                    .map_or(true, |t| !matches!(t.kind, ast::TyKind::ImplTrait(..)))
-            };
-            let is_opaque = |ty: &TyOpt| !is_type(ty);
-            let both_type = |left: &TyOpt, right: &TyOpt| is_type(left) && is_type(right);
-            let both_opaque = |left: &TyOpt, right: &TyOpt| is_opaque(left) && is_opaque(right);
+            let is_type = |ty: &TyOpt| opaque_ty(ty).is_none();
+            let is_opaque = |ty: &TyOpt| opaque_ty(ty).is_some();
+            let both_type = |l: &TyOpt, r: &TyOpt| is_type(l) && is_type(r);
+            let both_opaque = |l: &TyOpt, r: &TyOpt| is_opaque(l) && is_opaque(r);
             let need_empty_line = |a: &ast::AssocItemKind, b: &ast::AssocItemKind| match (a, b) {
                 (TyAlias(lty), TyAlias(rty))
                     if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
@@ -1508,43 +1506,38 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         ref bounds,
         ref ty,
     } = *ty_alias_kind;
-    let ty_opt = ty.as_ref().map(|t| &**t);
+    let ty_opt = ty.as_ref();
     let (ident, vis) = match visitor_kind {
         Item(i) => (i.ident, &i.vis),
         AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
         ForeignItem(i) => (i.ident, &i.vis),
     };
     let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
-
+    let op_ty = opaque_ty(ty);
     // Type Aliases are formatted slightly differently depending on the context
     // in which they appear, whether they are opaque, and whether they are associated.
     // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
     // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
-    match (visitor_kind, ty_opt) {
-        (Item(_), None) => {
-            let op_ty = OpaqueType { bounds };
-            rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis)
+    match (visitor_kind, &op_ty) {
+        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(ref op_bounds)) => {
+            let op = OpaqueType { bounds: op_bounds };
+            rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
+        }
+        (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
+            rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
         }
-        (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis),
         (AssocImplItem(_), _) => {
-            let result = if let Some(ast::Ty {
-                kind: ast::TyKind::ImplTrait(_, ref bounds),
-                ..
-            }) = ty_opt
-            {
-                let op_ty = OpaqueType { bounds };
-                rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
+            let result = if let Some(ref op_bounds) = op_ty {
+                let op = OpaqueType { bounds: op_bounds };
+                rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
             } else {
-                rewrite_ty(rw_info, None, ty.as_ref(), vis)
+                rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
             }?;
             match defaultness {
                 ast::Defaultness::Default(..) => Some(format!("default {}", result)),
                 _ => Some(result),
             }
         }
-        (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
-            rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
-        }
     }
 }
 
@@ -1867,6 +1860,12 @@ fn rewrite_static(
         Some(format!("{}{};", prefix, ty_str))
     }
 }
+
+// FIXME(calebcartwright) - This is a hack around a bug in the handling of TyKind::ImplTrait.
+// This should be removed once that bug is resolved, with the type alias formatting using the
+// defined Ty for the RHS directly.
+// https://github.com/rust-lang/rustfmt/issues/4373
+// https://github.com/rust-lang/rustfmt/issues/5027
 struct OpaqueType<'a> {
     bounds: &'a ast::GenericBounds,
 }
diff --git a/src/types.rs b/src/types.rs
index 9ea90c5e46d..891609783b6 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -2,6 +2,7 @@ use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
 use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_ast::ptr;
 use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
 use crate::comment::{combine_strs_with_missing_comments, contains_comment};
@@ -1031,6 +1032,13 @@ fn join_bounds_inner(
     }
 }
 
+pub(crate) fn opaque_ty(ty: &Option<ptr::P<ast::Ty>>) -> Option<&ast::GenericBounds> {
+    ty.as_ref().and_then(|t| match &t.kind {
+        ast::TyKind::ImplTrait(_, bounds) => Some(bounds),
+        _ => None,
+    })
+}
+
 pub(crate) fn can_be_overflowed_type(
     context: &RewriteContext<'_>,
     ty: &ast::Ty,

From 196e6765048b8306208ac88d743ab02e8faf4b6b Mon Sep 17 00:00:00 2001
From: mujpao <mujpao@gmail.com>
Date: Thu, 18 Nov 2021 17:06:49 -0800
Subject: [PATCH 099/195] Preserve normalized comments after last list item

---
 src/lists.rs                                  |  13 +-
 .../wrap-comments-not-normalized.rs           | 108 ++++++++++++++++
 tests/source/issue-4909/wrap-comments-true.rs | 109 ++++++++++++++++
 .../target/issue-4909/wrap-comments-false.rs  |  72 +++++++++++
 .../wrap-comments-not-normalized.rs           | 118 +++++++++++++++++
 tests/target/issue-4909/wrap-comments-true.rs | 119 ++++++++++++++++++
 6 files changed, 535 insertions(+), 4 deletions(-)
 create mode 100644 tests/source/issue-4909/wrap-comments-not-normalized.rs
 create mode 100644 tests/source/issue-4909/wrap-comments-true.rs
 create mode 100644 tests/target/issue-4909/wrap-comments-false.rs
 create mode 100644 tests/target/issue-4909/wrap-comments-not-normalized.rs
 create mode 100644 tests/target/issue-4909/wrap-comments-true.rs

diff --git a/src/lists.rs b/src/lists.rs
index d341ec8e6b0..3515dd17251 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -444,10 +444,15 @@ where
                 let offset = formatting.shape.indent + overhead;
                 let comment_shape = Shape::legacy(width, offset);
 
-                // Use block-style only for the last item or multiline comments.
-                let block_style = !formatting.ends_with_newline && last
-                    || comment.trim().contains('\n')
-                    || comment.trim().len() > width;
+                let block_style = if !formatting.ends_with_newline && last {
+                    true
+                } else if starts_with_newline(comment) {
+                    false
+                } else if comment.trim().contains('\n') || comment.trim().len() > width {
+                    true
+                } else {
+                    false
+                };
 
                 rewrite_comment(
                     comment.trim_start(),
diff --git a/tests/source/issue-4909/wrap-comments-not-normalized.rs b/tests/source/issue-4909/wrap-comments-not-normalized.rs
new file mode 100644
index 00000000000..cd8de2707f1
--- /dev/null
+++ b/tests/source/issue-4909/wrap-comments-not-normalized.rs
@@ -0,0 +1,108 @@
+// rustfmt-wrap_comments: true
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    ];
+}
diff --git a/tests/source/issue-4909/wrap-comments-true.rs b/tests/source/issue-4909/wrap-comments-true.rs
new file mode 100644
index 00000000000..f18d8d686e1
--- /dev/null
+++ b/tests/source/issue-4909/wrap-comments-true.rs
@@ -0,0 +1,109 @@
+// rustfmt-normalize_comments: true
+// rustfmt-wrap_comments: true
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    ];
+}
diff --git a/tests/target/issue-4909/wrap-comments-false.rs b/tests/target/issue-4909/wrap-comments-false.rs
new file mode 100644
index 00000000000..a8ead584f44
--- /dev/null
+++ b/tests/target/issue-4909/wrap-comments-false.rs
@@ -0,0 +1,72 @@
+// rustfmt-normalize_comments: true
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+}
diff --git a/tests/target/issue-4909/wrap-comments-not-normalized.rs b/tests/target/issue-4909/wrap-comments-not-normalized.rs
new file mode 100644
index 00000000000..2a3d803b3b1
--- /dev/null
+++ b/tests/target/issue-4909/wrap-comments-not-normalized.rs
@@ -0,0 +1,118 @@
+// rustfmt-wrap_comments: true
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    ];
+}
diff --git a/tests/target/issue-4909/wrap-comments-true.rs b/tests/target/issue-4909/wrap-comments-true.rs
new file mode 100644
index 00000000000..5376962a2ee
--- /dev/null
+++ b/tests/target/issue-4909/wrap-comments-true.rs
@@ -0,0 +1,119 @@
+// rustfmt-normalize_comments: true
+// rustfmt-wrap_comments: true
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S3 {
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo3(
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage through the inclusion
+    // pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v3 = vec![
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    ];
+}

From 826eba8984690b7c23aab8604b6a85587bb93edb Mon Sep 17 00:00:00 2001
From: Johannes Linke <karyon@users.noreply.github.com>
Date: Sat, 20 Nov 2021 02:22:50 +0100
Subject: [PATCH 100/195] Add a few missing tracking issues in
 Configurations.md (#5084)

* Add a few missing tracking issues in Configurations.md

* fix: tracking issue for imports_granularity stabilization

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
---
 Configurations.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 4a281251f22..a89fbe863e6 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -933,7 +933,7 @@ if any of the first five lines contains `@generated` marker.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080))
 
 ## `format_macro_matchers`
 
@@ -1064,7 +1064,7 @@ Control the case of the letters in hexadecimal literal values
 
 - **Default value**: `Preserve`
 - **Possible values**: `Upper`, `Lower`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5081](https://github.com/rust-lang/rustfmt/issues/5081))
 
 ## `hide_parse_errors`
 
@@ -1701,7 +1701,7 @@ How imports should be grouped into `use` statements. Imports will be merged or s
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991))
 
 #### `Preserve` (default):
 
@@ -2063,7 +2063,7 @@ Controls the strategy for how imports are grouped together.
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `StdExternalCrate`, `One`
-- **Stable**: No
+- **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083))
 
 #### `Preserve` (default):
 

From 4389a4ce49e737915af1f1b27b96b05598a4e388 Mon Sep 17 00:00:00 2001
From: Dom <dom@itsallbroken.com>
Date: Fri, 19 Nov 2021 20:15:33 +0100
Subject: [PATCH 101/195] fix: do not wrap reference-style doc links

Prevents wrap_comments from incorrectly wrapping reference-style doc
links.
---
 src/comment.rs             | 19 ++++++++++++++++++-
 tests/target/issue-5095.rs | 27 +++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 tests/target/issue-5095.rs

diff --git a/src/comment.rs b/src/comment.rs
index 7b76c232937..830d2b50aad 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -3,6 +3,8 @@
 use std::{self, borrow::Cow, iter};
 
 use itertools::{multipeek, MultiPeek};
+use lazy_static::lazy_static;
+use regex::Regex;
 use rustc_span::Span;
 
 use crate::config::Config;
@@ -15,6 +17,17 @@ use crate::utils::{
 };
 use crate::{ErrorKind, FormattingError};
 
+lazy_static! {
+    /// A regex matching reference doc links.
+    ///
+    /// ```markdown
+    /// /// An [example].
+    /// ///
+    /// /// [example]: this::is::a::link
+    /// ```
+    static ref REFERENCE_LINK_URL: Regex = Regex::new(r"^\[.+\]\s?:").unwrap();
+}
+
 fn is_custom_comment(comment: &str) -> bool {
     if !comment.starts_with("//") {
         false
@@ -842,7 +855,11 @@ fn trim_custom_comment_prefix(s: &str) -> String {
 /// Returns `true` if the given string MAY include URLs or alike.
 fn has_url(s: &str) -> bool {
     // This function may return false positive, but should get its job done in most cases.
-    s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://")
+    s.contains("https://")
+        || s.contains("http://")
+        || s.contains("ftp://")
+        || s.contains("file://")
+        || REFERENCE_LINK_URL.is_match(s)
 }
 
 /// Given the span, rewrite the missing comment inside it if available.
diff --git a/tests/target/issue-5095.rs b/tests/target/issue-5095.rs
new file mode 100644
index 00000000000..6981a65808c
--- /dev/null
+++ b/tests/target/issue-5095.rs
@@ -0,0 +1,27 @@
+// rustfmt-wrap_comments: true
+
+pub mod a_long_name {
+    pub mod b_long_name {
+        pub mod c_long_name {
+            pub mod d_long_name {
+                pub mod e_long_name {
+                    pub struct Bananas;
+                    impl Bananas {
+                        pub fn fantastic() {}
+                    }
+
+                    pub mod f_long_name {
+                        pub struct Apples;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/// Check out [my other struct] ([`Bananas`]) and [the method it has].
+///
+/// [my other struct]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::f_long_name::Apples
+/// [`Bananas`]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic()
+/// [the method it has]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic()
+pub struct A;

From 243cec7a0b9cc0ba3fba6e5ed849b0635f3496db Mon Sep 17 00:00:00 2001
From: Fabian Keller <bluenote10@users.noreply.github.com>
Date: Wed, 24 Nov 2021 10:38:55 +0100
Subject: [PATCH 102/195] Update README.md

---
 README.md | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index b3d21e6fb87..b3a968f0c04 100644
--- a/README.md
+++ b/README.md
@@ -48,12 +48,11 @@ cargo +nightly fmt
 ## Limitations
 
 Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
-doesn't even need to compile! As we approach a 1.0 release we are also looking
-to limit areas of instability; in particular, post-1.0, the formatting of most
-code should not change as Rustfmt improves. However, there are some things that
-Rustfmt can't do or can't do well (and thus where formatting might change
-significantly, even post-1.0). We would like to reduce the list of limitations
-over time.
+doesn't even need to compile! In general, we are looking to limit areas of
+instability; in particular, post-1.0, the formatting of most code should not
+change as Rustfmt improves. However, there are some things that Rustfmt can't
+do or can't do well (and thus where formatting might change significantly,
+even post-1.0). We would like to reduce the list of limitations over time.
 
 The following list enumerates areas where Rustfmt does not work or where the
 stability guarantees do not apply (we don't make a distinction between the two

From ea042b90c9b66cf5431acddd29e54468c05ea65b Mon Sep 17 00:00:00 2001
From: mujpao <mujpao@gmail.com>
Date: Wed, 24 Nov 2021 15:05:23 -0800
Subject: [PATCH 103/195] Add more tests for comments in lists

---
 .../wrap-comments-not-normalized.rs           | 21 ++++
 .../wrap-comments-true.rs                     | 21 ++++
 .../comments-in-lists/format-doc-comments.rs  | 96 +++++++++++++++++++
 .../wrap-comments-false.rs                    | 13 +++
 .../wrap-comments-not-normalized.rs           | 24 +++++
 .../wrap-comments-true.rs                     | 24 +++++
 6 files changed, 199 insertions(+)
 rename tests/source/{issue-4909 => comments-in-lists}/wrap-comments-not-normalized.rs (81%)
 rename tests/source/{issue-4909 => comments-in-lists}/wrap-comments-true.rs (81%)
 create mode 100644 tests/target/comments-in-lists/format-doc-comments.rs
 rename tests/target/{issue-4909 => comments-in-lists}/wrap-comments-false.rs (82%)
 rename tests/target/{issue-4909 => comments-in-lists}/wrap-comments-not-normalized.rs (81%)
 rename tests/target/{issue-4909 => comments-in-lists}/wrap-comments-true.rs (81%)

diff --git a/tests/source/issue-4909/wrap-comments-not-normalized.rs b/tests/source/comments-in-lists/wrap-comments-not-normalized.rs
similarity index 81%
rename from tests/source/issue-4909/wrap-comments-not-normalized.rs
rename to tests/source/comments-in-lists/wrap-comments-not-normalized.rs
index cd8de2707f1..b96c02802d6 100644
--- a/tests/source/issue-4909/wrap-comments-not-normalized.rs
+++ b/tests/source/comments-in-lists/wrap-comments-not-normalized.rs
@@ -1,5 +1,6 @@
 // rustfmt-wrap_comments: true
 
+// https://github.com/rust-lang/rustfmt/issues/4909
 pub enum E {
     // Expand as needed, numbers should be ascending according to the stage
     // through the inclusion pipeline, or according to the descriptions
@@ -105,4 +106,24 @@ fn main() {
         2,
         // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
     ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    }
 }
diff --git a/tests/source/issue-4909/wrap-comments-true.rs b/tests/source/comments-in-lists/wrap-comments-true.rs
similarity index 81%
rename from tests/source/issue-4909/wrap-comments-true.rs
rename to tests/source/comments-in-lists/wrap-comments-true.rs
index f18d8d686e1..360b838520e 100644
--- a/tests/source/issue-4909/wrap-comments-true.rs
+++ b/tests/source/comments-in-lists/wrap-comments-true.rs
@@ -1,6 +1,7 @@
 // rustfmt-normalize_comments: true
 // rustfmt-wrap_comments: true
 
+// https://github.com/rust-lang/rustfmt/issues/4909
 pub enum E {
     // Expand as needed, numbers should be ascending according to the stage
     // through the inclusion pipeline, or according to the descriptions
@@ -106,4 +107,24 @@ fn main() {
         2,
         // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
     ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions
+    }
 }
diff --git a/tests/target/comments-in-lists/format-doc-comments.rs b/tests/target/comments-in-lists/format-doc-comments.rs
new file mode 100644
index 00000000000..be31bf0a331
--- /dev/null
+++ b/tests/target/comments-in-lists/format-doc-comments.rs
@@ -0,0 +1,96 @@
+// rustfmt-format_code_in_doc_comments: true
+
+// https://github.com/rust-lang/rustfmt/issues/4420
+enum Minimal {
+    Example,
+    //[thisisremoved thatsleft
+    // canbeanything
+}
+
+struct Minimal2 {
+    Example: usize,
+    //[thisisremoved thatsleft
+    // canbeanything
+}
+
+pub enum E {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant1,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    Variant2,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub enum E2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S {
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    some_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    last_field: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+}
+
+pub struct S2 {
+    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
+// Expand as needed, numbers should be ascending according to the stage
+// through the inclusion pipeline, or according to the descriptions
+}
+
+fn foo(
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    a: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+    b: usize,
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn foo2(// Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
+) -> usize {
+    5
+}
+
+fn main() {
+    let v = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        1,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        2,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    let v2: Vec<i32> = vec![
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    ];
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+}
diff --git a/tests/target/issue-4909/wrap-comments-false.rs b/tests/target/comments-in-lists/wrap-comments-false.rs
similarity index 82%
rename from tests/target/issue-4909/wrap-comments-false.rs
rename to tests/target/comments-in-lists/wrap-comments-false.rs
index a8ead584f44..80aea59d1b5 100644
--- a/tests/target/issue-4909/wrap-comments-false.rs
+++ b/tests/target/comments-in-lists/wrap-comments-false.rs
@@ -1,5 +1,6 @@
 // rustfmt-normalize_comments: true
 
+// https://github.com/rust-lang/rustfmt/issues/4909
 pub enum E {
     // Expand as needed, numbers should be ascending according to the stage
     // through the inclusion pipeline, or according to the descriptions
@@ -69,4 +70,16 @@ fn main() {
         // Expand as needed, numbers should be ascending according to the stage
         // through the inclusion pipeline, or according to the descriptions
     ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
 }
diff --git a/tests/target/issue-4909/wrap-comments-not-normalized.rs b/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
similarity index 81%
rename from tests/target/issue-4909/wrap-comments-not-normalized.rs
rename to tests/target/comments-in-lists/wrap-comments-not-normalized.rs
index 2a3d803b3b1..52315f470e4 100644
--- a/tests/target/issue-4909/wrap-comments-not-normalized.rs
+++ b/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
@@ -1,5 +1,6 @@
 // rustfmt-wrap_comments: true
 
+// https://github.com/rust-lang/rustfmt/issues/4909
 pub enum E {
     // Expand as needed, numbers should be ascending according to the stage
     // through the inclusion pipeline, or according to the descriptions
@@ -115,4 +116,27 @@ fn main() {
         // Expand as needed, numbers should be ascending according to the stage through the
         // inclusion pipeline, or according to the descriptions
     ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    }
 }
diff --git a/tests/target/issue-4909/wrap-comments-true.rs b/tests/target/comments-in-lists/wrap-comments-true.rs
similarity index 81%
rename from tests/target/issue-4909/wrap-comments-true.rs
rename to tests/target/comments-in-lists/wrap-comments-true.rs
index 5376962a2ee..e0bfcf0b500 100644
--- a/tests/target/issue-4909/wrap-comments-true.rs
+++ b/tests/target/comments-in-lists/wrap-comments-true.rs
@@ -1,6 +1,7 @@
 // rustfmt-normalize_comments: true
 // rustfmt-wrap_comments: true
 
+// https://github.com/rust-lang/rustfmt/issues/4909
 pub enum E {
     // Expand as needed, numbers should be ascending according to the stage
     // through the inclusion pipeline, or according to the descriptions
@@ -116,4 +117,27 @@ fn main() {
         // Expand as needed, numbers should be ascending according to the stage through the
         // inclusion pipeline, or according to the descriptions
     ];
+
+    // https://github.com/rust-lang/rustfmt/issues/4430
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage
+        // through the inclusion pipeline, or according to the descriptions
+    }
+
+    match a {
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        b => c,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+        d => e,
+        // Expand as needed, numbers should be ascending according to the stage through the
+        // inclusion pipeline, or according to the descriptions
+    }
 }

From 67fd9ec3002d269c272f68fa0e34a1cb2ca5fd08 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Wed, 24 Nov 2021 03:35:01 -0500
Subject: [PATCH 104/195] Run Windows, Linux, and Mac CI tests with nightly and
 stable channels

---
 .github/workflows/linux.yml   | 5 ++++-
 .github/workflows/mac.yml     | 5 ++++-
 .github/workflows/windows.yml | 5 ++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 6eaae69c708..db497941642 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -8,7 +8,9 @@ on:
 jobs:
   test:
     runs-on: ubuntu-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits
       # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization.
@@ -20,6 +22,7 @@ jobs:
         target: [
           x86_64-unknown-linux-gnu,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     - name: checkout
diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml
index 79e4f69163e..55e1cc9539b 100644
--- a/.github/workflows/mac.yml
+++ b/.github/workflows/mac.yml
@@ -10,13 +10,16 @@ jobs:
     # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources
     # macOS Catalina 10.15
     runs-on: macos-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       fail-fast: false
       matrix:
         target: [
           x86_64-apple-darwin,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     - name: checkout
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index c05e8d4896a..dcb08b5412e 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -8,7 +8,9 @@ on:
 jobs:
   test:
     runs-on: windows-latest
-    name: (${{ matrix.target }}, nightly)
+    name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
+    env:
+      CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }}
     strategy:
       # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits
       # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization.
@@ -23,6 +25,7 @@ jobs:
           x86_64-pc-windows-gnu,
           x86_64-pc-windows-msvc,
         ]
+        cfg_release_channel: [nightly, stable]
 
     steps:
     # The Windows runners have autocrlf enabled by default

From a21f1b6c2a5734f39a1efe3fa84d6475843d14fe Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sat, 27 Nov 2021 17:14:15 -0500
Subject: [PATCH 105/195] Conditionally compile tests based on
 CFG_RELEASE_CHANNEL env var

Adds the ``nightly_only_test`` and ``stable_only_test`` attribute macros
that prevent or allow certain tests to compile on nightly and stable
respectively. This is achieved through conditionally outputting the
tests TokenStream.

If CFG_RELEASE_CHANNEL is not set, it's assumed that we're running in a
nightly environment.

To mark a test as nightly only:

    #[nightly_only_test]
    #[test]
    fn only_run_on_nightly() {
        ...
    }

To mark a test a stable only:

    #[stable_only_test]
    #[test]
    fn only_run_on_stable() {
        ...
    }
---
 config_proc_macro/src/lib.rs | 42 ++++++++++++++++++
 src/config/mod.rs            | 82 +++++++++++++++---------------------
 src/syntux/session.rs        | 15 +++----
 src/test/mod.rs              | 13 +++---
 4 files changed, 86 insertions(+), 66 deletions(-)

diff --git a/config_proc_macro/src/lib.rs b/config_proc_macro/src/lib.rs
index 78e7e098ed9..51301821319 100644
--- a/config_proc_macro/src/lib.rs
+++ b/config_proc_macro/src/lib.rs
@@ -8,6 +8,8 @@ mod item_enum;
 mod item_struct;
 mod utils;
 
+use std::str::FromStr;
+
 use proc_macro::TokenStream;
 use syn::parse_macro_input;
 
@@ -23,3 +25,43 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream {
 
     TokenStream::from(output)
 }
+
+/// Used to conditionally output the TokenStream for tests that need to be run on nightly only.
+///
+/// ```rust
+/// #[nightly_only_test]
+/// #[test]
+/// fn test_needs_nightly_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn nightly_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is true
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set to "nightly" or "dev"
+        TokenStream::from_str("").unwrap()
+    }
+}
+
+/// Used to conditionally output the TokenStream for tests that need to be run on stable only.
+///
+/// ```rust
+/// #[stable_only_test]
+/// #[test]
+/// fn test_needs_stable_rustfmt() {
+///   assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+    // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is false
+    if option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "stable") {
+        input
+    } else {
+        // output an empty token stream if CFG_RELEASE_CHANNEL is not set or is not 'stable'
+        TokenStream::from_str("").unwrap()
+    }
+}
diff --git a/src/config/mod.rs b/src/config/mod.rs
index c5419d860c9..5dbe532ac38 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -405,6 +405,8 @@ mod test {
     use super::*;
     use std::str;
 
+    use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
+
     #[allow(dead_code)]
     mod mock {
         use super::super::*;
@@ -525,21 +527,17 @@ mod test {
         assert!(config.license_template.is_none());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_valid_license_template_path() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
     }
 
+    #[nightly_only_test]
     #[test]
     fn test_override_existing_license_with_no_license() {
-        if !crate::is_nightly_channel!() {
-            return;
-        }
         let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
         let mut config = Config::from_toml(toml, Path::new("")).unwrap();
         assert!(config.license_template.is_some());
@@ -634,48 +632,42 @@ make_backup = false
         assert_eq!(&toml, &default_config);
     }
 
-    // FIXME(#2183): these tests cannot be run in parallel because they use env vars.
-    // #[test]
-    // fn test_as_not_nightly_channel() {
-    //     let mut config = Config::default();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    // }
+    #[stable_only_test]
+    #[test]
+    fn test_as_not_nightly_channel() {
+        let mut config = Config::default();
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.was_set().unstable_features(), false);
+    }
 
-    // #[test]
-    // fn test_as_nightly_channel() {
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     let mut config = Config::default();
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     config.set().unstable_features(true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
+    #[nightly_only_test]
+    #[test]
+    fn test_as_nightly_channel() {
+        let mut config = Config::default();
+        config.set().unstable_features(true);
+        // When we don't set the config from toml or command line options it
+        // doesn't get marked as set by the user.
+        assert_eq!(config.was_set().unstable_features(), false);
+        config.set().unstable_features(true);
+        assert_eq!(config.unstable_features(), true);
+    }
 
-    // #[test]
-    // fn test_unstable_from_toml() {
-    //     let mut config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), false);
-    //     let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from(""));
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly");
-    //     config = Config::from_toml("unstable_features = true").unwrap();
-    //     assert_eq!(config.was_set().unstable_features(), true);
-    //     assert_eq!(config.unstable_features(), true);
-    //     ::std::env::set_var("CFG_RELEASE_CHANNEL", v);
-    // }
+    #[nightly_only_test]
+    #[test]
+    fn test_unstable_from_toml() {
+        let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap();
+        assert_eq!(config.was_set().unstable_features(), true);
+        assert_eq!(config.unstable_features(), true);
+    }
 
     #[cfg(test)]
     mod deprecated_option_merge_imports {
         use super::*;
 
+        #[nightly_only_test]
         #[test]
         fn test_old_option_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -684,11 +676,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Crate);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_both_set() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -698,11 +688,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_new_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 merge_imports = true
@@ -712,11 +700,9 @@ make_backup = false
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
+        #[nightly_only_test]
         #[test]
         fn test_old_overridden() {
-            if !crate::is_nightly_channel!() {
-                return;
-            }
             let toml = r#"
                 unstable_features = true
                 imports_granularity = "Module"
diff --git a/src/syntux/session.rs b/src/syntux/session.rs
index cdb4893d443..dd7c7352686 100644
--- a/src/syntux/session.rs
+++ b/src/syntux/session.rs
@@ -286,10 +286,11 @@ impl LineRangeUtils for ParseSess {
 mod tests {
     use super::*;
 
+    use rustfmt_config_proc_macro::nightly_only_test;
+
     mod emitter {
         use super::*;
         use crate::config::IgnoreList;
-        use crate::is_nightly_channel;
         use crate::utils::mk_sp;
         use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP};
         use std::path::PathBuf;
@@ -371,11 +372,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#);
@@ -398,11 +397,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_recoverable_parse_error_in_non_ignored_file() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
@@ -424,11 +421,9 @@ mod tests {
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
 
+        #[nightly_only_test]
         #[test]
         fn handles_mix_of_recoverable_parse_error() {
-            if !is_nightly_channel!() {
-                return;
-            }
             let num_emitted_errors = Lrc::new(AtomicU32::new(0));
             let can_reset_errors = Lrc::new(AtomicBool::new(false));
             let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
diff --git a/src/test/mod.rs b/src/test/mod.rs
index e2620508c34..cceb28dfea6 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -15,6 +15,8 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu
 use crate::source_file;
 use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
 
+use rustfmt_config_proc_macro::nightly_only_test;
+
 mod configuration_snippet;
 mod mod_resolver;
 mod parser;
@@ -307,14 +309,11 @@ fn assert_output(source: &Path, expected_filename: &Path) {
 
 // Idempotence tests. Files in tests/target are checked to be unaltered by
 // rustfmt.
+#[nightly_only_test]
 #[test]
 fn idempotence_tests() {
     init_log();
     run_test_with(&TestSetting::default(), || {
-        // these tests require nightly
-        if !is_nightly_channel!() {
-            return;
-        }
         // Get all files in the tests/target directory.
         let files = get_test_files(Path::new("tests/target"), true);
         let (_reports, count, fails) = check_files(files, &None);
@@ -332,13 +331,11 @@ fn idempotence_tests() {
 
 // Run rustfmt on itself. This operation must be idempotent. We also check that
 // no warnings are emitted.
+// Issue-3443: these tests require nightly
+#[nightly_only_test]
 #[test]
 fn self_tests() {
     init_log();
-    // Issue-3443: these tests require nightly
-    if !is_nightly_channel!() {
-        return;
-    }
     let mut files = get_test_files(Path::new("tests"), false);
     let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
     for dir in bin_directories {

From 0fc846f979bc20d556cc07177b384094a421c54c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 28 Nov 2021 15:22:49 -0600
Subject: [PATCH 106/195] refactor: maintain more AST info when formatting a
 RHS

---
 src/expr.rs   | 57 +++++++++++++++++++++++++++++++++++++++++++--------
 src/items.rs  | 38 +++++++++++++++++++++++++++-------
 src/macros.rs |  5 +++--
 src/types.rs  |  5 +++--
 4 files changed, 86 insertions(+), 19 deletions(-)

diff --git a/src/expr.rs b/src/expr.rs
index 58942e442de..5fd86c1a4ea 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -196,9 +196,10 @@ pub(crate) fn format_expr(
                 capture, is_async, movability, fn_decl, body, expr.span, context, shape,
             )
         }
-        ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => {
-            rewrite_chain(expr, context, shape)
-        }
+        ast::ExprKind::Try(..)
+        | ast::ExprKind::Field(..)
+        | ast::ExprKind::MethodCall(..)
+        | 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(
@@ -377,7 +378,6 @@ pub(crate) fn format_expr(
                 ))
             }
         }
-        ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape),
         ast::ExprKind::Underscore => Some("_".to_owned()),
         ast::ExprKind::Err => None,
     };
@@ -829,6 +829,7 @@ impl<'a> ControlFlow<'a> {
                 &format!("{}{}{}", matcher, pat_string, self.connector),
                 expr,
                 cond_shape,
+                &RhsAssignKind::Expr(&expr.kind, expr.span),
                 RhsTactics::Default,
                 comments_span,
                 true,
@@ -1839,6 +1840,34 @@ fn rewrite_unary_op(
     rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape)
 }
 
+pub(crate) enum RhsAssignKind<'ast> {
+    Expr(&'ast ast::ExprKind, Span),
+    Bounds,
+    Ty,
+}
+
+impl<'ast> RhsAssignKind<'ast> {
+    // TODO(calebcartwright)
+    // Preemptive addition for handling RHS with chains, not yet utilized.
+    // It may make more sense to construct the chain first and then check
+    // whether there are actually chain elements.
+    #[allow(dead_code)]
+    fn is_chain(&self) -> bool {
+        match self {
+            RhsAssignKind::Expr(kind, _) => {
+                matches!(
+                    kind,
+                    ast::ExprKind::Try(..)
+                        | ast::ExprKind::Field(..)
+                        | ast::ExprKind::MethodCall(..)
+                        | ast::ExprKind::Await(_)
+                )
+            }
+            _ => false,
+        }
+    }
+}
+
 fn rewrite_assignment(
     context: &RewriteContext<'_>,
     lhs: &ast::Expr,
@@ -1855,7 +1884,13 @@ fn rewrite_assignment(
     let lhs_shape = shape.sub_width(operator_str.len() + 1)?;
     let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str);
 
-    rewrite_assign_rhs(context, lhs_str, rhs, shape)
+    rewrite_assign_rhs(
+        context,
+        lhs_str,
+        rhs,
+        &RhsAssignKind::Expr(&rhs.kind, rhs.span),
+        shape,
+    )
 }
 
 /// Controls where to put the rhs.
@@ -1876,9 +1911,10 @@ pub(crate) fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>(
     context: &RewriteContext<'_>,
     lhs: S,
     ex: &R,
+    rhs_kind: &RhsAssignKind<'_>,
     shape: Shape,
 ) -> Option<String> {
-    rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default)
+    rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default)
 }
 
 pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
@@ -1886,6 +1922,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     lhs: &str,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
     let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
@@ -1910,6 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
         ex,
         orig_shape,
         ex.rewrite(context, orig_shape),
+        rhs_kind,
         rhs_tactics,
         has_rhs_comment,
     )
@@ -1920,10 +1958,11 @@ pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
     lhs: S,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
     let lhs = lhs.into();
-    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?;
+    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
     Some(lhs + &rhs)
 }
 
@@ -1932,6 +1971,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
     lhs: S,
     ex: &R,
     shape: Shape,
+    rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
     between_span: Span,
     allow_extend: bool,
@@ -1943,7 +1983,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
     } else {
         shape
     };
-    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?;
+    let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
 
     if contains_comment {
         let rhs = rhs.trim_start();
@@ -1958,6 +1998,7 @@ fn choose_rhs<R: Rewrite>(
     expr: &R,
     shape: Shape,
     orig_rhs: Option<String>,
+    _rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
     has_rhs_comment: bool,
 ) -> Option<String> {
diff --git a/src/items.rs b/src/items.rs
index 63c32e012df..3fe827ce696 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -18,7 +18,7 @@ use crate::config::lists::*;
 use crate::config::{BraceStyle, Config, IndentStyle, Version};
 use crate::expr::{
     is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
-    rewrite_assign_rhs_with_comments, RhsTactics,
+    rewrite_assign_rhs_with_comments, RhsAssignKind, RhsTactics,
 };
 use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
 use crate::macros::{rewrite_macro, MacroPosition};
@@ -116,7 +116,13 @@ impl Rewrite for ast::Local {
             // 1 = trailing semicolon;
             let nested_shape = shape.sub_width(1)?;
 
-            result = rewrite_assign_rhs(context, result, init, nested_shape)?;
+            result = rewrite_assign_rhs(
+                context,
+                result,
+                init,
+                &RhsAssignKind::Expr(&init.kind, init.span),
+                nested_shape,
+            )?;
             // todo else
         }
 
@@ -564,11 +570,13 @@ impl<'a> FmtVisitor<'a> {
 
         let variant_body = if let Some(ref expr) = field.disr_expr {
             let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to);
+            let ex = &*expr.value;
             rewrite_assign_rhs_with(
                 &context,
                 lhs,
-                &*expr.value,
+                ex,
                 shape,
+                &RhsAssignKind::Expr(&ex.kind, ex.span),
                 RhsTactics::AllowOverflow,
             )?
         } else {
@@ -1033,6 +1041,7 @@ pub(crate) fn format_trait(
                 result + ":",
                 bounds,
                 shape,
+                &RhsAssignKind::Bounds,
                 RhsTactics::ForceNextLineWithoutIndent,
             )?;
         }
@@ -1213,7 +1222,14 @@ pub(crate) fn format_trait_alias(
         generic_bounds,
         generics,
     };
-    rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";")
+    rewrite_assign_rhs(
+        context,
+        lhs,
+        &trait_alias_bounds,
+        &RhsAssignKind::Bounds,
+        shape.sub_width(1)?,
+    )
+    .map(|s| s + ";")
 }
 
 fn format_unit_struct(
@@ -1630,7 +1646,7 @@ fn rewrite_ty<R: Rewrite>(
 
         // 1 = `;`
         let shape = Shape::indented(indent, context.config).sub_width(1)?;
-        rewrite_assign_rhs(context, lhs, &*ty, shape).map(|s| s + ";")
+        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
     } else {
         Some(format!("{};", result))
     }
@@ -1720,7 +1736,7 @@ pub(crate) fn rewrite_struct_field(
 
     let is_prefix_empty = prefix.is_empty();
     // We must use multiline. We are going to put attributes and a field on different lines.
-    let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
+    let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?;
     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
     let field_str = if is_prefix_empty {
         field_str.trim_start()
@@ -1850,6 +1866,7 @@ fn rewrite_static(
             &lhs,
             &**expr,
             Shape::legacy(remaining_width, offset.block_only()),
+            &RhsAssignKind::Expr(&expr.kind, expr.span),
             RhsTactics::Default,
             comments_span,
             true,
@@ -3147,7 +3164,14 @@ impl Rewrite for ast::ForeignItem {
                     rewrite_ident(context, self.ident)
                 );
                 // 1 = ;
-                rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
+                rewrite_assign_rhs(
+                    context,
+                    prefix,
+                    &**ty,
+                    &RhsAssignKind::Ty,
+                    shape.sub_width(1)?,
+                )
+                .map(|s| s + ";")
             }
             ast::ForeignItemKind::TyAlias(ref ty_alias) => {
                 let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
diff --git a/src/macros.rs b/src/macros.rs
index ef747638e33..a52568be9ea 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -27,7 +27,7 @@ use crate::comment::{
     contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
 };
 use crate::config::lists::*;
-use crate::expr::rewrite_array;
+use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
 use crate::rewrite::{Rewrite, RewriteContext};
@@ -1468,10 +1468,11 @@ fn format_lazy_static(
             id,
             ty.rewrite(context, nested_shape)?
         ));
-        result.push_str(&crate::expr::rewrite_assign_rhs(
+        result.push_str(&rewrite_assign_rhs(
             context,
             stmt,
             &*expr,
+            &RhsAssignKind::Expr(&expr.kind, expr.span),
             nested_shape.sub_width(1)?,
         )?);
         result.push(';');
diff --git a/src/types.rs b/src/types.rs
index 891609783b6..88f5dc43245 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -10,6 +10,7 @@ use crate::config::lists::*;
 use crate::config::{IndentStyle, TypeDensity, Version};
 use crate::expr::{
     format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
+    RhsAssignKind,
 };
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
@@ -430,7 +431,7 @@ impl Rewrite for ast::WherePredicate {
                     format!("{}{}", type_str, colon)
                 };
 
-                rewrite_assign_rhs(context, lhs, bounds, shape)?
+                rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)?
             }
             ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
                 ref lifetime,
@@ -443,7 +444,7 @@ impl Rewrite for ast::WherePredicate {
                 ..
             }) => {
                 let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?;
-                rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, shape)?
+                rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)?
             }
         };
 

From 1f28683ffacebc91b3bc47b94c56690633226ff9 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sun, 28 Nov 2021 23:39:31 -0500
Subject: [PATCH 107/195] Update nightly only test with #[nightly_only_test]
 attribute

---
 src/ignore_path.rs | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/src/ignore_path.rs b/src/ignore_path.rs
index d8974e12b8f..7738eee0a76 100644
--- a/src/ignore_path.rs
+++ b/src/ignore_path.rs
@@ -37,21 +37,17 @@ mod test {
     use crate::config::{Config, FileName};
     use crate::ignore_path::IgnorePathSet;
 
+    use rustfmt_config_proc_macro::nightly_only_test;
+
+    #[nightly_only_test]
     #[test]
     fn test_ignore_path_set() {
-        match option_env!("CFG_RELEASE_CHANNEL") {
-            // this test requires nightly
-            None | Some("nightly") => {
-                let config =
-                    Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new(""))
-                        .unwrap();
-                let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
+        let config =
+            Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap();
+        let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
 
-                assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));
-                assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs"))));
-                assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs"))));
-            }
-            _ => (),
-        };
+        assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));
+        assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs"))));
+        assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs"))));
     }
 }

From ec46ffd981d3d50572f1ad3f6033a7c33d27033f Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Fri, 19 Nov 2021 18:52:52 -0500
Subject: [PATCH 108/195] Determine when new comment lines are needed for
 itemized blocks

Fixes 5088

Previously, rustfmt would add a new comment line anytime it reformatted
an itemized block within a comment when ``wrap_comments=true``. This
would lead to rustfmt adding empty comments with trailing whitespace.

Now, new comment lines are only added if the original comment spanned
multiple lines, if the comment needs to be wrapped, or if the comment
originally started with an empty comment line.
---
 src/comment.rs                                | 43 +++++++++++++---
 ..._nested_long_comment_wrap_comments_true.rs | 33 +++++++++++++
 ..._long_itemized_block_wrap_comments_true.rs | 19 +++++++
 .../very_long_comment_wrap_comments_true.rs   | 13 +++++
 ...nested_long_comment_wrap_comments_false.rs | 33 +++++++++++++
 ..._nested_long_comment_wrap_comments_true.rs | 49 +++++++++++++++++++
 ...line_itemized_block_wrap_comments_false.rs | 17 +++++++
 ..._line_itemized_block_wrap_comments_true.rs | 17 +++++++
 ...with_itemized_block_wrap_comments_false.rs | 37 ++++++++++++++
 ..._with_itemized_block_wrap_comments_true.rs | 37 ++++++++++++++
 ...line_itemized_block_wrap_comments_false.rs |  9 ++++
 ..._line_itemized_block_wrap_comments_true.rs |  9 ++++
 ...long_itemized_block_wrap_comments_false.rs | 19 +++++++
 ..._long_itemized_block_wrap_comments_true.rs | 27 ++++++++++
 ..._with_empty_comment_wrap_comments_false.rs | 17 +++++++
 ...t_with_empty_comment_wrap_comments_true.rs | 17 +++++++
 .../very_long_comment_wrap_comments_false.rs  | 13 +++++
 .../very_long_comment_wrap_comments_true.rs   | 21 ++++++++
 18 files changed, 424 insertions(+), 6 deletions(-)
 create mode 100644 tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
 create mode 100644 tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
 create mode 100644 tests/source/issue-5088/very_long_comment_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5088/very_long_comment_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5088/very_long_comment_wrap_comments_true.rs

diff --git a/src/comment.rs b/src/comment.rs
index 830d2b50aad..0f850b9b2f2 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -519,6 +519,7 @@ struct CommentRewrite<'a> {
     opener: String,
     closer: String,
     line_start: String,
+    style: CommentStyle<'a>,
 }
 
 impl<'a> CommentRewrite<'a> {
@@ -528,10 +529,14 @@ impl<'a> CommentRewrite<'a> {
         shape: Shape,
         config: &'a Config,
     ) -> CommentRewrite<'a> {
-        let (opener, closer, line_start) = if block_style {
-            CommentStyle::SingleBullet.to_str_tuplet()
+        let ((opener, closer, line_start), style) = if block_style {
+            (
+                CommentStyle::SingleBullet.to_str_tuplet(),
+                CommentStyle::SingleBullet,
+            )
         } else {
-            comment_style(orig, config.normalize_comments()).to_str_tuplet()
+            let style = comment_style(orig, config.normalize_comments());
+            (style.to_str_tuplet(), style)
         };
 
         let max_width = shape
@@ -564,6 +569,7 @@ impl<'a> CommentRewrite<'a> {
             opener: opener.to_owned(),
             closer: closer.to_owned(),
             line_start: line_start.to_owned(),
+            style,
         };
         cr.result.push_str(opener);
         cr
@@ -583,6 +589,15 @@ impl<'a> CommentRewrite<'a> {
         result
     }
 
+    /// Check if any characters were written to the result buffer after the start of the comment.
+    /// when calling [`CommentRewrite::new()`] the result buffer is initiazlied with the opening
+    /// characters for the comment.
+    fn buffer_contains_comment(&self) -> bool {
+        // if self.result.len() < self.opener.len() then an empty comment is in the buffer
+        // if self.result.len() > self.opener.len() then a non empty comment is in the buffer
+        self.result.len() != self.opener.len()
+    }
+
     fn finish(mut self) -> String {
         if !self.code_block_buffer.is_empty() {
             // There is a code block that is not properly enclosed by backticks.
@@ -598,7 +613,12 @@ impl<'a> CommentRewrite<'a> {
             // the last few lines are part of an itemized block
             self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent);
             let item_fmt = ib.create_string_format(&self.fmt);
-            self.result.push_str(&self.comment_line_separator);
+
+            // only push a comment_line_separator for ItemizedBlocks if the comment is not empty
+            if self.buffer_contains_comment() {
+                self.result.push_str(&self.comment_line_separator);
+            }
+
             self.result.push_str(&ib.opener);
             match rewrite_string(
                 &ib.trimmed_block_as_string(),
@@ -632,7 +652,13 @@ impl<'a> CommentRewrite<'a> {
         line: &'a str,
         has_leading_whitespace: bool,
     ) -> bool {
-        let is_last = i == count_newlines(orig);
+        let num_newlines = count_newlines(orig);
+        let is_last = i == num_newlines;
+        let needs_new_comment_line = if self.style.is_block_comment() {
+            num_newlines > 0 || self.buffer_contains_comment()
+        } else {
+            self.buffer_contains_comment()
+        };
 
         if let Some(ref mut ib) = self.item_block {
             if ib.add_line(line) {
@@ -641,7 +667,12 @@ impl<'a> CommentRewrite<'a> {
             self.is_prev_line_multi_line = false;
             self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent);
             let item_fmt = ib.create_string_format(&self.fmt);
-            self.result.push_str(&self.comment_line_separator);
+
+            // only push a comment_line_separator if we need to start a new comment line
+            if needs_new_comment_line {
+                self.result.push_str(&self.comment_line_separator);
+            }
+
             self.result.push_str(&ib.opener);
             match rewrite_string(
                 &ib.trimmed_block_as_string(),
diff --git a/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
new file mode 100644
index 00000000000..09f68cae424
--- /dev/null
+++ b/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
@@ -0,0 +1,33 @@
+// rustfmt-wrap_comments: true
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
new file mode 100644
index 00000000000..75f748000f9
--- /dev/null
+++ b/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
@@ -0,0 +1,19 @@
+// rustfmt-wrap_comments: true
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs b/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs
new file mode 100644
index 00000000000..00437f00216
--- /dev/null
+++ b/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: true
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs b/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs
new file mode 100644
index 00000000000..f4801de0184
--- /dev/null
+++ b/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs
@@ -0,0 +1,33 @@
+// rustfmt-wrap_comments: false
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
new file mode 100644
index 00000000000..b289c9f859e
--- /dev/null
+++ b/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs
@@ -0,0 +1,49 @@
+// rustfmt-wrap_comments: true
+
+fn main() {
+    {
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                // - aaaa aaaaaaaaa aaaaaaaaa
+                                                //   aaaaaaaaa aaaaaaaaa
+                                                //   bbbbbbbbbb bbbbbbbbb
+                                                //   bbbbbbbbb ccc cccccccccc
+                                                //   ccccccc cccccccc
+
+                                                // * aaaa aaaaaaaaa aaaaaaaaa
+                                                //   aaaaaaaaa aaaaaaaaa
+                                                //   bbbbbbbbbb bbbbbbbbb
+                                                //   bbbbbbbbb ccc cccccccccc
+                                                //   ccccccc cccccccc
+
+                                                /* - aaaa aaaaaaaaa aaaaaaaaa
+                                                 *   aaaaaaaaa aaaaaaaaa
+                                                 *   bbbbbbbbbb bbbbbbbbb
+                                                 *   bbbbbbbbb ccc cccccccccc
+                                                 *   ccccccc cccccccc */
+
+                                                /* * aaaa aaaaaaaaa aaaaaaaaa
+                                                 *   aaaaaaaaa aaaaaaaaa
+                                                 *   bbbbbbbbbb bbbbbbbbb
+                                                 *   bbbbbbbbb ccc cccccccccc
+                                                 *   ccccccc cccccccc */
+                                            };
+                                        };
+                                    };
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+}
diff --git a/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs b/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs
new file mode 100644
index 00000000000..60beed1b048
--- /dev/null
+++ b/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: false
+
+// - some itemized block 1
+// - some itemized block 2
+
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6
+ */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8
+ */
diff --git a/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs b/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs
new file mode 100644
index 00000000000..84fba4b7c19
--- /dev/null
+++ b/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: true
+
+// - some itemized block 1
+// - some itemized block 2
+
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6
+ */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8
+ */
diff --git a/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs b/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs
new file mode 100644
index 00000000000..d1bf44f6c74
--- /dev/null
+++ b/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs
@@ -0,0 +1,37 @@
+// rustfmt-wrap_comments: false
+
+// Some text
+// - some itemized block 1
+// - some itemized block 2
+// Some more text
+// - some itemized block 3
+// - some itemized block 4
+// Even more text
+
+// Some text
+// * some itemized block 5
+// * some itemized block 6
+// Some more text
+// * some itemized block 7
+// * some itemized block 8
+// Even more text
+
+/*
+ * Some text
+ * - some itemized block 9
+ * - some itemized block 10
+ * Some more text
+ * - some itemized block 11
+ * - some itemized block 12
+ * Even more text
+ */
+
+/*
+ * Some text
+ * * some itemized block 13
+ * * some itemized block 14
+ * Some more text
+ * * some itemized block 15
+ * * some itemized block 16
+ * Even more text
+ */
diff --git a/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs b/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs
new file mode 100644
index 00000000000..f767491f902
--- /dev/null
+++ b/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs
@@ -0,0 +1,37 @@
+// rustfmt-wrap_comments: true
+
+// Some text
+// - some itemized block 1
+// - some itemized block 2
+// Some more text
+// - some itemized block 3
+// - some itemized block 4
+// Even more text
+
+// Some text
+// * some itemized block 5
+// * some itemized block 6
+// Some more text
+// * some itemized block 7
+// * some itemized block 8
+// Even more text
+
+/*
+ * Some text
+ * - some itemized block 9
+ * - some itemized block 10
+ * Some more text
+ * - some itemized block 11
+ * - some itemized block 12
+ * Even more text
+ */
+
+/*
+ * Some text
+ * * some itemized block 13
+ * * some itemized block 14
+ * Some more text
+ * * some itemized block 15
+ * * some itemized block 16
+ * Even more text
+ */
diff --git a/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs b/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs
new file mode 100644
index 00000000000..2cd85c787f9
--- /dev/null
+++ b/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs
@@ -0,0 +1,9 @@
+// rustfmt-wrap_comments: false
+
+// - some itemized block 1
+
+// * some itemized block 2
+
+/* - some itemized block 3 */
+
+/* * some itemized block 4 */
diff --git a/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs b/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs
new file mode 100644
index 00000000000..e9f343d75d5
--- /dev/null
+++ b/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs
@@ -0,0 +1,9 @@
+// rustfmt-wrap_comments: true
+
+// - some itemized block 1
+
+// * some itemized block 2
+
+/* - some itemized block 3 */
+
+/* * some itemized block 4 */
diff --git a/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs b/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs
new file mode 100644
index 00000000000..97bb7733d18
--- /dev/null
+++ b/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs
@@ -0,0 +1,19 @@
+// rustfmt-wrap_comments: false
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
new file mode 100644
index 00000000000..c8af8383e05
--- /dev/null
+++ b/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs
@@ -0,0 +1,27 @@
+// rustfmt-wrap_comments: true
+
+//
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+//
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/*
+ * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/*
+ * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
diff --git a/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs b/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs
new file mode 100644
index 00000000000..75cc42c0e66
--- /dev/null
+++ b/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: false
+
+//
+// - some itemized block 1
+// - some itemized block 2
+
+//
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6 */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8 */
diff --git a/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs b/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs
new file mode 100644
index 00000000000..ef2c8f90cd3
--- /dev/null
+++ b/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs
@@ -0,0 +1,17 @@
+// rustfmt-wrap_comments: true
+
+//
+// - some itemized block 1
+// - some itemized block 2
+
+//
+// * some itemized block 3
+// * some itemized block 4
+
+/*
+ * - some itemized block 5
+ * - some itemized block 6 */
+
+/*
+ * * some itemized block 7
+ * * some itemized block 8 */
diff --git a/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs b/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs
new file mode 100644
index 00000000000..c826cc5d4da
--- /dev/null
+++ b/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: false
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/
diff --git a/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs b/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs
new file mode 100644
index 00000000000..7f764dbd8a2
--- /dev/null
+++ b/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs
@@ -0,0 +1,21 @@
+// rustfmt-wrap_comments: true
+
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+//   tempor incididunt ut labore et dolore magna aliqua.
+
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */
+/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ *   tempor incididunt ut labore et dolore magna aliqua. */

From f40b1d9f1aeabca7a6e28d2d32d8458943111957 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Wed, 24 Nov 2021 18:47:37 -0500
Subject: [PATCH 109/195] Backport: Do not touch module with #![rustfmt::skip]
 (4297)

Although the implementation is slightly different than the original PR,
the general idea is the same. After collecting all modules we want to
exclude formatting those that contain the #![rustfmt::skip] attribute.
---
 src/formatting.rs                             | 52 +++++++++++++++----
 src/test/configuration_snippet.rs             | 21 +++++---
 src/test/mod_resolver.rs                      |  9 ++++
 src/visitor.rs                                | 13 ++---
 .../mod-resolver/skip-files-issue-5065/foo.rs |  5 ++
 .../skip-files-issue-5065/foo/bar/baz.rs      |  1 +
 .../skip-files-issue-5065/main.rs             |  9 ++++
 .../mod-resolver/skip-files-issue-5065/one.rs |  1 +
 .../target/skip/preserve_trailing_comment.rs  |  7 +++
 9 files changed, 93 insertions(+), 25 deletions(-)
 create mode 100644 tests/mod-resolver/skip-files-issue-5065/foo.rs
 create mode 100644 tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs
 create mode 100644 tests/mod-resolver/skip-files-issue-5065/main.rs
 create mode 100644 tests/mod-resolver/skip-files-issue-5065/one.rs
 create mode 100644 tests/target/skip/preserve_trailing_comment.rs

diff --git a/src/formatting.rs b/src/formatting.rs
index 7d0facb8f12..1972b5a87a5 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -5,6 +5,7 @@ use std::io::{self, Write};
 use std::time::{Duration, Instant};
 
 use rustc_ast::ast;
+use rustc_ast::AstLike;
 use rustc_span::Span;
 
 use self::newline_style::apply_newline_style;
@@ -15,7 +16,7 @@ use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
 use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
 use crate::syntux::session::ParseSess;
-use crate::utils::count_newlines;
+use crate::utils::{contains_skip, count_newlines};
 use crate::visitor::FmtVisitor;
 use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
 
@@ -58,6 +59,39 @@ impl<'b, T: Write + 'b> Session<'b, T> {
     }
 }
 
+/// Determine if a module should be skipped. True if the module should be skipped, false otherwise.
+fn should_skip_module<T: FormatHandler>(
+    config: &Config,
+    context: &FormatContext<'_, T>,
+    input_is_stdin: bool,
+    main_file: &FileName,
+    path: &FileName,
+    module: &Module<'_>,
+) -> bool {
+    if contains_skip(module.attrs()) {
+        return true;
+    }
+
+    if config.skip_children() && path != main_file {
+        return true;
+    }
+
+    if !input_is_stdin && context.ignore_file(&path) {
+        return true;
+    }
+
+    if !config.format_generated_files() {
+        let source_file = context.parse_session.span_to_file_contents(module.span);
+        let src = source_file.src.as_ref().expect("SourceFile without src");
+
+        if is_generated_file(src) {
+            return true;
+        }
+    }
+
+    false
+}
+
 // Format an entire crate (or subset of the module tree).
 fn format_project<T: FormatHandler>(
     input: Input,
@@ -97,7 +131,12 @@ fn format_project<T: FormatHandler>(
         directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
         !input_is_stdin && !config.skip_children(),
     )
-    .visit_crate(&krate)?;
+    .visit_crate(&krate)?
+    .into_iter()
+    .filter(|(path, module)| {
+        !should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
+    })
+    .collect::<Vec<_>>();
 
     timer = timer.done_parsing();
 
@@ -105,15 +144,6 @@ fn format_project<T: FormatHandler>(
     context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
-        let source_file = context.parse_session.span_to_file_contents(module.span);
-        let src = source_file.src.as_ref().expect("SourceFile without src");
-
-        let should_ignore = (!input_is_stdin && context.ignore_file(&path))
-            || (!config.format_generated_files() && is_generated_file(src));
-
-        if (config.skip_children() && path != main_file) || should_ignore {
-            continue;
-        }
         should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
         context.format_file(path, &module, is_macro_def)?;
     }
diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs
index ef7dd0ddcd1..92949ab576a 100644
--- a/src/test/configuration_snippet.rs
+++ b/src/test/configuration_snippet.rs
@@ -110,14 +110,7 @@ impl ConfigCodeBlock {
         assert!(self.code_block.is_some() && self.code_block_start.is_some());
 
         // See if code block begins with #![rustfmt::skip].
-        let fmt_skip = self
-            .code_block
-            .as_ref()
-            .unwrap()
-            .lines()
-            .nth(0)
-            .unwrap_or("")
-            == "#![rustfmt::skip]";
+        let fmt_skip = self.fmt_skip();
 
         if self.config_name.is_none() && !fmt_skip {
             write_message(&format!(
@@ -138,6 +131,17 @@ impl ConfigCodeBlock {
         true
     }
 
+    /// True if the code block starts with #![rustfmt::skip]
+    fn fmt_skip(&self) -> bool {
+        self.code_block
+            .as_ref()
+            .unwrap()
+            .lines()
+            .nth(0)
+            .unwrap_or("")
+            == "#![rustfmt::skip]"
+    }
+
     fn has_parsing_errors<T: Write>(&self, session: &Session<'_, T>) -> bool {
         if session.has_parsing_errors() {
             write_message(&format!(
@@ -251,6 +255,7 @@ fn configuration_snippet_tests() {
     let blocks = get_code_blocks();
     let failures = blocks
         .iter()
+        .filter(|block| !block.fmt_skip())
         .map(ConfigCodeBlock::formatted_is_idempotent)
         .fold(0, |acc, r| acc + (!r as u32));
 
diff --git a/src/test/mod_resolver.rs b/src/test/mod_resolver.rs
index ae4a0d0fccb..ec9ed0f0b8d 100644
--- a/src/test/mod_resolver.rs
+++ b/src/test/mod_resolver.rs
@@ -41,3 +41,12 @@ fn out_of_line_nested_inline_within_out_of_line() {
         ],
     );
 }
+
+#[test]
+fn skip_out_of_line_nested_inline_within_out_of_line() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5065
+    verify_mod_resolution(
+        "tests/mod-resolver/skip-files-issue-5065/main.rs",
+        &["tests/mod-resolver/skip-files-issue-5065/one.rs"],
+    );
+}
diff --git a/src/visitor.rs b/src/visitor.rs
index e4a7be742ab..ba446200232 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -948,12 +948,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
     pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) {
         self.block_indent = Indent::empty();
-        if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) {
-            self.push_skipped_with_span(m.attrs(), m.span, m.span);
-        } else {
-            self.walk_mod_items(&m.items);
-            self.format_missing_with_indent(end_pos);
-        }
+        let skipped = self.visit_attrs(m.attrs(), ast::AttrStyle::Inner);
+        assert!(
+            !skipped,
+            "Skipping module must be handled before reaching this line."
+        );
+        self.walk_mod_items(&m.items);
+        self.format_missing_with_indent(end_pos);
     }
 
     pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) {
diff --git a/tests/mod-resolver/skip-files-issue-5065/foo.rs b/tests/mod-resolver/skip-files-issue-5065/foo.rs
new file mode 100644
index 00000000000..74889acf0c3
--- /dev/null
+++ b/tests/mod-resolver/skip-files-issue-5065/foo.rs
@@ -0,0 +1,5 @@
+#![rustfmt::skip]
+
+mod bar {
+
+        mod baz;}
\ No newline at end of file
diff --git a/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs b/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs
new file mode 100644
index 00000000000..3519b0ee59c
--- /dev/null
+++ b/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs
@@ -0,0 +1 @@
+fn    baz()    {       }
\ No newline at end of file
diff --git a/tests/mod-resolver/skip-files-issue-5065/main.rs b/tests/mod-resolver/skip-files-issue-5065/main.rs
new file mode 100644
index 00000000000..3122e4f220f
--- /dev/null
+++ b/tests/mod-resolver/skip-files-issue-5065/main.rs
@@ -0,0 +1,9 @@
+#![rustfmt::skip]
+
+mod foo;
+mod one;
+
+fn main() {println!("Hello, world!");
+}
+
+// trailing commet
diff --git a/tests/mod-resolver/skip-files-issue-5065/one.rs b/tests/mod-resolver/skip-files-issue-5065/one.rs
new file mode 100644
index 00000000000..e7eb2c2d64d
--- /dev/null
+++ b/tests/mod-resolver/skip-files-issue-5065/one.rs
@@ -0,0 +1 @@
+struct One {   value:    String }
\ No newline at end of file
diff --git a/tests/target/skip/preserve_trailing_comment.rs b/tests/target/skip/preserve_trailing_comment.rs
new file mode 100644
index 00000000000..f85de33257c
--- /dev/null
+++ b/tests/target/skip/preserve_trailing_comment.rs
@@ -0,0 +1,7 @@
+#![rustfmt::skip]
+
+fn main() {
+    println!("Hello, world!");
+}
+
+// Trailing Comment

From 740fb57f5ddacddd9bcf074df701bcc50b46e69f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sun, 12 Dec 2021 20:15:08 +0100
Subject: [PATCH 110/195] clippy fixes

---
 src/bin/main.rs   |  2 +-
 src/expr.rs       |  4 +---
 src/formatting.rs |  2 +-
 src/items.rs      | 10 +++++-----
 src/lists.rs      |  4 +---
 src/visitor.rs    | 12 ++++++------
 6 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 9d2e97c9479..4d845547cdf 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -26,7 +26,7 @@ fn main() {
     let exit_code = match execute(&opts) {
         Ok(code) => code,
         Err(e) => {
-            eprintln!("{}", e.to_string());
+            eprintln!("{}", e);
             1
         }
     };
diff --git a/src/expr.rs b/src/expr.rs
index 5fd86c1a4ea..edd004ac63f 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -2003,9 +2003,7 @@ fn choose_rhs<R: Rewrite>(
     has_rhs_comment: bool,
 ) -> Option<String> {
     match orig_rhs {
-        Some(ref new_str) if new_str.is_empty() => {
-            return Some(String::new());
-        }
+        Some(ref new_str) if new_str.is_empty() => Some(String::new()),
         Some(ref new_str)
             if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
         {
diff --git a/src/formatting.rs b/src/formatting.rs
index 1972b5a87a5..b39480a0ef9 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -76,7 +76,7 @@ fn should_skip_module<T: FormatHandler>(
         return true;
     }
 
-    if !input_is_stdin && context.ignore_file(&path) {
+    if !input_is_stdin && context.ignore_file(path) {
         return true;
     }
 
diff --git a/src/items.rs b/src/items.rs
index f36bdba26e9..a77b7c10876 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1535,7 +1535,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
     // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
     match (visitor_kind, &op_ty) {
-        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(ref op_bounds)) => {
+        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
             let op = OpaqueType { bounds: op_bounds };
             rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
         }
@@ -1543,7 +1543,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
             rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
         }
         (AssocImplItem(_), _) => {
-            let result = if let Some(ref op_bounds) = op_ty {
+            let result = if let Some(op_bounds) = op_ty {
                 let op = OpaqueType { bounds: op_bounds };
                 rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
             } else {
@@ -3124,7 +3124,7 @@ impl Rewrite for ast::ForeignItem {
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, self.ident, sig, &self.vis, Some(body)),
                         generics,
                         &sig.decl,
                         self.span,
@@ -3137,7 +3137,7 @@ impl Rewrite for ast::ForeignItem {
                         context,
                         shape.indent,
                         self.ident,
-                        &FnSig::from_method_sig(&sig, generics, &self.vis),
+                        &FnSig::from_method_sig(sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
                     )
@@ -3166,7 +3166,7 @@ impl Rewrite for ast::ForeignItem {
                 .map(|s| s + ";")
             }
             ast::ForeignItemKind::TyAlias(ref ty_alias) => {
-                let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
+                let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span);
                 rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
diff --git a/src/lists.rs b/src/lists.rs
index 3515dd17251..7aa0315f18c 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -448,10 +448,8 @@ where
                     true
                 } else if starts_with_newline(comment) {
                     false
-                } else if comment.trim().contains('\n') || comment.trim().len() > width {
-                    true
                 } else {
-                    false
+                    comment.trim().contains('\n') || comment.trim().len() > width
                 };
 
                 rewrite_comment(
diff --git a/src/visitor.rs b/src/visitor.rs
index ba446200232..1896a4744fe 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -552,7 +552,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)),
+                            visit::FnKind::Fn(fn_ctxt, item.ident, sig, &item.vis, Some(body)),
                             generics,
                             &sig.decl,
                             item.span,
@@ -562,14 +562,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     } else {
                         let indent = self.block_indent;
                         let rewrite = self.rewrite_required_fn(
-                            indent, item.ident, &sig, &item.vis, generics, item.span,
+                            indent, item.ident, sig, &item.vis, generics, item.span,
                         );
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
                 ast::ItemKind::TyAlias(ref ty_alias) => {
                     use ItemVisitorKind::Item;
-                    self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
+                    self.visit_ty_alias_kind(ty_alias, &Item(item), item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
@@ -619,17 +619,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         skip_out_of_file_lines_range_visitor!(self, ai.span);
 
         if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
+            self.push_skipped_with_span(ai.attrs.as_slice(), skip_span, skip_span);
             return;
         }
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
         match (&ai.kind, visitor_kind) {
             (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
-                self.visit_static(&StaticParts::from_trait_item(&ai))
+                self.visit_static(&StaticParts::from_trait_item(ai))
             }
             (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
-                self.visit_static(&StaticParts::from_impl_item(&ai))
+                self.visit_static(&StaticParts::from_impl_item(ai))
             }
             (ast::AssocItemKind::Fn(ref fn_kind), _) => {
                 let ast::Fn {

From 57ac92bf1658a576fdc066b82a37aa3a7de2c96b Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Wed, 17 Nov 2021 20:46:48 -0500
Subject: [PATCH 111/195] Prevent duplicate comma when formatting struct
 pattern with ".."

Fixes 5066

When a struct pattern that contained a ".." was formatted, it was
assumed that a trailing comma should always be added if the struct
fields weren't formatted vertically.

Now, a trailing comma is only added if not already included in the
reformatted struct fields.
---
 src/patterns.rs                                        |  7 ++++---
 ..._struct_trailing_comma_always_struct_lit_width_0.rs | 10 ++++++++++
 ...e_struct_trailing_comma_never_struct_lit_width_0.rs | 10 ++++++++++
 .../multi_line_struct_with_trailing_comma_always.rs    | 10 ++++++++++
 .../multi_line_struct_with_trailing_comma_never.rs     | 10 ++++++++++
 tests/target/issue-5066/with_trailing_comma_always.rs  |  5 +++++
 tests/target/issue-5066/with_trailing_comma_never.rs   |  5 +++++
 7 files changed, 54 insertions(+), 3 deletions(-)
 create mode 100644 tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs
 create mode 100644 tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs
 create mode 100644 tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs
 create mode 100644 tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs
 create mode 100644 tests/target/issue-5066/with_trailing_comma_always.rs
 create mode 100644 tests/target/issue-5066/with_trailing_comma_never.rs

diff --git a/src/patterns.rs b/src/patterns.rs
index a80d63201f9..9b74b35f314 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -318,10 +318,12 @@ fn rewrite_struct_pat(
     let mut fields_str = write_list(&item_vec, &fmt)?;
     let one_line_width = h_shape.map_or(0, |shape| shape.width);
 
+    let has_trailing_comma = fmt.needs_trailing_separator();
+
     if ellipsis {
         if fields_str.contains('\n') || fields_str.len() > one_line_width {
             // Add a missing trailing comma.
-            if context.config.trailing_comma() == SeparatorTactic::Never {
+            if !has_trailing_comma {
                 fields_str.push(',');
             }
             fields_str.push('\n');
@@ -329,8 +331,7 @@ fn rewrite_struct_pat(
         } else {
             if !fields_str.is_empty() {
                 // there are preceding struct fields being matched on
-                if tactic == DefinitiveListTactic::Vertical {
-                    // if the tactic is Vertical, write_list already added a trailing ,
+                if has_trailing_comma {
                     fields_str.push(' ');
                 } else {
                     fields_str.push_str(", ");
diff --git a/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs b/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs
new file mode 100644
index 00000000000..c7122c67623
--- /dev/null
+++ b/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs
@@ -0,0 +1,10 @@
+// rustfmt-trailing_comma: Always
+// rustfmt-struct_lit_single_line: false
+// rustfmt-struct_lit_width: 0
+
+fn main() {
+    let Foo {
+        a,
+        ..
+    } = b;
+}
diff --git a/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs b/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs
new file mode 100644
index 00000000000..68e89c4179f
--- /dev/null
+++ b/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs
@@ -0,0 +1,10 @@
+// rustfmt-trailing_comma: Never
+// rustfmt-struct_lit_single_line: false
+// rustfmt-struct_lit_width: 0
+
+fn main() {
+    let Foo {
+        a,
+        ..
+    } = b;
+}
diff --git a/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs b/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs
new file mode 100644
index 00000000000..3368f070386
--- /dev/null
+++ b/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs
@@ -0,0 +1,10 @@
+// rustfmt-trailing_comma: Always
+// rustfmt-struct_lit_single_line: false
+
+// There is an issue with how this is formatted.
+// formatting should look like ./multi_line_struct_trailing_comma_always_struct_lit_width_0.rs
+fn main() {
+    let Foo {
+        a, ..
+    } = b;
+}
diff --git a/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs b/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs
new file mode 100644
index 00000000000..cf63c4c983c
--- /dev/null
+++ b/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs
@@ -0,0 +1,10 @@
+// rustfmt-trailing_comma: Never
+// rustfmt-struct_lit_single_line: false
+
+// There is an issue with how this is formatted.
+// formatting should look like ./multi_line_struct_trailing_comma_never_struct_lit_width_0.rs
+fn main() {
+    let Foo {
+        a, ..
+    } = b;
+}
diff --git a/tests/target/issue-5066/with_trailing_comma_always.rs b/tests/target/issue-5066/with_trailing_comma_always.rs
new file mode 100644
index 00000000000..e20bcec9316
--- /dev/null
+++ b/tests/target/issue-5066/with_trailing_comma_always.rs
@@ -0,0 +1,5 @@
+// rustfmt-trailing_comma: Always
+
+fn main() {
+    let Foo { a, .. } = b;
+}
diff --git a/tests/target/issue-5066/with_trailing_comma_never.rs b/tests/target/issue-5066/with_trailing_comma_never.rs
new file mode 100644
index 00000000000..8b95bb137bc
--- /dev/null
+++ b/tests/target/issue-5066/with_trailing_comma_never.rs
@@ -0,0 +1,5 @@
+// rustfmt-trailing_comma: Never
+
+fn main() {
+    let Foo { a, .. } = b;
+}

From b214938ff3fcd82f568d9eae0b0bda5d528a15ae Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 11:58:27 -0600
Subject: [PATCH 112/195] chore: bump toolchain

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index 1d2cad66751..c97b5ec6609 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-11-08"
+channel = "nightly-2021-12-20"
 components = ["rustc-dev"]

From 40b73d8feec5938a4b6d542840641eceb563930c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 17:55:48 -0600
Subject: [PATCH 113/195] refactor: rename syntux mod to parse

---
 src/formatting.rs                | 4 ++--
 src/lib.rs                       | 4 ++--
 src/modules.rs                   | 4 ++--
 src/modules/visitor.rs           | 4 ++--
 src/parse/mod.rs                 | 2 ++
 src/{syntux => parse}/parser.rs  | 2 +-
 src/{syntux => parse}/session.rs | 2 +-
 src/rewrite.rs                   | 2 +-
 src/source_file.rs               | 2 +-
 src/visitor.rs                   | 2 +-
 10 files changed, 15 insertions(+), 13 deletions(-)
 create mode 100644 src/parse/mod.rs
 rename src/{syntux => parse}/parser.rs (99%)
 rename src/{syntux => parse}/session.rs (99%)

diff --git a/src/formatting.rs b/src/formatting.rs
index b39480a0ef9..67cf1232f66 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -14,8 +14,8 @@ use crate::config::{Config, FileName, Verbosity};
 use crate::formatting::generated::is_generated_file;
 use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
-use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
-use crate::syntux::session::ParseSess;
+use crate::parse::parser::{DirectoryOwnership, Parser, ParserError};
+use crate::parse::session::ParseSess;
 use crate::utils::{contains_skip, count_newlines};
 use crate::visitor::FmtVisitor;
 use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
diff --git a/src/lib.rs b/src/lib.rs
index 792a1080f0e..f59ebad97ce 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,8 +40,8 @@ use crate::emitter::Emitter;
 use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile};
 use crate::issues::Issue;
 use crate::modules::ModuleResolutionError;
+use crate::parse::parser::DirectoryOwnership;
 use crate::shape::Indent;
-use crate::syntux::parser::DirectoryOwnership;
 use crate::utils::indent_next_line;
 
 pub use crate::config::{
@@ -77,6 +77,7 @@ mod missed_spans;
 pub(crate) mod modules;
 mod overflow;
 mod pairs;
+mod parse;
 mod patterns;
 mod release_channel;
 mod reorder;
@@ -89,7 +90,6 @@ pub(crate) mod source_map;
 mod spanned;
 mod stmt;
 mod string;
-mod syntux;
 #[cfg(test)]
 mod test;
 mod types;
diff --git a/src/modules.rs b/src/modules.rs
index 9d438a80d94..9c964b274e0 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -12,10 +12,10 @@ use thiserror::Error;
 use crate::attr::MetaVisitor;
 use crate::config::FileName;
 use crate::items::is_mod_decl;
-use crate::syntux::parser::{
+use crate::parse::parser::{
     Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
 };
-use crate::syntux::session::ParseSess;
+use crate::parse::session::ParseSess;
 use crate::utils::{contains_skip, mk_sp};
 
 mod visitor;
diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs
index d5acf3f1cbc..7486a4c4ee1 100644
--- a/src/modules/visitor.rs
+++ b/src/modules/visitor.rs
@@ -3,8 +3,8 @@ use rustc_ast::visit::Visitor;
 use rustc_span::Symbol;
 
 use crate::attr::MetaVisitor;
-use crate::syntux::parser::Parser;
-use crate::syntux::session::ParseSess;
+use crate::parse::parser::Parser;
+use crate::parse::session::ParseSess;
 
 pub(crate) struct ModItem {
     pub(crate) item: ast::Item,
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
new file mode 100644
index 00000000000..bb7d9ca87d4
--- /dev/null
+++ b/src/parse/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod parser;
+pub(crate) mod session;
diff --git a/src/syntux/parser.rs b/src/parse/parser.rs
similarity index 99%
rename from src/syntux/parser.rs
rename to src/parse/parser.rs
index 23d065c9cc9..024b38cebb6 100644
--- a/src/syntux/parser.rs
+++ b/src/parse/parser.rs
@@ -11,7 +11,7 @@ use rustc_parse::{
 use rustc_span::{sym, symbol::kw, Span};
 
 use crate::attr::first_attr_value_str_by_name;
-use crate::syntux::session::ParseSess;
+use crate::parse::session::ParseSess;
 use crate::Input;
 
 pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
diff --git a/src/syntux/session.rs b/src/parse/session.rs
similarity index 99%
rename from src/syntux/session.rs
rename to src/parse/session.rs
index dd7c7352686..624fed0d2de 100644
--- a/src/syntux/session.rs
+++ b/src/parse/session.rs
@@ -222,7 +222,7 @@ impl ParseSess {
     }
 }
 
-// Methods that should be restricted within the syntux module.
+// Methods that should be restricted within the parse module.
 impl ParseSess {
     pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
         for diagnostic in diagnostics {
diff --git a/src/rewrite.rs b/src/rewrite.rs
index c8abe70141b..4a3bd129d16 100644
--- a/src/rewrite.rs
+++ b/src/rewrite.rs
@@ -7,9 +7,9 @@ use rustc_ast::ptr;
 use rustc_span::Span;
 
 use crate::config::{Config, IndentStyle};
+use crate::parse::session::ParseSess;
 use crate::shape::Shape;
 use crate::skip::SkipContext;
-use crate::syntux::session::ParseSess;
 use crate::visitor::SnippetProvider;
 use crate::FormatReport;
 
diff --git a/src/source_file.rs b/src/source_file.rs
index 853336004d8..56d4ab40038 100644
--- a/src/source_file.rs
+++ b/src/source_file.rs
@@ -4,7 +4,7 @@ use std::path::Path;
 
 use crate::config::FileName;
 use crate::emitter::{self, Emitter};
-use crate::syntux::session::ParseSess;
+use crate::parse::session::ParseSess;
 use crate::NewlineStyle;
 
 #[cfg(test)]
diff --git a/src/visitor.rs b/src/visitor.rs
index 1896a4744fe..0177689958a 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -16,13 +16,13 @@ use crate::items::{
 };
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
+use crate::parse::session::ParseSess;
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::skip::{is_skip_attr, SkipContext};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt::Stmt;
-use crate::syntux::session::ParseSess;
 use crate::utils::{
     self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes,
     last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr,

From 9ce5470a8ce0abdfdb5b19c8f9a2b0773f0b6432 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 18:59:01 -0600
Subject: [PATCH 114/195] refactor: move macro arg parsing to parse mod

---
 src/macros.rs           | 216 ++++------------------------------------
 src/parse/macros/mod.rs | 216 ++++++++++++++++++++++++++++++++++++++++
 src/parse/mod.rs        |   1 +
 3 files changed, 234 insertions(+), 199 deletions(-)
 create mode 100644 src/parse/macros/mod.rs

diff --git a/src/macros.rs b/src/macros.rs
index a52568be9ea..26a68dfdcf2 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -16,8 +16,6 @@ use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind};
 use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
-use rustc_parse::parser::{ForceCollect, Parser};
-use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
 use rustc_span::{
     symbol::{self, kw},
     BytePos, Span, Symbol, DUMMY_SP,
@@ -30,6 +28,7 @@ use crate::config::lists::*;
 use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
+use crate::parse::macros::{build_parser, parse_macro_args, ParsedMacroArgs};
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::source_map::SpanUtils;
@@ -60,7 +59,7 @@ pub(crate) enum MacroArg {
 }
 
 impl MacroArg {
-    fn is_item(&self) -> bool {
+    pub(crate) fn is_item(&self) -> bool {
         match self {
             MacroArg::Item(..) => true,
             _ => false,
@@ -90,61 +89,6 @@ impl Rewrite for MacroArg {
     }
 }
 
-fn build_parser<'a>(context: &RewriteContext<'a>, cursor: Cursor) -> Parser<'a> {
-    stream_to_parser(
-        context.parse_sess.inner(),
-        cursor.collect(),
-        MACRO_ARGUMENTS,
-    )
-}
-
-fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
-    macro_rules! parse_macro_arg {
-        ($macro_arg:ident, $parser:expr, $f:expr) => {
-            let mut cloned_parser = (*parser).clone();
-            match $parser(&mut cloned_parser) {
-                Ok(x) => {
-                    if parser.sess.span_diagnostic.has_errors() {
-                        parser.sess.span_diagnostic.reset_err_count();
-                    } else {
-                        // Parsing succeeded.
-                        *parser = cloned_parser;
-                        return Some(MacroArg::$macro_arg($f(x)?));
-                    }
-                }
-                Err(mut e) => {
-                    e.cancel();
-                    parser.sess.span_diagnostic.reset_err_count();
-                }
-            }
-        };
-    }
-
-    parse_macro_arg!(
-        Expr,
-        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
-        |x: ptr::P<ast::Expr>| Some(x)
-    );
-    parse_macro_arg!(
-        Ty,
-        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
-        |x: ptr::P<ast::Ty>| Some(x)
-    );
-    parse_macro_arg!(
-        Pat,
-        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None),
-        |x: ptr::P<ast::Pat>| Some(x)
-    );
-    // `parse_item` returns `Option<ptr::P<ast::Item>>`.
-    parse_macro_arg!(
-        Item,
-        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
-        |x: Option<ptr::P<ast::Item>>| x
-    );
-
-    None
-}
-
 /// Rewrite macro name without using pretty-printer if possible.
 fn rewrite_macro_name(
     context: &RewriteContext<'_>,
@@ -232,25 +176,6 @@ pub(crate) fn rewrite_macro(
     }
 }
 
-fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
-    for &keyword in RUST_KW.iter() {
-        if parser.token.is_keyword(keyword)
-            && parser.look_ahead(1, |t| {
-                t.kind == TokenKind::Eof
-                    || t.kind == TokenKind::Comma
-                    || t.kind == TokenKind::CloseDelim(DelimToken::NoDelim)
-            })
-        {
-            parser.bump();
-            return Some(MacroArg::Keyword(
-                symbol::Ident::with_dummy_span(keyword),
-                parser.prev_token.span,
-            ));
-        }
-    }
-    None
-}
-
 fn rewrite_macro_inner(
     mac: &ast::MacCall,
     extra_ident: Option<symbol::Ident>,
@@ -269,8 +194,9 @@ fn rewrite_macro_inner(
     let original_style = macro_style(mac, context);
 
     let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
+    let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&&macro_name[..]);
 
-    let style = if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) && !is_nested_macro {
+    let style = if is_forced_bracket && !is_nested_macro {
         DelimToken::Bracket
     } else {
         original_style
@@ -294,67 +220,21 @@ fn rewrite_macro_inner(
     }
     // Format well-known macros which cannot be parsed as a valid AST.
     if macro_name == "lazy_static!" && !has_comment {
-        if let success @ Some(..) = format_lazy_static(context, shape, &ts) {
+        if let success @ Some(..) = format_lazy_static(context, shape, ts.trees().collect()) {
             return success;
         }
     }
 
-    let mut parser = build_parser(context, ts.trees());
-    let mut arg_vec = Vec::new();
-    let mut vec_with_semi = false;
-    let mut trailing_comma = false;
-
-    if DelimToken::Brace != style {
-        loop {
-            if let Some(arg) = check_keyword(&mut parser) {
-                arg_vec.push(arg);
-            } else if let Some(arg) = parse_macro_arg(&mut parser) {
-                arg_vec.push(arg);
-            } else {
-                return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
-            }
-
-            match parser.token.kind {
-                TokenKind::Eof => break,
-                TokenKind::Comma => (),
-                TokenKind::Semi => {
-                    // Try to parse `vec![expr; expr]`
-                    if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
-                        parser.bump();
-                        if parser.token.kind != TokenKind::Eof {
-                            match parse_macro_arg(&mut parser) {
-                                Some(arg) => {
-                                    arg_vec.push(arg);
-                                    parser.bump();
-                                    if parser.token.kind == TokenKind::Eof && arg_vec.len() == 2 {
-                                        vec_with_semi = true;
-                                        break;
-                                    }
-                                }
-                                None => {
-                                    return return_macro_parse_failure_fallback(
-                                        context,
-                                        shape.indent,
-                                        mac.span(),
-                                    );
-                                }
-                            }
-                        }
-                    }
-                    return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
-                }
-                _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue,
-                _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span()),
-            }
-
-            parser.bump();
-
-            if parser.token.kind == TokenKind::Eof {
-                trailing_comma = true;
-                break;
-            }
+    let ParsedMacroArgs {
+        args: arg_vec,
+        vec_with_semi,
+        trailing_comma,
+    } = match parse_macro_args(context, ts, style, is_forced_bracket) {
+        Some(args) => args,
+        None => {
+            return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
         }
-    }
+    };
 
     if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
         return rewrite_macro_with_items(
@@ -1179,7 +1059,7 @@ pub(crate) fn convert_try_mac(
     let path = &pprust::path_to_string(&mac.path);
     if path == "try" || path == "r#try" {
         let ts = mac.args.inner_tokens();
-        let mut parser = build_parser(context, ts.trees());
+        let mut parser = build_parser(context, ts);
 
         Some(ast::Expr {
             id: ast::NodeId::root(), // dummy value
@@ -1414,10 +1294,10 @@ impl MacroBranch {
 fn format_lazy_static(
     context: &RewriteContext<'_>,
     shape: Shape,
-    ts: &TokenStream,
+    ts: TokenStream,
 ) -> Option<String> {
     let mut result = String::with_capacity(1024);
-    let mut parser = build_parser(context, ts.trees());
+    let mut parser = build_parser(context, ts);
     let nested_shape = shape
         .block_indent(context.config.tab_spaces())
         .with_max_width(context.config);
@@ -1528,65 +1408,3 @@ fn rewrite_macro_with_items(
     result.push_str(trailing_semicolon);
     Some(result)
 }
-
-const RUST_KW: [Symbol; 59] = [
-    kw::PathRoot,
-    kw::DollarCrate,
-    kw::Underscore,
-    kw::As,
-    kw::Box,
-    kw::Break,
-    kw::Const,
-    kw::Continue,
-    kw::Crate,
-    kw::Else,
-    kw::Enum,
-    kw::Extern,
-    kw::False,
-    kw::Fn,
-    kw::For,
-    kw::If,
-    kw::Impl,
-    kw::In,
-    kw::Let,
-    kw::Loop,
-    kw::Match,
-    kw::Mod,
-    kw::Move,
-    kw::Mut,
-    kw::Pub,
-    kw::Ref,
-    kw::Return,
-    kw::SelfLower,
-    kw::SelfUpper,
-    kw::Static,
-    kw::Struct,
-    kw::Super,
-    kw::Trait,
-    kw::True,
-    kw::Type,
-    kw::Unsafe,
-    kw::Use,
-    kw::Where,
-    kw::While,
-    kw::Abstract,
-    kw::Become,
-    kw::Do,
-    kw::Final,
-    kw::Macro,
-    kw::Override,
-    kw::Priv,
-    kw::Typeof,
-    kw::Unsized,
-    kw::Virtual,
-    kw::Yield,
-    kw::Dyn,
-    kw::Async,
-    kw::Try,
-    kw::UnderscoreLifetime,
-    kw::StaticLifetime,
-    kw::Auto,
-    kw::Catch,
-    kw::Default,
-    kw::Union,
-];
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
new file mode 100644
index 00000000000..e7844c9a4dc
--- /dev/null
+++ b/src/parse/macros/mod.rs
@@ -0,0 +1,216 @@
+use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind};
+use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
+use rustc_ast::{ast, ptr};
+use rustc_parse::parser::{ForceCollect, Parser};
+use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
+use rustc_span::{
+    symbol::{self, kw},
+    BytePos, Span, Symbol, DUMMY_SP,
+};
+
+use crate::macros::MacroArg;
+use crate::rewrite::{Rewrite, RewriteContext};
+
+pub(crate) fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
+    stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
+}
+
+fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
+    macro_rules! parse_macro_arg {
+        ($macro_arg:ident, $parser:expr, $f:expr) => {
+            let mut cloned_parser = (*parser).clone();
+            match $parser(&mut cloned_parser) {
+                Ok(x) => {
+                    if parser.sess.span_diagnostic.has_errors() {
+                        parser.sess.span_diagnostic.reset_err_count();
+                    } else {
+                        // Parsing succeeded.
+                        *parser = cloned_parser;
+                        return Some(MacroArg::$macro_arg($f(x)?));
+                    }
+                }
+                Err(mut e) => {
+                    e.cancel();
+                    parser.sess.span_diagnostic.reset_err_count();
+                }
+            }
+        };
+    }
+
+    parse_macro_arg!(
+        Expr,
+        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
+        |x: ptr::P<ast::Expr>| Some(x)
+    );
+    parse_macro_arg!(
+        Ty,
+        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
+        |x: ptr::P<ast::Ty>| Some(x)
+    );
+    parse_macro_arg!(
+        Pat,
+        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None),
+        |x: ptr::P<ast::Pat>| Some(x)
+    );
+    // `parse_item` returns `Option<ptr::P<ast::Item>>`.
+    parse_macro_arg!(
+        Item,
+        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
+        |x: Option<ptr::P<ast::Item>>| x
+    );
+
+    None
+}
+
+pub(crate) struct ParsedMacroArgs {
+    pub(crate) vec_with_semi: bool,
+    pub(crate) trailing_comma: bool,
+    pub(crate) args: Vec<MacroArg>,
+}
+
+fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
+    for &keyword in RUST_KW.iter() {
+        if parser.token.is_keyword(keyword)
+            && parser.look_ahead(1, |t| {
+                t.kind == TokenKind::Eof
+                    || t.kind == TokenKind::Comma
+                    || t.kind == TokenKind::CloseDelim(DelimToken::NoDelim)
+            })
+        {
+            parser.bump();
+            return Some(MacroArg::Keyword(
+                symbol::Ident::with_dummy_span(keyword),
+                parser.prev_token.span,
+            ));
+        }
+    }
+    None
+}
+
+pub(crate) fn parse_macro_args(
+    context: &RewriteContext<'_>,
+    tokens: TokenStream,
+    style: DelimToken,
+    forced_bracket: bool,
+) -> Option<ParsedMacroArgs> {
+    let mut parser = build_parser(context, tokens);
+    let mut args = Vec::new();
+    let mut vec_with_semi = false;
+    let mut trailing_comma = false;
+
+    if DelimToken::Brace != style {
+        loop {
+            if let Some(arg) = check_keyword(&mut parser) {
+                args.push(arg);
+            } else if let Some(arg) = parse_macro_arg(&mut parser) {
+                args.push(arg);
+            } else {
+                return None;
+            }
+
+            match parser.token.kind {
+                TokenKind::Eof => break,
+                TokenKind::Comma => (),
+                TokenKind::Semi => {
+                    // Try to parse `vec![expr; expr]`
+                    if forced_bracket {
+                        parser.bump();
+                        if parser.token.kind != TokenKind::Eof {
+                            match parse_macro_arg(&mut parser) {
+                                Some(arg) => {
+                                    args.push(arg);
+                                    parser.bump();
+                                    if parser.token.kind == TokenKind::Eof && args.len() == 2 {
+                                        vec_with_semi = true;
+                                        break;
+                                    }
+                                }
+                                None => {
+                                    return None;
+                                }
+                            }
+                        }
+                    }
+                    return None;
+                }
+                _ if args.last().map_or(false, MacroArg::is_item) => continue,
+                _ => return None,
+            }
+
+            parser.bump();
+
+            if parser.token.kind == TokenKind::Eof {
+                trailing_comma = true;
+                break;
+            }
+        }
+    }
+
+    Some(ParsedMacroArgs {
+        vec_with_semi,
+        trailing_comma,
+        args,
+    })
+}
+
+const RUST_KW: [Symbol; 59] = [
+    kw::PathRoot,
+    kw::DollarCrate,
+    kw::Underscore,
+    kw::As,
+    kw::Box,
+    kw::Break,
+    kw::Const,
+    kw::Continue,
+    kw::Crate,
+    kw::Else,
+    kw::Enum,
+    kw::Extern,
+    kw::False,
+    kw::Fn,
+    kw::For,
+    kw::If,
+    kw::Impl,
+    kw::In,
+    kw::Let,
+    kw::Loop,
+    kw::Match,
+    kw::Mod,
+    kw::Move,
+    kw::Mut,
+    kw::Pub,
+    kw::Ref,
+    kw::Return,
+    kw::SelfLower,
+    kw::SelfUpper,
+    kw::Static,
+    kw::Struct,
+    kw::Super,
+    kw::Trait,
+    kw::True,
+    kw::Type,
+    kw::Unsafe,
+    kw::Use,
+    kw::Where,
+    kw::While,
+    kw::Abstract,
+    kw::Become,
+    kw::Do,
+    kw::Final,
+    kw::Macro,
+    kw::Override,
+    kw::Priv,
+    kw::Typeof,
+    kw::Unsized,
+    kw::Virtual,
+    kw::Yield,
+    kw::Dyn,
+    kw::Async,
+    kw::Try,
+    kw::UnderscoreLifetime,
+    kw::StaticLifetime,
+    kw::Auto,
+    kw::Catch,
+    kw::Default,
+    kw::Union,
+];
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index bb7d9ca87d4..5e88826ea8c 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -1,2 +1,3 @@
+pub(crate) mod macros;
 pub(crate) mod parser;
 pub(crate) mod session;

From c8cf454173ec332acf3860863c7d2f088876e40b Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 19:38:00 -0600
Subject: [PATCH 115/195] refactor: move lazy_static parsing to parse mod

---
 src/macros.rs                   | 43 ++++------------------------
 src/parse/macros/lazy_static.rs | 50 +++++++++++++++++++++++++++++++++
 src/parse/macros/mod.rs         |  2 ++
 3 files changed, 58 insertions(+), 37 deletions(-)
 create mode 100644 src/parse/macros/lazy_static.rs

diff --git a/src/macros.rs b/src/macros.rs
index 26a68dfdcf2..b14b67f2a0a 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -28,6 +28,7 @@ use crate::config::lists::*;
 use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
+use crate::parse::macros::lazy_static::parse_lazy_static;
 use crate::parse::macros::{build_parser, parse_macro_args, ParsedMacroArgs};
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
@@ -1297,7 +1298,6 @@ fn format_lazy_static(
     ts: TokenStream,
 ) -> Option<String> {
     let mut result = String::with_capacity(1024);
-    let mut parser = build_parser(context, ts);
     let nested_shape = shape
         .block_indent(context.config.tab_spaces())
         .with_max_width(context.config);
@@ -1305,42 +1305,11 @@ fn format_lazy_static(
     result.push_str("lazy_static! {");
     result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
 
-    macro_rules! parse_or {
-        ($method:ident $(,)* $($arg:expr),* $(,)*) => {
-            match parser.$method($($arg,)*) {
-                Ok(val) => {
-                    if parser.sess.span_diagnostic.has_errors() {
-                        parser.sess.span_diagnostic.reset_err_count();
-                        return None;
-                    } else {
-                        val
-                    }
-                }
-                Err(mut err) => {
-                    err.cancel();
-                    parser.sess.span_diagnostic.reset_err_count();
-                    return None;
-                }
-            }
-        }
-    }
-
-    while parser.token.kind != TokenKind::Eof {
-        // Parse a `lazy_static!` item.
-        let vis = crate::utils::format_visibility(
-            context,
-            &parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No),
-        );
-        parser.eat_keyword(kw::Static);
-        parser.eat_keyword(kw::Ref);
-        let id = parse_or!(parse_ident);
-        parser.eat(&TokenKind::Colon);
-        let ty = parse_or!(parse_ty);
-        parser.eat(&TokenKind::Eq);
-        let expr = parse_or!(parse_expr);
-        parser.eat(&TokenKind::Semi);
-
+    let parsed_elems = parse_lazy_static(context, ts)?;
+    let last = parsed_elems.len() - 1;
+    for (i, (vis, id, ty, expr)) in parsed_elems.iter().enumerate() {
         // Rewrite as a static item.
+        let vis = crate::utils::format_visibility(context, vis);
         let mut stmt = String::with_capacity(128);
         stmt.push_str(&format!(
             "{}static ref {}: {} =",
@@ -1356,7 +1325,7 @@ fn format_lazy_static(
             nested_shape.sub_width(1)?,
         )?);
         result.push(';');
-        if parser.token.kind != TokenKind::Eof {
+        if i != last {
             result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
         }
     }
diff --git a/src/parse/macros/lazy_static.rs b/src/parse/macros/lazy_static.rs
new file mode 100644
index 00000000000..9c8651aa3fa
--- /dev/null
+++ b/src/parse/macros/lazy_static.rs
@@ -0,0 +1,50 @@
+use rustc_ast::ast;
+use rustc_ast::ptr::P;
+use rustc_ast::token::TokenKind;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_span::symbol::{self, kw};
+
+use crate::rewrite::RewriteContext;
+
+pub(crate) fn parse_lazy_static(
+    context: &RewriteContext<'_>,
+    ts: TokenStream,
+) -> Option<Vec<(ast::Visibility, symbol::Ident, P<ast::Ty>, P<ast::Expr>)>> {
+    let mut result = vec![];
+    let mut parser = super::build_parser(context, ts);
+    macro_rules! parse_or {
+        ($method:ident $(,)* $($arg:expr),* $(,)*) => {
+            match parser.$method($($arg,)*) {
+                Ok(val) => {
+                    if parser.sess.span_diagnostic.has_errors() {
+                        parser.sess.span_diagnostic.reset_err_count();
+                        return None;
+                    } else {
+                        val
+                    }
+                }
+                Err(mut err) => {
+                    err.cancel();
+                    parser.sess.span_diagnostic.reset_err_count();
+                    return None;
+                }
+            }
+        }
+    }
+
+    while parser.token.kind != TokenKind::Eof {
+        // Parse a `lazy_static!` item.
+        let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No);
+        parser.eat_keyword(kw::Static);
+        parser.eat_keyword(kw::Ref);
+        let id = parse_or!(parse_ident);
+        parser.eat(&TokenKind::Colon);
+        let ty = parse_or!(parse_ty);
+        parser.eat(&TokenKind::Eq);
+        let expr = parse_or!(parse_expr);
+        parser.eat(&TokenKind::Semi);
+        result.push((vis, id, ty, expr));
+    }
+
+    Some(result)
+}
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index e7844c9a4dc..7115302a479 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -11,6 +11,8 @@ use rustc_span::{
 use crate::macros::MacroArg;
 use crate::rewrite::{Rewrite, RewriteContext};
 
+pub(crate) mod lazy_static;
+
 pub(crate) fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
     stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
 }

From 62987562e2fbb6ea83fa20598b9e0c91bee536e3 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 19:44:23 -0600
Subject: [PATCH 116/195] refactor: extract final rustc_parse touchpoint from
 macros.rs

---
 src/macros.rs           |  5 ++---
 src/parse/macros/mod.rs | 10 +++++++++-
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/macros.rs b/src/macros.rs
index b14b67f2a0a..f29552caf8d 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -29,7 +29,7 @@ use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
 use crate::parse::macros::lazy_static::parse_lazy_static;
-use crate::parse::macros::{build_parser, parse_macro_args, ParsedMacroArgs};
+use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs};
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::source_map::SpanUtils;
@@ -1060,11 +1060,10 @@ pub(crate) fn convert_try_mac(
     let path = &pprust::path_to_string(&mac.path);
     if path == "try" || path == "r#try" {
         let ts = mac.args.inner_tokens();
-        let mut parser = build_parser(context, ts);
 
         Some(ast::Expr {
             id: ast::NodeId::root(), // dummy value
-            kind: ast::ExprKind::Try(parser.parse_expr().ok()?),
+            kind: ast::ExprKind::Try(parse_expr(context, ts)?),
             span: mac.span(), // incorrect span, but shouldn't matter too much
             attrs: ast::AttrVec::new(),
             tokens: None,
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index 7115302a479..414b72f2921 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -13,7 +13,7 @@ use crate::rewrite::{Rewrite, RewriteContext};
 
 pub(crate) mod lazy_static;
 
-pub(crate) fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
+fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
     stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
 }
 
@@ -155,6 +155,14 @@ pub(crate) fn parse_macro_args(
     })
 }
 
+pub(crate) fn parse_expr(
+    context: &RewriteContext<'_>,
+    tokens: TokenStream,
+) -> Option<ptr::P<ast::Expr>> {
+    let mut parser = build_parser(context, tokens);
+    parser.parse_expr().ok()
+}
+
 const RUST_KW: [Symbol; 59] = [
     kw::PathRoot,
     kw::DollarCrate,

From 97c3e48834c1485168a59473385cb755d76c9287 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 20:28:55 -0600
Subject: [PATCH 117/195] refactor: encapsulate cfg_if parsing within parse mod

---
 src/modules/visitor.rs     |  4 +-
 src/parse/macros/cfg_if.rs | 89 ++++++++++++++++++++++++++++++++++++++
 src/parse/macros/mod.rs    |  8 +++-
 src/parse/parser.rs        | 80 ----------------------------------
 4 files changed, 98 insertions(+), 83 deletions(-)
 create mode 100644 src/parse/macros/cfg_if.rs

diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs
index 7486a4c4ee1..ea67977c17a 100644
--- a/src/modules/visitor.rs
+++ b/src/modules/visitor.rs
@@ -3,7 +3,7 @@ use rustc_ast::visit::Visitor;
 use rustc_span::Symbol;
 
 use crate::attr::MetaVisitor;
-use crate::parse::parser::Parser;
+use crate::parse::macros::cfg_if::parse_cfg_if;
 use crate::parse::session::ParseSess;
 
 pub(crate) struct ModItem {
@@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
             }
         };
 
-        let items = Parser::parse_cfg_if(self.parse_sess, mac)?;
+        let items = parse_cfg_if(self.parse_sess, mac)?;
         self.mods
             .append(&mut items.into_iter().map(|item| ModItem { item }).collect());
 
diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs
new file mode 100644
index 00000000000..e10fbe64bcd
--- /dev/null
+++ b/src/parse/macros/cfg_if.rs
@@ -0,0 +1,89 @@
+use std::panic::{catch_unwind, AssertUnwindSafe};
+
+use rustc_ast::ast;
+use rustc_ast::token::{DelimToken, TokenKind};
+use rustc_parse::parser::ForceCollect;
+use rustc_span::symbol::kw;
+
+use crate::parse::macros::build_stream_parser;
+use crate::parse::session::ParseSess;
+
+pub(crate) fn parse_cfg_if<'a>(
+    sess: &'a ParseSess,
+    mac: &'a ast::MacCall,
+) -> Result<Vec<ast::Item>, &'static str> {
+    match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) {
+        Ok(Ok(items)) => Ok(items),
+        Ok(err @ Err(_)) => err,
+        Err(..) => Err("failed to parse cfg_if!"),
+    }
+}
+
+fn parse_cfg_if_inner<'a>(
+    sess: &'a ParseSess,
+    mac: &'a ast::MacCall,
+) -> Result<Vec<ast::Item>, &'static str> {
+    let ts = mac.args.inner_tokens();
+    let mut parser = build_stream_parser(sess.inner(), ts);
+
+    let mut items = vec![];
+    let mut process_if_cfg = true;
+
+    while parser.token.kind != TokenKind::Eof {
+        if process_if_cfg {
+            if !parser.eat_keyword(kw::If) {
+                return Err("Expected `if`");
+            }
+            // Inner attributes are not actually syntactically permitted here, but we don't
+            // care about inner vs outer attributes in this position. Our purpose with this
+            // special case parsing of cfg_if macros is to ensure we can correctly resolve
+            // imported modules that may have a custom `path` defined.
+            //
+            // As such, we just need to advance the parser past the attribute and up to
+            // to the opening brace.
+            // See also https://github.com/rust-lang/rust/pull/79433
+            parser
+                .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
+                .map_err(|_| "Failed to parse attributes")?;
+        }
+
+        if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
+            return Err("Expected an opening brace");
+        }
+
+        while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
+            && parser.token.kind != TokenKind::Eof
+        {
+            let item = match parser.parse_item(ForceCollect::No) {
+                Ok(Some(item_ptr)) => item_ptr.into_inner(),
+                Ok(None) => continue,
+                Err(mut err) => {
+                    err.cancel();
+                    parser.sess.span_diagnostic.reset_err_count();
+                    return Err(
+                        "Expected item inside cfg_if block, but failed to parse it as an item",
+                    );
+                }
+            };
+            if let ast::ItemKind::Mod(..) = item.kind {
+                items.push(item);
+            }
+        }
+
+        if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
+            return Err("Expected a closing brace");
+        }
+
+        if parser.eat(&TokenKind::Eof) {
+            break;
+        }
+
+        if !parser.eat_keyword(kw::Else) {
+            return Err("Expected `else`");
+        }
+
+        process_if_cfg = parser.token.is_keyword(kw::If);
+    }
+
+    Ok(items)
+}
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index 414b72f2921..fbd8c3f9095 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
+use rustc_session::parse::ParseSess;
 use rustc_span::{
     symbol::{self, kw},
     BytePos, Span, Symbol, DUMMY_SP,
@@ -11,10 +12,15 @@ use rustc_span::{
 use crate::macros::MacroArg;
 use crate::rewrite::{Rewrite, RewriteContext};
 
+pub(crate) mod cfg_if;
 pub(crate) mod lazy_static;
 
+fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
+    stream_to_parser(sess, tokens, MACRO_ARGUMENTS)
+}
+
 fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
-    stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
+    build_stream_parser(context.parse_sess.inner(), tokens)
 }
 
 fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 024b38cebb6..8efd2bf257b 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -175,84 +175,4 @@ impl<'a> Parser<'a> {
             Err(_) => Err(ParserError::ParsePanicError),
         }
     }
-
-    pub(crate) fn parse_cfg_if(
-        sess: &'a ParseSess,
-        mac: &'a ast::MacCall,
-    ) -> Result<Vec<ast::Item>, &'static str> {
-        match catch_unwind(AssertUnwindSafe(|| Parser::parse_cfg_if_inner(sess, mac))) {
-            Ok(Ok(items)) => Ok(items),
-            Ok(err @ Err(_)) => err,
-            Err(..) => Err("failed to parse cfg_if!"),
-        }
-    }
-
-    fn parse_cfg_if_inner(
-        sess: &'a ParseSess,
-        mac: &'a ast::MacCall,
-    ) -> Result<Vec<ast::Item>, &'static str> {
-        let token_stream = mac.args.inner_tokens();
-        let mut parser = rustc_parse::stream_to_parser(sess.inner(), token_stream, Some(""));
-
-        let mut items = vec![];
-        let mut process_if_cfg = true;
-
-        while parser.token.kind != TokenKind::Eof {
-            if process_if_cfg {
-                if !parser.eat_keyword(kw::If) {
-                    return Err("Expected `if`");
-                }
-                // Inner attributes are not actually syntactically permitted here, but we don't
-                // care about inner vs outer attributes in this position. Our purpose with this
-                // special case parsing of cfg_if macros is to ensure we can correctly resolve
-                // imported modules that may have a custom `path` defined.
-                //
-                // As such, we just need to advance the parser past the attribute and up to
-                // to the opening brace.
-                // See also https://github.com/rust-lang/rust/pull/79433
-                parser
-                    .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
-                    .map_err(|_| "Failed to parse attributes")?;
-            }
-
-            if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
-                return Err("Expected an opening brace");
-            }
-
-            while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
-                && parser.token.kind != TokenKind::Eof
-            {
-                let item = match parser.parse_item(ForceCollect::No) {
-                    Ok(Some(item_ptr)) => item_ptr.into_inner(),
-                    Ok(None) => continue,
-                    Err(mut err) => {
-                        err.cancel();
-                        parser.sess.span_diagnostic.reset_err_count();
-                        return Err(
-                            "Expected item inside cfg_if block, but failed to parse it as an item",
-                        );
-                    }
-                };
-                if let ast::ItemKind::Mod(..) = item.kind {
-                    items.push(item);
-                }
-            }
-
-            if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
-                return Err("Expected a closing brace");
-            }
-
-            if parser.eat(&TokenKind::Eof) {
-                break;
-            }
-
-            if !parser.eat_keyword(kw::Else) {
-                return Err("Expected `else`");
-            }
-
-            process_if_cfg = parser.token.is_keyword(kw::If);
-        }
-
-        Ok(items)
-    }
 }

From 7b8303d47968a0e1fcad4b143e0ff4b5e512f37b Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 20 Dec 2021 20:33:20 -0600
Subject: [PATCH 118/195] chore: cleanup unused imports

---
 src/parse/macros/mod.rs | 12 +++++-------
 src/parse/parser.rs     |  9 +++------
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index fbd8c3f9095..7e12f82af15 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -1,16 +1,14 @@
-use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind};
-use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
+use rustc_ast::token::{DelimToken, TokenKind};
+use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ast, ptr};
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
 use rustc_session::parse::ParseSess;
-use rustc_span::{
-    symbol::{self, kw},
-    BytePos, Span, Symbol, DUMMY_SP,
-};
+use rustc_span::symbol::{self, kw};
+use rustc_span::Symbol;
 
 use crate::macros::MacroArg;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::RewriteContext;
 
 pub(crate) mod cfg_if;
 pub(crate) mod lazy_static;
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 8efd2bf257b..657217633f4 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -1,14 +1,11 @@
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::path::{Path, PathBuf};
 
-use rustc_ast::token::{DelimToken, TokenKind};
+use rustc_ast::token::TokenKind;
 use rustc_ast::{ast, ptr};
 use rustc_errors::Diagnostic;
-use rustc_parse::{
-    new_parser_from_file,
-    parser::{ForceCollect, Parser as RawParser},
-};
-use rustc_span::{sym, symbol::kw, Span};
+use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
+use rustc_span::{sym, Span};
 
 use crate::attr::first_attr_value_str_by_name;
 use crate::parse::session::ParseSess;

From 0b2fd9b1329a41702ff2db51426003a37c1db510 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 23 Dec 2021 14:23:51 -0800
Subject: [PATCH 119/195] Fix static async closure qualifier order

---
 src/closures.rs             | 14 +++++++-------
 tests/source/async_block.rs | 16 ++++++++++++++++
 tests/target/async_block.rs | 10 ++++++++++
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/src/closures.rs b/src/closures.rs
index 34d73a77fd3..e688db1c39d 100644
--- a/src/closures.rs
+++ b/src/closures.rs
@@ -236,21 +236,21 @@ fn rewrite_closure_fn_decl(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<(String, usize)> {
+    let immovable = if movability == ast::Movability::Static {
+        "static "
+    } else {
+        ""
+    };
     let is_async = if asyncness.is_async() { "async " } else { "" };
     let mover = if capture == ast::CaptureBy::Value {
         "move "
     } else {
         ""
     };
-    let immovable = if movability == ast::Movability::Static {
-        "static "
-    } else {
-        ""
-    };
     // 4 = "|| {".len(), which is overconservative when the closure consists of
     // a single expression.
     let nested_shape = shape
-        .shrink_left(is_async.len() + mover.len() + immovable.len())?
+        .shrink_left(immovable.len() + is_async.len() + mover.len())?
         .sub_width(4)?;
 
     // 1 = |
@@ -288,7 +288,7 @@ fn rewrite_closure_fn_decl(
         .tactic(tactic)
         .preserve_newline(true);
     let list_str = write_list(&item_vec, &fmt)?;
-    let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str);
+    let mut prefix = format!("{}{}{}|{}|", immovable, is_async, mover, list_str);
 
     if !ret_str.is_empty() {
         if prefix.contains('\n') {
diff --git a/tests/source/async_block.rs b/tests/source/async_block.rs
index 3de51a084d2..18cb4fb5f5c 100644
--- a/tests/source/async_block.rs
+++ b/tests/source/async_block.rs
@@ -32,4 +32,20 @@ fn baz() {
             Ok(())
         },
     );
+
+    spawn(
+        a,
+        static async || {
+            action();
+            Ok(())
+        },
+    );
+
+    spawn(
+        a,
+        static async move || {
+            action();
+            Ok(())
+        },
+    );
 }
diff --git a/tests/target/async_block.rs b/tests/target/async_block.rs
index 258dd937a6f..137d849c9ee 100644
--- a/tests/target/async_block.rs
+++ b/tests/target/async_block.rs
@@ -22,4 +22,14 @@ fn baz() {
         action();
         Ok(())
     });
+
+    spawn(a, static async || {
+        action();
+        Ok(())
+    });
+
+    spawn(a, static async move || {
+        action();
+        Ok(())
+    });
 }

From 76eb077fb298a01137c878a9f10854b44c5edf37 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Thu, 23 Dec 2021 20:22:09 -0500
Subject: [PATCH 120/195] Retain qualified path when rewriting struct literals

Fixes 5151

Details about the qualified path are now passed along so that rustfmt
can include them when formatting struct literals.
---
 src/expr.rs                                | 19 ++++++++++++++++---
 tests/target/issue-5151/minimum_example.rs | 16 ++++++++++++++++
 2 files changed, 32 insertions(+), 3 deletions(-)
 create mode 100644 tests/target/issue-5151/minimum_example.rs

diff --git a/src/expr.rs b/src/expr.rs
index edd004ac63f..c9c8852cd3b 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -108,9 +108,21 @@ pub(crate) fn format_expr(
         ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
         ast::ExprKind::Struct(ref struct_expr) => {
             let ast::StructExpr {
-                fields, path, rest, ..
+                qself,
+                fields,
+                path,
+                rest,
             } = &**struct_expr;
-            rewrite_struct_lit(context, path, fields, rest, &expr.attrs, expr.span, shape)
+            rewrite_struct_lit(
+                context,
+                path,
+                qself.as_ref(),
+                fields,
+                rest,
+                &expr.attrs,
+                expr.span,
+                shape,
+            )
         }
         ast::ExprKind::Tup(ref items) => {
             rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1)
@@ -1511,6 +1523,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool
 fn rewrite_struct_lit<'a>(
     context: &RewriteContext<'_>,
     path: &ast::Path,
+    qself: Option<&ast::QSelf>,
     fields: &'a [ast::ExprField],
     struct_rest: &ast::StructRest,
     attrs: &[ast::Attribute],
@@ -1527,7 +1540,7 @@ fn rewrite_struct_lit<'a>(
 
     // 2 = " {".len()
     let path_shape = shape.sub_width(2)?;
-    let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;
+    let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
 
     let has_base_or_rest = match struct_rest {
         ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
diff --git a/tests/target/issue-5151/minimum_example.rs b/tests/target/issue-5151/minimum_example.rs
new file mode 100644
index 00000000000..2ed3d936e32
--- /dev/null
+++ b/tests/target/issue-5151/minimum_example.rs
@@ -0,0 +1,16 @@
+#![feature(more_qualified_paths)]
+
+struct Struct {}
+
+trait Trait {
+    type Type;
+}
+
+impl Trait for Struct {
+    type Type = Self;
+}
+
+fn main() {
+    // keep the qualified path details
+    let _ = <Struct as Trait>::Type {};
+}

From e8afb62c71f5c789c554e23c835efc019cb42685 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 27 Dec 2021 17:42:48 -0600
Subject: [PATCH 121/195] chore: reduce some vis. for updated unreachable_pub
 lint

---
 src/config/file_lines.rs |  8 ++++----
 src/config/options.rs    | 14 +++++++-------
 src/rustfmt_diff.rs      | 10 +++++-----
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs
index 4b799780d85..7b498dc46b3 100644
--- a/src/config/file_lines.rs
+++ b/src/config/file_lines.rs
@@ -13,9 +13,9 @@ use thiserror::Error;
 
 /// A range of lines in a file, inclusive of both ends.
 pub struct LineRange {
-    pub file: Lrc<SourceFile>,
-    pub lo: usize,
-    pub hi: usize,
+    pub(crate) file: Lrc<SourceFile>,
+    pub(crate) lo: usize,
+    pub(crate) hi: usize,
 }
 
 /// Defines the name of an input - either a file or stdin.
@@ -75,7 +75,7 @@ impl Serialize for FileName {
 }
 
 impl LineRange {
-    pub fn file_name(&self) -> FileName {
+    pub(crate) fn file_name(&self) -> FileName {
         self.file.name.clone().into()
     }
 }
diff --git a/src/config/options.rs b/src/config/options.rs
index bce9e5d07f2..d857c29be29 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -218,24 +218,24 @@ pub enum Verbosity {
 pub struct WidthHeuristics {
     // Maximum width of the args of a function call before falling back
     // to vertical formatting.
-    pub fn_call_width: usize,
+    pub(crate) fn_call_width: usize,
     // Maximum width of the args of a function-like attributes before falling
     // back to vertical formatting.
-    pub attr_fn_like_width: usize,
+    pub(crate) attr_fn_like_width: usize,
     // Maximum width in the body of a struct lit before falling back to
     // vertical formatting.
-    pub struct_lit_width: usize,
+    pub(crate) struct_lit_width: usize,
     // Maximum width in the body of a struct variant before falling back
     // to vertical formatting.
-    pub struct_variant_width: usize,
+    pub(crate) struct_variant_width: usize,
     // Maximum width of an array literal before falling back to vertical
     // formatting.
-    pub array_width: usize,
+    pub(crate) array_width: usize,
     // Maximum length of a chain to fit on a single line.
-    pub chain_width: usize,
+    pub(crate) chain_width: usize,
     // Maximum line length for single line if-else expressions. A value
     // of zero means always break if-else expressions.
-    pub single_line_if_else_max_width: usize,
+    pub(crate) single_line_if_else_max_width: usize,
 }
 
 impl fmt::Display for WidthHeuristics {
diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs
index a394ce07398..1724a0f87bf 100644
--- a/src/rustfmt_diff.rs
+++ b/src/rustfmt_diff.rs
@@ -6,20 +6,20 @@ use std::io::Write;
 use crate::config::{Color, Config, Verbosity};
 
 #[derive(Debug, PartialEq)]
-pub enum DiffLine {
+pub(crate) enum DiffLine {
     Context(String),
     Expected(String),
     Resulting(String),
 }
 
 #[derive(Debug, PartialEq)]
-pub struct Mismatch {
+pub(crate) struct Mismatch {
     /// The line number in the formatted version.
-    pub line_number: u32,
+    pub(crate) line_number: u32,
     /// The line number in the original version.
-    pub line_number_orig: u32,
+    pub(crate) line_number_orig: u32,
     /// The set of lines (context and old/new) in the mismatch.
-    pub lines: Vec<DiffLine>,
+    pub(crate) lines: Vec<DiffLine>,
 }
 
 impl Mismatch {

From 50bbb43dab5af3b42338bd6a9748da9a27136bf2 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Tue, 28 Dec 2021 19:23:31 -0600
Subject: [PATCH 122/195] chore: bump toolchain

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index c97b5ec6609..d4cdcec2018 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-12-20"
+channel = "nightly-2021-12-29"
 components = ["rustc-dev"]

From f935f0cf89f53a9df3a443b9cc09bb1bcc33064b Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Tue, 28 Dec 2021 19:23:51 -0600
Subject: [PATCH 123/195] feat: support parsing asm! args

---
 src/lib.rs              |  1 +
 src/parse/macros/asm.rs | 11 +++++++++++
 src/parse/macros/mod.rs |  1 +
 3 files changed, 13 insertions(+)
 create mode 100644 src/parse/macros/asm.rs

diff --git a/src/lib.rs b/src/lib.rs
index f59ebad97ce..ad23b16e02e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,6 +15,7 @@ extern crate log;
 // N.B. these crates are loaded from the sysroot, so they need extern crate.
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
+extern crate rustc_builtin_macros;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_expand;
diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs
new file mode 100644
index 00000000000..cc9fb5072ce
--- /dev/null
+++ b/src/parse/macros/asm.rs
@@ -0,0 +1,11 @@
+use rustc_ast::ast;
+use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs};
+
+use crate::rewrite::RewriteContext;
+
+#[allow(dead_code)]
+pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
+    let ts = mac.args.inner_tokens();
+    let mut parser = super::build_parser(context, ts);
+    parse_asm_args(&mut parser, context.parse_sess.inner(), mac.span(), false).ok()
+}
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index 7e12f82af15..2e9ce1d35f4 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -10,6 +10,7 @@ use rustc_span::Symbol;
 use crate::macros::MacroArg;
 use crate::rewrite::RewriteContext;
 
+pub(crate) mod asm;
 pub(crate) mod cfg_if;
 pub(crate) mod lazy_static;
 

From 4a053f206fd6799a25823c307f7d7f9d897be118 Mon Sep 17 00:00:00 2001
From: David Lattimore <dml@google.com>
Date: Thu, 30 Dec 2021 10:13:45 +1100
Subject: [PATCH 124/195] Do not flatten match arm block with leading
 attributes

This is a backport of #4124.

Fixes #4109
---
 src/matches.rs        |  6 +++++-
 tests/source/match.rs | 19 +++++++++++++++++++
 tests/target/match.rs | 19 +++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/matches.rs b/src/matches.rs
index 22d23fc1cdb..85d9c5d2b9b 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -322,7 +322,11 @@ fn flatten_arm_body<'a>(
     if let Some(block) = block_can_be_flattened(context, body) {
         if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
             if let ast::ExprKind::Block(..) = expr.kind {
-                flatten_arm_body(context, expr, None)
+                if expr.attrs.is_empty() {
+                    flatten_arm_body(context, expr, None)
+                } else {
+                    (true, body)
+                }
             } else {
                 let cond_becomes_muti_line = opt_shape
                     .and_then(|shape| rewrite_cond(context, expr, shape))
diff --git a/tests/source/match.rs b/tests/source/match.rs
index da20517203a..b5dc9957a2c 100644
--- a/tests/source/match.rs
+++ b/tests/source/match.rs
@@ -568,3 +568,22 @@ fn issue_3774() {
         }
     }
 }
+
+// #4109
+fn issue_4109() {
+    match () {
+        _ => {
+#[cfg(debug_assertions)]
+{
+println!("Foo");
+}
+}
+}
+
+match () {
+_ => {
+#[allow(unsafe_code)]
+unsafe {}
+}
+}
+}
diff --git a/tests/target/match.rs b/tests/target/match.rs
index e2c522bea10..1bf3fb758ee 100644
--- a/tests/target/match.rs
+++ b/tests/target/match.rs
@@ -608,3 +608,22 @@ fn issue_3774() {
         }
     }
 }
+
+// #4109
+fn issue_4109() {
+    match () {
+        _ => {
+            #[cfg(debug_assertions)]
+            {
+                println!("Foo");
+            }
+        }
+    }
+
+    match () {
+        _ => {
+            #[allow(unsafe_code)]
+            unsafe {}
+        }
+    }
+}

From 737e6f704671dbf30e81dababa0133b585c03b48 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sun, 19 Dec 2021 21:27:25 -0500
Subject: [PATCH 125/195] Improve out of line module resolution

Fixes 5119

When the directory structure was laid out as follows:

```
dir
 |---mod_a
 |    |---sub_mod_1.rs
 |    |---sub_mod_2.rs
 |---mod_a.rs
```

And ``mod_a.rs`` contains the following content:

```rust
mod mod_a {
    mod sub_mod_1;
    mod sub_mod_2;
}
```

rustfmt previously tried to find ``sub_mod_1.rs`` and ``sub_mod_2.rs``
in ``./mod_a/mod_a/``. This directory does not exist and this caused
rustfmt to fail with the error message:

    Error writing files: failed to resolve mod

Now, both ``sub_mod_1.rs`` and ``sub_mod_2.rs`` are resolved correctly
and found at ``mod_a/sub_mod_1.rs`` and ``mod_a/sub_mod_2.rs``.
---
 src/modules.rs                                |  9 ++++++-
 src/test/mod_resolver.rs                      | 14 +++++++++++
 tests/cargo-fmt/main.rs                       | 24 +++++++++++++++++++
 .../test-submodule-issue-5119/Cargo.toml      |  8 +++++++
 .../test-submodule-issue-5119/src/lib.rs      |  7 ++++++
 .../test-submodule-issue-5119/tests/test1.rs  |  8 +++++++
 .../tests/test1/sub1.rs                       |  6 +++++
 .../tests/test1/sub2.rs                       |  6 +++++
 .../tests/test1/sub3/mod.rs                   |  1 +
 .../tests/test1/sub3/sub4.rs                  |  0
 10 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/Cargo.toml
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/src/lib.rs
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs
 create mode 100644 tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs

diff --git a/src/modules.rs b/src/modules.rs
index 9c964b274e0..70b937b0283 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -458,6 +458,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             self.directory.path.push(path.as_str());
             self.directory.ownership = DirectoryOwnership::Owned { relative: None };
         } else {
+            let id = id.as_str();
             // We have to push on the current module name in the case of relative
             // paths in order to ensure that any additional module paths from inline
             // `mod x { ... }` come after the relative extension.
@@ -468,9 +469,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 if let Some(ident) = relative.take() {
                     // remove the relative offset
                     self.directory.path.push(ident.as_str());
+
+                    // In the case where there is an x.rs and an ./x directory we want
+                    // to prevent adding x twice. For example, ./x/x
+                    if self.directory.path.exists() && !self.directory.path.join(id).exists() {
+                        return;
+                    }
                 }
             }
-            self.directory.path.push(id.as_str());
+            self.directory.path.push(id);
         }
     }
 
diff --git a/src/test/mod_resolver.rs b/src/test/mod_resolver.rs
index ec9ed0f0b8d..fcff6d14e6f 100644
--- a/src/test/mod_resolver.rs
+++ b/src/test/mod_resolver.rs
@@ -50,3 +50,17 @@ fn skip_out_of_line_nested_inline_within_out_of_line() {
         &["tests/mod-resolver/skip-files-issue-5065/one.rs"],
     );
 }
+
+#[test]
+fn fmt_out_of_line_test_modules() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5119
+    verify_mod_resolution(
+        "tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs",
+        &[
+            "tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs",
+            "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs",
+            "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs",
+            "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs",
+        ],
+    )
+}
diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs
index 5493b09e4aa..bf81f253f69 100644
--- a/tests/cargo-fmt/main.rs
+++ b/tests/cargo-fmt/main.rs
@@ -2,6 +2,7 @@
 
 use std::env;
 use std::process::Command;
+use std::path::Path;
 
 /// Run the cargo-fmt executable and return its output.
 fn cargo_fmt(args: &[&str]) -> (String, String) {
@@ -71,3 +72,26 @@ fn rustfmt_help() {
     assert_that!(&["--", "-h"], contains("Format Rust code"));
     assert_that!(&["--", "--help=config"], contains("Configuration Options:"));
 }
+
+#[test]
+fn cargo_fmt_out_of_line_test_modules() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5119
+    let expected_modified_files = [
+        "tests/mod-resolver/test-submodule-issue-5119/src/lib.rs",
+        "tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs",
+        "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs",
+        "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs",
+        "tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs",
+    ];
+    let args = [
+        "-v",
+        "--check",
+        "--manifest-path",
+        "tests/mod-resolver/test-submodule-issue-5119/Cargo.toml",
+    ];
+    let (stdout, _) = cargo_fmt(&args);
+    for file in expected_modified_files {
+        let path = Path::new(file).canonicalize().unwrap();
+        assert!(stdout.contains(&format!("Diff in {}", path.display())))
+    }
+}
diff --git a/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml b/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml
new file mode 100644
index 00000000000..0993f127959
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "rustfmt-test-submodule-issue"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs b/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs
new file mode 100644
index 00000000000..3f7ddba8a28
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs
@@ -0,0 +1,7 @@
+pub fn foo() -> i32 {
+3
+}
+
+pub fn bar() -> i32 {
+4
+}
diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs b/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs
new file mode 100644
index 00000000000..da4e86169ad
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs
@@ -0,0 +1,8 @@
+mod test1 {
+#[cfg(unix)]
+mod sub1;
+#[cfg(not(unix))]
+mod sub2;
+
+mod sub3;
+}
diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs
new file mode 100644
index 00000000000..b760ba23cd2
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs
@@ -0,0 +1,6 @@
+use rustfmt_test_submodule_issue::foo;
+
+#[test]
+fn test_foo() {
+assert_eq!(3, foo());
+}
diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs
new file mode 100644
index 00000000000..4fd8286eac4
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs
@@ -0,0 +1,6 @@
+use rustfmt_test_submodule_issue::bar;
+
+#[test]
+fn test_bar() {
+assert_eq!(4, bar());
+}
diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs
new file mode 100644
index 00000000000..e029785bc24
--- /dev/null
+++ b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs
@@ -0,0 +1 @@
+mod sub4;
diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs b/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs
new file mode 100644
index 00000000000..e69de29bb2d

From 93b7de5b0110a1ab79714c3dfd009a4aae3e34b1 Mon Sep 17 00:00:00 2001
From: Chris Emerson <github@mail.nosreme.org>
Date: Wed, 6 Nov 2019 10:15:34 +0000
Subject: [PATCH 126/195] Make `--check` work when running from stdin. (#3896)

# Conflicts:
#	src/bin/main.rs
---
 src/bin/main.rs                   | 31 ++++++-----
 src/emitter/checkstyle.rs         | 12 ++--
 src/emitter/json.rs               | 20 +++++--
 src/test/mod.rs                   | 93 +++++++++++++++++++++++++++++++
 tests/writemode/source/stdin.rs   |  6 ++
 tests/writemode/target/stdin.json |  1 +
 tests/writemode/target/stdin.xml  |  2 +
 7 files changed, 139 insertions(+), 26 deletions(-)
 create mode 100644 tests/writemode/source/stdin.rs
 create mode 100644 tests/writemode/target/stdin.json
 create mode 100644 tests/writemode/target/stdin.xml

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 4d845547cdf..6f5b09fc86a 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -74,14 +74,10 @@ pub enum OperationError {
     /// An io error during reading or writing.
     #[error("{0}")]
     IoError(IoError),
-    /// Attempt to use --check with stdin, which isn't currently
-    /// supported.
-    #[error("The `--check` option is not supported with standard input.")]
-    CheckWithStdin,
-    /// Attempt to use --emit=json with stdin, which isn't currently
-    /// supported.
-    #[error("Using `--emit` other than stdout is not supported with standard input.")]
-    EmitWithStdin,
+    /// Attempt to use --emit with a mode which is not currently
+    /// supported with stdandard input.
+    #[error("Emit mode {0} not supported with standard output.")]
+    StdinBadEmit(EmitMode),
 }
 
 impl From<IoError> for OperationError {
@@ -255,15 +251,20 @@ fn format_string(input: String, options: GetOptsOptions) -> Result<i32> {
     let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?;
 
     if options.check {
-        return Err(OperationError::CheckWithStdin.into());
-    }
-    if let Some(emit_mode) = options.emit_mode {
-        if emit_mode != EmitMode::Stdout {
-            return Err(OperationError::EmitWithStdin.into());
+        config.set().emit_mode(EmitMode::Diff);
+    } else {
+        match options.emit_mode {
+            // Emit modes which work with standard input
+            // None means default, which is Stdout.
+            None | Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => {}
+            Some(emit_mode) => {
+                return Err(OperationError::StdinBadEmit(emit_mode).into());
+            }
         }
+        config
+            .set()
+            .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout));
     }
-    // emit mode is always Stdout for Stdin.
-    config.set().emit_mode(EmitMode::Stdout);
     config.set().verbose(Verbosity::Quiet);
 
     // parse file_lines
diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs
index 76f2527db3d..545b259979d 100644
--- a/src/emitter/checkstyle.rs
+++ b/src/emitter/checkstyle.rs
@@ -2,7 +2,6 @@ use self::xml::XmlEscaped;
 use super::*;
 use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
 use std::io::{self, Write};
-use std::path::Path;
 
 mod xml;
 
@@ -30,7 +29,6 @@ impl Emitter for CheckstyleEmitter {
         }: FormattedFile<'_>,
     ) -> Result<EmitterResult, io::Error> {
         const CONTEXT_SIZE: usize = 0;
-        let filename = ensure_real_path(filename);
         let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE);
         output_checkstyle_file(output, filename, diff)?;
         Ok(EmitterResult::default())
@@ -39,13 +37,13 @@ impl Emitter for CheckstyleEmitter {
 
 pub(crate) fn output_checkstyle_file<T>(
     mut writer: T,
-    filename: &Path,
+    filename: &FileName,
     diff: Vec<Mismatch>,
 ) -> Result<(), io::Error>
 where
     T: Write,
 {
-    write!(writer, r#"<file name="{}">"#, filename.display())?;
+    write!(writer, r#"<file name="{}">"#, filename)?;
     for mismatch in diff {
         let begin_line = mismatch.line_number;
         let mut current_line;
@@ -77,7 +75,11 @@ mod tests {
     fn emits_empty_record_on_file_with_no_mismatches() {
         let file_name = "src/well_formatted.rs";
         let mut writer = Vec::new();
-        let _ = output_checkstyle_file(&mut writer, &PathBuf::from(file_name), vec![]);
+        let _ = output_checkstyle_file(
+            &mut writer,
+            &FileName::Real(PathBuf::from(file_name)),
+            vec![],
+        );
         assert_eq!(
             &writer[..],
             format!(r#"<file name="{}"></file>"#, file_name).as_bytes()
diff --git a/src/emitter/json.rs b/src/emitter/json.rs
index 269dd2d4daf..4d6f972c5e3 100644
--- a/src/emitter/json.rs
+++ b/src/emitter/json.rs
@@ -3,7 +3,6 @@ use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
 use serde::Serialize;
 use serde_json::to_string as to_json_string;
 use std::io::{self, Write};
-use std::path::Path;
 
 #[derive(Debug, Default)]
 pub(crate) struct JsonEmitter {
@@ -47,7 +46,6 @@ impl Emitter for JsonEmitter {
         }: FormattedFile<'_>,
     ) -> Result<EmitterResult, io::Error> {
         const CONTEXT_SIZE: usize = 0;
-        let filename = ensure_real_path(filename);
         let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE);
         let has_diff = !diff.is_empty();
 
@@ -62,7 +60,7 @@ impl Emitter for JsonEmitter {
 
 fn output_json_file<T>(
     mut writer: T,
-    filename: &Path,
+    filename: &FileName,
     diff: Vec<Mismatch>,
     num_emitted_files: u32,
 ) -> Result<(), io::Error>
@@ -106,7 +104,7 @@ where
         });
     }
     let json = to_json_string(&MismatchedFile {
-        name: String::from(filename.to_str().unwrap()),
+        name: format!("{}", filename),
         mismatches,
     })?;
     let prefix = if num_emitted_files > 0 { "," } else { "" };
@@ -148,7 +146,12 @@ mod tests {
 
         let mut writer = Vec::new();
         let exp_json = to_json_string(&mismatched_file).unwrap();
-        let _ = output_json_file(&mut writer, &PathBuf::from(file), vec![mismatch], 0);
+        let _ = output_json_file(
+            &mut writer,
+            &FileName::Real(PathBuf::from(file)),
+            vec![mismatch],
+            0,
+        );
         assert_eq!(&writer[..], format!("{}", exp_json).as_bytes());
     }
 
@@ -188,7 +191,12 @@ mod tests {
 
         let mut writer = Vec::new();
         let exp_json = to_json_string(&mismatched_file).unwrap();
-        let _ = output_json_file(&mut writer, &PathBuf::from(file), vec![mismatch], 0);
+        let _ = output_json_file(
+            &mut writer,
+            &FileName::Real(PathBuf::from(file)),
+            vec![mismatch],
+            0,
+        );
         assert_eq!(&writer[..], format!("{}", exp_json).as_bytes());
     }
 
diff --git a/src/test/mod.rs b/src/test/mod.rs
index cceb28dfea6..e1a7972ec82 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -307,6 +307,52 @@ fn assert_output(source: &Path, expected_filename: &Path) {
     }
 }
 
+// Helper function for comparing the results of rustfmt
+// to a known output generated by one of the write modes.
+fn assert_stdin_output(
+    source: &Path,
+    expected_filename: &Path,
+    emit_mode: EmitMode,
+    has_diff: bool,
+) {
+    let mut config = Config::default();
+    config.set().newline_style(NewlineStyle::Unix);
+    config.set().emit_mode(emit_mode);
+
+    let mut source_file = fs::File::open(&source).expect("couldn't open source");
+    let mut source_text = String::new();
+    source_file
+        .read_to_string(&mut source_text)
+        .expect("Failed reading target");
+    let input = Input::Text(source_text);
+
+    // Populate output by writing to a vec.
+    let mut buf: Vec<u8> = vec![];
+    {
+        let mut session = Session::new(config, Some(&mut buf));
+        session.format(input).unwrap();
+        let errors = ReportedErrors {
+            has_diff: has_diff,
+            ..Default::default()
+        };
+        assert_eq!(session.errors, errors);
+    }
+
+    let mut expected_file = fs::File::open(&expected_filename).expect("couldn't open target");
+    let mut expected_text = String::new();
+    expected_file
+        .read_to_string(&mut expected_text)
+        .expect("Failed reading target");
+
+    let output = String::from_utf8(buf).unwrap();
+    let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE);
+    if !compare.is_empty() {
+        let mut failures = HashMap::new();
+        failures.insert(source.to_owned(), compare);
+        print_mismatches_default_message(failures);
+        panic!("Text does not match expected output");
+    }
+}
 // Idempotence tests. Files in tests/target are checked to be unaltered by
 // rustfmt.
 #[nightly_only_test]
@@ -463,6 +509,30 @@ fn stdin_works_with_modified_lines() {
     assert_eq!(buf, output.as_bytes());
 }
 
+/// Ensures that `EmitMode::Json` works with input from `stdin`.
+#[test]
+fn stdin_works_with_json() {
+    init_log();
+    assert_stdin_output(
+        Path::new("tests/writemode/source/stdin.rs"),
+        Path::new("tests/writemode/target/stdin.json"),
+        EmitMode::Json,
+        true,
+    );
+}
+
+/// Ensures that `EmitMode::Checkstyle` works with input from `stdin`.
+#[test]
+fn stdin_works_with_checkstyle() {
+    init_log();
+    assert_stdin_output(
+        Path::new("tests/writemode/source/stdin.rs"),
+        Path::new("tests/writemode/target/stdin.xml"),
+        EmitMode::Checkstyle,
+        false,
+    );
+}
+
 #[test]
 fn stdin_disable_all_formatting_test() {
     init_log();
@@ -896,3 +966,26 @@ fn verify_check_works() {
         .status()
         .expect("run with check option failed");
 }
+
+#[test]
+fn verify_check_works_with_stdin() {
+    init_log();
+
+    let mut child = Command::new(rustfmt().to_str().unwrap())
+        .arg("--check")
+        .stdin(Stdio::piped())
+        .stderr(Stdio::piped())
+        .spawn()
+        .expect("run with check option failed");
+
+    {
+        let stdin = child.stdin.as_mut().expect("Failed to open stdin");
+        stdin
+            .write_all("fn main() {}\n".as_bytes())
+            .expect("Failed to write to rustfmt --check");
+    }
+    let output = child
+        .wait_with_output()
+        .expect("Failed to wait on rustfmt child");
+    assert!(output.status.success());
+}
diff --git a/tests/writemode/source/stdin.rs b/tests/writemode/source/stdin.rs
new file mode 100644
index 00000000000..06f8a0c288d
--- /dev/null
+++ b/tests/writemode/source/stdin.rs
@@ -0,0 +1,6 @@
+
+fn
+ some( )
+{
+}
+fn main () {}
diff --git a/tests/writemode/target/stdin.json b/tests/writemode/target/stdin.json
new file mode 100644
index 00000000000..20e38f57f4a
--- /dev/null
+++ b/tests/writemode/target/stdin.json
@@ -0,0 +1 @@
+[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}","expected":"fn some() {}\nfn main() {}"}]}]
\ No newline at end of file
diff --git a/tests/writemode/target/stdin.xml b/tests/writemode/target/stdin.xml
new file mode 100644
index 00000000000..e70708338f5
--- /dev/null
+++ b/tests/writemode/target/stdin.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<checkstyle version="4.3"><file name="stdin"><error line="1" severity="warning" message="Should be `fn some() {}`" /><error line="2" severity="warning" message="Should be `fn main() {}`" /></file></checkstyle>

From 34263cd6bdb29df23258a96ea18fe986efe8dad0 Mon Sep 17 00:00:00 2001
From: Chris Emerson <github@mail.nosreme.org>
Date: Tue, 12 Nov 2019 02:55:04 +0000
Subject: [PATCH 127/195] Fix --check -l with stdin. (#3910)

* Fix some possible panics when using `--check` with stdin.

One case which doesn't work is when there are only line ending fixes;
with stdin rustfmt is unable to detect the difference as it stores
the input with Unix line endings.

* Add test for `rustfmt --check -l` with stdin.
---
 src/emitter/diff.rs |  5 ++---
 src/test/mod.rs     | 26 ++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs
index 7264ad8bbf3..5e1f1344656 100644
--- a/src/emitter/diff.rs
+++ b/src/emitter/diff.rs
@@ -28,7 +28,7 @@ impl Emitter for DiffEmitter {
 
         if has_diff {
             if self.config.print_misformatted_file_names() {
-                writeln!(output, "{}", ensure_real_path(filename).display())?;
+                writeln!(output, "{}", filename)?;
             } else {
                 print_diff(
                     mismatch,
@@ -40,8 +40,7 @@ impl Emitter for DiffEmitter {
             // This occurs when the only difference between the original and formatted values
             // is the newline style. This happens because The make_diff function compares the
             // original and formatted values line by line, independent of line endings.
-            let file_path = ensure_real_path(filename);
-            writeln!(output, "Incorrect newline style in {}", file_path.display())?;
+            writeln!(output, "Incorrect newline style in {}", filename)?;
             return Ok(EmitterResult { has_diff: true });
         }
 
diff --git a/src/test/mod.rs b/src/test/mod.rs
index e1a7972ec82..db1cf88479c 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -989,3 +989,29 @@ fn verify_check_works_with_stdin() {
         .expect("Failed to wait on rustfmt child");
     assert!(output.status.success());
 }
+
+#[test]
+fn verify_check_l_works_with_stdin() {
+    init_log();
+
+    let mut child = Command::new(rustfmt().to_str().unwrap())
+        .arg("--check")
+        .arg("-l")
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .stderr(Stdio::piped())
+        .spawn()
+        .expect("run with check option failed");
+
+    {
+        let stdin = child.stdin.as_mut().expect("Failed to open stdin");
+        stdin
+            .write_all("fn main()\n{}\n".as_bytes())
+            .expect("Failed to write to rustfmt --check");
+    }
+    let output = child
+        .wait_with_output()
+        .expect("Failed to wait on rustfmt child");
+    assert!(output.status.success());
+    assert_eq!(std::str::from_utf8(&output.stdout).unwrap(), "stdin\n");
+}

From 776baf93f8fd1e2f3a66da4c2a1dd92114cef9c6 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <calebcartwright@users.noreply.github.com>
Date: Mon, 9 Dec 2019 04:41:16 -0600
Subject: [PATCH 128/195] refactor: update json emitter to better handle errors
 (#3953)

---
 src/emitter/json.rs                | 169 +++++++++++++----------------
 tests/writemode/target/output.json |   2 +-
 tests/writemode/target/stdin.json  |   2 +-
 3 files changed, 80 insertions(+), 93 deletions(-)

diff --git a/src/emitter/json.rs b/src/emitter/json.rs
index 4d6f972c5e3..7c0f862cbc6 100644
--- a/src/emitter/json.rs
+++ b/src/emitter/json.rs
@@ -6,10 +6,10 @@ use std::io::{self, Write};
 
 #[derive(Debug, Default)]
 pub(crate) struct JsonEmitter {
-    num_files: u32,
+    mismatched_files: Vec<MismatchedFile>,
 }
 
-#[derive(Debug, Default, Serialize)]
+#[derive(Debug, Default, PartialEq, Serialize)]
 struct MismatchedBlock {
     original_begin_line: u32,
     original_end_line: u32,
@@ -19,26 +19,20 @@ struct MismatchedBlock {
     expected: String,
 }
 
-#[derive(Debug, Default, Serialize)]
+#[derive(Debug, Default, PartialEq, Serialize)]
 struct MismatchedFile {
     name: String,
     mismatches: Vec<MismatchedBlock>,
 }
 
 impl Emitter for JsonEmitter {
-    fn emit_header(&self, output: &mut dyn Write) -> Result<(), io::Error> {
-        write!(output, "[")?;
-        Ok(())
-    }
-
     fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> {
-        write!(output, "]")?;
-        Ok(())
+        writeln!(output, "{}", &to_json_string(&self.mismatched_files)?)
     }
 
     fn emit_formatted_file(
         &mut self,
-        output: &mut dyn Write,
+        _output: &mut dyn Write,
         FormattedFile {
             filename,
             original_text,
@@ -50,66 +44,61 @@ impl Emitter for JsonEmitter {
         let has_diff = !diff.is_empty();
 
         if has_diff {
-            output_json_file(output, filename, diff, self.num_files)?;
-            self.num_files += 1;
+            self.add_misformatted_file(filename, diff)?;
         }
 
         Ok(EmitterResult { has_diff })
     }
 }
 
-fn output_json_file<T>(
-    mut writer: T,
-    filename: &FileName,
-    diff: Vec<Mismatch>,
-    num_emitted_files: u32,
-) -> Result<(), io::Error>
-where
-    T: Write,
-{
-    let mut mismatches = vec![];
-    for mismatch in diff {
-        let original_begin_line = mismatch.line_number_orig;
-        let expected_begin_line = mismatch.line_number;
-        let mut original_end_line = original_begin_line;
-        let mut expected_end_line = expected_begin_line;
-        let mut original_line_counter = 0;
-        let mut expected_line_counter = 0;
-        let mut original_lines = vec![];
-        let mut expected_lines = vec![];
+impl JsonEmitter {
+    fn add_misformatted_file(
+        &mut self,
+        filename: &FileName,
+        diff: Vec<Mismatch>,
+    ) -> Result<(), io::Error> {
+        let mut mismatches = vec![];
+        for mismatch in diff {
+            let original_begin_line = mismatch.line_number_orig;
+            let expected_begin_line = mismatch.line_number;
+            let mut original_end_line = original_begin_line;
+            let mut expected_end_line = expected_begin_line;
+            let mut original_line_counter = 0;
+            let mut expected_line_counter = 0;
+            let mut original_lines = vec![];
+            let mut expected_lines = vec![];
 
-        for line in mismatch.lines {
-            match line {
-                DiffLine::Expected(msg) => {
-                    expected_end_line = expected_begin_line + expected_line_counter;
-                    expected_line_counter += 1;
-                    expected_lines.push(msg)
+            for line in mismatch.lines {
+                match line {
+                    DiffLine::Expected(msg) => {
+                        expected_end_line = expected_begin_line + expected_line_counter;
+                        expected_line_counter += 1;
+                        expected_lines.push(msg)
+                    }
+                    DiffLine::Resulting(msg) => {
+                        original_end_line = original_begin_line + original_line_counter;
+                        original_line_counter += 1;
+                        original_lines.push(msg)
+                    }
+                    DiffLine::Context(_) => continue,
                 }
-                DiffLine::Resulting(msg) => {
-                    original_end_line = original_begin_line + original_line_counter;
-                    original_line_counter += 1;
-                    original_lines.push(msg)
-                }
-                DiffLine::Context(_) => continue,
             }
-        }
 
-        mismatches.push(MismatchedBlock {
-            original_begin_line,
-            original_end_line,
-            expected_begin_line,
-            expected_end_line,
-            original: original_lines.join("\n"),
-            expected: expected_lines.join("\n"),
+            mismatches.push(MismatchedBlock {
+                original_begin_line,
+                original_end_line,
+                expected_begin_line,
+                expected_end_line,
+                original: original_lines.join("\n"),
+                expected: expected_lines.join("\n"),
+            });
+        }
+        self.mismatched_files.push(MismatchedFile {
+            name: format!("{}", filename),
+            mismatches,
         });
+        Ok(())
     }
-    let json = to_json_string(&MismatchedFile {
-        name: format!("{}", filename),
-        mismatches,
-    })?;
-    let prefix = if num_emitted_files > 0 { "," } else { "" };
-    write!(writer, "{}{}", prefix, &json)?;
-    Ok(())
 }
 
 #[cfg(test)]
@@ -120,6 +109,9 @@ mod tests {
 
     #[test]
     fn expected_line_range_correct_when_single_line_split() {
+        let mut emitter = JsonEmitter {
+            mismatched_files: vec![],
+        };
         let file = "foo/bar.rs";
         let mismatched_file = MismatchedFile {
             name: String::from(file),
@@ -144,19 +136,19 @@ mod tests {
             ],
         };
 
-        let mut writer = Vec::new();
-        let exp_json = to_json_string(&mismatched_file).unwrap();
-        let _ = output_json_file(
-            &mut writer,
-            &FileName::Real(PathBuf::from(file)),
-            vec![mismatch],
-            0,
-        );
-        assert_eq!(&writer[..], format!("{}", exp_json).as_bytes());
+        let _ = emitter
+            .add_misformatted_file(&FileName::Real(PathBuf::from(file)), vec![mismatch])
+            .unwrap();
+
+        assert_eq!(emitter.mismatched_files.len(), 1);
+        assert_eq!(emitter.mismatched_files[0], mismatched_file);
     }
 
     #[test]
     fn context_lines_ignored() {
+        let mut emitter = JsonEmitter {
+            mismatched_files: vec![],
+        };
         let file = "src/lib.rs";
         let mismatched_file = MismatchedFile {
             name: String::from(file),
@@ -189,15 +181,12 @@ mod tests {
             ],
         };
 
-        let mut writer = Vec::new();
-        let exp_json = to_json_string(&mismatched_file).unwrap();
-        let _ = output_json_file(
-            &mut writer,
-            &FileName::Real(PathBuf::from(file)),
-            vec![mismatch],
-            0,
-        );
-        assert_eq!(&writer[..], format!("{}", exp_json).as_bytes());
+        let _ = emitter
+            .add_misformatted_file(&FileName::Real(PathBuf::from(file)), vec![mismatch])
+            .unwrap();
+
+        assert_eq!(emitter.mismatched_files.len(), 1);
+        assert_eq!(emitter.mismatched_files[0], mismatched_file);
     }
 
     #[test]
@@ -217,7 +206,7 @@ mod tests {
             .unwrap();
         let _ = emitter.emit_footer(&mut writer);
         assert_eq!(result.has_diff, false);
-        assert_eq!(&writer[..], "[]".as_bytes());
+        assert_eq!(&writer[..], "[]\n".as_bytes());
     }
 
     #[test]
@@ -263,7 +252,7 @@ mod tests {
             )
             .unwrap();
         let _ = emitter.emit_footer(&mut writer);
-        let exp_json = to_json_string(&MismatchedFile {
+        let exp_json = to_json_string(&vec![MismatchedFile {
             name: String::from(file_name),
             mismatches: vec![
                 MismatchedBlock {
@@ -287,10 +276,10 @@ mod tests {
                     ),
                 },
             ],
-        })
+        }])
         .unwrap();
         assert_eq!(result.has_diff, true);
-        assert_eq!(&writer[..], format!("[{}]", exp_json).as_bytes());
+        assert_eq!(&writer[..], format!("{}\n", exp_json).as_bytes());
     }
 
     #[test]
@@ -325,7 +314,7 @@ mod tests {
             )
             .unwrap();
         let _ = emitter.emit_footer(&mut writer);
-        let exp_bin_json = to_json_string(&MismatchedFile {
+        let exp_bin = MismatchedFile {
             name: String::from(bin_file),
             mismatches: vec![MismatchedBlock {
                 original_begin_line: 2,
@@ -335,9 +324,9 @@ mod tests {
                 original: String::from("println!(\"Hello, world!\");"),
                 expected: String::from("    println!(\"Hello, world!\");"),
             }],
-        })
-        .unwrap();
-        let exp_lib_json = to_json_string(&MismatchedFile {
+        };
+
+        let exp_lib = MismatchedFile {
             name: String::from(lib_file),
             mismatches: vec![MismatchedBlock {
                 original_begin_line: 2,
@@ -347,11 +336,9 @@ mod tests {
                 original: String::from("println!(\"Greetings!\");"),
                 expected: String::from("    println!(\"Greetings!\");"),
             }],
-        })
-        .unwrap();
-        assert_eq!(
-            &writer[..],
-            format!("[{},{}]", exp_bin_json, exp_lib_json).as_bytes()
-        );
+        };
+
+        let exp_json = to_json_string(&vec![exp_bin, exp_lib]).unwrap();
+        assert_eq!(&writer[..], format!("{}\n", exp_json).as_bytes());
     }
 }
diff --git a/tests/writemode/target/output.json b/tests/writemode/target/output.json
index b5f327b0a1c..acb33dea7ef 100644
--- a/tests/writemode/target/output.json
+++ b/tests/writemode/target/output.json
@@ -1 +1 @@
-[{"name":"tests/writemode/source/json.rs","mismatches":[{"original_begin_line":5,"original_end_line":7,"expected_begin_line":5,"expected_end_line":5,"original":"fn foo_expr() {\n    1\n}","expected":"fn foo_expr() { 1 }"},{"original_begin_line":9,"original_end_line":11,"expected_begin_line":7,"expected_end_line":7,"original":"fn foo_stmt() {\n    foo();\n}","expected":"fn foo_stmt() { foo(); }"},{"original_begin_line":13,"original_end_line":15,"expected_begin_line":9,"expected_end_line":9,"original":"fn foo_decl_local()  {\n    let z = 5;\n   }","expected":"fn foo_decl_local() { let z = 5; }"},{"original_begin_line":17,"original_end_line":19,"expected_begin_line":11,"expected_end_line":11,"original":"fn    foo_decl_item(x: &mut i32) {\n    x = 3;\n}","expected":"fn foo_decl_item(x: &mut i32) { x = 3; }"},{"original_begin_line":21,"original_end_line":21,"expected_begin_line":13,"expected_end_line":13,"original":"   fn empty()     {","expected":"fn empty() {}"},{"original_begin_line":23,"original_end_line":23,"expected_begin_line":15,"expected_end_line":15,"original":"}","expected":"fn foo_return() -> String { \"yay\" }"},{"original_begin_line":25,"original_end_line":29,"expected_begin_line":17,"expected_end_line":20,"original":"fn foo_return() -> String {\n    \"yay\"\n}\n\nfn foo_where() -> T where T: Sync {","expected":"fn foo_where() -> T\nwhere\n    T: Sync,\n{"},{"original_begin_line":64,"original_end_line":66,"expected_begin_line":55,"expected_end_line":55,"original":"fn lots_of_space                      ()                                                           {\n                           1                 \n}","expected":"fn lots_of_space() { 1 }"},{"original_begin_line":71,"original_end_line":72,"expected_begin_line":60,"expected_end_line":60,"original":"    fn dummy(&self) {\n    }","expected":"    fn dummy(&self) {}"},{"original_begin_line":75,"original_end_line":75,"expected_begin_line":63,"expected_end_line":64,"original":"trait CoolerTypes { fn dummy(&self) { ","expected":"trait CoolerTypes {\n    fn dummy(&self) {}"},{"original_begin_line":77,"original_end_line":77,"expected_begin_line":66,"expected_end_line":66,"original":"}","expected":""},{"original_begin_line":79,"original_end_line":79,"expected_begin_line":67,"expected_end_line":70,"original":"fn Foo<T>() where T: Bar {","expected":"fn Foo<T>()\nwhere\n    T: Bar,\n{"}]}]
\ No newline at end of file
+[{"name":"tests/writemode/source/json.rs","mismatches":[{"original_begin_line":5,"original_end_line":7,"expected_begin_line":5,"expected_end_line":5,"original":"fn foo_expr() {\n    1\n}","expected":"fn foo_expr() { 1 }"},{"original_begin_line":9,"original_end_line":11,"expected_begin_line":7,"expected_end_line":7,"original":"fn foo_stmt() {\n    foo();\n}","expected":"fn foo_stmt() { foo(); }"},{"original_begin_line":13,"original_end_line":15,"expected_begin_line":9,"expected_end_line":9,"original":"fn foo_decl_local()  {\n    let z = 5;\n   }","expected":"fn foo_decl_local() { let z = 5; }"},{"original_begin_line":17,"original_end_line":19,"expected_begin_line":11,"expected_end_line":11,"original":"fn    foo_decl_item(x: &mut i32) {\n    x = 3;\n}","expected":"fn foo_decl_item(x: &mut i32) { x = 3; }"},{"original_begin_line":21,"original_end_line":21,"expected_begin_line":13,"expected_end_line":13,"original":"   fn empty()     {","expected":"fn empty() {}"},{"original_begin_line":23,"original_end_line":23,"expected_begin_line":15,"expected_end_line":15,"original":"}","expected":"fn foo_return() -> String { \"yay\" }"},{"original_begin_line":25,"original_end_line":29,"expected_begin_line":17,"expected_end_line":20,"original":"fn foo_return() -> String {\n    \"yay\"\n}\n\nfn foo_where() -> T where T: Sync {","expected":"fn foo_where() -> T\nwhere\n    T: Sync,\n{"},{"original_begin_line":64,"original_end_line":66,"expected_begin_line":55,"expected_end_line":55,"original":"fn lots_of_space                      ()                                                           {\n                           1                 \n}","expected":"fn lots_of_space() { 1 }"},{"original_begin_line":71,"original_end_line":72,"expected_begin_line":60,"expected_end_line":60,"original":"    fn dummy(&self) {\n    }","expected":"    fn dummy(&self) {}"},{"original_begin_line":75,"original_end_line":75,"expected_begin_line":63,"expected_end_line":64,"original":"trait CoolerTypes { fn dummy(&self) { ","expected":"trait CoolerTypes {\n    fn dummy(&self) {}"},{"original_begin_line":77,"original_end_line":77,"expected_begin_line":66,"expected_end_line":66,"original":"}","expected":""},{"original_begin_line":79,"original_end_line":79,"expected_begin_line":67,"expected_end_line":70,"original":"fn Foo<T>() where T: Bar {","expected":"fn Foo<T>()\nwhere\n    T: Bar,\n{"}]}]
diff --git a/tests/writemode/target/stdin.json b/tests/writemode/target/stdin.json
index 20e38f57f4a..ae6796863e5 100644
--- a/tests/writemode/target/stdin.json
+++ b/tests/writemode/target/stdin.json
@@ -1 +1 @@
-[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}","expected":"fn some() {}\nfn main() {}"}]}]
\ No newline at end of file
+[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}","expected":"fn some() {}\nfn main() {}"}]}]

From 894a3c0e7745ece39fcee89d38389a789cfe520a Mon Sep 17 00:00:00 2001
From: Tim <tdhutt@gmail.com>
Date: Tue, 23 Jun 2020 01:20:29 +0100
Subject: [PATCH 129/195] Fix newlines in JSON output (#4262)

* Fix newlines in JSON output

This changes the JSON output to be more consistent about where newlines are included. Previously it only included them between lines in a multiline diff. That meant single line changes were treated a bit weirdly. This changes it to append a newline to every line.

When feeding the results into `arc lint` this behaves correctly. I have only done limited testing though, in particular there's a possibility it might not work with files with `\r\n` endings (though that would have been the case before too).

Fixes #4259

* Update tests
# Conflicts:
#	tests/writemode/target/output.json
---
 src/emitter/json.rs                | 38 ++++++++++++++++--------------
 tests/writemode/target/output.json |  2 +-
 tests/writemode/target/stdin.json  |  2 +-
 3 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/src/emitter/json.rs b/src/emitter/json.rs
index 7c0f862cbc6..c7f68d4675a 100644
--- a/src/emitter/json.rs
+++ b/src/emitter/json.rs
@@ -65,20 +65,22 @@ impl JsonEmitter {
             let mut expected_end_line = expected_begin_line;
             let mut original_line_counter = 0;
             let mut expected_line_counter = 0;
-            let mut original_lines = vec![];
-            let mut expected_lines = vec![];
+            let mut original = String::new();
+            let mut expected = String::new();
 
             for line in mismatch.lines {
                 match line {
                     DiffLine::Expected(msg) => {
                         expected_end_line = expected_begin_line + expected_line_counter;
                         expected_line_counter += 1;
-                        expected_lines.push(msg)
+                        expected.push_str(&msg);
+                        expected.push('\n');
                     }
                     DiffLine::Resulting(msg) => {
                         original_end_line = original_begin_line + original_line_counter;
                         original_line_counter += 1;
-                        original_lines.push(msg)
+                        original.push_str(&msg);
+                        original.push('\n');
                     }
                     DiffLine::Context(_) => continue,
                 }
@@ -89,8 +91,8 @@ impl JsonEmitter {
                 original_end_line,
                 expected_begin_line,
                 expected_end_line,
-                original: original_lines.join("\n"),
-                expected: expected_lines.join("\n"),
+                original,
+                expected,
             });
         }
         self.mismatched_files.push(MismatchedFile {
@@ -120,8 +122,8 @@ mod tests {
                 original_end_line: 79,
                 expected_begin_line: 79,
                 expected_end_line: 82,
-                original: String::from("fn Foo<T>() where T: Bar {"),
-                expected: String::from("fn Foo<T>()\nwhere\n    T: Bar,\n{"),
+                original: String::from("fn Foo<T>() where T: Bar {\n"),
+                expected: String::from("fn Foo<T>()\nwhere\n    T: Bar,\n{\n"),
             }],
         };
         let mismatch = Mismatch {
@@ -158,10 +160,10 @@ mod tests {
                 expected_begin_line: 5,
                 expected_end_line: 5,
                 original: String::from(
-                    "fn foo(_x: &u64) -> Option<&(dyn::std::error::Error + 'static)> {",
+                    "fn foo(_x: &u64) -> Option<&(dyn::std::error::Error + 'static)> {\n",
                 ),
                 expected: String::from(
-                    "fn foo(_x: &u64) -> Option<&(dyn ::std::error::Error + 'static)> {",
+                    "fn foo(_x: &u64) -> Option<&(dyn ::std::error::Error + 'static)> {\n",
                 ),
             }],
         };
@@ -260,8 +262,8 @@ mod tests {
                     original_end_line: 2,
                     expected_begin_line: 2,
                     expected_end_line: 2,
-                    original: String::from("println!(\"Hello, world!\");"),
-                    expected: String::from("    println!(\"Hello, world!\");"),
+                    original: String::from("println!(\"Hello, world!\");\n"),
+                    expected: String::from("    println!(\"Hello, world!\");\n"),
                 },
                 MismatchedBlock {
                     original_begin_line: 7,
@@ -269,10 +271,10 @@ mod tests {
                     expected_begin_line: 7,
                     expected_end_line: 10,
                     original: String::from(
-                        "#[test]\nfn it_works() {\n    assert_eq!(2 + 2, 4);\n}",
+                        "#[test]\nfn it_works() {\n    assert_eq!(2 + 2, 4);\n}\n",
                     ),
                     expected: String::from(
-                        "    #[test]\n    fn it_works() {\n        assert_eq!(2 + 2, 4);\n    }",
+                        "    #[test]\n    fn it_works() {\n        assert_eq!(2 + 2, 4);\n    }\n",
                     ),
                 },
             ],
@@ -321,8 +323,8 @@ mod tests {
                 original_end_line: 2,
                 expected_begin_line: 2,
                 expected_end_line: 2,
-                original: String::from("println!(\"Hello, world!\");"),
-                expected: String::from("    println!(\"Hello, world!\");"),
+                original: String::from("println!(\"Hello, world!\");\n"),
+                expected: String::from("    println!(\"Hello, world!\");\n"),
             }],
         };
 
@@ -333,8 +335,8 @@ mod tests {
                 original_end_line: 2,
                 expected_begin_line: 2,
                 expected_end_line: 2,
-                original: String::from("println!(\"Greetings!\");"),
-                expected: String::from("    println!(\"Greetings!\");"),
+                original: String::from("println!(\"Greetings!\");\n"),
+                expected: String::from("    println!(\"Greetings!\");\n"),
             }],
         };
 
diff --git a/tests/writemode/target/output.json b/tests/writemode/target/output.json
index acb33dea7ef..d8b5467ee91 100644
--- a/tests/writemode/target/output.json
+++ b/tests/writemode/target/output.json
@@ -1 +1 @@
-[{"name":"tests/writemode/source/json.rs","mismatches":[{"original_begin_line":5,"original_end_line":7,"expected_begin_line":5,"expected_end_line":5,"original":"fn foo_expr() {\n    1\n}","expected":"fn foo_expr() { 1 }"},{"original_begin_line":9,"original_end_line":11,"expected_begin_line":7,"expected_end_line":7,"original":"fn foo_stmt() {\n    foo();\n}","expected":"fn foo_stmt() { foo(); }"},{"original_begin_line":13,"original_end_line":15,"expected_begin_line":9,"expected_end_line":9,"original":"fn foo_decl_local()  {\n    let z = 5;\n   }","expected":"fn foo_decl_local() { let z = 5; }"},{"original_begin_line":17,"original_end_line":19,"expected_begin_line":11,"expected_end_line":11,"original":"fn    foo_decl_item(x: &mut i32) {\n    x = 3;\n}","expected":"fn foo_decl_item(x: &mut i32) { x = 3; }"},{"original_begin_line":21,"original_end_line":21,"expected_begin_line":13,"expected_end_line":13,"original":"   fn empty()     {","expected":"fn empty() {}"},{"original_begin_line":23,"original_end_line":23,"expected_begin_line":15,"expected_end_line":15,"original":"}","expected":"fn foo_return() -> String { \"yay\" }"},{"original_begin_line":25,"original_end_line":29,"expected_begin_line":17,"expected_end_line":20,"original":"fn foo_return() -> String {\n    \"yay\"\n}\n\nfn foo_where() -> T where T: Sync {","expected":"fn foo_where() -> T\nwhere\n    T: Sync,\n{"},{"original_begin_line":64,"original_end_line":66,"expected_begin_line":55,"expected_end_line":55,"original":"fn lots_of_space                      ()                                                           {\n                           1                 \n}","expected":"fn lots_of_space() { 1 }"},{"original_begin_line":71,"original_end_line":72,"expected_begin_line":60,"expected_end_line":60,"original":"    fn dummy(&self) {\n    }","expected":"    fn dummy(&self) {}"},{"original_begin_line":75,"original_end_line":75,"expected_begin_line":63,"expected_end_line":64,"original":"trait CoolerTypes { fn dummy(&self) { ","expected":"trait CoolerTypes {\n    fn dummy(&self) {}"},{"original_begin_line":77,"original_end_line":77,"expected_begin_line":66,"expected_end_line":66,"original":"}","expected":""},{"original_begin_line":79,"original_end_line":79,"expected_begin_line":67,"expected_end_line":70,"original":"fn Foo<T>() where T: Bar {","expected":"fn Foo<T>()\nwhere\n    T: Bar,\n{"}]}]
+[{"name":"tests/writemode/source/json.rs","mismatches":[{"original_begin_line":5,"original_end_line":7,"expected_begin_line":5,"expected_end_line":5,"original":"fn foo_expr() {\n    1\n}\n","expected":"fn foo_expr() { 1 }\n"},{"original_begin_line":9,"original_end_line":11,"expected_begin_line":7,"expected_end_line":7,"original":"fn foo_stmt() {\n    foo();\n}\n","expected":"fn foo_stmt() { foo(); }\n"},{"original_begin_line":13,"original_end_line":15,"expected_begin_line":9,"expected_end_line":9,"original":"fn foo_decl_local()  {\n    let z = 5;\n   }\n","expected":"fn foo_decl_local() { let z = 5; }\n"},{"original_begin_line":17,"original_end_line":19,"expected_begin_line":11,"expected_end_line":11,"original":"fn    foo_decl_item(x: &mut i32) {\n    x = 3;\n}\n","expected":"fn foo_decl_item(x: &mut i32) { x = 3; }\n"},{"original_begin_line":21,"original_end_line":21,"expected_begin_line":13,"expected_end_line":13,"original":"   fn empty()     {\n","expected":"fn empty() {}\n"},{"original_begin_line":23,"original_end_line":23,"expected_begin_line":15,"expected_end_line":15,"original":"}\n","expected":"fn foo_return() -> String { \"yay\" }\n"},{"original_begin_line":25,"original_end_line":29,"expected_begin_line":17,"expected_end_line":20,"original":"fn foo_return() -> String {\n    \"yay\"\n}\n\nfn foo_where() -> T where T: Sync {\n","expected":"fn foo_where() -> T\nwhere\n    T: Sync,\n{\n"},{"original_begin_line":64,"original_end_line":66,"expected_begin_line":55,"expected_end_line":55,"original":"fn lots_of_space                      ()                                                           {\n                           1                 \n}\n","expected":"fn lots_of_space() { 1 }\n"},{"original_begin_line":71,"original_end_line":72,"expected_begin_line":60,"expected_end_line":60,"original":"    fn dummy(&self) {\n    }\n","expected":"    fn dummy(&self) {}\n"},{"original_begin_line":75,"original_end_line":75,"expected_begin_line":63,"expected_end_line":64,"original":"trait CoolerTypes { fn dummy(&self) { \n","expected":"trait CoolerTypes {\n    fn dummy(&self) {}\n"},{"original_begin_line":77,"original_end_line":77,"expected_begin_line":66,"expected_end_line":66,"original":"}\n","expected":""},{"original_begin_line":79,"original_end_line":79,"expected_begin_line":67,"expected_end_line":70,"original":"fn Foo<T>() where T: Bar {\n","expected":"fn Foo<T>()\nwhere\n    T: Bar,\n{\n"}]}]
diff --git a/tests/writemode/target/stdin.json b/tests/writemode/target/stdin.json
index ae6796863e5..6f5d5bfb8ca 100644
--- a/tests/writemode/target/stdin.json
+++ b/tests/writemode/target/stdin.json
@@ -1 +1 @@
-[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}","expected":"fn some() {}\nfn main() {}"}]}]
+[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}\n","expected":"fn some() {}\nfn main() {}\n"}]}]

From 34d374ee5d23951d166ca3f51d477ddf6526a2fa Mon Sep 17 00:00:00 2001
From: Seiichi Uchida <seuchida@gmail.com>
Date: Fri, 3 Jul 2020 11:13:16 +0900
Subject: [PATCH 130/195] Use <stdin> when emitting stdin as filename (#4298)

# Conflicts:
#	src/config/file_lines.rs
#	src/rustfmt/main.rs
#	src/test/mod.rs
---
 src/config/file_lines.rs          | 2 +-
 src/test/mod.rs                   | 6 +++---
 tests/writemode/target/stdin.json | 2 +-
 tests/writemode/target/stdin.xml  | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs
index 7b498dc46b3..e4e51a3f3b4 100644
--- a/src/config/file_lines.rs
+++ b/src/config/file_lines.rs
@@ -39,7 +39,7 @@ impl fmt::Display for FileName {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()),
-            FileName::Stdin => write!(f, "stdin"),
+            FileName::Stdin => write!(f, "<stdin>"),
         }
     }
 }
diff --git a/src/test/mod.rs b/src/test/mod.rs
index db1cf88479c..2d5a8f22053 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -466,9 +466,9 @@ fn stdin_formatting_smoke_test() {
     }
 
     #[cfg(not(windows))]
-    assert_eq!(buf, "stdin:\n\nfn main() {}\n".as_bytes());
+    assert_eq!(buf, "<stdin>:\n\nfn main() {}\n".as_bytes());
     #[cfg(windows)]
-    assert_eq!(buf, "stdin:\n\nfn main() {}\r\n".as_bytes());
+    assert_eq!(buf, "<stdin>:\n\nfn main() {}\r\n".as_bytes());
 }
 
 #[test]
@@ -1013,5 +1013,5 @@ fn verify_check_l_works_with_stdin() {
         .wait_with_output()
         .expect("Failed to wait on rustfmt child");
     assert!(output.status.success());
-    assert_eq!(std::str::from_utf8(&output.stdout).unwrap(), "stdin\n");
+    assert_eq!(std::str::from_utf8(&output.stdout).unwrap(), "<stdin>\n");
 }
diff --git a/tests/writemode/target/stdin.json b/tests/writemode/target/stdin.json
index 6f5d5bfb8ca..dbf2c486322 100644
--- a/tests/writemode/target/stdin.json
+++ b/tests/writemode/target/stdin.json
@@ -1 +1 @@
-[{"name":"stdin","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}\n","expected":"fn some() {}\nfn main() {}\n"}]}]
+[{"name":"<stdin>","mismatches":[{"original_begin_line":1,"original_end_line":6,"expected_begin_line":1,"expected_end_line":2,"original":"\nfn\n some( )\n{\n}\nfn main () {}\n","expected":"fn some() {}\nfn main() {}\n"}]}]
diff --git a/tests/writemode/target/stdin.xml b/tests/writemode/target/stdin.xml
index e70708338f5..a7301bbc553 100644
--- a/tests/writemode/target/stdin.xml
+++ b/tests/writemode/target/stdin.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8"?>
-<checkstyle version="4.3"><file name="stdin"><error line="1" severity="warning" message="Should be `fn some() {}`" /><error line="2" severity="warning" message="Should be `fn main() {}`" /></file></checkstyle>
+<?xml version="1.0" encoding="utf-8"?>
+<checkstyle version="4.3"><file name="<stdin>"><error line="1" severity="warning" message="Should be `fn some() {}`" /><error line="2" severity="warning" message="Should be `fn main() {}`" /></file></checkstyle>

From 5056f4cfb311a084420f1828cd58af94d143f5e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Wed, 5 Jan 2022 21:19:36 +0100
Subject: [PATCH 131/195] some minor clippy fixes

---
 src/cargo-fmt/main.rs          | 3 +--
 src/format_report_formatter.rs | 1 +
 src/macros.rs                  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 759b21218c3..8cb7b4585ec 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -387,8 +387,7 @@ fn get_targets_root_only(
                         .unwrap_or_default()
                         == current_dir_manifest
             })
-            .map(|p| p.targets)
-            .flatten()
+            .flat_map(|p| p.targets)
             .collect(),
     };
 
diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs
index c820259256c..90406cdb95e 100644
--- a/src/format_report_formatter.rs
+++ b/src/format_report_formatter.rs
@@ -20,6 +20,7 @@ impl<'a> FormatReportFormatterBuilder<'a> {
     }
 
     /// Enables colors and formatting in the output.
+    #[must_use]
     pub fn enable_colors(self, enable_colors: bool) -> Self {
         Self {
             enable_colors,
diff --git a/src/macros.rs b/src/macros.rs
index f29552caf8d..fdbe3374615 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -152,7 +152,7 @@ pub(crate) fn rewrite_macro(
 ) -> Option<String> {
     let should_skip = context
         .skip_context
-        .skip_macro(&context.snippet(mac.path.span).to_owned());
+        .skip_macro(context.snippet(mac.path.span));
     if should_skip {
         None
     } else {

From 9e1973f1d9b94914c3e5539f3ed992c19389b4a7 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 23 Jan 2022 11:18:17 -0600
Subject: [PATCH 132/195] chore: bump toolchain, update test

---
 rust-toolchain  | 2 +-
 src/test/mod.rs | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/rust-toolchain b/rust-toolchain
index d4cdcec2018..d8bf02aec85 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-12-29"
+channel = "nightly-2022-01-23"
 components = ["rustc-dev"]
diff --git a/src/test/mod.rs b/src/test/mod.rs
index c399512ba7e..ab966d4a360 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -572,7 +572,10 @@ fn stdin_generated_files_issue_5172() {
         assert!(session.has_no_errors());
     }
     // N.B. this should be changed once `format_generated_files` is supported with stdin
-    assert_eq!(buf, "stdin:\n\n//@generated\nfn main() {}\n".as_bytes());
+    assert_eq!(
+        String::from_utf8(buf).unwrap(),
+        "<stdin>:\n\n//@generated\nfn main() {}\n",
+    );
 }
 
 #[test]

From b4a4bf0bf8a16913b9f16f2aee7030065ff00931 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szymon=20Giba=C5=82a?= <szymongib@gmail.com>
Date: Sat, 29 Jan 2022 05:55:47 +0100
Subject: [PATCH 133/195] Fix formatting of comments in empty structs (#5171)

* Fix formatting of comments in empty structs

* Add tests

* Add single line tests

* Fix block comments

* Revert changes of test source files
---
 src/items.rs                                  |  10 +-
 tests/source/issue_4854.rs                    | 113 +++++++++++++++++
 .../comments-in-lists/format-doc-comments.rs  |  10 +-
 .../comments-in-lists/wrap-comments-false.rs  |  10 +-
 .../wrap-comments-not-normalized.rs           |   8 +-
 .../comments-in-lists/wrap-comments-true.rs   |   8 +-
 tests/target/issue_4854.rs                    | 115 ++++++++++++++++++
 7 files changed, 251 insertions(+), 23 deletions(-)
 create mode 100644 tests/source/issue_4854.rs
 create mode 100644 tests/target/issue_4854.rs

diff --git a/src/items.rs b/src/items.rs
index babc56f86ed..4c7a33c86d2 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1374,17 +1374,21 @@ fn format_empty_struct_or_tuple(
         result.push_str(&offset.to_string_with_newline(context.config))
     }
     result.push_str(opener);
-    match rewrite_missing_comment(span, Shape::indented(offset, context.config), context) {
+
+    // indented shape for proper indenting of multi-line comments
+    let shape = Shape::indented(offset.block_indent(context.config), context.config);
+    match rewrite_missing_comment(span, shape, context) {
         Some(ref s) if s.is_empty() => (),
         Some(ref s) => {
-            if !is_single_line(s) || first_line_contains_single_line_comment(s) {
+            let is_multi_line = !is_single_line(s);
+            if is_multi_line || first_line_contains_single_line_comment(s) {
                 let nested_indent_str = offset
                     .block_indent(context.config)
                     .to_string_with_newline(context.config);
                 result.push_str(&nested_indent_str);
             }
             result.push_str(s);
-            if last_line_contains_single_line_comment(s) {
+            if is_multi_line || last_line_contains_single_line_comment(s) {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
         }
diff --git a/tests/source/issue_4854.rs b/tests/source/issue_4854.rs
new file mode 100644
index 00000000000..35d6e21affe
--- /dev/null
+++ b/tests/source/issue_4854.rs
@@ -0,0 +1,113 @@
+struct Struct {
+    // Multiline comment
+    // should be formatted
+    // properly.
+}
+
+struct Struct2 {
+    // This formatting
+// Should be changed
+}
+
+struct Struct3(
+    // This
+    // is
+    // correct
+);
+
+struct Struct4(
+    // This
+// is
+// not
+// correct
+);
+
+struct Struct5 {
+    /*
+    Comment block
+    with many lines.
+    */
+}
+
+struct Struct6(
+    /*
+    Comment block
+    with many lines.
+    */
+);
+
+struct Struct7 {
+    /*
+Invalid
+format
+*/
+}
+
+struct Struct8(
+    /*
+Invalid
+format
+*/
+);
+
+struct Struct9 { /* bar */ }
+
+struct Struct10 { /* bar
+baz
+*/ }
+
+mod module {
+    struct Struct {
+        // Multiline comment
+        // should be formatted
+        // properly.
+    }
+
+    struct Struct2 {
+        // This formatting
+// Should be changed
+    }
+
+    struct Struct3(
+        // This
+        // is
+        // correct
+    );
+
+    struct Struct4(
+        // This
+    // is
+    // not
+// correct
+    );
+
+    struct Struct5 {
+        /*
+        Comment block
+        with many lines.
+         */
+    }
+
+    struct Struct6(
+        /*
+        Comment block
+        with many lines.
+        */
+    );
+
+    struct Struct7 {
+        /*
+Invalid
+format
+*/
+    }
+
+    struct Struct8(
+        /*
+Invalid
+format
+*/
+    );
+
+    struct Struct9 { /* bar */ }
+}
diff --git a/tests/target/comments-in-lists/format-doc-comments.rs b/tests/target/comments-in-lists/format-doc-comments.rs
index be31bf0a331..be4b7a8c42e 100644
--- a/tests/target/comments-in-lists/format-doc-comments.rs
+++ b/tests/target/comments-in-lists/format-doc-comments.rs
@@ -25,9 +25,8 @@ pub enum E {
 }
 
 pub enum E2 {
-    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub struct S {
@@ -42,9 +41,8 @@ pub struct S {
 }
 
 pub struct S2 {
-    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 fn foo(
diff --git a/tests/target/comments-in-lists/wrap-comments-false.rs b/tests/target/comments-in-lists/wrap-comments-false.rs
index 80aea59d1b5..db4da622372 100644
--- a/tests/target/comments-in-lists/wrap-comments-false.rs
+++ b/tests/target/comments-in-lists/wrap-comments-false.rs
@@ -13,9 +13,8 @@ pub enum E {
 }
 
 pub enum E2 {
-    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub struct S {
@@ -30,9 +29,8 @@ pub struct S {
 }
 
 pub struct S2 {
-    // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 fn foo(
diff --git a/tests/target/comments-in-lists/wrap-comments-not-normalized.rs b/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
index 52315f470e4..9b9147eb124 100644
--- a/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
+++ b/tests/target/comments-in-lists/wrap-comments-not-normalized.rs
@@ -14,8 +14,8 @@ pub enum E {
 
 pub enum E2 {
     // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub enum E3 {
@@ -42,8 +42,8 @@ pub struct S {
 
 pub struct S2 {
     // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub struct S3 {
diff --git a/tests/target/comments-in-lists/wrap-comments-true.rs b/tests/target/comments-in-lists/wrap-comments-true.rs
index e0bfcf0b500..c1531d22a4a 100644
--- a/tests/target/comments-in-lists/wrap-comments-true.rs
+++ b/tests/target/comments-in-lists/wrap-comments-true.rs
@@ -15,8 +15,8 @@ pub enum E {
 
 pub enum E2 {
     // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub enum E3 {
@@ -43,8 +43,8 @@ pub struct S {
 
 pub struct S2 {
     // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed
-// Expand as needed, numbers should be ascending according to the stage
-// through the inclusion pipeline, or according to the descriptions
+    // Expand as needed, numbers should be ascending according to the stage
+    // through the inclusion pipeline, or according to the descriptions
 }
 
 pub struct S3 {
diff --git a/tests/target/issue_4854.rs b/tests/target/issue_4854.rs
new file mode 100644
index 00000000000..a81c5a5171f
--- /dev/null
+++ b/tests/target/issue_4854.rs
@@ -0,0 +1,115 @@
+struct Struct {
+    // Multiline comment
+    // should be formatted
+    // properly.
+}
+
+struct Struct2 {
+    // This formatting
+    // Should be changed
+}
+
+struct Struct3(
+    // This
+    // is
+    // correct
+);
+
+struct Struct4(
+    // This
+    // is
+    // not
+    // correct
+);
+
+struct Struct5 {
+    /*
+    Comment block
+    with many lines.
+    */
+}
+
+struct Struct6(
+    /*
+    Comment block
+    with many lines.
+    */
+);
+
+struct Struct7 {
+    /*
+    Invalid
+    format
+    */
+}
+
+struct Struct8(
+    /*
+    Invalid
+    format
+    */
+);
+
+struct Struct9 {/* bar */}
+
+struct Struct10 {
+    /* bar
+    baz
+    */
+}
+
+mod module {
+    struct Struct {
+        // Multiline comment
+        // should be formatted
+        // properly.
+    }
+
+    struct Struct2 {
+        // This formatting
+        // Should be changed
+    }
+
+    struct Struct3(
+        // This
+        // is
+        // correct
+    );
+
+    struct Struct4(
+        // This
+        // is
+        // not
+        // correct
+    );
+
+    struct Struct5 {
+        /*
+        Comment block
+        with many lines.
+         */
+    }
+
+    struct Struct6(
+        /*
+        Comment block
+        with many lines.
+        */
+    );
+
+    struct Struct7 {
+        /*
+        Invalid
+        format
+        */
+    }
+
+    struct Struct8(
+        /*
+        Invalid
+        format
+        */
+    );
+
+    struct Struct9 {/* bar */}
+}

From 8b0b213cddb23a9bbe421b717d1a0e5fb3982712 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Thu, 9 Dec 2021 23:17:43 -0500
Subject: [PATCH 134/195] Prevent adding trailing whitespace when rewriting
 ast::Param

Fixes 5125

Previously, a newline was always added, even if the parameter name was
not preceded by any param attrs.

Now a newline is only added if there were param attrs.
---
 src/items.rs                                  |  8 ++++++-
 .../attributes_in_formal_fuction_parameter.rs |  6 +++++
 .../long_parameter_in_different_positions.rs  | 24 +++++++++++++++++++
 tests/target/issue-5125/minimum_example.rs    |  6 +++++
 .../with_leading_and_inline_comments.rs       |  7 ++++++
 5 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs
 create mode 100644 tests/target/issue-5125/long_parameter_in_different_positions.rs
 create mode 100644 tests/target/issue-5125/minimum_example.rs
 create mode 100644 tests/target/issue-5125/with_leading_and_inline_comments.rs

diff --git a/src/items.rs b/src/items.rs
index 4c7a33c86d2..007609aba24 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -2018,9 +2018,15 @@ impl Rewrite for ast::Param {
                 {
                     result.push_str(&ty_str);
                 } else {
+                    let prev_str = if param_attrs_result.is_empty() {
+                        param_attrs_result
+                    } else {
+                        param_attrs_result + &shape.to_string_with_newline(context.config)
+                    };
+
                     result = combine_strs_with_missing_comments(
                         context,
-                        &(param_attrs_result + &shape.to_string_with_newline(context.config)),
+                        &prev_str,
                         param_name,
                         span,
                         shape,
diff --git a/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs b/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs
new file mode 100644
index 00000000000..5d167932828
--- /dev/null
+++ b/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs
@@ -0,0 +1,6 @@
+fn foo(
+    #[unused] a: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType,
+) {
+}
diff --git a/tests/target/issue-5125/long_parameter_in_different_positions.rs b/tests/target/issue-5125/long_parameter_in_different_positions.rs
new file mode 100644
index 00000000000..cab20381ce8
--- /dev/null
+++ b/tests/target/issue-5125/long_parameter_in_different_positions.rs
@@ -0,0 +1,24 @@
+fn middle(
+    a: usize,
+    b: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType,
+    c: bool,
+) {
+}
+
+fn last(
+    a: usize,
+    b: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType,
+) {
+}
+
+fn first(
+    a: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType,
+    b: usize,
+) {
+}
diff --git a/tests/target/issue-5125/minimum_example.rs b/tests/target/issue-5125/minimum_example.rs
new file mode 100644
index 00000000000..8003e66968c
--- /dev/null
+++ b/tests/target/issue-5125/minimum_example.rs
@@ -0,0 +1,6 @@
+fn foo(
+    a: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType,
+) {
+}
diff --git a/tests/target/issue-5125/with_leading_and_inline_comments.rs b/tests/target/issue-5125/with_leading_and_inline_comments.rs
new file mode 100644
index 00000000000..2340b2f3472
--- /dev/null
+++ b/tests/target/issue-5125/with_leading_and_inline_comments.rs
@@ -0,0 +1,7 @@
+fn foo(
+    // Pre Comment
+    a: <u16 as intercom::type_system::ExternType<
+        intercom::type_system::AutomationTypeSystem,
+    >>::ForeignType, // Inline comment
+) {
+}

From 368a9b7cef25c22c3e836453e73d8584b251b578 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Wed, 2 Feb 2022 02:06:14 +0100
Subject: [PATCH 135/195] Handle non-ascii character at boundary (#5089)

* Handle non-ascii character at boundary

* Replace substraction underflow check with early termination
---
 src/string.rs              |  5 ++++-
 tests/source/issue-5023.rs | 22 ++++++++++++++++++++++
 tests/target/issue-5023.rs | 23 +++++++++++++++++++++++
 3 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue-5023.rs
 create mode 100644 tests/target/issue-5023.rs

diff --git a/src/string.rs b/src/string.rs
index 64ae15672df..b65aa5b33b2 100644
--- a/src/string.rs
+++ b/src/string.rs
@@ -278,6 +278,9 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
         }
         cur_index
     };
+    if max_width_index_in_input == 0 {
+        return SnippetState::EndOfInput(input.concat());
+    }
 
     // Find the position in input for breaking the string
     if line_end.is_empty()
@@ -301,7 +304,7 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
         return if trim_end {
             SnippetState::LineEnd(input[..=url_index_end].concat(), index_plus_ws + 1)
         } else {
-            return SnippetState::LineEnd(input[..=index_plus_ws].concat(), index_plus_ws + 1);
+            SnippetState::LineEnd(input[..=index_plus_ws].concat(), index_plus_ws + 1)
         };
     }
 
diff --git a/tests/source/issue-5023.rs b/tests/source/issue-5023.rs
new file mode 100644
index 00000000000..ae1c723eff7
--- /dev/null
+++ b/tests/source/issue-5023.rs
@@ -0,0 +1,22 @@
+// rustfmt-wrap_comments: true
+
+/// A comment to test special unicode characters on boundaries
+/// 是,是,是,是,是,是,是,是,是,是,是,是  it should break right here this goes to the next line
+fn main() {
+    if xxx {
+        let xxx = xxx
+            .into_iter()
+            .filter(|(xxx, xxx)| {
+                if let Some(x) = Some(1) {
+                    // xxxxxxxxxxxxxxxxxx, xxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxx xxx xxxxxxx, xxxxx xxx
+                    // xxxxxxxxxx. xxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxx xxx xxxxxxx
+                    // 是sdfadsdfxxxxxxxxx,sdfaxxxxxx_xxxxx_masdfaonxxx,
+                    if false {
+                        return true;
+                    }
+                }
+                false
+            })
+            .collect();
+    }
+}
diff --git a/tests/target/issue-5023.rs b/tests/target/issue-5023.rs
new file mode 100644
index 00000000000..4e84c7d9842
--- /dev/null
+++ b/tests/target/issue-5023.rs
@@ -0,0 +1,23 @@
+// rustfmt-wrap_comments: true
+
+/// A comment to test special unicode characters on boundaries
+/// 是,是,是,是,是,是,是,是,是,是,是,是  it should break right here
+/// this goes to the next line
+fn main() {
+    if xxx {
+        let xxx = xxx
+            .into_iter()
+            .filter(|(xxx, xxx)| {
+                if let Some(x) = Some(1) {
+                    // xxxxxxxxxxxxxxxxxx, xxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxx xxx xxxxxxx, xxxxx xxx
+                    // xxxxxxxxxx. xxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxx xxx xxxxxxx
+                    // 是sdfadsdfxxxxxxxxx,sdfaxxxxxx_xxxxx_masdfaonxxx,
+                    if false {
+                        return true;
+                    }
+                }
+                false
+            })
+            .collect();
+    }
+}

From 606894eb0b1dcc3a4616aff4b54dbd19a2a46ba5 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sun, 19 Dec 2021 16:47:13 -0500
Subject: [PATCH 136/195] Retain trailing separator when extracting the last
 inline post comment

Fixes 5042

Previously, trailing commas were removed from the last inline comment.
This lead to rustfmt refusing to format code snippets because
the original comment did not match the rewritten comment.

Now, when rustfmt extracts the last inline comment it leaves trailing
separators alone. Rustfmt does not need to remove these separators
because they are commented out.
---
 src/lists.rs                                  | 27 ++++++++++++++-----
 .../multi-line_comment_with_trailing_comma.rs | 24 +++++++++++++++++
 ...lti-line_comment_without_trailing_comma.rs | 24 +++++++++++++++++
 ...single-line_comment_with_trailing_comma.rs |  9 +++++++
 ...gle-line_comment_without_trailing_comma.rs | 10 +++++++
 .../multi-line_comment_with_trailing_comma.rs | 24 +++++++++++++++++
 ...lti-line_comment_without_trailing_comma.rs | 24 +++++++++++++++++
 ...single-line_comment_with_trailing_comma.rs |  7 +++++
 ...gle-line_comment_without_trailing_comma.rs |  7 +++++
 9 files changed, 149 insertions(+), 7 deletions(-)
 create mode 100644 tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs
 create mode 100644 tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs
 create mode 100644 tests/source/issue-5042/single-line_comment_with_trailing_comma.rs
 create mode 100644 tests/source/issue-5042/single-line_comment_without_trailing_comma.rs
 create mode 100644 tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs
 create mode 100644 tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs
 create mode 100644 tests/target/issue-5042/single-line_comment_with_trailing_comma.rs
 create mode 100644 tests/target/issue-5042/single-line_comment_without_trailing_comma.rs

diff --git a/src/lists.rs b/src/lists.rs
index 7aa0315f18c..97eea19f932 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -611,15 +611,30 @@ pub(crate) fn extract_post_comment(
     post_snippet: &str,
     comment_end: usize,
     separator: &str,
+    is_last: bool,
 ) -> Option<String> {
     let white_space: &[_] = &[' ', '\t'];
 
     // Cleanup post-comment: strip separators and whitespace.
     let post_snippet = post_snippet[..comment_end].trim();
+
+    let last_inline_comment_ends_with_separator = if is_last {
+        if let Some(line) = post_snippet.lines().last() {
+            line.ends_with(separator) && line.trim().starts_with("//")
+        } else {
+            false
+        }
+    } else {
+        false
+    };
+
     let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') {
         post_snippet[1..].trim_matches(white_space)
     } else if let Some(stripped) = post_snippet.strip_prefix(separator) {
         stripped.trim_matches(white_space)
+    } else if last_inline_comment_ends_with_separator {
+        // since we're on the last item it's fine to keep any trailing separators in comments
+        post_snippet.trim_matches(white_space)
     }
     // not comment or over two lines
     else if post_snippet.ends_with(',')
@@ -748,14 +763,12 @@ where
                 .snippet_provider
                 .span_to_snippet(mk_sp((self.get_hi)(&item), next_start))
                 .unwrap_or("");
-            let comment_end = get_comment_end(
-                post_snippet,
-                self.separator,
-                self.terminator,
-                self.inner.peek().is_none(),
-            );
+            let is_last = self.inner.peek().is_none();
+            let comment_end =
+                get_comment_end(post_snippet, self.separator, self.terminator, is_last);
             let new_lines = has_extra_newline(post_snippet, comment_end);
-            let post_comment = extract_post_comment(post_snippet, comment_end, self.separator);
+            let post_comment =
+                extract_post_comment(post_snippet, comment_end, self.separator, is_last);
 
             self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
 
diff --git a/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs b/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs
new file mode 100644
index 00000000000..5d171f32a1a
--- /dev/null
+++ b/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs
@@ -0,0 +1,24 @@
+fn main() {
+    // 5042 deals with trailing commas, not the indentation issue of these comments
+    // When a future PR fixes the inentation issues these test can be updated
+    let _ = std::ops::Add::add(10, 20
+        // ...
+        // ...,
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        /* ... */
+        // ...,
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        // ...,
+        // ...,
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        // ...,
+        /* ...
+        */,
+        );
+}
diff --git a/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs b/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs
new file mode 100644
index 00000000000..b8a824b34b7
--- /dev/null
+++ b/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs
@@ -0,0 +1,24 @@
+fn main() {
+    // 5042 deals with trailing commas, not the indentation issue of these comments
+    // When a future PR fixes the inentation issues these test can be updated
+    let _ = std::ops::Add::add(10, 20
+        // ...
+        // ...
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        /* ... */
+        // ...
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        // ...
+        // ...
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        // ...
+        /* ...
+        */
+        );
+}
diff --git a/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs b/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs
new file mode 100644
index 00000000000..bd765b7b41f
--- /dev/null
+++ b/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let _ = std::ops::Add::add(10, 20
+        // ...,
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        /* ... */,
+        );
+}
diff --git a/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs b/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs
new file mode 100644
index 00000000000..2ed8de875ad
--- /dev/null
+++ b/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let _ = std::ops::Add::add(10, 20
+        // ...
+        );
+
+    let _ = std::ops::Add::add(10, 20
+        /* ... */
+        );
+}
+
diff --git a/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs b/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs
new file mode 100644
index 00000000000..1ae1212b488
--- /dev/null
+++ b/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs
@@ -0,0 +1,24 @@
+fn main() {
+    // 5042 deals with trailing commas, not the indentation issue of these comments
+    // When a future PR fixes the inentation issues these test can be updated
+    let _ = std::ops::Add::add(
+        10, 20, // ...
+           // ...,
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, /* ... */
+           // ...,
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, // ...,
+           // ...,
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, // ...,
+           /* ...
+            */
+    );
+}
diff --git a/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs b/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs
new file mode 100644
index 00000000000..30d174664c9
--- /dev/null
+++ b/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs
@@ -0,0 +1,24 @@
+fn main() {
+    // 5042 deals with trailing commas, not the indentation issue of these comments
+    // When a future PR fixes the inentation issues these test can be updated
+    let _ = std::ops::Add::add(
+        10, 20, // ...
+           // ...
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, /* ... */
+           // ...
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, // ...
+           // ...
+    );
+
+    let _ = std::ops::Add::add(
+        10, 20, // ...
+           /* ...
+            */
+    );
+}
diff --git a/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs b/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs
new file mode 100644
index 00000000000..87b651dd285
--- /dev/null
+++ b/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let _ = std::ops::Add::add(
+        10, 20, // ...,
+    );
+
+    let _ = std::ops::Add::add(10, 20 /* ... */);
+}
diff --git a/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs b/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs
new file mode 100644
index 00000000000..116df86a4b5
--- /dev/null
+++ b/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let _ = std::ops::Add::add(
+        10, 20, // ...
+    );
+
+    let _ = std::ops::Add::add(10, 20 /* ... */);
+}

From b2c7a52ea865f877bc0b57075fe1a88f83120546 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Mon, 31 Jan 2022 23:45:30 +0100
Subject: [PATCH 137/195] Fix import_granularity option when the use tree has
 an alias

---
 src/imports.rs       |  6 ++++--
 tests/source/5131.rs | 33 +++++++++++++++++++++++++++++++++
 tests/target/5131.rs | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 tests/source/5131.rs
 create mode 100644 tests/target/5131.rs

diff --git a/src/imports.rs b/src/imports.rs
index 40e0d06f99d..c60bec6d4a2 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -238,7 +238,8 @@ impl fmt::Display for UseSegment {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             UseSegment::Glob => write!(f, "*"),
-            UseSegment::Ident(ref s, _) => write!(f, "{}", s),
+            UseSegment::Ident(ref s, Some(ref alias)) => write!(f, "{} as {}", s, alias),
+            UseSegment::Ident(ref s, None) => write!(f, "{}", s),
             UseSegment::Slf(..) => write!(f, "self"),
             UseSegment::Super(..) => write!(f, "super"),
             UseSegment::Crate(..) => write!(f, "crate"),
@@ -622,7 +623,8 @@ impl UseTree {
     fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) {
         let mut prefix = 0;
         for (a, b) in self.path.iter().zip(other.path.iter()) {
-            if a.equal_except_alias(b) {
+            // only discard the alias at the root of the tree
+            if (prefix == 0 && a.equal_except_alias(b)) || a == b {
                 prefix += 1;
             } else {
                 break;
diff --git a/tests/source/5131.rs b/tests/source/5131.rs
new file mode 100644
index 00000000000..3e9139177c5
--- /dev/null
+++ b/tests/source/5131.rs
@@ -0,0 +1,33 @@
+// rustfmt-imports_granularity: Module
+
+#![allow(dead_code)]
+
+mod a {
+    pub mod b {
+        pub struct Data {
+            pub a: i32,
+        }
+    }
+
+    use crate::a::b::Data;
+    use crate::a::b::Data as Data2;
+
+    pub fn data(a: i32) -> Data {
+        Data { a }
+    }
+
+    pub fn data2(a: i32) -> Data2 {
+        Data2 { a }
+    }
+
+    #[cfg(test)]
+    mod tests {
+        use super::*;
+
+        #[test]
+        pub fn test() {
+            data(1);
+            data2(1);
+        }
+    }
+}
diff --git a/tests/target/5131.rs b/tests/target/5131.rs
new file mode 100644
index 00000000000..763024d6fa4
--- /dev/null
+++ b/tests/target/5131.rs
@@ -0,0 +1,32 @@
+// rustfmt-imports_granularity: Module
+
+#![allow(dead_code)]
+
+mod a {
+    pub mod b {
+        pub struct Data {
+            pub a: i32,
+        }
+    }
+
+    use crate::a::b::{Data, Data as Data2};
+
+    pub fn data(a: i32) -> Data {
+        Data { a }
+    }
+
+    pub fn data2(a: i32) -> Data2 {
+        Data2 { a }
+    }
+
+    #[cfg(test)]
+    mod tests {
+        use super::*;
+
+        #[test]
+        pub fn test() {
+            data(1);
+            data2(1);
+        }
+    }
+}

From fd6e11cc57da5728a9a52c0a515fd80e811a43d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Wed, 2 Feb 2022 15:43:31 +0100
Subject: [PATCH 138/195] Add tests for the One and Crate variants

---
 tests/source/5131_crate.rs               | 14 ++++++++++++++
 tests/source/{5131.rs => 5131_module.rs} |  0
 tests/source/5131_one.rs                 | 15 +++++++++++++++
 tests/target/5131_crate.rs               |  9 +++++++++
 tests/target/{5131.rs => 5131_module.rs} |  0
 tests/target/5131_one.rs                 | 12 ++++++++++++
 6 files changed, 50 insertions(+)
 create mode 100644 tests/source/5131_crate.rs
 rename tests/source/{5131.rs => 5131_module.rs} (100%)
 create mode 100644 tests/source/5131_one.rs
 create mode 100644 tests/target/5131_crate.rs
 rename tests/target/{5131.rs => 5131_module.rs} (100%)
 create mode 100644 tests/target/5131_one.rs

diff --git a/tests/source/5131_crate.rs b/tests/source/5131_crate.rs
new file mode 100644
index 00000000000..96a31659022
--- /dev/null
+++ b/tests/source/5131_crate.rs
@@ -0,0 +1,14 @@
+// rustfmt-imports_granularity: Crate
+
+use foo::a;
+use foo::a;
+use foo::b;
+use foo::b as b2;
+use foo::b::f;
+use foo::b::g;
+use foo::b::g as g2;
+use foo::c;
+use foo::d::e;
+use qux::h;
+use qux::h as h2;
+use qux::i;
diff --git a/tests/source/5131.rs b/tests/source/5131_module.rs
similarity index 100%
rename from tests/source/5131.rs
rename to tests/source/5131_module.rs
diff --git a/tests/source/5131_one.rs b/tests/source/5131_one.rs
new file mode 100644
index 00000000000..61ddf13410d
--- /dev/null
+++ b/tests/source/5131_one.rs
@@ -0,0 +1,15 @@
+// rustfmt-imports_granularity: One
+
+pub use foo::x;
+pub use foo::x as x2;
+pub use foo::y;
+use bar::a;
+use bar::b;
+use bar::b::f;
+use bar::b::f as f2;
+use bar::b::g;
+use bar::c;
+use bar::d::e;
+use bar::d::e as e2;
+use qux::h;
+use qux::i;
diff --git a/tests/target/5131_crate.rs b/tests/target/5131_crate.rs
new file mode 100644
index 00000000000..557d6670355
--- /dev/null
+++ b/tests/target/5131_crate.rs
@@ -0,0 +1,9 @@
+// rustfmt-imports_granularity: Crate
+
+use foo::{
+    a, b, b as b2,
+    b::{f, g, g as g2},
+    c,
+    d::e,
+};
+use qux::{h, h as h2, i};
diff --git a/tests/target/5131.rs b/tests/target/5131_module.rs
similarity index 100%
rename from tests/target/5131.rs
rename to tests/target/5131_module.rs
diff --git a/tests/target/5131_one.rs b/tests/target/5131_one.rs
new file mode 100644
index 00000000000..a086dae5a42
--- /dev/null
+++ b/tests/target/5131_one.rs
@@ -0,0 +1,12 @@
+// rustfmt-imports_granularity: One
+
+pub use foo::{x, x as x2, y};
+use {
+    bar::{
+        a,
+        b::{self, f, g},
+        c,
+        d::{e, e as e2},
+    },
+    qux::{h, i},
+};

From 5df8c8f7e554e036fcb14a2d93d145c92d56bc2e Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Mon, 7 Feb 2022 10:57:39 +0800
Subject: [PATCH 139/195] Fix doc of generic items formmating error (#5124)

* Fix doc of generic items formmating error

* Remove tracked `attrs_end_with_doc_comment` flag in `RewriteContext`

* Fix duplicated doc comments of const generic params

* Fix `<ast::GenericParam as Spanned>::span()`

* Remove duplicated source file of `doc-of-generic-item.rs`
---
 src/spanned.rs                      | 15 ++++-----------
 src/types.rs                        | 11 ++++++++++-
 tests/target/doc-of-generic-item.rs | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 12 deletions(-)
 create mode 100644 tests/target/doc-of-generic-item.rs

diff --git a/src/spanned.rs b/src/spanned.rs
index 8e6c75a3744..2136cfeae1a 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -113,17 +113,10 @@ impl Spanned for ast::Param {
 
 impl Spanned for ast::GenericParam {
     fn span(&self) -> Span {
-        let lo = if let ast::GenericParamKind::Const {
-            ty: _,
-            kw_span,
-            default: _,
-        } = self.kind
-        {
-            kw_span.lo()
-        } else if self.attrs.is_empty() {
-            self.ident.span.lo()
-        } else {
-            self.attrs[0].span.lo()
+        let lo = match self.kind {
+            _ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
+            ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
+            _ => self.ident.span.lo(),
         };
         let hi = if self.bounds.is_empty() {
             self.ident.span.hi()
diff --git a/src/types.rs b/src/types.rs
index 5de30129266..b13e75a93b3 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -575,7 +575,16 @@ impl Rewrite for ast::GenericParam {
         let mut result = String::with_capacity(128);
         // FIXME: If there are more than one attributes, this will force multiline.
         match self.attrs.rewrite(context, shape) {
-            Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)),
+            Some(ref rw) if !rw.is_empty() => {
+                result.push_str(rw);
+                // When rewriting generic params, an extra newline should be put
+                // if the attributes end with a doc comment
+                if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) {
+                    result.push_str(&shape.indent.to_string_with_newline(context.config));
+                } else {
+                    result.push(' ');
+                }
+            }
             _ => (),
         }
 
diff --git a/tests/target/doc-of-generic-item.rs b/tests/target/doc-of-generic-item.rs
new file mode 100644
index 00000000000..2efc5e09a3d
--- /dev/null
+++ b/tests/target/doc-of-generic-item.rs
@@ -0,0 +1,14 @@
+// Non-doc pre-comment of Foo
+/// doc of Foo
+// Non-doc post-comment of Foo
+struct Foo<
+    // Non-doc pre-comment of 'a
+    /// doc of 'a
+    'a,
+    // Non-doc pre-comment of T
+    /// doc of T
+    T,
+    // Non-doc pre-comment of N
+    /// doc of N
+    const N: item,
+>;

From ace7241087bedd2ea26d7b1dfcdd6133cbf77ce7 Mon Sep 17 00:00:00 2001
From: Gabriel Smith <ga29smith@gmail.com>
Date: Sat, 29 Jan 2022 16:44:49 -0500
Subject: [PATCH 140/195] Fix incorrect string indentation in macro defs with
 `format_strings`

---
 CHANGELOG.md                     |  4 ++++
 src/utils.rs                     | 19 ++++++++++++++++---
 tests/source/issue-4036/one.rs   | 11 +++++++++++
 tests/source/issue-4036/three.rs | 12 ++++++++++++
 tests/source/issue-4036/two.rs   | 11 +++++++++++
 tests/target/issue-4036/one.rs   | 12 ++++++++++++
 tests/target/issue-4036/three.rs | 17 +++++++++++++++++
 tests/target/issue-4036/two.rs   | 16 ++++++++++++++++
 8 files changed, 99 insertions(+), 3 deletions(-)
 create mode 100644 tests/source/issue-4036/one.rs
 create mode 100644 tests/source/issue-4036/three.rs
 create mode 100644 tests/source/issue-4036/two.rs
 create mode 100644 tests/target/issue-4036/one.rs
 create mode 100644 tests/target/issue-4036/three.rs
 create mode 100644 tests/target/issue-4036/two.rs

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b59438dc4fe..1b9208d31e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 ## [Unreleased]
 
+### Fixed
+
+- Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+
 ## [1.4.38] 2021-10-20
 
 ### Changed
diff --git a/src/utils.rs b/src/utils.rs
index 2428d8cb0fd..35512e78fa6 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -646,9 +646,22 @@ pub(crate) fn trim_left_preserve_layout(
 }
 
 /// Based on the given line, determine if the next line can be indented or not.
-/// This allows to preserve the indentation of multi-line literals.
-pub(crate) fn indent_next_line(kind: FullCodeCharKind, _line: &str, config: &Config) -> bool {
-    !(kind.is_string() || (config.version() == Version::Two && kind.is_commented_string()))
+/// This allows to preserve the indentation of multi-line literals when
+/// re-inserted a code block that has been formatted separately from the rest
+/// of the code, such as code in macro defs or code blocks doc comments.
+pub(crate) fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool {
+    if kind.is_string() {
+        // If the string ends with '\', the string has been wrapped over
+        // multiple lines. If `format_strings = true`, then the indentation of
+        // strings wrapped over multiple lines will have been adjusted while
+        // formatting the code block, therefore the string's indentation needs
+        // to be adjusted for the code surrounding the code block.
+        config.format_strings() && line.ends_with('\\')
+    } else if config.version() == Version::Two {
+        !kind.is_commented_string()
+    } else {
+        true
+    }
 }
 
 pub(crate) fn is_empty_line(s: &str) -> bool {
diff --git a/tests/source/issue-4036/one.rs b/tests/source/issue-4036/one.rs
new file mode 100644
index 00000000000..9f9675f5163
--- /dev/null
+++ b/tests/source/issue-4036/one.rs
@@ -0,0 +1,11 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "We asserted that `buffer.len()` is exactly `$n` so we can expect `ApInt::from_iter` to be successful.",
+            )
+        }
+    };
+}
diff --git a/tests/source/issue-4036/three.rs b/tests/source/issue-4036/three.rs
new file mode 100644
index 00000000000..e1865dd0868
--- /dev/null
+++ b/tests/source/issue-4036/three.rs
@@ -0,0 +1,12 @@
+// rustfmt-format_strings: true
+// rustfmt-hard_tabs: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}
diff --git a/tests/source/issue-4036/two.rs b/tests/source/issue-4036/two.rs
new file mode 100644
index 00000000000..fa54d2e3e09
--- /dev/null
+++ b/tests/source/issue-4036/two.rs
@@ -0,0 +1,11 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}
diff --git a/tests/target/issue-4036/one.rs b/tests/target/issue-4036/one.rs
new file mode 100644
index 00000000000..54e490b7fbe
--- /dev/null
+++ b/tests/target/issue-4036/one.rs
@@ -0,0 +1,12 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "We asserted that `buffer.len()` is exactly `$n` so we can expect \
+                 `ApInt::from_iter` to be successful.",
+            )
+        }
+    };
+}
diff --git a/tests/target/issue-4036/three.rs b/tests/target/issue-4036/three.rs
new file mode 100644
index 00000000000..394dc8633f5
--- /dev/null
+++ b/tests/target/issue-4036/three.rs
@@ -0,0 +1,17 @@
+// rustfmt-format_strings: true
+// rustfmt-hard_tabs: true
+
+macro_rules! test {
+	() => {
+		fn from() {
+			None.expect(
+				"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor \
+				 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis \
+				 nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
+				 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu \
+				 fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
+				 culpa qui officia deserunt mollit anim id est laborum.",
+			)
+		}
+	};
+}
diff --git a/tests/target/issue-4036/two.rs b/tests/target/issue-4036/two.rs
new file mode 100644
index 00000000000..01cafa76b68
--- /dev/null
+++ b/tests/target/issue-4036/two.rs
@@ -0,0 +1,16 @@
+// rustfmt-format_strings: true
+
+macro_rules! test {
+    () => {
+        fn from() {
+            None.expect(
+                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor \
+                 incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis \
+                 nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
+                 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu \
+                 fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
+                 culpa qui officia deserunt mollit anim id est laborum.",
+            )
+        }
+    };
+}

From 813d127c824eb22e3fe1fc7a34bf12ad4c0fa2f6 Mon Sep 17 00:00:00 2001
From: Stepan Koltsov <stepan.koltsov@gmail.com>
Date: Mon, 7 Feb 2022 04:39:53 +0000
Subject: [PATCH 141/195] Clarify generated marker requires a config option

---
 CHANGELOG.md      | 1 +
 Configurations.md | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b9208d31e0..5b233608583 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,7 @@ Note this hit the rustup distributions prior to the v1.4.38 release as part of a
 
 - New `One` variant added to `imports_granularity` configuration option which can be used to reformat all imports into a single use statement [#4669](https://github.com/rust-lang/rustfmt/issues/4669)
 - rustfmt will now skip files that are annotated with `@generated` at the top of the file [#3958](https://github.com/rust-lang/rustfmt/issues/3958)
+  if `format_generated_files` option is set to `false` (by default `@generated` files are formatted)
 - New configuration option `hex_literal_case` that allows user to control the casing utilized for hex literals [PR #4903](https://github.com/rust-lang/rustfmt/pull/4903)
 
 See the section on the configuration site for more information
diff --git a/Configurations.md b/Configurations.md
index 4476f2a449b..2e2b0f7cfbe 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -930,6 +930,8 @@ fn add_one(x: i32) -> i32 {
 
 Format generated files. A file is considered generated
 if any of the first five lines contain a `@generated` comment marker.
+By default, generated files are reformatted, i. e. `@generated` marker is ignored.
+This option is currently ignored for stdin (`@generated` in stdin is ignored.)
 
 - **Default value**: `true`
 - **Possible values**: `true`, `false`

From b05b3138001c97cbabeb3e20a0960b9f75341ee0 Mon Sep 17 00:00:00 2001
From: Tharun Rajendran <rajendrantharun@live.com>
Date: Fri, 11 Feb 2022 10:05:45 +0530
Subject: [PATCH 142/195] chore(rustfmt): remove executable path from usage
 string (#5216)

* chore(rustfmt): remove executable path from usage string

* add unit test for usage string

* rename test and check usage text in a single assert
---
 src/bin/main.rs       | 5 ++---
 tests/rustfmt/main.rs | 9 +++++++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 6f5b09fc86a..196de6056b5 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -394,9 +394,8 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) {
         format!("{}\n\n", reason)
     };
     let msg = format!(
-        "{}Format Rust code\n\nusage: {} [options] <file>...",
-        sep,
-        env::args_os().next().unwrap().to_string_lossy()
+        "{}Format Rust code\n\nusage: rustfmt [options] <file>...",
+        sep
     );
     println!("{}", opts.usage(&msg));
 }
diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 8effb1c6fca..6976cc4d346 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -106,3 +106,12 @@ fn inline_config() {
             && contains("format_strings = true")
     );
 }
+
+#[test]
+fn rustfmt_usage_text() {
+    let args = [
+        "--help",
+    ];
+    let (stdout, _) = rustfmt(&args);
+    assert!(stdout.contains(&format!("Format Rust code\n\nusage: rustfmt [options] <file>...")));
+}

From 1e78a2b258470fcab13e8c933212667e64b21d3e Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Wed, 29 Dec 2021 19:59:54 -0500
Subject: [PATCH 143/195] Leverage itemized blocks to support formatting
 markdown block quotes

Fixes 5157

Doc comments support markdown, but rustfmt didn't previously assign any
semantic value to leading '> ' in comments. This lead to poor formatting
when using ``wrap_comments=true``.

Now, rustfmt treats block quotes as itemized blocks, which greatly
improves how block quotes are formatted when ``wrap_comments=true``.
---
 src/comment.rs                                | 46 ++++++++++++++++---
 .../indented_itemized_markdown_blockquote.rs  |  4 ++
 .../nested_itemized_markdown_blockquote.rs    | 10 ++++
 .../support_itemized_markdown_blockquote.rs   |  4 ++
 .../indented_itemized_markdown_blockquote.rs  |  6 +++
 .../nested_itemized_markdown_blockquote.rs    | 18 ++++++++
 .../support_itemized_markdown_blockquote.rs   |  6 +++
 7 files changed, 87 insertions(+), 7 deletions(-)
 create mode 100644 tests/source/issue-5157/indented_itemized_markdown_blockquote.rs
 create mode 100644 tests/source/issue-5157/nested_itemized_markdown_blockquote.rs
 create mode 100644 tests/source/issue-5157/support_itemized_markdown_blockquote.rs
 create mode 100644 tests/target/issue-5157/indented_itemized_markdown_blockquote.rs
 create mode 100644 tests/target/issue-5157/nested_itemized_markdown_blockquote.rs
 create mode 100644 tests/target/issue-5157/support_itemized_markdown_blockquote.rs

diff --git a/src/comment.rs b/src/comment.rs
index 0f850b9b2f2..96778c4ef1d 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -432,16 +432,16 @@ impl CodeBlockAttribute {
 
 /// Block that is formatted as an item.
 ///
-/// An item starts with either a star `*` or a dash `-`. Different level of indentation are
-/// handled by shrinking the shape accordingly.
+/// An item starts with either a star `*` a dash `-` or a greater-than `>`.
+/// Different level of indentation are handled by shrinking the shape accordingly.
 struct ItemizedBlock {
     /// the lines that are identified as part of an itemized block
     lines: Vec<String>,
-    /// the number of whitespaces up to the item sigil
+    /// the number of characters (typically whitespaces) up to the item sigil
     indent: usize,
     /// the string that marks the start of an item
     opener: String,
-    /// sequence of whitespaces to prefix new lines that are part of the item
+    /// sequence of characters (typically whitespaces) to prefix new lines that are part of the item
     line_start: String,
 }
 
@@ -449,19 +449,32 @@ impl ItemizedBlock {
     /// Returns `true` if the line is formatted as an item
     fn is_itemized_line(line: &str) -> bool {
         let trimmed = line.trim_start();
-        trimmed.starts_with("* ") || trimmed.starts_with("- ")
+        trimmed.starts_with("* ") || trimmed.starts_with("- ") || trimmed.starts_with("> ")
     }
 
     /// Creates a new ItemizedBlock described with the given line.
     /// The `is_itemized_line` needs to be called first.
     fn new(line: &str) -> ItemizedBlock {
         let space_to_sigil = line.chars().take_while(|c| c.is_whitespace()).count();
-        let indent = space_to_sigil + 2;
+        // +2 = '* ', which will add the appropriate amount of whitespace to keep itemized
+        // content formatted correctly.
+        let mut indent = space_to_sigil + 2;
+        let mut line_start = " ".repeat(indent);
+
+        // Markdown blockquote start with a "> "
+        if line.trim_start().starts_with(">") {
+            // remove the original +2 indent because there might be multiple nested block quotes
+            // and it's easier to reason about the final indent by just taking the length
+            // of th new line_start. We update the indent because it effects the max width
+            // of each formatted line.
+            line_start = itemized_block_quote_start(line, line_start, 2);
+            indent = line_start.len();
+        }
         ItemizedBlock {
             lines: vec![line[indent..].to_string()],
             indent,
             opener: line[..indent].to_string(),
-            line_start: " ".repeat(indent),
+            line_start,
         }
     }
 
@@ -504,6 +517,25 @@ impl ItemizedBlock {
     }
 }
 
+/// Determine the line_start when formatting markdown block quotes.
+/// The original line_start likely contains indentation (whitespaces), which we'd like to
+/// replace with '> ' characters.
+fn itemized_block_quote_start(line: &str, mut line_start: String, remove_indent: usize) -> String {
+    let quote_level = line
+        .chars()
+        .take_while(|c| !c.is_alphanumeric())
+        .fold(0, |acc, c| if c == '>' { acc + 1 } else { acc });
+
+    for _ in 0..remove_indent {
+        line_start.pop();
+    }
+
+    for _ in 0..quote_level {
+        line_start.push_str("> ")
+    }
+    line_start
+}
+
 struct CommentRewrite<'a> {
     result: String,
     code_block_buffer: String,
diff --git a/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs b/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..5c1d79a7430
--- /dev/null
+++ b/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs
@@ -0,0 +1,4 @@
+// rustfmt-wrap_comments: true
+
+///        > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+fn block_quote() {}
diff --git a/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs b/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..cf200d04e08
--- /dev/null
+++ b/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs
@@ -0,0 +1,10 @@
+// rustfmt-wrap_comments: true
+
+/// > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+///
+/// > > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+///
+/// > > > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+///
+/// > > > > > > > > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+fn block_quote() {}
diff --git a/tests/source/issue-5157/support_itemized_markdown_blockquote.rs b/tests/source/issue-5157/support_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..eb436402e4e
--- /dev/null
+++ b/tests/source/issue-5157/support_itemized_markdown_blockquote.rs
@@ -0,0 +1,4 @@
+// rustfmt-wrap_comments: true
+
+/// > For each sample received, the middleware internally maintains a sample_state relative to each DataReader. The sample_state can either be READ or NOT_READ.
+fn block_quote() {}
diff --git a/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs b/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..e47677f2039
--- /dev/null
+++ b/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs
@@ -0,0 +1,6 @@
+// rustfmt-wrap_comments: true
+
+///        > For each sample received, the middleware internally maintains a
+///        > sample_state relative to each DataReader. The sample_state can
+///        > either be READ or NOT_READ.
+fn block_quote() {}
diff --git a/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs b/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..079510442b7
--- /dev/null
+++ b/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs
@@ -0,0 +1,18 @@
+// rustfmt-wrap_comments: true
+
+/// > For each sample received, the middleware internally maintains a
+/// > sample_state relative to each DataReader. The sample_state can either be
+/// > READ or NOT_READ.
+///
+/// > > For each sample received, the middleware internally maintains a
+/// > > sample_state relative to each DataReader. The sample_state can either be
+/// > > READ or NOT_READ.
+///
+/// > > > For each sample received, the middleware internally maintains a
+/// > > > sample_state relative to each DataReader. The sample_state can either
+/// > > > be READ or NOT_READ.
+///
+/// > > > > > > > > For each sample received, the middleware internally
+/// > > > > > > > > maintains a sample_state relative to each DataReader. The
+/// > > > > > > > > sample_state can either be READ or NOT_READ.
+fn block_quote() {}
diff --git a/tests/target/issue-5157/support_itemized_markdown_blockquote.rs b/tests/target/issue-5157/support_itemized_markdown_blockquote.rs
new file mode 100644
index 00000000000..029ee37d22a
--- /dev/null
+++ b/tests/target/issue-5157/support_itemized_markdown_blockquote.rs
@@ -0,0 +1,6 @@
+// rustfmt-wrap_comments: true
+
+/// > For each sample received, the middleware internally maintains a
+/// > sample_state relative to each DataReader. The sample_state can either be
+/// > READ or NOT_READ.
+fn block_quote() {}

From 6c476127aedc37b43769469f87e0fbc382382739 Mon Sep 17 00:00:00 2001
From: Travis Finkenauer <tmfink@users.noreply.github.com>
Date: Tue, 15 Feb 2022 15:25:44 -0800
Subject: [PATCH 144/195] Add context to get_toml_path() error (#5207)

* rustfmt: print full error chain

* Add context to get_toml_path() error

Instead of an error like:

```
Permission denied (os error 13)
```

Gives error like:

```
Failed to get metadata for config file "/root/.rustfmt.toml": Permission denied (os error 13)
```
---
 src/bin/main.rs   | 2 +-
 src/config/mod.rs | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 196de6056b5..ad10b9ede60 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -26,7 +26,7 @@ fn main() {
     let exit_code = match execute(&opts) {
         Ok(code) => code,
         Err(e) => {
-            eprintln!("{}", e);
+            eprintln!("{:#}", e);
             1
         }
     };
diff --git a/src/config/mod.rs b/src/config/mod.rs
index cd90e0904b6..5041e1e36dd 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -364,7 +364,9 @@ fn get_toml_path(dir: &Path) -> Result<Option<PathBuf>, Error> {
             // find the project file yet, and continue searching.
             Err(e) => {
                 if e.kind() != ErrorKind::NotFound {
-                    return Err(e);
+                    let ctx = format!("Failed to get metadata for config file {:?}", &config_file);
+                    let err = anyhow::Error::new(e).context(ctx);
+                    return Err(Error::new(ErrorKind::Other, err));
                 }
             }
             _ => {}

From d5aabccfebc645d9fce62f91512b03ca0fa1fb6d Mon Sep 17 00:00:00 2001
From: Cameron Steffen <cam.steffen94@gmail.com>
Date: Tue, 1 Feb 2022 13:38:54 -0600
Subject: [PATCH 145/195] Format code

---
 config_proc_macro/src/utils.rs | 4 ++--
 tests/cargo-fmt/main.rs        | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/config_proc_macro/src/utils.rs b/config_proc_macro/src/utils.rs
index 5b68d274849..f5cba87b07b 100644
--- a/config_proc_macro/src/utils.rs
+++ b/config_proc_macro/src/utils.rs
@@ -22,10 +22,10 @@ pub fn is_unit(v: &syn::Variant) -> bool {
 #[cfg(feature = "debug-with-rustfmt")]
 /// Pretty-print the output of proc macro using rustfmt.
 pub fn debug_with_rustfmt(input: &TokenStream) {
-    use std::io::Write;
-    use std::process::{Command, Stdio};
     use std::env;
     use std::ffi::OsStr;
+    use std::io::Write;
+    use std::process::{Command, Stdio};
 
     let rustfmt_var = env::var_os("RUSTFMT");
     let rustfmt = match &rustfmt_var {
diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs
index bf81f253f69..3713552c66a 100644
--- a/tests/cargo-fmt/main.rs
+++ b/tests/cargo-fmt/main.rs
@@ -1,8 +1,8 @@
 // Integration tests for cargo-fmt.
 
 use std::env;
-use std::process::Command;
 use std::path::Path;
+use std::process::Command;
 
 /// Run the cargo-fmt executable and return its output.
 fn cargo_fmt(args: &[&str]) -> (String, String) {

From c63d42e80473a0c18714b55058f27506fd24955c Mon Sep 17 00:00:00 2001
From: Cameron Steffen <cam.steffen94@gmail.com>
Date: Tue, 1 Feb 2022 13:39:01 -0600
Subject: [PATCH 146/195] Use cargo-fmt in self_tests

---
 src/test/mod.rs | 46 ++++++++++++----------------------------------
 1 file changed, 12 insertions(+), 34 deletions(-)

diff --git a/src/test/mod.rs b/src/test/mod.rs
index ab966d4a360..4191e3e96b0 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -375,43 +375,21 @@ fn idempotence_tests() {
     });
 }
 
-// Run rustfmt on itself. This operation must be idempotent. We also check that
-// no warnings are emitted.
-// Issue-3443: these tests require nightly
 #[nightly_only_test]
 #[test]
 fn self_tests() {
-    init_log();
-    let mut files = get_test_files(Path::new("tests"), false);
-    let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
-    for dir in bin_directories {
-        let mut path = PathBuf::from("src");
-        path.push(dir);
-        path.push("main.rs");
-        files.push(path);
-    }
-    files.push(PathBuf::from("src/lib.rs"));
-
-    let (reports, count, fails) = check_files(files, &Some(PathBuf::from("rustfmt.toml")));
-    let mut warnings = 0;
-
-    // Display results.
-    println!("Ran {} self tests.", count);
-    assert_eq!(fails, 0, "{} self tests failed", fails);
-
-    for format_report in reports {
-        println!(
-            "{}",
-            FormatReportFormatterBuilder::new(&format_report).build()
-        );
-        warnings += format_report.warning_count();
-    }
-
-    assert_eq!(
-        warnings, 0,
-        "Rustfmt's code generated {} warnings",
-        warnings
-    );
+    let get_exe_path = |name| {
+        let mut path = env::current_exe().unwrap();
+        path.pop();
+        path.set_file_name(format!("{name}{}", env::consts::EXE_SUFFIX));
+        path
+    };
+    let status = Command::new(get_exe_path("cargo-fmt"))
+        .args(["--check", "--all"])
+        .env("RUSTFMT", get_exe_path("rustfmt"))
+        .status()
+        .unwrap();
+    assert!(status.success());
 }
 
 #[test]

From 281bf03e6492bf2627c24ea502ce5fd567d7a08e Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Tue, 15 Feb 2022 20:49:36 -0600
Subject: [PATCH 147/195] fix: formatting in new test

---
 tests/rustfmt/main.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 6976cc4d346..2262ae3aaac 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -109,9 +109,7 @@ fn inline_config() {
 
 #[test]
 fn rustfmt_usage_text() {
-    let args = [
-        "--help",
-    ];
+    let args = ["--help"];
     let (stdout, _) = rustfmt(&args);
-    assert!(stdout.contains(&format!("Format Rust code\n\nusage: rustfmt [options] <file>...")));
+    assert!(stdout.contains("Format Rust code\n\nusage: rustfmt [options] <file>..."));
 }

From 89ca3f3a100456d652b156b1a62b8e244e526c4e Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 23 Feb 2022 21:37:42 -0600
Subject: [PATCH 148/195] fix: unused test imports on non-nightly, prevent
 regression

---
 .github/workflows/linux.yml | 4 ++++
 src/ignore_path.rs          | 9 ++++-----
 src/lib.rs                  | 1 -
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index db497941642..45f63b83c05 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -40,6 +40,10 @@ jobs:
         rustc -Vv
         cargo -V
         cargo build
+      env:
+        RUSTFLAGS: '-D warnings'
 
     - name: test
       run: cargo test
+      env:
+        RUSTFLAGS: '-D warnings'
diff --git a/src/ignore_path.rs b/src/ignore_path.rs
index 7738eee0a76..d955949496a 100644
--- a/src/ignore_path.rs
+++ b/src/ignore_path.rs
@@ -32,16 +32,15 @@ impl IgnorePathSet {
 
 #[cfg(test)]
 mod test {
-    use std::path::{Path, PathBuf};
-
-    use crate::config::{Config, FileName};
-    use crate::ignore_path::IgnorePathSet;
-
     use rustfmt_config_proc_macro::nightly_only_test;
 
     #[nightly_only_test]
     #[test]
     fn test_ignore_path_set() {
+        use crate::config::{Config, FileName};
+        use crate::ignore_path::IgnorePathSet;
+        use std::path::{Path, PathBuf};
+
         let config =
             Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap();
         let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
diff --git a/src/lib.rs b/src/lib.rs
index fae8080c02e..ad23b16e02e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,6 @@
 #![warn(unreachable_pub)]
 #![recursion_limit = "256"]
 #![allow(clippy::match_like_matches_macro)]
-#![allow(unreachable_pub)]
 
 #[macro_use]
 extern crate derive_new;

From 12048e444f8a68b3c13e98b15c11a69de9f0b485 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sun, 30 Jan 2022 13:46:53 -0500
Subject: [PATCH 149/195] fallback to dir_path when relative external mod
 resolution fails

We only want to fall back if two conditions are met:

1) Initial module resolution is performed relative to some nested
   directory.
2) Module resolution fails because of a ModError::FileNotFound error.

When these conditions are met we can try to fallback to searching for
the module's file relative to the dir_path instead of the nested
relative directory.

Fixes 5198

As demonstrated by 5198, it's possible that a directory name conflicts
with a rust file name. For example, src/lib/ and src/lib.rs.

If src/lib.rs references an external module like ``mod foo;``, then
module resolution will try to resolve ``foo`` to src/lib/foo.rs or
src/lib/foo/mod.rs. Module resolution would fail with a file not
found error if the ``foo`` module were defined at src/foo.rs.

When encountering these kinds of module resolution issues we now fall
back to the current directory and attempt to resolve the module again.

Given the current example, this means that if we can't find the module
``foo`` at src/lib/foo.rs or src/lib/foo/mod.rs, we'll attempt
to resolve the module to src/foo.rs.
---
 src/parse/session.rs                          | 22 +++++++++++++++++--
 src/test/mod_resolver.rs                      | 16 ++++++++++++++
 tests/mod-resolver/issue-5198/a.rs            |  1 +
 tests/mod-resolver/issue-5198/lib.rs          |  3 +++
 tests/mod-resolver/issue-5198/lib/b.rs        |  1 +
 tests/mod-resolver/issue-5198/lib/c/d.rs      |  3 +++
 .../issue-5198/lib/c/d/explanation.txt        | 16 ++++++++++++++
 tests/mod-resolver/issue-5198/lib/c/d/f.rs    |  1 +
 .../mod-resolver/issue-5198/lib/c/d/g/mod.rs  |  1 +
 tests/mod-resolver/issue-5198/lib/c/e.rs      |  1 +
 tests/mod-resolver/issue-5198/lib/c/mod.rs    |  3 +++
 .../issue-5198/lib/explanation.txt            | 16 ++++++++++++++
 12 files changed, 82 insertions(+), 2 deletions(-)
 create mode 100644 tests/mod-resolver/issue-5198/a.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/b.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/d.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/d/f.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/e.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/c/mod.rs
 create mode 100644 tests/mod-resolver/issue-5198/lib/explanation.txt

diff --git a/src/parse/session.rs b/src/parse/session.rs
index 624fed0d2de..fb9182152d1 100644
--- a/src/parse/session.rs
+++ b/src/parse/session.rs
@@ -12,6 +12,7 @@ use rustc_span::{
 
 use crate::config::file_lines::LineRange;
 use crate::ignore_path::IgnorePathSet;
+use crate::parse::parser::{ModError, ModulePathSuccess};
 use crate::source_map::LineRangeUtils;
 use crate::utils::starts_with_newline;
 use crate::visitor::SnippetProvider;
@@ -145,13 +146,30 @@ impl ParseSess {
         })
     }
 
+    /// Determine the submodule path for the given module identifier.
+    ///
+    /// * `id` - The name of the module
+    /// * `relative` - If Some(symbol), the symbol name is a directory relative to the dir_path.
+    ///   If relative is Some, resolve the submodle at {dir_path}/{symbol}/{id}.rs
+    ///   or {dir_path}/{symbol}/{id}/mod.rs. if None, resolve the module at {dir_path}/{id}.rs.
+    /// *  `dir_path` - Module resolution will occur relative to this direcotry.
     pub(crate) fn default_submod_path(
         &self,
         id: symbol::Ident,
         relative: Option<symbol::Ident>,
         dir_path: &Path,
-    ) -> Result<rustc_expand::module::ModulePathSuccess, rustc_expand::module::ModError<'_>> {
-        rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path)
+    ) -> Result<ModulePathSuccess, ModError<'_>> {
+        rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path).or_else(
+            |e| {
+                // If resloving a module relative to {dir_path}/{symbol} fails because a file
+                // could not be found, then try to resolve the module relative to {dir_path}.
+                if matches!(e, ModError::FileNotFound(..)) && relative.is_some() {
+                    rustc_expand::module::default_submod_path(&self.parse_sess, id, None, dir_path)
+                } else {
+                    Err(e)
+                }
+            },
+        )
     }
 
     pub(crate) fn is_file_parsed(&self, path: &Path) -> bool {
diff --git a/src/test/mod_resolver.rs b/src/test/mod_resolver.rs
index fcff6d14e6f..aacb2acc684 100644
--- a/src/test/mod_resolver.rs
+++ b/src/test/mod_resolver.rs
@@ -64,3 +64,19 @@ fn fmt_out_of_line_test_modules() {
         ],
     )
 }
+
+#[test]
+fn fallback_and_try_to_resolve_external_submod_relative_to_current_dir_path() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5198
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-5198/lib.rs",
+        &[
+            "tests/mod-resolver/issue-5198/a.rs",
+            "tests/mod-resolver/issue-5198/lib/b.rs",
+            "tests/mod-resolver/issue-5198/lib/c/mod.rs",
+            "tests/mod-resolver/issue-5198/lib/c/e.rs",
+            "tests/mod-resolver/issue-5198/lib/c/d/f.rs",
+            "tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs",
+        ],
+    )
+}
diff --git a/tests/mod-resolver/issue-5198/a.rs b/tests/mod-resolver/issue-5198/a.rs
new file mode 100644
index 00000000000..cd686f56116
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/a.rs
@@ -0,0 +1 @@
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib.rs b/tests/mod-resolver/issue-5198/lib.rs
new file mode 100644
index 00000000000..696832913c8
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib.rs
@@ -0,0 +1,3 @@
+mod a;
+mod b;
+mod c;
diff --git a/tests/mod-resolver/issue-5198/lib/b.rs b/tests/mod-resolver/issue-5198/lib/b.rs
new file mode 100644
index 00000000000..cd686f56116
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/b.rs
@@ -0,0 +1 @@
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib/c/d.rs b/tests/mod-resolver/issue-5198/lib/c/d.rs
new file mode 100644
index 00000000000..d1604aa23a3
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/d.rs
@@ -0,0 +1,3 @@
+mod e;
+mod f;
+mod g;
diff --git a/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
new file mode 100644
index 00000000000..92c9e302143
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
@@ -0,0 +1,16 @@
+This file is contained in the './lib/c/d/' directory.
+
+The directory name './lib/c/d/' conflicts with the './lib/c/d.rs' file name.
+
+'./lib/c/d.rs' defines 3 external modules:
+
+    * mod e;
+    * mod f;
+    * 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
+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
+to resolve these modules with no problems.
\ No newline at end of file
diff --git a/tests/mod-resolver/issue-5198/lib/c/d/f.rs b/tests/mod-resolver/issue-5198/lib/c/d/f.rs
new file mode 100644
index 00000000000..cd686f56116
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/d/f.rs
@@ -0,0 +1 @@
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs b/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs
new file mode 100644
index 00000000000..cd686f56116
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs
@@ -0,0 +1 @@
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib/c/e.rs b/tests/mod-resolver/issue-5198/lib/c/e.rs
new file mode 100644
index 00000000000..cd686f56116
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/e.rs
@@ -0,0 +1 @@
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib/c/mod.rs b/tests/mod-resolver/issue-5198/lib/c/mod.rs
new file mode 100644
index 00000000000..81904619650
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/c/mod.rs
@@ -0,0 +1,3 @@
+mod d;
+
+fn main(        ) {   println!("Hello World!")                         }
diff --git a/tests/mod-resolver/issue-5198/lib/explanation.txt b/tests/mod-resolver/issue-5198/lib/explanation.txt
new file mode 100644
index 00000000000..d436a8076cd
--- /dev/null
+++ b/tests/mod-resolver/issue-5198/lib/explanation.txt
@@ -0,0 +1,16 @@
+This file is contained in the './lib' directory.
+
+The directory name './lib' conflicts with the './lib.rs' file name.
+
+'lib.rs' defines 3 external modules:
+
+    * mod a;
+    * mod b;
+    * 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
+rustfmt should format.
+
+'./lib/b.rs' and './lib/c/mod.rs' exist at the default submodule paths so we should be able
+to resolve these modules with no problems.

From 272fb42f06479afb62a9503f181540101f67982a Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Fri, 25 Feb 2022 11:31:09 -0500
Subject: [PATCH 150/195] Prevent wrapping markdown headers in doc comments

Fixes 5238

A markdown header is defined by a string that starts with `#`.

Previously, rustfmt would wrap long markdown headers when
`wrap_comments=true`. This lead to issues when rendering these headers
in HTML using rustdoc.

Now, rustfmt leaves markdown headers alone when wrapping comments.
---
 src/comment.rs                                 | 18 ++++++++++++++----
 .../markdown_header_wrap_comments_false.rs     | 11 +++++++++++
 .../markdown_header_wrap_comments_true.rs      | 11 +++++++++++
 .../markdown_header_wrap_comments_false.rs     | 11 +++++++++++
 .../markdown_header_wrap_comments_true.rs      | 14 ++++++++++++++
 5 files changed, 61 insertions(+), 4 deletions(-)
 create mode 100644 tests/source/issue-5238/markdown_header_wrap_comments_false.rs
 create mode 100644 tests/source/issue-5238/markdown_header_wrap_comments_true.rs
 create mode 100644 tests/target/issue-5238/markdown_header_wrap_comments_false.rs
 create mode 100644 tests/target/issue-5238/markdown_header_wrap_comments_true.rs

diff --git a/src/comment.rs b/src/comment.rs
index 96778c4ef1d..f9d8a0fa70c 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -683,6 +683,7 @@ impl<'a> CommentRewrite<'a> {
         i: usize,
         line: &'a str,
         has_leading_whitespace: bool,
+        is_doc_comment: bool,
     ) -> bool {
         let num_newlines = count_newlines(orig);
         let is_last = i == num_newlines;
@@ -789,10 +790,19 @@ impl<'a> CommentRewrite<'a> {
             }
         }
 
-        if self.fmt.config.wrap_comments()
+        let is_markdown_header_doc_comment = is_doc_comment && line.starts_with("#");
+
+        // We only want to wrap the comment if:
+        // 1) wrap_comments = true is configured
+        // 2) The comment is not the start of a markdown header doc comment
+        // 3) The comment width exceeds the shape's width
+        // 4) No URLS were found in the commnet
+        let should_wrap_comment = self.fmt.config.wrap_comments()
+            && !is_markdown_header_doc_comment
             && unicode_str_width(line) > self.fmt.shape.width
-            && !has_url(line)
-        {
+            && !has_url(line);
+
+        if should_wrap_comment {
             match rewrite_string(line, &self.fmt, self.max_width) {
                 Some(ref s) => {
                     self.is_prev_line_multi_line = s.contains('\n');
@@ -882,7 +892,7 @@ fn rewrite_comment_inner(
         });
 
     for (i, (line, has_leading_whitespace)) in lines.enumerate() {
-        if rewriter.handle_line(orig, i, line, has_leading_whitespace) {
+        if rewriter.handle_line(orig, i, line, has_leading_whitespace, is_doc_comment) {
             break;
         }
     }
diff --git a/tests/source/issue-5238/markdown_header_wrap_comments_false.rs b/tests/source/issue-5238/markdown_header_wrap_comments_false.rs
new file mode 100644
index 00000000000..229c6e5753d
--- /dev/null
+++ b/tests/source/issue-5238/markdown_header_wrap_comments_false.rs
@@ -0,0 +1,11 @@
+// rustfmt-wrap_comments: false
+
+/// no markdown header so rustfmt should wrap this comment when `format_code_in_doc_comments = true` and `wrap_comments = true`
+fn not_documented_with_markdown_header() {
+    // This is just a normal inline comment so rustfmt should wrap this comment when `wrap_comments = true`
+}
+
+/// # We're using a markdown header here so rustfmt should refuse to wrap this comment in all circumstances
+fn documented_with_markdown_header() {
+    // # We're using a markdown header in an inline comment. rustfmt should be able to wrap this comment when `wrap_comments = true`
+}
diff --git a/tests/source/issue-5238/markdown_header_wrap_comments_true.rs b/tests/source/issue-5238/markdown_header_wrap_comments_true.rs
new file mode 100644
index 00000000000..c547ff35c69
--- /dev/null
+++ b/tests/source/issue-5238/markdown_header_wrap_comments_true.rs
@@ -0,0 +1,11 @@
+// rustfmt-wrap_comments: true
+
+/// no markdown header so rustfmt should wrap this comment when `format_code_in_doc_comments = true` and `wrap_comments = true`
+fn not_documented_with_markdown_header() {
+    // This is just a normal inline comment so rustfmt should wrap this comment when `wrap_comments = true`
+}
+
+/// # We're using a markdown header here so rustfmt should refuse to wrap this comment in all circumstances
+fn documented_with_markdown_header() {
+    // # We're using a markdown header in an inline comment. rustfmt should be able to wrap this comment when `wrap_comments = true`
+}
diff --git a/tests/target/issue-5238/markdown_header_wrap_comments_false.rs b/tests/target/issue-5238/markdown_header_wrap_comments_false.rs
new file mode 100644
index 00000000000..229c6e5753d
--- /dev/null
+++ b/tests/target/issue-5238/markdown_header_wrap_comments_false.rs
@@ -0,0 +1,11 @@
+// rustfmt-wrap_comments: false
+
+/// no markdown header so rustfmt should wrap this comment when `format_code_in_doc_comments = true` and `wrap_comments = true`
+fn not_documented_with_markdown_header() {
+    // This is just a normal inline comment so rustfmt should wrap this comment when `wrap_comments = true`
+}
+
+/// # We're using a markdown header here so rustfmt should refuse to wrap this comment in all circumstances
+fn documented_with_markdown_header() {
+    // # We're using a markdown header in an inline comment. rustfmt should be able to wrap this comment when `wrap_comments = true`
+}
diff --git a/tests/target/issue-5238/markdown_header_wrap_comments_true.rs b/tests/target/issue-5238/markdown_header_wrap_comments_true.rs
new file mode 100644
index 00000000000..87dae58eccd
--- /dev/null
+++ b/tests/target/issue-5238/markdown_header_wrap_comments_true.rs
@@ -0,0 +1,14 @@
+// rustfmt-wrap_comments: true
+
+/// no markdown header so rustfmt should wrap this comment when
+/// `format_code_in_doc_comments = true` and `wrap_comments = true`
+fn not_documented_with_markdown_header() {
+    // This is just a normal inline comment so rustfmt should wrap this comment
+    // when `wrap_comments = true`
+}
+
+/// # We're using a markdown header here so rustfmt should refuse to wrap this comment in all circumstances
+fn documented_with_markdown_header() {
+    // # We're using a markdown header in an inline comment. rustfmt should be
+    // able to wrap this comment when `wrap_comments = true`
+}

From ee130515e3788d886cdf18442871936a99c134b6 Mon Sep 17 00:00:00 2001
From: cassaundra <cass@cassaundra.io>
Date: Wed, 29 Dec 2021 15:41:26 -0800
Subject: [PATCH 151/195] Fix missing struct field separators under certain
 conditions

When struct_field_align_threshold is non-zero and trailing_comma is set to
"Never," struct field separators are omitted between field groups. This issue is
resolved by forcing separators between groups.

Fixes #4791.

A test is included with a minimal reproducible example.
---
 src/vertical.rs            | 23 ++++++++++++++++++++---
 tests/source/issue_4791.rs | 14 ++++++++++++++
 tests/target/issue_4791.rs | 14 ++++++++++++++
 3 files changed, 48 insertions(+), 3 deletions(-)
 create mode 100644 tests/source/issue_4791.rs
 create mode 100644 tests/target/issue_4791.rs

diff --git a/src/vertical.rs b/src/vertical.rs
index c4208848c6c..a06bc995aa5 100644
--- a/src/vertical.rs
+++ b/src/vertical.rs
@@ -160,8 +160,18 @@ pub(crate) fn rewrite_with_alignment<T: AlignedItem>(
     };
     let init_span = mk_sp(span.lo(), init_last_pos);
     let one_line_width = if rest.is_empty() { one_line_width } else { 0 };
-    let result =
-        rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?;
+
+    // if another group follows, we must force a separator
+    let force_separator = !rest.is_empty();
+
+    let result = rewrite_aligned_items_inner(
+        context,
+        init,
+        init_span,
+        shape.indent,
+        one_line_width,
+        force_separator,
+    )?;
     if rest.is_empty() {
         Some(result + spaces)
     } else {
@@ -201,6 +211,7 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
     span: Span,
     offset: Indent,
     one_line_width: usize,
+    force_trailing_separator: bool,
 ) -> Option<String> {
     // 1 = ","
     let item_shape = Shape::indented(offset, context.config).sub_width(1)?;
@@ -246,9 +257,15 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
             });
     }
 
+    let separator_tactic = if force_trailing_separator {
+        SeparatorTactic::Always
+    } else {
+        context.config.trailing_comma()
+    };
+
     let fmt = ListFormatting::new(item_shape, context.config)
         .tactic(tactic)
-        .trailing_separator(context.config.trailing_comma())
+        .trailing_separator(separator_tactic)
         .preserve_newline(true);
     write_list(&items, &fmt)
 }
diff --git a/tests/source/issue_4791.rs b/tests/source/issue_4791.rs
new file mode 100644
index 00000000000..4760022eeaf
--- /dev/null
+++ b/tests/source/issue_4791.rs
@@ -0,0 +1,14 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-trailing_comma: Never
+
+struct Foo {
+    group_a: u8,
+
+    group_b: u8,
+}
+
+struct Bar {
+    group_a: u8,
+
+    group_b: u8
+}
diff --git a/tests/target/issue_4791.rs b/tests/target/issue_4791.rs
new file mode 100644
index 00000000000..fff58be99a5
--- /dev/null
+++ b/tests/target/issue_4791.rs
@@ -0,0 +1,14 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-trailing_comma: Never
+
+struct Foo {
+    group_a: u8,
+
+    group_b: u8
+}
+
+struct Bar {
+    group_a: u8,
+
+    group_b: u8
+}

From ab9f2a8ac78a66ae1fb0f92ae5a32ce5c0db0d8d Mon Sep 17 00:00:00 2001
From: cassaundra <cass@cassaundra.io>
Date: Fri, 14 Jan 2022 17:25:46 -0800
Subject: [PATCH 152/195] Add more tests for struct_field_align_threshold and
 trailing_comma

---
 .../source/{issue_4791.rs => issue-4791/buggy.rs}  |  0
 tests/source/issue-4791/trailing_comma.rs          | 14 ++++++++++++++
 .../target/{issue_4791.rs => issue-4791/buggy.rs}  |  0
 tests/target/issue-4791/no_trailing_comma.rs       |  8 ++++++++
 tests/target/issue-4791/trailing_comma.rs          | 14 ++++++++++++++
 5 files changed, 36 insertions(+)
 rename tests/source/{issue_4791.rs => issue-4791/buggy.rs} (100%)
 create mode 100644 tests/source/issue-4791/trailing_comma.rs
 rename tests/target/{issue_4791.rs => issue-4791/buggy.rs} (100%)
 create mode 100644 tests/target/issue-4791/no_trailing_comma.rs
 create mode 100644 tests/target/issue-4791/trailing_comma.rs

diff --git a/tests/source/issue_4791.rs b/tests/source/issue-4791/buggy.rs
similarity index 100%
rename from tests/source/issue_4791.rs
rename to tests/source/issue-4791/buggy.rs
diff --git a/tests/source/issue-4791/trailing_comma.rs b/tests/source/issue-4791/trailing_comma.rs
new file mode 100644
index 00000000000..c56c70faeae
--- /dev/null
+++ b/tests/source/issue-4791/trailing_comma.rs
@@ -0,0 +1,14 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-trailing_comma: Always
+
+struct Foo {
+    group_a: u8,
+
+    group_b: u8
+}
+
+struct Bar {
+    group_a: u8,
+
+    group_b: u8,
+}
diff --git a/tests/target/issue_4791.rs b/tests/target/issue-4791/buggy.rs
similarity index 100%
rename from tests/target/issue_4791.rs
rename to tests/target/issue-4791/buggy.rs
diff --git a/tests/target/issue-4791/no_trailing_comma.rs b/tests/target/issue-4791/no_trailing_comma.rs
new file mode 100644
index 00000000000..4a37163969a
--- /dev/null
+++ b/tests/target/issue-4791/no_trailing_comma.rs
@@ -0,0 +1,8 @@
+// rustfmt-struct_field_align_threshold: 0
+// rustfmt-trailing_comma: Never
+
+pub struct Baz {
+    group_a: u8,
+
+    group_b: u8
+}
diff --git a/tests/target/issue-4791/trailing_comma.rs b/tests/target/issue-4791/trailing_comma.rs
new file mode 100644
index 00000000000..29a224b3f6d
--- /dev/null
+++ b/tests/target/issue-4791/trailing_comma.rs
@@ -0,0 +1,14 @@
+// rustfmt-struct_field_align_threshold: 30
+// rustfmt-trailing_comma: Always
+
+struct Foo {
+    group_a: u8,
+
+    group_b: u8,
+}
+
+struct Bar {
+    group_a: u8,
+
+    group_b: u8,
+}

From 58de4142c525cc50824dab1cf199dc967c88356f Mon Sep 17 00:00:00 2001
From: cassaundra <cass@cassaundra.io>
Date: Sat, 5 Mar 2022 14:17:15 -0800
Subject: [PATCH 153/195] Add test for issue #4791

---
 tests/target/issue-4791/issue_4928.rs | 70 +++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 tests/target/issue-4791/issue_4928.rs

diff --git a/tests/target/issue-4791/issue_4928.rs b/tests/target/issue-4791/issue_4928.rs
new file mode 100644
index 00000000000..588656b535f
--- /dev/null
+++ b/tests/target/issue-4791/issue_4928.rs
@@ -0,0 +1,70 @@
+// rustfmt-brace_style: SameLineWhere
+// rustfmt-comment_width: 100
+// rustfmt-edition: 2018
+// rustfmt-fn_args_layout: Compressed
+// rustfmt-hard_tabs: false
+// rustfmt-match_block_trailing_comma: true
+// rustfmt-max_width: 100
+// rustfmt-merge_derives: false
+// rustfmt-newline_style: Unix
+// rustfmt-normalize_doc_attributes: true
+// rustfmt-overflow_delimited_expr: true
+// rustfmt-reorder_imports: false
+// rustfmt-reorder_modules: true
+// rustfmt-struct_field_align_threshold: 20
+// rustfmt-tab_spaces: 4
+// rustfmt-trailing_comma: Never
+// rustfmt-use_small_heuristics: Max
+// rustfmt-use_try_shorthand: true
+// rustfmt-wrap_comments: true
+
+/// Lorem ipsum dolor sit amet.
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
+pub struct BufferAttr {
+    /* NOTE: Blah blah blah blah blah. */
+    /// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
+    /// ut labore et dolore magna aliqua. Morbi quis commodo odio aenean sed adipiscing. Nunc
+    /// congue nisi vitae suscipit tellus mauris a. Consectetur adipiscing elit pellentesque
+    /// habitant morbi tristique senectus.
+    pub foo: u32,
+
+    /// Elit eget gravida cum sociis natoque penatibus et magnis dis. Consequat semper viverra nam
+    /// libero. Accumsan in nisl nisi scelerisque eu. Pellentesque id nibh tortor id aliquet. Sed
+    /// velit dignissim sodales ut. Facilisis sed odio morbi quis commodo odio aenean sed. Et
+    /// ultrices neque ornare aenean euismod elementum. Condimentum lacinia quis vel eros donec ac
+    /// odio tempor.
+    ///
+    /// Lacinia at quis risus sed vulputate odio ut enim. Etiam erat velit scelerisque in dictum.
+    /// Nibh tellus molestie nunc non blandit massa enim nec. Nascetur ridiculus mus mauris vitae.
+    pub bar: u32,
+
+    /// Mi proin sed libero enim sed faucibus turpis. Amet consectetur adipiscing elit duis
+    /// tristique sollicitudin nibh sit amet. Congue quisque egestas diam in arcu cursus euismod
+    /// quis viverra. Cum sociis natoque penatibus et magnis dis parturient montes. Enim sit amet
+    /// venenatis urna cursus eget nunc scelerisque viverra. Cras semper auctor neque vitae tempus
+    /// quam pellentesque. Tortor posuere ac ut consequat semper viverra nam libero justo. Vitae
+    /// auctor eu augue ut lectus arcu bibendum at. Faucibus vitae aliquet nec ullamcorper sit amet
+    /// risus nullam. Maecenas accumsan lacus vel facilisis volutpat. Arcu non odio euismod
+    /// lacinia.
+    ///
+    /// [`FooBar::beep()`]: crate::foobar::FooBar::beep
+    /// [`FooBar::boop()`]: crate::foobar::FooBar::boop
+    /// [`foobar::BazBaq::BEEP_BOOP`]: crate::foobar::BazBaq::BEEP_BOOP
+    pub baz: u32,
+
+    /// Eu consequat ac felis donec et odio pellentesque diam. Ut eu sem integer vitae justo eget.
+    /// Consequat ac felis donec et odio pellentesque diam volutpat.
+    pub baq: u32,
+
+    /// Amet consectetur adipiscing elit pellentesque habitant. Ut morbi tincidunt augue interdum
+    /// velit euismod in pellentesque. Imperdiet sed euismod nisi porta lorem. Nec tincidunt
+    /// praesent semper feugiat. Facilisis leo vel fringilla est. Egestas diam in arcu cursus
+    /// euismod quis viverra. Sagittis eu volutpat odio facilisis mauris sit amet. Posuere morbi
+    /// leo urna molestie at.
+    ///
+    /// Pretium aenean pharetra magna ac. Nisl condimentum id venenatis a condimentum vitae. Semper
+    /// quis lectus nulla at volutpat diam ut venenatis tellus. Egestas tellus rutrum tellus
+    /// pellentesque eu tincidunt tortor aliquam.
+    pub foobar: u32
+}

From 18c0369688d5854ea67dbe29cfac3cc8380cb20e Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Mon, 10 Jan 2022 20:45:27 -0500
Subject: [PATCH 154/195] Improve mod resolution error for mods with multiple
 candidate files

Fixes 5167

When ``a.rs`` and ``a/mod.rs`` are both present we would emit an error
message telling the user that the module couldn't be found. However,
this behavior is misleading because we're dealing with an ambiguous
module path, not a "file not found" error.

Is the file ``a.rs`` or is it ``a/mod.rs``? Rustfmt can't decide, and
the user needs to resolve this ambiguity themselves.

Now, the error message displayed to the user is in line with what they
would see if they went to compile their code with these conflicting
module names.
---
 src/modules.rs                                | 38 +++++++++++++---
 src/parse/session.rs                          |  3 ++
 tests/mod-resolver/issue-5167/src/a.rs        |  0
 tests/mod-resolver/issue-5167/src/a/mod.rs    |  0
 tests/mod-resolver/issue-5167/src/lib.rs      |  1 +
 .../bad_path_attribute/lib.rs                 |  3 ++
 .../module-not-found/relative_module/a.rs     |  2 +
 .../module-not-found/relative_module/lib.rs   |  1 +
 .../module-not-found/sibling_module/lib.rs    |  2 +
 tests/rustfmt/main.rs                         | 44 +++++++++++++++++++
 10 files changed, 88 insertions(+), 6 deletions(-)
 create mode 100644 tests/mod-resolver/issue-5167/src/a.rs
 create mode 100644 tests/mod-resolver/issue-5167/src/a/mod.rs
 create mode 100644 tests/mod-resolver/issue-5167/src/lib.rs
 create mode 100644 tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs
 create mode 100644 tests/mod-resolver/module-not-found/relative_module/a.rs
 create mode 100644 tests/mod-resolver/module-not-found/relative_module/lib.rs
 create mode 100644 tests/mod-resolver/module-not-found/sibling_module/lib.rs

diff --git a/src/modules.rs b/src/modules.rs
index 70b937b0283..49c99403974 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -81,6 +81,7 @@ pub struct ModuleResolutionError {
     pub(crate) kind: ModuleResolutionErrorKind,
 }
 
+/// Defines variants similar to those of [rustc_expand::module::ModError]
 #[derive(Debug, Error)]
 pub(crate) enum ModuleResolutionErrorKind {
     /// Find a file that cannot be parsed.
@@ -89,6 +90,12 @@ pub(crate) enum ModuleResolutionErrorKind {
     /// File cannot be found.
     #[error("{file} does not exist")]
     NotFound { file: PathBuf },
+    /// File a.rs and a/mod.rs both exist
+    #[error("file for module found at both {default_path:?} and {secondary_path:?}")]
+    MultipleCandidates {
+        default_path: PathBuf,
+        secondary_path: PathBuf,
+    },
 }
 
 #[derive(Clone)]
@@ -444,12 +451,31 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 }
                 Ok(Some(SubModKind::MultiExternal(mods_outside_ast)))
             }
-            Err(_) => Err(ModuleResolutionError {
-                module: mod_name.to_string(),
-                kind: ModuleResolutionErrorKind::NotFound {
-                    file: self.directory.path.clone(),
-                },
-            }),
+            Err(e) => match e {
+                ModError::FileNotFound(_, default_path, _secondary_path) => {
+                    Err(ModuleResolutionError {
+                        module: mod_name.to_string(),
+                        kind: ModuleResolutionErrorKind::NotFound { file: default_path },
+                    })
+                }
+                ModError::MultipleCandidates(_, default_path, secondary_path) => {
+                    Err(ModuleResolutionError {
+                        module: mod_name.to_string(),
+                        kind: ModuleResolutionErrorKind::MultipleCandidates {
+                            default_path,
+                            secondary_path,
+                        },
+                    })
+                }
+                ModError::ParserError(_)
+                | ModError::CircularInclusion(_)
+                | ModError::ModInBlock(_) => Err(ModuleResolutionError {
+                    module: mod_name.to_string(),
+                    kind: ModuleResolutionErrorKind::ParseError {
+                        file: self.directory.path.clone(),
+                    },
+                }),
+            },
         }
     }
 
diff --git a/src/parse/session.rs b/src/parse/session.rs
index fb9182152d1..87ab8fbf20a 100644
--- a/src/parse/session.rs
+++ b/src/parse/session.rs
@@ -163,8 +163,11 @@ impl ParseSess {
             |e| {
                 // If resloving a module relative to {dir_path}/{symbol} fails because a file
                 // could not be found, then try to resolve the module relative to {dir_path}.
+                // If we still can't find the module after searching for it in {dir_path},
+                // surface the original error.
                 if matches!(e, ModError::FileNotFound(..)) && relative.is_some() {
                     rustc_expand::module::default_submod_path(&self.parse_sess, id, None, dir_path)
+                        .map_err(|_| e)
                 } else {
                     Err(e)
                 }
diff --git a/tests/mod-resolver/issue-5167/src/a.rs b/tests/mod-resolver/issue-5167/src/a.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/mod-resolver/issue-5167/src/a/mod.rs b/tests/mod-resolver/issue-5167/src/a/mod.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/mod-resolver/issue-5167/src/lib.rs b/tests/mod-resolver/issue-5167/src/lib.rs
new file mode 100644
index 00000000000..f21af614da0
--- /dev/null
+++ b/tests/mod-resolver/issue-5167/src/lib.rs
@@ -0,0 +1 @@
+mod a;
diff --git a/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs b/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs
new file mode 100644
index 00000000000..2a63c961be8
--- /dev/null
+++ b/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs
@@ -0,0 +1,3 @@
+// module resolution fails because the path does not exist.
+#[path = "path/to/does_not_exist.rs"]
+mod a;
diff --git a/tests/mod-resolver/module-not-found/relative_module/a.rs b/tests/mod-resolver/module-not-found/relative_module/a.rs
new file mode 100644
index 00000000000..4a1eac8965d
--- /dev/null
+++ b/tests/mod-resolver/module-not-found/relative_module/a.rs
@@ -0,0 +1,2 @@
+// module resolution fails because `./a/b.rs` does not exist
+mod b;
diff --git a/tests/mod-resolver/module-not-found/relative_module/lib.rs b/tests/mod-resolver/module-not-found/relative_module/lib.rs
new file mode 100644
index 00000000000..f21af614da0
--- /dev/null
+++ b/tests/mod-resolver/module-not-found/relative_module/lib.rs
@@ -0,0 +1 @@
+mod a;
diff --git a/tests/mod-resolver/module-not-found/sibling_module/lib.rs b/tests/mod-resolver/module-not-found/sibling_module/lib.rs
new file mode 100644
index 00000000000..d9d9e1e3c90
--- /dev/null
+++ b/tests/mod-resolver/module-not-found/sibling_module/lib.rs
@@ -0,0 +1,2 @@
+// module resolution fails because `./a.rs` does not exist
+mod a;
diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 2262ae3aaac..450051d2fec 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -113,3 +113,47 @@ fn rustfmt_usage_text() {
     let (stdout, _) = rustfmt(&args);
     assert!(stdout.contains("Format Rust code\n\nusage: rustfmt [options] <file>..."));
 }
+
+#[test]
+fn mod_resolution_error_multiple_candidate_files() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5167
+    let default_path = Path::new("tests/mod-resolver/issue-5167/src/a.rs");
+    let secondary_path = Path::new("tests/mod-resolver/issue-5167/src/a/mod.rs");
+    let error_message = format!(
+        "file for module found at both {:?} and {:?}",
+        default_path.canonicalize().unwrap(),
+        secondary_path.canonicalize().unwrap(),
+    );
+
+    let args = ["tests/mod-resolver/issue-5167/src/lib.rs"];
+    let (_stdout, stderr) = rustfmt(&args);
+    assert!(stderr.contains(&error_message))
+}
+
+#[test]
+fn mod_resolution_error_sibling_module_not_found() {
+    let args = ["tests/mod-resolver/module-not-found/sibling_module/lib.rs"];
+    let (_stdout, stderr) = rustfmt(&args);
+    // Module resolution fails because we're unable to find `a.rs` in the same directory as lib.rs
+    assert!(stderr.contains("a.rs does not exist"))
+}
+
+#[test]
+fn mod_resolution_error_relative_module_not_found() {
+    let args = ["tests/mod-resolver/module-not-found/relative_module/lib.rs"];
+    let (_stdout, stderr) = rustfmt(&args);
+    // The file `./a.rs` and directory `./a` both exist.
+    // Module resolution fails becuase we're unable to find `./a/b.rs`
+    #[cfg(not(windows))]
+    assert!(stderr.contains("a/b.rs does not exist"));
+    #[cfg(windows)]
+    assert!(stderr.contains("a\\b.rs does not exist"));
+}
+
+#[test]
+fn mod_resolution_error_path_attribute_does_not_exist() {
+    let args = ["tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs"];
+    let (_stdout, stderr) = rustfmt(&args);
+    // The path attribute points to a file that does not exist
+    assert!(stderr.contains("does_not_exist.rs does not exist"));
+}

From b4de150dbc65a6bb95c86517430726c55251d0b0 Mon Sep 17 00:00:00 2001
From: Tom Milligan <tom@reinfer.io>
Date: Fri, 4 Mar 2022 18:13:08 +0000
Subject: [PATCH 155/195] fix: imports_granularity module with path containing
 self

---
 src/imports.rs                             | 50 ++++++++++++++++------
 tests/source/imports_granularity_module.rs |  1 +
 tests/target/imports_granularity_module.rs |  2 +
 3 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/src/imports.rs b/src/imports.rs
index c60bec6d4a2..02319809486 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -190,13 +190,17 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
             continue;
         }
 
-        for flattened in use_tree.flatten() {
+        for mut flattened in use_tree.flatten() {
             if let Some(tree) = result
                 .iter_mut()
                 .find(|tree| tree.share_prefix(&flattened, merge_by))
             {
                 tree.merge(&flattened, merge_by);
             } else {
+                // If this is the first tree with this prefix, handle potential trailing ::self
+                if merge_by == SharedPrefix::Module {
+                    flattened = flattened.nest_trailing_self();
+                }
                 result.push(flattened);
             }
         }
@@ -208,17 +212,7 @@ pub(crate) fn flatten_use_trees(use_trees: Vec<UseTree>) -> Vec<UseTree> {
     use_trees
         .into_iter()
         .flat_map(UseTree::flatten)
-        .map(|mut tree| {
-            // If a path ends in `::self`, rewrite it to `::{self}`.
-            if let Some(UseSegment::Slf(..)) = tree.path.last() {
-                let self_segment = tree.path.pop().unwrap();
-                tree.path.push(UseSegment::List(vec![UseTree::from_path(
-                    vec![self_segment],
-                    DUMMY_SP,
-                )]));
-            }
-            tree
-        })
+        .map(UseTree::nest_trailing_self)
         .collect()
 }
 
@@ -635,6 +629,18 @@ impl UseTree {
             self.span = self.span.to(other.span);
         }
     }
+
+    /// If this tree ends in `::self`, rewrite it to `::{self}`.
+    fn nest_trailing_self(mut self) -> UseTree {
+        if let Some(UseSegment::Slf(..)) = self.path.last() {
+            let self_segment = self.path.pop().unwrap();
+            self.path.push(UseSegment::List(vec![UseTree::from_path(
+                vec![self_segment],
+                DUMMY_SP,
+            )]));
+        }
+        self
+    }
 }
 
 fn merge_rest(
@@ -1311,4 +1317,24 @@ mod test {
                 < parse_use_tree("std::cmp::{b, e, g, f}").normalize()
         );
     }
+
+    #[test]
+    fn test_use_tree_nest_trailing_self() {
+        assert_eq!(
+            parse_use_tree("a::b::self").nest_trailing_self(),
+            parse_use_tree("a::b::{self}")
+        );
+        assert_eq!(
+            parse_use_tree("a::b::c").nest_trailing_self(),
+            parse_use_tree("a::b::c")
+        );
+        assert_eq!(
+            parse_use_tree("a::b::{c, d}").nest_trailing_self(),
+            parse_use_tree("a::b::{c, d}")
+        );
+        assert_eq!(
+            parse_use_tree("a::b::{self, c}").nest_trailing_self(),
+            parse_use_tree("a::b::{self, c}")
+        );
+    }
 }
diff --git a/tests/source/imports_granularity_module.rs b/tests/source/imports_granularity_module.rs
index 5a4fad5872b..2d7bb299aaa 100644
--- a/tests/source/imports_granularity_module.rs
+++ b/tests/source/imports_granularity_module.rs
@@ -4,6 +4,7 @@ use a::{b::c, d::e};
 use a::{f, g::{h, i}};
 use a::{j::{self, k::{self, l}, m}, n::{o::p, q}};
 pub use a::{r::s, t};
+use b::{c::d, self};
 
 #[cfg(test)]
 use foo::{a::b, c::d};
diff --git a/tests/target/imports_granularity_module.rs b/tests/target/imports_granularity_module.rs
index 9c1387c466a..e4e1a299e58 100644
--- a/tests/target/imports_granularity_module.rs
+++ b/tests/target/imports_granularity_module.rs
@@ -10,6 +10,8 @@ use a::n::o::p;
 use a::n::q;
 pub use a::r::s;
 pub use a::t;
+use b::c::d;
+use b::{self};
 
 use foo::e;
 #[cfg(test)]

From 9c65db61bee3f4f47a8d889ea781902283c5b5bd Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sat, 12 Mar 2022 01:14:38 -0500
Subject: [PATCH 156/195] Correct tracking issue link for `skip_children`

Update the issue link to point to issue 3389
---
 Configurations.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Configurations.md b/Configurations.md
index 2e2b0f7cfbe..ecec97dca52 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2206,7 +2206,7 @@ Don't reformat out of line modules
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: [#3389](https://github.com/rust-lang/rustfmt/issues/3386))
+- **Stable**: No (tracking issue: [#3389](https://github.com/rust-lang/rustfmt/issues/3389))
 
 ## `single_line_if_else_max_width`
 

From 5696e3859707d2abf12465e7bfbdcf2d9f42c8a2 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sat, 12 Mar 2022 01:16:08 -0500
Subject: [PATCH 157/195] Add test to verify tracking issue links

Now, tracking issue links are checked against the reference number
listed in the link text to ensure they match.
---
 src/test/configuration_snippet.rs | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs
index 92949ab576a..c8fda7c8556 100644
--- a/src/test/configuration_snippet.rs
+++ b/src/test/configuration_snippet.rs
@@ -290,3 +290,33 @@ fn get_code_blocks() -> Vec<ConfigCodeBlock> {
 
     code_blocks
 }
+
+#[test]
+fn check_unstable_option_tracking_issue_numbers() {
+    // Ensure that tracking issue links point to the correct issue number
+    let tracking_issue =
+        regex::Regex::new(r"\(tracking issue: \[#(?P<number>\d+)\]\((?P<link>\S+)\)\)")
+            .expect("failed creating configuration pattern");
+
+    let lines = BufReader::new(
+        fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME))
+            .unwrap_or_else(|_| panic!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)),
+    )
+    .lines()
+    .map(Result::unwrap)
+    .enumerate();
+
+    for (idx, line) in lines {
+        if let Some(capture) = tracking_issue.captures(&line) {
+            let number = capture.name("number").unwrap().as_str();
+            let link = capture.name("link").unwrap().as_str();
+            assert!(
+                link.ends_with(number),
+                "{} on line {} does not point to issue #{}",
+                link,
+                idx + 1,
+                number,
+            );
+        }
+    }
+}

From 1bb85bdf6b6dc0e205009b9f531a6220fe2031f9 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 9 Mar 2022 20:53:51 -0600
Subject: [PATCH 158/195] chore: add utility function for relative span
 positions

---
 src/parse/session.rs | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/parse/session.rs b/src/parse/session.rs
index 87ab8fbf20a..a95324bbb0e 100644
--- a/src/parse/session.rs
+++ b/src/parse/session.rs
@@ -218,6 +218,15 @@ impl ParseSess {
         self.parse_sess.source_map().lookup_char_pos(pos).line
     }
 
+    // TODO(calebcartwright): Preemptive, currently unused addition
+    // that will be used to support formatting scenarios that take original
+    // positions into account
+    /// Determines whether two byte positions are in the same source line.
+    #[allow(dead_code)]
+    pub(crate) fn byte_pos_same_line(&self, a: BytePos, b: BytePos) -> bool {
+        self.line_of_byte_pos(a) == self.line_of_byte_pos(b)
+    }
+
     pub(crate) fn span_to_debug_info(&self, span: Span) -> String {
         self.parse_sess.source_map().span_to_diagnostic_string(span)
     }

From 432b8dea64b84cec3efc3205bdc9e6687d59812d Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Wed, 16 Mar 2022 22:26:15 -0500
Subject: [PATCH 159/195] chore: bump toolchain

---
 Cargo.lock     | 4 ++--
 rust-toolchain | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2ef83ddd1ae..b932e15ef74 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -275,9 +275,9 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.9.0"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
 dependencies = [
  "either",
 ]
diff --git a/rust-toolchain b/rust-toolchain
index d8bf02aec85..0d407f11994 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-01-23"
+channel = "nightly-2022-03-17"
 components = ["rustc-dev"]

From e41329ce87409df929ecfa191297f944472cc999 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sun, 20 Mar 2022 13:21:44 -0400
Subject: [PATCH 160/195] Search for struct body span after any generic
 arguments

Fixes 5273

Previously, rustfmt searched for the start of a struct body after the
opening `{`. In most cases this works just fine, but const values can
also be defined between `{ }`, which lead to issues when rewriting the
struct body.

Now, rustfmt will search for the `{` after the generic argument list to
guarantee that the `{` it finds is the start of the struct body.
---
 src/items.rs               | 8 +++++++-
 tests/target/issue_5273.rs | 3 +++
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 tests/target/issue_5273.rs

diff --git a/src/items.rs b/src/items.rs
index 9b35d28f119..92f423bbb62 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1273,7 +1273,13 @@ pub(crate) fn format_struct_struct(
     result.push_str(&header_str);
 
     let header_hi = struct_parts.ident.span.hi();
-    let body_lo = context.snippet_provider.span_after(span, "{");
+    let body_lo = if let Some(generics) = struct_parts.generics {
+        // Adjust the span to start at the end of the generic arguments before searching for the '{'
+        let span = span.with_lo(generics.span.hi());
+        context.snippet_provider.span_after(span, "{")
+    } else {
+        context.snippet_provider.span_after(span, "{")
+    };
 
     let generics_str = match struct_parts.generics {
         Some(g) => format_generics(
diff --git a/tests/target/issue_5273.rs b/tests/target/issue_5273.rs
new file mode 100644
index 00000000000..3bb9048a5fd
--- /dev/null
+++ b/tests/target/issue_5273.rs
@@ -0,0 +1,3 @@
+struct Example<const N: usize = { 1048576 }> {
+    //
+}

From 0dba01aee15a45b8417c06df69e38af6956e03a8 Mon Sep 17 00:00:00 2001
From: 123vivekr <123vivekr@gmail.com>
Date: Sun, 13 Feb 2022 17:54:09 +0530
Subject: [PATCH 161/195] Add `short_item_threshold` config option

Allow custom short item threshold values via config
---
 Configurations.md                             | 34 +++++++++++++++++++
 src/config/mod.rs                             |  3 ++
 src/overflow.rs                               | 13 ++++---
 .../short_array_element_width_threshold/10.rs | 11 ++++++
 .../short_array_element_width_threshold/20.rs | 11 ++++++
 .../greater_than_max_width.rs                 | 12 +++++++
 .../short_array_element_width_threshold/10.rs | 11 ++++++
 .../short_array_element_width_threshold/20.rs |  8 +++++
 .../greater_than_max_width.rs                 | 12 +++++++
 9 files changed, 110 insertions(+), 5 deletions(-)
 create mode 100644 tests/source/configs/short_array_element_width_threshold/10.rs
 create mode 100644 tests/source/configs/short_array_element_width_threshold/20.rs
 create mode 100644 tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs
 create mode 100644 tests/target/configs/short_array_element_width_threshold/10.rs
 create mode 100644 tests/target/configs/short_array_element_width_threshold/20.rs
 create mode 100644 tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs

diff --git a/Configurations.md b/Configurations.md
index ecec97dca52..a47439b9ba9 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2200,6 +2200,40 @@ specific version of rustfmt is used in your CI, use this option.
 - **Possible values**: any published version (e.g. `"0.3.8"`)
 - **Stable**: No (tracking issue: [#3386](https://github.com/rust-lang/rustfmt/issues/3386))
 
+## `short_array_element_width_threshold`
+
+The width threshold for an array element to be considered "short".
+
+The layout of an array is dependent on the length of each of its elements. 
+If the length of every element in an array is below this threshold (all elements are "short") then the array can be formatted in the mixed/compressed style, but if any one element has a length that exceeds this threshold then the array elements will have to be formatted vertically.
+
+- **Default value**: `10`
+- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
+- **Stable**: Yes
+
+#### `10` (default):
+```rust
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
+```
+#### `20`:
+```rust
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
+```
+See also [`max_width`](#max_width).
+
 ## `skip_children`
 
 Don't reformat out of line modules
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 5041e1e36dd..18e1854612b 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -106,6 +106,8 @@ create_config! {
     // Misc.
     remove_nested_parens: bool, true, true, "Remove nested parens";
     combine_control_expr: bool, true, false, "Combine control expressions with function calls";
+    short_array_element_width_threshold: usize, 10, true,
+        "Width threshold for an array element to be considered short";
     overflow_delimited_expr: bool, false, false,
         "Allow trailing bracket/brace delimited expressions to overflow";
     struct_field_align_threshold: usize, 0, false,
@@ -591,6 +593,7 @@ spaces_around_ranges = false
 binop_separator = "Front"
 remove_nested_parens = true
 combine_control_expr = true
+short_array_element_width_threshold = 10
 overflow_delimited_expr = false
 struct_field_align_threshold = 0
 enum_discrim_align_threshold = 0
diff --git a/src/overflow.rs b/src/overflow.rs
index 3475f5c378c..80aed998d73 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -26,8 +26,6 @@ use crate::spanned::Spanned;
 use crate::types::{can_be_overflowed_type, SegmentParam};
 use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp};
 
-const SHORT_ITEM_THRESHOLD: usize = 10;
-
 /// A list of `format!`-like macros, that take a long format string and a list of arguments to
 /// format.
 ///
@@ -572,7 +570,12 @@ impl<'a> Context<'a> {
                             if one_line {
                                 tactic = DefinitiveListTactic::SpecialMacro(num_args_before);
                             };
-                        } else if is_every_expr_simple(&self.items) && no_long_items(list_items) {
+                        } else if is_every_expr_simple(&self.items)
+                            && no_long_items(
+                                list_items,
+                                self.context.config.short_array_element_width_threshold(),
+                            )
+                        {
                             tactic = DefinitiveListTactic::Mixed;
                         }
                     }
@@ -755,9 +758,9 @@ fn shape_from_indent_style(
     }
 }
 
-fn no_long_items(list: &[ListItem]) -> bool {
+fn no_long_items(list: &[ListItem], short_array_element_width_threshold: usize) -> bool {
     list.iter()
-        .all(|item| item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD)
+        .all(|item| item.inner_as_ref().len() <= short_array_element_width_threshold)
 }
 
 /// In case special-case style is required, returns an offset from which we start horizontal layout.
diff --git a/tests/source/configs/short_array_element_width_threshold/10.rs b/tests/source/configs/short_array_element_width_threshold/10.rs
new file mode 100644
index 00000000000..7d0d70919a6
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/10.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 10
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
\ No newline at end of file
diff --git a/tests/source/configs/short_array_element_width_threshold/20.rs b/tests/source/configs/short_array_element_width_threshold/20.rs
new file mode 100644
index 00000000000..8a93a51d6a2
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/20.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 20
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
\ No newline at end of file
diff --git a/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs b/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs
new file mode 100644
index 00000000000..710b6fe7c4b
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs
@@ -0,0 +1,12 @@
+// rustfmt-max_width: 20
+// rustfmt-short_array_element_width_threshold: 30
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/10.rs b/tests/target/configs/short_array_element_width_threshold/10.rs
new file mode 100644
index 00000000000..78c4adba1c1
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/10.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 10
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/20.rs b/tests/target/configs/short_array_element_width_threshold/20.rs
new file mode 100644
index 00000000000..6084690652f
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/20.rs
@@ -0,0 +1,8 @@
+// rustfmt-short_array_element_width_threshold: 20
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs b/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs
new file mode 100644
index 00000000000..710b6fe7c4b
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs
@@ -0,0 +1,12 @@
+// rustfmt-max_width: 20
+// rustfmt-short_array_element_width_threshold: 30
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}

From 8984438a6faf11e0cb8e876e80f177a42a43904d Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Fri, 18 Mar 2022 09:48:45 -0400
Subject: [PATCH 162/195] Honor `#[rustfmt::skip::attributes(derive)]`
 attribute

Fixes 5270

Previously, rustfmt only checked the `merge_derives` configuration value
to determine if it should merge_derives. This lead to derives being
merged even when annotated with the `rustfmt::skip` attribute.

Now, rustfmt also checks if derives are explicitly being skipped in the
current context via the `rustfmt::skip` attribute.
---
 src/attr.rs                                   |  6 +-
 tests/source/issue-5270/merge_derives_true.rs | 62 +++++++++++++++++++
 .../target/issue-5270/merge_derives_false.rs  | 62 +++++++++++++++++++
 tests/target/issue-5270/merge_derives_true.rs | 60 ++++++++++++++++++
 4 files changed, 189 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/issue-5270/merge_derives_true.rs
 create mode 100644 tests/target/issue-5270/merge_derives_false.rs
 create mode 100644 tests/target/issue-5270/merge_derives_true.rs

diff --git a/src/attr.rs b/src/attr.rs
index 3887a8051f2..befe12ae2c4 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -389,6 +389,10 @@ impl Rewrite for [ast::Attribute] {
         let mut attrs = self;
         let mut result = String::new();
 
+        // 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");
+
         // 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
         // merging derives into a single attribute.
@@ -431,7 +435,7 @@ impl Rewrite for [ast::Attribute] {
             }
 
             // Handle derives if we will merge them.
-            if context.config.merge_derives() && is_derive(&attrs[0]) {
+            if !skip_derives && context.config.merge_derives() && is_derive(&attrs[0]) {
                 let derives = take_while_with_pred(context, attrs, is_derive);
                 let derive_str = format_derive(derives, shape, context)?;
                 result.push_str(&derive_str);
diff --git a/tests/source/issue-5270/merge_derives_true.rs b/tests/source/issue-5270/merge_derives_true.rs
new file mode 100644
index 00000000000..b31bbf095e7
--- /dev/null
+++ b/tests/source/issue-5270/merge_derives_true.rs
@@ -0,0 +1,62 @@
+// rustfmt-merge_derives:true
+
+#[rustfmt::skip::attributes(derive)]
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+struct DoNotMergeDerives {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[rustfmt::skip::attributes(derive)]
+#[derive(Clone)]
+struct DoNotMergeDerivesSkipInMiddle {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+#[rustfmt::skip::attributes(derive)]
+struct DoNotMergeDerivesSkipAtEnd {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+struct MergeDerives {
+    field: String,
+}
+
+mod inner_attribute_derive_skip {
+    #![rustfmt::skip::attributes(derive)]
+
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+#[rustfmt::skip::attributes(derive)]
+mod outer_attribute_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+mod no_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct MergeDerives {
+        field: String,
+    }
+}
diff --git a/tests/target/issue-5270/merge_derives_false.rs b/tests/target/issue-5270/merge_derives_false.rs
new file mode 100644
index 00000000000..3b6f7e66993
--- /dev/null
+++ b/tests/target/issue-5270/merge_derives_false.rs
@@ -0,0 +1,62 @@
+// rustfmt-merge_derives:false
+
+#[rustfmt::skip::attributes(derive)]
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+struct DoNotMergeDerives {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[rustfmt::skip::attributes(derive)]
+#[derive(Clone)]
+struct DoNotMergeDerivesSkipInMiddle {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+#[rustfmt::skip::attributes(derive)]
+struct DoNotMergeDerivesSkipAtEnd {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+struct MergeDerives {
+    field: String,
+}
+
+mod inner_attribute_derive_skip {
+    #![rustfmt::skip::attributes(derive)]
+
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+#[rustfmt::skip::attributes(derive)]
+mod outer_attribute_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+mod no_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct MergeDerives {
+        field: String,
+    }
+}
diff --git a/tests/target/issue-5270/merge_derives_true.rs b/tests/target/issue-5270/merge_derives_true.rs
new file mode 100644
index 00000000000..5f488b4542d
--- /dev/null
+++ b/tests/target/issue-5270/merge_derives_true.rs
@@ -0,0 +1,60 @@
+// rustfmt-merge_derives:true
+
+#[rustfmt::skip::attributes(derive)]
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+struct DoNotMergeDerives {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[rustfmt::skip::attributes(derive)]
+#[derive(Clone)]
+struct DoNotMergeDerivesSkipInMiddle {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField)]
+#[derive(Clone)]
+#[rustfmt::skip::attributes(derive)]
+struct DoNotMergeDerivesSkipAtEnd {
+    field: String,
+}
+
+#[allow(dead_code)]
+#[derive(StructField, Clone)]
+struct MergeDerives {
+    field: String,
+}
+
+mod inner_attribute_derive_skip {
+    #![rustfmt::skip::attributes(derive)]
+
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+#[rustfmt::skip::attributes(derive)]
+mod outer_attribute_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField)]
+    #[derive(Clone)]
+    struct DoNotMergeDerives {
+        field: String,
+    }
+}
+
+mod no_derive_skip {
+    #[allow(dead_code)]
+    #[derive(StructField, Clone)]
+    struct MergeDerives {
+        field: String,
+    }
+}

From c2039d95c6fd5c27a90e768e79c630af374fcaf0 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 27 Mar 2022 20:46:25 -0500
Subject: [PATCH 163/195] chore: bump toolchain

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index 0d407f11994..94b57d506c2 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-03-17"
+channel = "nightly-2022-03-27"
 components = ["rustc-dev"]

From 4fecede7fdaeeb859b066394bf27401fd13743a7 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 28 Mar 2022 20:27:42 -0500
Subject: [PATCH 164/195] Revert "Use cargo-fmt in self_tests"

This reverts commit c63d42e80473a0c18714b55058f27506fd24955c.
---
 src/test/mod.rs | 46 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/test/mod.rs b/src/test/mod.rs
index 4191e3e96b0..ab966d4a360 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -375,21 +375,43 @@ fn idempotence_tests() {
     });
 }
 
+// Run rustfmt on itself. This operation must be idempotent. We also check that
+// no warnings are emitted.
+// Issue-3443: these tests require nightly
 #[nightly_only_test]
 #[test]
 fn self_tests() {
-    let get_exe_path = |name| {
-        let mut path = env::current_exe().unwrap();
-        path.pop();
-        path.set_file_name(format!("{name}{}", env::consts::EXE_SUFFIX));
-        path
-    };
-    let status = Command::new(get_exe_path("cargo-fmt"))
-        .args(["--check", "--all"])
-        .env("RUSTFMT", get_exe_path("rustfmt"))
-        .status()
-        .unwrap();
-    assert!(status.success());
+    init_log();
+    let mut files = get_test_files(Path::new("tests"), false);
+    let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"];
+    for dir in bin_directories {
+        let mut path = PathBuf::from("src");
+        path.push(dir);
+        path.push("main.rs");
+        files.push(path);
+    }
+    files.push(PathBuf::from("src/lib.rs"));
+
+    let (reports, count, fails) = check_files(files, &Some(PathBuf::from("rustfmt.toml")));
+    let mut warnings = 0;
+
+    // Display results.
+    println!("Ran {} self tests.", count);
+    assert_eq!(fails, 0, "{} self tests failed", fails);
+
+    for format_report in reports {
+        println!(
+            "{}",
+            FormatReportFormatterBuilder::new(&format_report).build()
+        );
+        warnings += format_report.warning_count();
+    }
+
+    assert_eq!(
+        warnings, 0,
+        "Rustfmt's code generated {} warnings",
+        warnings
+    );
 }
 
 #[test]

From e0c7b7d5d30d5b47f9d6a9fd3c449fc610a330b9 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Mon, 28 Mar 2022 20:29:05 -0500
Subject: [PATCH 165/195] tests: ignore cargo fmt test for rust-lang/rust runs

---
 tests/cargo-fmt/main.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs
index 3713552c66a..348876cd264 100644
--- a/tests/cargo-fmt/main.rs
+++ b/tests/cargo-fmt/main.rs
@@ -73,6 +73,7 @@ fn rustfmt_help() {
     assert_that!(&["--", "--help=config"], contains("Configuration Options:"));
 }
 
+#[ignore]
 #[test]
 fn cargo_fmt_out_of_line_test_modules() {
     // See also https://github.com/rust-lang/rustfmt/issues/5119

From 8e94761a94162f43e6c3e9bfbbc5005da3dbeea5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Tue, 29 Mar 2022 13:09:28 -0700
Subject: [PATCH 166/195] Add test of macro calls inside extern block

---
 tests/source/extern.rs | 13 +++++++++++++
 tests/target/extern.rs | 13 +++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/tests/source/extern.rs b/tests/source/extern.rs
index d0a033b1243..5b981385d2b 100644
--- a/tests/source/extern.rs
+++ b/tests/source/extern.rs
@@ -77,3 +77,16 @@ libc::c_long;
 extern {
 
 }
+
+macro_rules! x {
+    ($tt:tt) => {};
+}
+
+extern "macros" {
+    x!(ident);
+    // x!(#); FIXME
+    x![ident];
+    // x![#]; FIXME
+    x! {ident}
+    x! {#}
+}
diff --git a/tests/target/extern.rs b/tests/target/extern.rs
index 44ed6d4b475..570d21c17df 100644
--- a/tests/target/extern.rs
+++ b/tests/target/extern.rs
@@ -82,3 +82,16 @@ extern "C" {
 }
 
 extern "C" {}
+
+macro_rules! x {
+    ($tt:tt) => {};
+}
+
+extern "macros" {
+    x!(ident);
+    // x!(#); FIXME
+    x![ident];
+    // x![#]; FIXME
+    x! {ident}
+    x! {#}
+}

From 5ff7b632a95bac6955611d85040859128902c580 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Tue, 29 Mar 2022 12:59:07 -0700
Subject: [PATCH 167/195] Preserve semicolon after macro call inside foreign
 mod

---
 src/macros.rs          | 14 ++++++++++++--
 tests/source/extern.rs |  4 ++--
 tests/target/extern.rs |  4 ++--
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/macros.rs b/src/macros.rs
index fdbe3374615..664f152e8be 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -112,6 +112,7 @@ fn rewrite_macro_name(
 fn return_macro_parse_failure_fallback(
     context: &RewriteContext<'_>,
     indent: Indent,
+    position: MacroPosition,
     span: Span,
 ) -> Option<String> {
     // Mark this as a failure however we format it
@@ -140,7 +141,11 @@ fn return_macro_parse_failure_fallback(
     ));
 
     // Return the snippet unmodified if the macro is not block-like
-    Some(context.snippet(span).to_owned())
+    let mut snippet = context.snippet(span).to_owned();
+    if position == MacroPosition::Item {
+        snippet.push(';');
+    }
+    Some(snippet)
 }
 
 pub(crate) fn rewrite_macro(
@@ -233,7 +238,12 @@ fn rewrite_macro_inner(
     } = match parse_macro_args(context, ts, style, is_forced_bracket) {
         Some(args) => args,
         None => {
-            return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
+            return return_macro_parse_failure_fallback(
+                context,
+                shape.indent,
+                position,
+                mac.span(),
+            );
         }
     };
 
diff --git a/tests/source/extern.rs b/tests/source/extern.rs
index 5b981385d2b..f51ba6e98c9 100644
--- a/tests/source/extern.rs
+++ b/tests/source/extern.rs
@@ -84,9 +84,9 @@ macro_rules! x {
 
 extern "macros" {
     x!(ident);
-    // x!(#); FIXME
+    x!(#);
     x![ident];
-    // x![#]; FIXME
+    x![#];
     x! {ident}
     x! {#}
 }
diff --git a/tests/target/extern.rs b/tests/target/extern.rs
index 570d21c17df..d1741360cfd 100644
--- a/tests/target/extern.rs
+++ b/tests/target/extern.rs
@@ -89,9 +89,9 @@ macro_rules! x {
 
 extern "macros" {
     x!(ident);
-    // x!(#); FIXME
+    x!(#);
     x![ident];
-    // x![#]; FIXME
+    x![#];
     x! {ident}
     x! {#}
 }

From 1dcdfb276d8a10470ce1c6a6fd20a6104c313d82 Mon Sep 17 00:00:00 2001
From: Tharun Rajendran <rajendrantharun@live.com>
Date: Sat, 2 Apr 2022 05:30:53 +0530
Subject: [PATCH 168/195] fix(rustfmt): fix struct field formatting with doc
 comments present (#5217)

* fix(rustfmt): fix struct field formatting with doc comments present

Fixes #5215

* fix review feedbacks

* add unit test without doc comment

* move tests to a seperate file

* add additional test cases

* reintroduce a newline at the of test/souce/structs.rs
---
 src/items.rs                             |  2 +-
 tests/source/struct_field_doc_comment.rs | 72 ++++++++++++++++++++++++
 tests/target/struct_field_doc_comment.rs | 69 +++++++++++++++++++++++
 3 files changed, 142 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/struct_field_doc_comment.rs
 create mode 100644 tests/target/struct_field_doc_comment.rs

diff --git a/src/items.rs b/src/items.rs
index 92f423bbb62..79f6ff69aa9 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1771,7 +1771,7 @@ pub(crate) fn rewrite_struct_field(
         .offset_left(overhead + spacing.len())
         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
     if let Some(ref ty) = orig_ty {
-        if !ty.contains('\n') {
+        if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) {
             return Some(attr_prefix + &spacing + ty);
         }
     }
diff --git a/tests/source/struct_field_doc_comment.rs b/tests/source/struct_field_doc_comment.rs
new file mode 100644
index 00000000000..191a6210045
--- /dev/null
+++ b/tests/source/struct_field_doc_comment.rs
@@ -0,0 +1,72 @@
+// #5215
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */ u32,
+    /// Doc Comments
+    // TODO note
+    u64,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    u64,
+    #[cfg(not(unix))] /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)]
+    // some comment
+    u64,
+    #[cfg(not(unix))]
+    /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    pub u64,
+    #[cfg(not(unix))] /*block comment */
+    pub(crate) u32,
+);
+
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) u64,
+);
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    a: u64,
+    #[cfg(not(unix))] /*block comment */
+    b: u32,
+}
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    pub a: u64,
+    #[cfg(not(unix))] /*block comment */
+    pub(crate) b: u32,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    a: u32,
+    /// Doc Comments
+    // TODO note
+    b: u64,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub a: u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) b: u64,
+}
diff --git a/tests/target/struct_field_doc_comment.rs b/tests/target/struct_field_doc_comment.rs
new file mode 100644
index 00000000000..ebb01a668f4
--- /dev/null
+++ b/tests/target/struct_field_doc_comment.rs
@@ -0,0 +1,69 @@
+// #5215
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    u32,
+    /// Doc Comments
+    // TODO note
+    u64,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    u64,
+    #[cfg(not(unix))] /*block comment */ u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)]
+    // some comment
+    u64,
+    #[cfg(not(unix))]
+    /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    pub  u64,
+    #[cfg(not(unix))] /*block comment */ pub(crate)  u32,
+);
+
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub  u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate)  u64,
+);
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    a: u64,
+    #[cfg(not(unix))] /*block comment */ b: u32,
+}
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    pub a: u64,
+    #[cfg(not(unix))] /*block comment */ pub(crate) b: u32,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    a: u32,
+    /// Doc Comments
+    // TODO note
+    b: u64,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub a: u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) b: u64,
+}

From 7d6ca7c35c275ab7a6a50d290babe874cb8e3fc7 Mon Sep 17 00:00:00 2001
From: Light Ning <light4@users.noreply.github.com>
Date: Sat, 2 Apr 2022 23:45:38 +0800
Subject: [PATCH 169/195] Bump deps (#5237)

* bump deps

* sort the deps
---
 Cargo.lock | 338 +++++++++++++++++++++++++++--------------------------
 Cargo.toml |  41 +++----
 2 files changed, 194 insertions(+), 185 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b932e15ef74..1b444136585 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,64 +4,60 @@ version = 3
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.6"
+version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "annotate-snippets"
-version = "0.8.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
+checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"
 dependencies = [
+ "unicode-width",
  "yansi-term",
 ]
 
 [[package]]
 name = "ansi_term"
-version = "0.11.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
 dependencies = [
  "winapi",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.25"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
+checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
 
 [[package]]
 name = "atty"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
+ "hermit-abi",
  "libc",
  "winapi",
 ]
 
-[[package]]
-name = "autocfg"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
 [[package]]
 name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bstr"
-version = "0.2.8"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
 dependencies = [
  "memchr",
 ]
@@ -77,27 +73,27 @@ dependencies = [
 
 [[package]]
 name = "camino"
-version = "1.0.5"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
+checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7"
+checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cargo_metadata"
-version = "0.14.0"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
+checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
 dependencies = [
  "camino",
  "cargo-platform",
@@ -106,12 +102,6 @@ dependencies = [
  "serde_json",
 ]
 
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -120,9 +110,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clap"
-version = "2.33.0"
+version = "2.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
 dependencies = [
  "ansi_term",
  "atty",
@@ -135,20 +125,19 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.3"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
 dependencies = [
- "autocfg",
- "cfg-if 1.0.0",
+ "cfg-if",
  "lazy_static",
 ]
 
 [[package]]
 name = "derive-new"
-version = "0.5.8"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
+checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -157,25 +146,45 @@ dependencies = [
 
 [[package]]
 name = "diff"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
+checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
 
 [[package]]
 name = "dirs"
-version = "2.0.2"
+version = "4.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
 dependencies = [
- "cfg-if 0.1.10",
  "dirs-sys",
 ]
 
 [[package]]
-name = "dirs-sys"
-version = "0.3.6"
+name = "dirs-next"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
 dependencies = [
  "libc",
  "redox_users",
@@ -184,15 +193,15 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.5.3"
+version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
 [[package]]
 name = "env_logger"
-version = "0.8.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
 dependencies = [
  "atty",
  "humantime",
@@ -203,9 +212,9 @@ dependencies = [
 
 [[package]]
 name = "fnv"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "getopts"
@@ -218,20 +227,20 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.3"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "wasi",
 ]
 
 [[package]]
 name = "globset"
-version = "0.4.6"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
+checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -242,13 +251,22 @@ dependencies = [
 
 [[package]]
 name = "heck"
-version = "0.3.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
 dependencies = [
  "unicode-segmentation",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "humantime"
 version = "2.1.0"
@@ -257,9 +275,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "ignore"
-version = "0.4.17"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
+checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
 dependencies = [
  "crossbeam-utils",
  "globset",
@@ -284,9 +302,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "0.4.4"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
 
 [[package]]
 name = "lazy_static"
@@ -296,9 +314,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.77"
+version = "0.2.121"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
+checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
 
 [[package]]
 name = "libm"
@@ -308,34 +326,40 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
 name = "memchr"
-version = "2.2.1"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "once_cell"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
 
 [[package]]
 name = "packed_simd_2"
-version = "0.3.4"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
+checksum = "defdcfef86dcc44ad208f71d9ff4ce28df6537a4e0d6b0e8e845cb8ca10059a6"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "libm",
 ]
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.11"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -346,71 +370,69 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.11"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
- "syn-mid",
  "version_check",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.6"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
+checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.4"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "redox_users"
-version = "0.4.0"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
  "getrandom",
  "redox_syscall",
+ "thiserror",
 ]
 
 [[package]]
 name = "regex"
-version = "1.4.3"
+version = "1.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
 dependencies = [
  "aho-corasick",
  "memchr",
  "regex-syntax",
- "thread_local",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.22"
+version = "0.6.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 [[package]]
 name = "rustc-workspace-hack"
@@ -459,43 +481,49 @@ dependencies = [
 ]
 
 [[package]]
-name = "ryu"
-version = "1.0.2"
+name = "rustversion"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
+[[package]]
+name = "ryu"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
 
 [[package]]
 name = "same-file"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
 dependencies = [
  "winapi-util",
 ]
 
 [[package]]
 name = "semver"
-version = "1.0.4"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.126"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.126"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -504,9 +532,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.59"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
 dependencies = [
  "itoa",
  "ryu",
@@ -521,9 +549,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.11"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
+checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
 dependencies = [
  "clap",
  "lazy_static",
@@ -532,9 +560,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.4"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -545,43 +573,33 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.65"
+version = "1.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
+checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-xid",
 ]
 
-[[package]]
-name = "syn-mid"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "term"
-version = "0.6.1"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
+checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
 dependencies = [
- "dirs",
+ "dirs-next",
+ "rustversion",
  "winapi",
 ]
 
 [[package]]
 name = "termcolor"
-version = "1.0.5"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
 dependencies = [
- "wincolor",
+ "winapi-util",
 ]
 
 [[package]]
@@ -595,18 +613,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.6"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6b305ec0e323c7b6cfff6098a22516e0063d0bb7c3d88660a890217dca099a"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.6"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45ba8d810d9c48fc456b7ad54574e8bfb7c7918a57ad7a6e6a0985d7959e8597"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -615,39 +633,39 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.0.1"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
 dependencies = [
- "lazy_static",
+ "once_cell",
 ]
 
 [[package]]
 name = "toml"
-version = "0.5.3"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.3.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.6"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
 
 [[package]]
 name = "unicode-xid"
-version = "0.2.0"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 
 [[package]]
 name = "unicode_categories"
@@ -657,21 +675,21 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
 
 [[package]]
 name = "vec_map"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
 [[package]]
 name = "version_check"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "walkdir"
-version = "2.2.9"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
 dependencies = [
  "same-file",
  "winapi",
@@ -686,9 +704,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
 
 [[package]]
 name = "winapi"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
 dependencies = [
  "winapi-i686-pc-windows-gnu",
  "winapi-x86_64-pc-windows-gnu",
@@ -702,9 +720,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.2"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
 dependencies = [
  "winapi",
 ]
@@ -715,16 +733,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "wincolor"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
-dependencies = [
- "winapi",
- "winapi-util",
-]
-
 [[package]]
 name = "yansi-term"
 version = "0.1.2"
diff --git a/Cargo.toml b/Cargo.toml
index 764714638a9..4325f46db9f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,30 +33,31 @@ rustfmt-format-diff = []
 generic-simd = ["bytecount/generic-simd"]
 
 [dependencies]
-itertools = "0.10.1"
-toml = "0.5"
+annotate-snippets = { version = "0.9", features = ["color"] }
+anyhow = "1.0"
+bytecount = "0.6"
+cargo_metadata = "0.14"
+derive-new = "0.5"
+diff = "0.1"
+dirs = "4.0"
+env_logger = "0.9"
+getopts = "0.2"
+ignore = "0.4"
+itertools = "0.10"
+lazy_static = "1.4"
+log = "0.4"
+regex = "1.5"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-unicode-segmentation = "1.0.0"
-regex = "1.0"
-term = "0.6"
-diff = "0.1"
-log = "0.4.14"
-env_logger = "0.8"
-getopts = "0.2"
-derive-new = "0.5"
-cargo_metadata = "0.14"
-bytecount = "0.6"
-unicode-width = "0.1.5"
-unicode_categories = "0.1.1"
-dirs = "2.0.1"
-ignore = "0.4.17"
-annotate-snippets = { version = "0.8", features = ["color"] }
 structopt = "0.3"
-rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
-lazy_static = "1.0.0"
-anyhow = "1.0"
+term = "0.7"
 thiserror = "1.0"
+toml = "0.5"
+unicode-segmentation = "1.9"
+unicode-width = "0.1"
+unicode_categories = "0.1"
+
+rustfmt-config_proc_macro = { version = "0.2", 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`

From 91995b6142faf1a5e56e1b7b1cb922504726197c Mon Sep 17 00:00:00 2001
From: Expyron <5100376+Expyron@users.noreply.github.com>
Date: Thu, 7 Apr 2022 09:57:58 +0200
Subject: [PATCH 170/195] Replace `structopt` dependency by `clap`

---
 Cargo.lock                | 129 +++++++++++++++++++-------------------
 Cargo.toml                |   2 +-
 src/cargo-fmt/main.rs     |  33 +++++-----
 src/cargo-fmt/test/mod.rs |  42 +++++++------
 src/format-diff/main.rs   |  45 ++++++-------
 5 files changed, 131 insertions(+), 120 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1b444136585..4eaaee74cf9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -21,15 +21,6 @@ dependencies = [
  "yansi-term",
 ]
 
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "anyhow"
 version = "1.0.56"
@@ -47,6 +38,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
 [[package]]
 name = "bitflags"
 version = "1.3.2"
@@ -110,17 +107,32 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clap"
-version = "2.34.0"
+version = "3.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
 dependencies = [
- "ansi_term",
  "atty",
  "bitflags",
+ "clap_derive",
+ "indexmap",
+ "lazy_static",
+ "os_str_bytes",
  "strsim",
+ "termcolor",
  "textwrap",
- "unicode-width",
- "vec_map",
+]
+
+[[package]]
+name = "clap_derive"
+version = "3.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -250,13 +262,16 @@ dependencies = [
 ]
 
 [[package]]
-name = "heck"
-version = "0.3.3"
+name = "hashbrown"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
-dependencies = [
- "unicode-segmentation",
-]
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
 
 [[package]]
 name = "hermit-abi"
@@ -291,6 +306,16 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "indexmap"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
 [[package]]
 name = "itertools"
 version = "0.10.3"
@@ -314,9 +339,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.121"
+version = "0.2.122"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
+checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
 
 [[package]]
 name = "libm"
@@ -345,6 +370,15 @@ version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
 
+[[package]]
+name = "os_str_bytes"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "packed_simd_2"
 version = "0.3.7"
@@ -381,9 +415,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.36"
+version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
 dependencies = [
  "unicode-xid",
 ]
@@ -457,6 +491,7 @@ dependencies = [
  "anyhow",
  "bytecount",
  "cargo_metadata",
+ "clap",
  "derive-new",
  "diff",
  "dirs",
@@ -471,7 +506,6 @@ dependencies = [
  "rustfmt-config_proc_macro",
  "serde",
  "serde_json",
- "structopt",
  "term",
  "thiserror",
  "toml",
@@ -543,39 +577,15 @@ dependencies = [
 
 [[package]]
 name = "strsim"
-version = "0.8.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "structopt"
-version = "0.3.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
-version = "1.0.90"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
+checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -604,12 +614,9 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.11.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
 
 [[package]]
 name = "thiserror"
@@ -673,12 +680,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
 
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
 [[package]]
 name = "version_check"
 version = "0.9.4"
diff --git a/Cargo.toml b/Cargo.toml
index 4325f46db9f..0be9723bc4d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,6 +37,7 @@ annotate-snippets = { version = "0.9", features = ["color"] }
 anyhow = "1.0"
 bytecount = "0.6"
 cargo_metadata = "0.14"
+clap = { version = "3.1", features = ["derive"] }
 derive-new = "0.5"
 diff = "0.1"
 dirs = "4.0"
@@ -49,7 +50,6 @@ log = "0.4"
 regex = "1.5"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-structopt = "0.3"
 term = "0.7"
 thiserror = "1.0"
 toml = "0.5"
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 8cb7b4585ec..3542536f29b 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -15,54 +15,59 @@ use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
-use structopt::StructOpt;
+use clap::{CommandFactory, Parser};
 
 #[path = "test/mod.rs"]
 #[cfg(test)]
 mod cargo_fmt_tests;
 
-#[derive(StructOpt, Debug)]
-#[structopt(
+#[derive(Parser)]
+#[clap(
     bin_name = "cargo fmt",
     about = "This utility formats all bin and lib files of \
              the current crate using rustfmt."
 )]
 pub struct Opts {
     /// No output printed to stdout
-    #[structopt(short = "q", long = "quiet")]
+    #[clap(short = 'q', long = "quiet")]
     quiet: bool,
 
     /// Use verbose output
-    #[structopt(short = "v", long = "verbose")]
+    #[clap(short = 'v', long = "verbose")]
     verbose: bool,
 
     /// Print rustfmt version and exit
-    #[structopt(long = "version")]
+    #[clap(long = "version")]
     version: bool,
 
     /// Specify package to format
-    #[structopt(short = "p", long = "package", value_name = "package")]
+    #[clap(
+        short = 'p',
+        long = "package",
+        value_name = "package",
+        multiple_values = true
+    )]
     packages: Vec<String>,
 
     /// Specify path to Cargo.toml
-    #[structopt(long = "manifest-path", value_name = "manifest-path")]
+    #[clap(long = "manifest-path", value_name = "manifest-path")]
     manifest_path: Option<String>,
 
     /// Specify message-format: short|json|human
-    #[structopt(long = "message-format", value_name = "message-format")]
+    #[clap(long = "message-format", value_name = "message-format")]
     message_format: Option<String>,
 
     /// Options passed to rustfmt
     // 'raw = true' to make `--` explicit.
-    #[structopt(name = "rustfmt_options", raw(true))]
+    #[clap(name = "rustfmt_options", raw(true))]
     rustfmt_options: Vec<String>,
 
     /// Format all packages, and also their local path-based dependencies
-    #[structopt(long = "all")]
+    #[clap(long = "all")]
     format_all: bool,
 
     /// Run rustfmt in check mode
-    #[structopt(long = "check")]
+    #[clap(long = "check")]
     check: bool,
 }
 
@@ -87,7 +92,7 @@ fn execute() -> i32 {
         }
     });
 
-    let opts = Opts::from_iter(args);
+    let opts = Opts::parse_from(args);
 
     let verbosity = match (opts.verbose, opts.quiet) {
         (false, false) => Verbosity::Normal,
@@ -204,7 +209,7 @@ fn convert_message_format_to_rustfmt_args(
 
 fn print_usage_to_stderr(reason: &str) {
     eprintln!("{}", reason);
-    let app = Opts::clap();
+    let app = Opts::command();
     app.after_help("")
         .write_help(&mut io::stderr())
         .expect("failed to write to stderr");
diff --git a/src/cargo-fmt/test/mod.rs b/src/cargo-fmt/test/mod.rs
index 360503632c7..56e52fbabb6 100644
--- a/src/cargo-fmt/test/mod.rs
+++ b/src/cargo-fmt/test/mod.rs
@@ -6,7 +6,7 @@ mod targets;
 #[test]
 fn default_options() {
     let empty: Vec<String> = vec![];
-    let o = Opts::from_iter(&empty);
+    let o = Opts::parse_from(&empty);
     assert_eq!(false, o.quiet);
     assert_eq!(false, o.verbose);
     assert_eq!(false, o.version);
@@ -20,7 +20,7 @@ fn default_options() {
 
 #[test]
 fn good_options() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "-q",
         "-p",
@@ -47,8 +47,8 @@ fn good_options() {
 #[test]
 fn unexpected_option() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "unexpected"])
+        Opts::command()
+            .try_get_matches_from(&["test", "unexpected"])
             .is_err()
     );
 }
@@ -56,8 +56,8 @@ fn unexpected_option() {
 #[test]
 fn unexpected_flag() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "--flag"])
+        Opts::command()
+            .try_get_matches_from(&["test", "--flag"])
             .is_err()
     );
 }
@@ -65,20 +65,20 @@ fn unexpected_flag() {
 #[test]
 fn mandatory_separator() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "--emit"])
+        Opts::command()
+            .try_get_matches_from(&["test", "--emit"])
             .is_err()
     );
     assert!(
-        !Opts::clap()
-            .get_matches_from_safe(&["test", "--", "--emit"])
+        !Opts::command()
+            .try_get_matches_from(&["test", "--", "--emit"])
             .is_err()
     );
 }
 
 #[test]
 fn multiple_packages_one_by_one() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "-p",
         "package1",
@@ -92,7 +92,7 @@ fn multiple_packages_one_by_one() {
 
 #[test]
 fn multiple_packages_grouped() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "--package",
         "package1",
@@ -106,14 +106,18 @@ fn multiple_packages_grouped() {
 
 #[test]
 fn empty_packages_1() {
-    assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err());
+    assert!(
+        Opts::command()
+            .try_get_matches_from(&["test", "-p"])
+            .is_err()
+    );
 }
 
 #[test]
 fn empty_packages_2() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--", "--check"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--", "--check"])
             .is_err()
     );
 }
@@ -121,8 +125,8 @@ fn empty_packages_2() {
 #[test]
 fn empty_packages_3() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--verbose"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--verbose"])
             .is_err()
     );
 }
@@ -130,8 +134,8 @@ fn empty_packages_3() {
 #[test]
 fn empty_packages_4() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--check"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--check"])
             .is_err()
     );
 }
diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs
index 655aeda42bf..f6b739e1c2a 100644
--- a/src/format-diff/main.rs
+++ b/src/format-diff/main.rs
@@ -19,8 +19,7 @@ use std::process;
 
 use regex::Regex;
 
-use structopt::clap::AppSettings;
-use structopt::StructOpt;
+use clap::{CommandFactory, Parser};
 
 /// The default pattern of files to format.
 ///
@@ -37,16 +36,16 @@ enum FormatDiffError {
     IoError(#[from] io::Error),
 }
 
-#[derive(StructOpt, Debug)]
-#[structopt(
+#[derive(Parser, Debug)]
+#[clap(
     name = "rustfmt-format-diff",
-    setting = AppSettings::DisableVersion,
-    setting = AppSettings::NextLineHelp
+    disable_version_flag = true,
+    next_line_help = true
 )]
 pub struct Opts {
     /// Skip the smallest prefix containing NUMBER slashes
-    #[structopt(
-        short = "p",
+    #[clap(
+        short = 'p',
         long = "skip-prefix",
         value_name = "NUMBER",
         default_value = "0"
@@ -54,8 +53,8 @@ pub struct Opts {
     skip_prefix: u32,
 
     /// Custom pattern selecting file paths to reformat
-    #[structopt(
-        short = "f",
+    #[clap(
+        short = 'f',
         long = "filter",
         value_name = "PATTERN",
         default_value = DEFAULT_PATTERN
@@ -65,10 +64,12 @@ pub struct Opts {
 
 fn main() {
     env_logger::Builder::from_env("RUSTFMT_LOG").init();
-    let opts = Opts::from_args();
+    let opts = Opts::parse();
     if let Err(e) = run(opts) {
         println!("{}", e);
-        Opts::clap().print_help().expect("cannot write to stdout");
+        Opts::command()
+            .print_help()
+            .expect("cannot write to stdout");
         process::exit(1);
     }
 }
@@ -230,14 +231,14 @@ mod cmd_line_tests {
     #[test]
     fn default_options() {
         let empty: Vec<String> = vec![];
-        let o = Opts::from_iter(&empty);
+        let o = Opts::parse_from(&empty);
         assert_eq!(DEFAULT_PATTERN, o.filter);
         assert_eq!(0, o.skip_prefix);
     }
 
     #[test]
     fn good_options() {
-        let o = Opts::from_iter(&["test", "-p", "10", "-f", r".*\.hs"]);
+        let o = Opts::parse_from(&["test", "-p", "10", "-f", r".*\.hs"]);
         assert_eq!(r".*\.hs", o.filter);
         assert_eq!(10, o.skip_prefix);
     }
@@ -245,8 +246,8 @@ mod cmd_line_tests {
     #[test]
     fn unexpected_option() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "unexpected"])
+            Opts::command()
+                .try_get_matches_from(&["test", "unexpected"])
                 .is_err()
         );
     }
@@ -254,8 +255,8 @@ mod cmd_line_tests {
     #[test]
     fn unexpected_flag() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "--flag"])
+            Opts::command()
+                .try_get_matches_from(&["test", "--flag"])
                 .is_err()
         );
     }
@@ -263,8 +264,8 @@ mod cmd_line_tests {
     #[test]
     fn overridden_option() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "10", "-p", "20"])
+            Opts::command()
+                .try_get_matches_from(&["test", "-p", "10", "-p", "20"])
                 .is_err()
         );
     }
@@ -272,8 +273,8 @@ mod cmd_line_tests {
     #[test]
     fn negative_filter() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "-1"])
+            Opts::command()
+                .try_get_matches_from(&["test", "-p", "-1"])
                 .is_err()
         );
     }

From 2d9bc460108df4e3587be82e36a58f2fb3f4813f Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <calebcartwright@users.noreply.github.com>
Date: Tue, 14 Jul 2020 00:03:13 -0500
Subject: [PATCH 171/195] Backport 4326

refactor: rename some private whitelist names
---
 src/overflow.rs | 12 ++++++------
 src/test/mod.rs |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/overflow.rs b/src/overflow.rs
index 80aed998d73..c296961d1f0 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -32,7 +32,7 @@ use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_wid
 /// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of
 /// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result,
 /// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`).
-const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[
+const SPECIAL_CASE_MACROS: &[(&str, usize)] = &[
     // format! like macros
     // From the Rust Standard Library.
     ("eprint!", 0),
@@ -60,7 +60,7 @@ const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[
     ("debug_assert_ne!", 2),
 ];
 
-const SPECIAL_ATTR_WHITELIST: &[(&str, usize)] = &[
+const SPECIAL_CASE_ATTR: &[(&str, usize)] = &[
     // From the `failure` crate.
     ("fail", 0),
 ];
@@ -182,10 +182,10 @@ impl<'a> OverflowableItem<'a> {
         }
     }
 
-    fn whitelist(&self) -> &'static [(&'static str, usize)] {
+    fn special_cases(&self) -> &'static [(&'static str, usize)] {
         match self {
-            OverflowableItem::MacroArg(..) => SPECIAL_MACRO_WHITELIST,
-            OverflowableItem::NestedMetaItem(..) => SPECIAL_ATTR_WHITELIST,
+            OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS,
+            OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR,
             _ => &[],
         }
     }
@@ -770,7 +770,7 @@ pub(crate) fn maybe_get_args_offset(
 ) -> Option<(bool, usize)> {
     if let Some(&(_, num_args_before)) = args
         .get(0)?
-        .whitelist()
+        .special_cases()
         .iter()
         .find(|&&(s, _)| s == callee_str)
     {
diff --git a/src/test/mod.rs b/src/test/mod.rs
index ab966d4a360..4bad8e71481 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -24,7 +24,7 @@ mod parser;
 const DIFF_CONTEXT_SIZE: usize = 3;
 
 // A list of files on which we want to skip testing.
-const SKIP_FILE_WHITE_LIST: &[&str] = &[
+const FILE_SKIP_LIST: &[&str] = &[
     // We want to make sure that the `skip_children` is correctly working,
     // so we do not want to test this file directly.
     "configs/skip_children/foo/mod.rs",
@@ -90,7 +90,7 @@ where
 }
 
 fn is_file_skip(path: &Path) -> bool {
-    SKIP_FILE_WHITE_LIST
+    FILE_SKIP_LIST
         .iter()
         .any(|file_path| is_subpath(path, file_path))
 }

From 4f3f87fb9a629db8bf0c6e04604320cd028f79e8 Mon Sep 17 00:00:00 2001
From: Tom Milligan <tom@reinfer.io>
Date: Sat, 5 Mar 2022 23:01:43 +0000
Subject: [PATCH 172/195] group_imports: test and document non-consecutive
 imports

---
 Configurations.md                             |  6 ++++-
 .../StdExternalCrate-non_consecutive.rs       | 27 +++++++++++++++++++
 .../StdExternalCrate-non_consecutive.rs       | 18 +++++++++++++
 3 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs
 create mode 100644 tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs

diff --git a/Configurations.md b/Configurations.md
index a47439b9ba9..dc8d38267a8 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2061,12 +2061,16 @@ use sit;
 
 ## `group_imports`
 
-Controls the strategy for how imports are grouped together.
+Controls the strategy for how consecutive imports are grouped together.
+
+Controls the strategy for grouping sets of consecutive imports. Imports may contain newlines between imports and still be grouped together as a single set, but other statements between imports will result in different grouping sets.
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `StdExternalCrate`, `One`
 - **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083))
 
+Each set of imports (one or more `use` statements, optionally separated by newlines) will be formatted independently. Other statements such as `mod ...` or `extern crate ...` will cause imports to not be grouped together.
+
 #### `Preserve` (default):
 
 Preserve the source file's import groups.
diff --git a/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs b/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs
new file mode 100644
index 00000000000..f239a0efa08
--- /dev/null
+++ b/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs
@@ -0,0 +1,27 @@
+// rustfmt-group_imports: StdExternalCrate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+
+
+
+
+use juniper::{FieldError, FieldResult};
+
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+extern crate uuid;
+
+
+
+
+
+use std::sync::Arc;
+
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs b/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs
new file mode 100644
index 00000000000..ecc8ede02cc
--- /dev/null
+++ b/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs
@@ -0,0 +1,18 @@
+// rustfmt-group_imports: StdExternalCrate
+use alloc::alloc::Layout;
+
+use chrono::Utc;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+
+use super::update::convert_publish_payload;
+
+extern crate uuid;
+
+use core::f32;
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use crate::models::Event;

From ba0351a1460e1e415293aa5e2b347b83e933703f Mon Sep 17 00:00:00 2001
From: Paul Gey <narpfel@gmx.de>
Date: Sun, 17 Oct 2021 16:21:53 +0200
Subject: [PATCH 173/195] Preserve attributes for `imports_granularity=Item`

Fixes #5030
---
 src/imports.rs             | 52 ++++++++++++++++++++++++++++----------
 src/reorder.rs             | 15 +++--------
 tests/source/issue-5030.rs |  7 +++++
 tests/target/issue-5030.rs |  6 +++++
 4 files changed, 56 insertions(+), 24 deletions(-)
 create mode 100644 tests/source/issue-5030.rs
 create mode 100644 tests/target/issue-5030.rs

diff --git a/src/imports.rs b/src/imports.rs
index 02319809486..485a72b85da 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -10,6 +10,7 @@ use rustc_span::{
 
 use crate::comment::combine_strs_with_missing_comments;
 use crate::config::lists::*;
+use crate::config::ImportGranularity;
 use crate::config::{Edition, IndentStyle};
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
@@ -182,7 +183,18 @@ impl UseSegment {
     }
 }
 
-pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -> Vec<UseTree> {
+pub(crate) fn regroup_use_trees(
+    use_trees: Vec<UseTree>,
+    import_granularity: ImportGranularity,
+) -> Vec<UseTree> {
+    let merge_by = match import_granularity {
+        ImportGranularity::Item => return flatten_use_trees(use_trees, ImportGranularity::Item),
+        ImportGranularity::Preserve => return use_trees,
+        ImportGranularity::Crate => SharedPrefix::Crate,
+        ImportGranularity::Module => SharedPrefix::Module,
+        ImportGranularity::One => SharedPrefix::One,
+    };
+
     let mut result = Vec::with_capacity(use_trees.len());
     for use_tree in use_trees {
         if use_tree.has_comment() || use_tree.attrs.is_some() {
@@ -190,7 +202,7 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
             continue;
         }
 
-        for mut flattened in use_tree.flatten() {
+        for mut flattened in use_tree.flatten(import_granularity) {
             if let Some(tree) = result
                 .iter_mut()
                 .find(|tree| tree.share_prefix(&flattened, merge_by))
@@ -208,10 +220,13 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
     result
 }
 
-pub(crate) fn flatten_use_trees(use_trees: Vec<UseTree>) -> Vec<UseTree> {
+fn flatten_use_trees(
+    use_trees: Vec<UseTree>,
+    import_granularity: ImportGranularity,
+) -> Vec<UseTree> {
     use_trees
         .into_iter()
-        .flat_map(UseTree::flatten)
+        .flat_map(|tree| tree.flatten(import_granularity))
         .map(UseTree::nest_trailing_self)
         .collect()
 }
@@ -581,7 +596,7 @@ impl UseTree {
         }
     }
 
-    fn flatten(self) -> Vec<UseTree> {
+    fn flatten(self, import_granularity: ImportGranularity) -> Vec<UseTree> {
         if self.path.is_empty() {
             return vec![self];
         }
@@ -595,7 +610,7 @@ impl UseTree {
                 let prefix = &self.path[..self.path.len() - 1];
                 let mut result = vec![];
                 for nested_use_tree in list {
-                    for flattend in &mut nested_use_tree.clone().flatten() {
+                    for flattend in &mut nested_use_tree.clone().flatten(import_granularity) {
                         let mut new_path = prefix.to_vec();
                         new_path.append(&mut flattend.path);
                         result.push(UseTree {
@@ -603,7 +618,11 @@ impl UseTree {
                             span: self.span,
                             list_item: None,
                             visibility: self.visibility.clone(),
-                            attrs: None,
+                            // only retain attributes for `ImportGranularity::Item`
+                            attrs: match import_granularity {
+                                ImportGranularity::Item => self.attrs.clone(),
+                                _ => None,
+                            },
                         });
                     }
                 }
@@ -951,7 +970,7 @@ impl Rewrite for UseTree {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum SharedPrefix {
+enum SharedPrefix {
     Crate,
     Module,
     One,
@@ -1106,7 +1125,7 @@ mod test {
     macro_rules! test_merge {
         ($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => {
             assert_eq!(
-                merge_use_trees(parse_use_trees!($($input,)*), SharedPrefix::$by),
+                regroup_use_trees(parse_use_trees!($($input,)*), ImportGranularity::$by),
                 parse_use_trees!($($output,)*),
             );
         }
@@ -1215,12 +1234,18 @@ mod test {
     #[test]
     fn test_flatten_use_trees() {
         assert_eq!(
-            flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]),
+            flatten_use_trees(
+                parse_use_trees!["foo::{a::{b, c}, d::e}"],
+                ImportGranularity::Item
+            ),
             parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"]
         );
 
         assert_eq!(
-            flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]),
+            flatten_use_trees(
+                parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"],
+                ImportGranularity::Item
+            ),
             parse_use_trees![
                 "foo::{self}",
                 "foo::a",
@@ -1234,12 +1259,13 @@ mod test {
     #[test]
     fn test_use_tree_flatten() {
         assert_eq!(
-            parse_use_tree("a::b::{c, d, e, f}").flatten(),
+            parse_use_tree("a::b::{c, d, e, f}").flatten(ImportGranularity::Item),
             parse_use_trees!("a::b::c", "a::b::d", "a::b::e", "a::b::f",)
         );
 
         assert_eq!(
-            parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}").flatten(),
+            parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}")
+                .flatten(ImportGranularity::Item),
             parse_use_trees![
                 "a::b::c::d",
                 "a::b::c::e",
diff --git a/src/reorder.rs b/src/reorder.rs
index 13bfc92507d..f565612ded1 100644
--- a/src/reorder.rs
+++ b/src/reorder.rs
@@ -11,8 +11,8 @@ use std::cmp::{Ord, Ordering};
 use rustc_ast::ast;
 use rustc_span::{symbol::sym, Span};
 
-use crate::config::{Config, GroupImportsTactic, ImportGranularity};
-use crate::imports::{flatten_use_trees, merge_use_trees, SharedPrefix, UseSegment, UseTree};
+use crate::config::{Config, GroupImportsTactic};
+use crate::imports::{regroup_use_trees, UseSegment, UseTree};
 use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
 use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
 use crate::rewrite::RewriteContext;
@@ -107,15 +107,8 @@ fn rewrite_reorderable_or_regroupable_items(
             for (item, list_item) in normalized_items.iter_mut().zip(list_items) {
                 item.list_item = Some(list_item.clone());
             }
-            normalized_items = match context.config.imports_granularity() {
-                ImportGranularity::Crate => merge_use_trees(normalized_items, SharedPrefix::Crate),
-                ImportGranularity::Module => {
-                    merge_use_trees(normalized_items, SharedPrefix::Module)
-                }
-                ImportGranularity::Item => flatten_use_trees(normalized_items),
-                ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One),
-                ImportGranularity::Preserve => normalized_items,
-            };
+            normalized_items =
+                regroup_use_trees(normalized_items, context.config.imports_granularity());
 
             let mut regrouped_items = match context.config.group_imports() {
                 GroupImportsTactic::Preserve | GroupImportsTactic::One => {
diff --git a/tests/source/issue-5030.rs b/tests/source/issue-5030.rs
new file mode 100644
index 00000000000..f367e79f01f
--- /dev/null
+++ b/tests/source/issue-5030.rs
@@ -0,0 +1,7 @@
+// rustfmt-imports_granularity: Item
+
+#[cfg(feature = "foo")]
+use std::collections::{
+    HashMap,
+    HashSet,
+};
diff --git a/tests/target/issue-5030.rs b/tests/target/issue-5030.rs
new file mode 100644
index 00000000000..b371331ed00
--- /dev/null
+++ b/tests/target/issue-5030.rs
@@ -0,0 +1,6 @@
+// rustfmt-imports_granularity: Item
+
+#[cfg(feature = "foo")]
+use std::collections::HashMap;
+#[cfg(feature = "foo")]
+use std::collections::HashSet;

From 9b1b3d69559750cf459638076dc32202110ec40e Mon Sep 17 00:00:00 2001
From: Tom Milligan <tom@reinfer.io>
Date: Sat, 16 Apr 2022 11:50:24 +0100
Subject: [PATCH 174/195] [review] rename internal function

---
 src/imports.rs | 7 +++++--
 src/reorder.rs | 8 +++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/imports.rs b/src/imports.rs
index 485a72b85da..efe4e9498c9 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -183,7 +183,7 @@ impl UseSegment {
     }
 }
 
-pub(crate) fn regroup_use_trees(
+pub(crate) fn normalize_use_trees_with_granularity(
     use_trees: Vec<UseTree>,
     import_granularity: ImportGranularity,
 ) -> Vec<UseTree> {
@@ -1125,7 +1125,10 @@ mod test {
     macro_rules! test_merge {
         ($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => {
             assert_eq!(
-                regroup_use_trees(parse_use_trees!($($input,)*), ImportGranularity::$by),
+                normalize_use_trees_with_granularity(
+                    parse_use_trees!($($input,)*),
+                    ImportGranularity::$by,
+                ),
                 parse_use_trees!($($output,)*),
             );
         }
diff --git a/src/reorder.rs b/src/reorder.rs
index f565612ded1..8ae297de25b 100644
--- a/src/reorder.rs
+++ b/src/reorder.rs
@@ -12,7 +12,7 @@ use rustc_ast::ast;
 use rustc_span::{symbol::sym, Span};
 
 use crate::config::{Config, GroupImportsTactic};
-use crate::imports::{regroup_use_trees, UseSegment, UseTree};
+use crate::imports::{normalize_use_trees_with_granularity, UseSegment, UseTree};
 use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
 use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
 use crate::rewrite::RewriteContext;
@@ -107,8 +107,10 @@ fn rewrite_reorderable_or_regroupable_items(
             for (item, list_item) in normalized_items.iter_mut().zip(list_items) {
                 item.list_item = Some(list_item.clone());
             }
-            normalized_items =
-                regroup_use_trees(normalized_items, context.config.imports_granularity());
+            normalized_items = normalize_use_trees_with_granularity(
+                normalized_items,
+                context.config.imports_granularity(),
+            );
 
             let mut regrouped_items = match context.config.group_imports() {
                 GroupImportsTactic::Preserve | GroupImportsTactic::One => {

From acdab00ecc4c5064b6a42f87a523961304678c06 Mon Sep 17 00:00:00 2001
From: Tom Milligan <tom@reinfer.io>
Date: Sat, 16 Apr 2022 12:12:27 +0100
Subject: [PATCH 175/195] [review] check interaction with import grouping

---
 tests/source/issue-5030.rs | 15 +++++++++++++++
 tests/target/issue-5030.rs | 15 +++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/tests/source/issue-5030.rs b/tests/source/issue-5030.rs
index f367e79f01f..08ffaac7d1d 100644
--- a/tests/source/issue-5030.rs
+++ b/tests/source/issue-5030.rs
@@ -1,7 +1,22 @@
 // rustfmt-imports_granularity: Item
+// rustfmt-group_imports: One
 
+// Confirm that attributes are duplicated to all items in the use statement
 #[cfg(feature = "foo")]
 use std::collections::{
     HashMap,
     HashSet,
 };
+
+// Separate the imports below from the ones above
+const A: usize = 0;
+
+// Copying attrs works with import grouping as well
+#[cfg(feature = "foo")]
+use std::collections::{
+    HashMap,
+    HashSet,
+};
+
+#[cfg(feature = "spam")]
+use qux::{bar, baz};
diff --git a/tests/target/issue-5030.rs b/tests/target/issue-5030.rs
index b371331ed00..8ac3888bdbe 100644
--- a/tests/target/issue-5030.rs
+++ b/tests/target/issue-5030.rs
@@ -1,5 +1,20 @@
 // rustfmt-imports_granularity: Item
+// rustfmt-group_imports: One
 
+// Confirm that attributes are duplicated to all items in the use statement
+#[cfg(feature = "foo")]
+use std::collections::HashMap;
+#[cfg(feature = "foo")]
+use std::collections::HashSet;
+
+// Separate the imports below from the ones above
+const A: usize = 0;
+
+// Copying attrs works with import grouping as well
+#[cfg(feature = "spam")]
+use qux::bar;
+#[cfg(feature = "spam")]
+use qux::baz;
 #[cfg(feature = "foo")]
 use std::collections::HashMap;
 #[cfg(feature = "foo")]

From a37d3ab0e1c7c05f1a6410fb7ddf5539f0d030f8 Mon Sep 17 00:00:00 2001
From: hkalbasi <hamidrezakalbasi@protonmail.com>
Date: Wed, 15 Dec 2021 19:38:31 +0330
Subject: [PATCH 176/195] Memoize format_expr

---
 src/expr.rs                            |   51 +-
 src/formatting.rs                      |    2 +
 src/rewrite.rs                         |   13 +
 src/shape.rs                           |    4 +-
 src/visitor.rs                         |    7 +-
 tests/source/performance/issue-4476.rs |  638 +++
 tests/source/performance/issue-5128.rs | 5127 ++++++++++++++++++++++++
 tests/target/performance/issue-4476.rs |  705 ++++
 tests/target/performance/issue-4867.rs |   13 +
 tests/target/performance/issue-5128.rs | 4898 ++++++++++++++++++++++
 10 files changed, 11454 insertions(+), 4 deletions(-)
 create mode 100644 tests/source/performance/issue-4476.rs
 create mode 100644 tests/source/performance/issue-5128.rs
 create mode 100644 tests/target/performance/issue-4476.rs
 create mode 100644 tests/target/performance/issue-4867.rs
 create mode 100644 tests/target/performance/issue-5128.rs

diff --git a/src/expr.rs b/src/expr.rs
index 4f333cd27ce..cfecc9b9d89 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::cmp::min;
+use std::collections::HashMap;
 
 use itertools::Itertools;
 use rustc_ast::token::{DelimToken, LitKind};
@@ -22,7 +23,7 @@ use crate::macros::{rewrite_macro, MacroPosition};
 use crate::matches::rewrite_match;
 use crate::overflow::{self, IntoOverflowableItem, OverflowableItem};
 use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{QueryId, Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
@@ -53,6 +54,54 @@ pub(crate) fn format_expr(
     expr_type: ExprType,
     context: &RewriteContext<'_>,
     shape: Shape,
+) -> Option<String> {
+    // when max_width is tight, we should check all possible formattings, in order to find
+    // if we can fit expression in the limit. Doing it recursively takes exponential time
+    // relative to input size, and people hit it with rustfmt takes minutes in #4476 #4867 #5128
+    // By memoization of format_expr function, we format each pair of expression and shape
+    // only once, so worst case execution time becomes O(n*max_width^3).
+    if context.inside_macro() || context.is_macro_def {
+        // span ids are not unique in macros, so we don't memoize result of them.
+        return format_expr_inner(expr, expr_type, context, shape);
+    }
+    let clean;
+    let query_id = QueryId {
+        shape,
+        span: expr.span,
+    };
+    if let Some(map) = context.memoize.take() {
+        if let Some(r) = map.get(&query_id) {
+            let r = r.clone();
+            context.memoize.set(Some(map)); // restore map in the memoize cell for other users
+            return r;
+        }
+        context.memoize.set(Some(map));
+        clean = false;
+    } else {
+        context.memoize.set(Some(HashMap::default()));
+        clean = true; // We got None, so we are the top level called function. When
+        // this function finishes, no one is interested in what is in the map, because
+        // all of them are sub expressions of this top level expression, and this is
+        // done. So we should clean up memoize map to save some memory.
+    }
+
+    let r = format_expr_inner(expr, expr_type, context, shape);
+    if clean {
+        context.memoize.set(None);
+    } else {
+        if let Some(mut map) = context.memoize.take() {
+            map.insert(query_id, r.clone()); // insert the result in the memoize map
+            context.memoize.set(Some(map)); // so it won't be computed again
+        }
+    }
+    r
+}
+
+fn format_expr_inner(
+    expr: &ast::Expr,
+    expr_type: ExprType,
+    context: &RewriteContext<'_>,
+    shape: Shape,
 ) -> Option<String> {
     skip_out_of_file_lines_range!(context, expr.span);
 
diff --git a/src/formatting.rs b/src/formatting.rs
index ca93955a549..281d3e4e808 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -2,6 +2,7 @@
 
 use std::collections::HashMap;
 use std::io::{self, Write};
+use std::rc::Rc;
 use std::time::{Duration, Instant};
 
 use rustc_ast::ast;
@@ -190,6 +191,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
             self.config,
             &snippet_provider,
             self.report.clone(),
+            Rc::default(),
         );
         visitor.skip_context.update_with_attrs(&self.krate.attrs);
         visitor.is_macro_def = is_macro_def;
diff --git a/src/rewrite.rs b/src/rewrite.rs
index 4a3bd129d16..f97df70cc6a 100644
--- a/src/rewrite.rs
+++ b/src/rewrite.rs
@@ -12,6 +12,7 @@ use crate::shape::Shape;
 use crate::skip::SkipContext;
 use crate::visitor::SnippetProvider;
 use crate::FormatReport;
+use rustc_data_structures::stable_map::FxHashMap;
 
 pub(crate) trait Rewrite {
     /// Rewrite self into shape.
@@ -24,10 +25,22 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub(crate) struct QueryId {
+    pub(crate) shape: Shape,
+    pub(crate) span: Span,
+}
+
+// We use Option<HashMap> instead of HashMap, because in case of `None`
+// the function clean the memoize map, but it doesn't clean when
+// there is `Some(empty)`, so they are different.
+pub(crate) type Memoize = Rc<Cell<Option<FxHashMap<QueryId, Option<String>>>>>;
+
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
     pub(crate) parse_sess: &'a ParseSess,
     pub(crate) config: &'a Config,
+    pub(crate) memoize: Memoize,
     pub(crate) inside_macro: Rc<Cell<bool>>,
     // Force block indent style even if we are using visual indent style.
     pub(crate) use_block: Cell<bool>,
diff --git a/src/shape.rs b/src/shape.rs
index 4376fd12b52..b3f785a9470 100644
--- a/src/shape.rs
+++ b/src/shape.rs
@@ -4,7 +4,7 @@ use std::ops::{Add, Sub};
 
 use crate::Config;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) struct Indent {
     // Width of the block indent, in characters. Must be a multiple of
     // Config::tab_spaces.
@@ -139,7 +139,7 @@ impl Sub<usize> for Indent {
 // 8096 is close enough to infinite for rustfmt.
 const INFINITE_SHAPE_WIDTH: usize = 8096;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) struct Shape {
     pub(crate) width: usize,
     // The current indentation of code.
diff --git a/src/visitor.rs b/src/visitor.rs
index 3ebfa551d1c..06736e3079a 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -17,7 +17,7 @@ use crate::items::{
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
 use crate::parse::session::ParseSess;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Memoize, Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::skip::{is_skip_attr, SkipContext};
 use crate::source_map::{LineRangeUtils, SpanUtils};
@@ -71,6 +71,7 @@ impl SnippetProvider {
 
 pub(crate) struct FmtVisitor<'a> {
     parent_context: Option<&'a RewriteContext<'a>>,
+    pub(crate) memoize: Memoize,
     pub(crate) parse_sess: &'a ParseSess,
     pub(crate) buffer: String,
     pub(crate) last_pos: BytePos,
@@ -754,6 +755,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ctx.config,
             ctx.snippet_provider,
             ctx.report.clone(),
+            ctx.memoize.clone(),
         );
         visitor.skip_context.update(ctx.skip_context.clone());
         visitor.set_parent_context(ctx);
@@ -765,10 +767,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         config: &'a Config,
         snippet_provider: &'a SnippetProvider,
         report: FormatReport,
+        memoize: Memoize,
     ) -> FmtVisitor<'a> {
         FmtVisitor {
             parent_context: None,
             parse_sess: parse_session,
+            memoize,
             buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
             last_pos: BytePos(0),
             block_indent: Indent::empty(),
@@ -991,6 +995,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         RewriteContext {
             parse_sess: self.parse_sess,
             config: self.config,
+            memoize: self.memoize.clone(),
             inside_macro: Rc::new(Cell::new(false)),
             use_block: Cell::new(false),
             is_if_else_block: Cell::new(false),
diff --git a/tests/source/performance/issue-4476.rs b/tests/source/performance/issue-4476.rs
new file mode 100644
index 00000000000..8da3f19b62d
--- /dev/null
+++ b/tests/source/performance/issue-4476.rs
@@ -0,0 +1,638 @@
+use super::SemverParser;
+
+#[allow(dead_code, non_camel_case_types)]
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub enum Rule {
+  EOI,
+  range_set,
+  logical_or,
+  range,
+  empty,
+  hyphen,
+  simple,
+  primitive,
+  primitive_op,
+  partial,
+  xr,
+  xr_op,
+  nr,
+  tilde,
+  caret,
+  qualifier,
+  parts,
+  part,
+  space,
+}
+#[allow(clippy::all)]
+impl ::pest::Parser<Rule> for SemverParser {
+  fn parse<'i>(
+    rule: Rule,
+    input: &'i str,
+  ) -> ::std::result::Result<::pest::iterators::Pairs<'i, Rule>, ::pest::error::Error<Rule>> {
+    mod rules {
+      pub mod hidden {
+        use super::super::Rule;
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn skip(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          Ok(state)
+        }
+      }
+      pub mod visible {
+        use super::super::Rule;
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn range_set(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::range_set, |state| {
+            state.sequence(|state| {
+              self::SOI(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::range(state))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      state
+                        .sequence(|state| {
+                          self::logical_or(state)
+                            .and_then(|state| super::hidden::skip(state))
+                            .and_then(|state| self::range(state))
+                        })
+                        .and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state).and_then(|state| {
+                                state.sequence(|state| {
+                                  self::logical_or(state)
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| self::range(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::EOI(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn logical_or(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::logical_or, |state| {
+            state.sequence(|state| {
+              state
+                .sequence(|state| {
+                  state.optional(|state| {
+                    self::space(state).and_then(|state| {
+                      state.repeat(|state| {
+                        state.sequence(|state| {
+                          super::hidden::skip(state).and_then(|state| self::space(state))
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| state.match_string("||"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn range(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::range, |state| {
+            self::hyphen(state)
+              .or_else(|state| {
+                state.sequence(|state| {
+                  self::simple(state)
+                    .and_then(|state| super::hidden::skip(state))
+                    .and_then(|state| {
+                      state.sequence(|state| {
+                        state.optional(|state| {
+                          state
+                            .sequence(|state| {
+                              state
+                                .optional(|state| state.match_string(","))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                  state.sequence(|state| {
+                                    self::space(state)
+                                      .and_then(|state| super::hidden::skip(state))
+                                      .and_then(|state| {
+                                        state.sequence(|state| {
+                                          state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                              state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                  super::hidden::skip(state)
+                                                    .and_then(|state| self::space(state))
+                                                })
+                                              })
+                                            })
+                                          })
+                                        })
+                                      })
+                                  })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::simple(state))
+                            })
+                            .and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| {
+                                    state.sequence(|state| {
+                                      state
+                                        .optional(|state| state.match_string(","))
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                          state.sequence(|state| {
+                                            self::space(state)
+                                              .and_then(|state| super::hidden::skip(state))
+                                              .and_then(|state| {
+                                                state.sequence(|state| {
+                                                  state.optional(|state| {
+                                                    self::space(state).and_then(|state| {
+                                                      state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                          super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                        })
+                                                      })
+                                                    })
+                                                  })
+                                                })
+                                              })
+                                          })
+                                        })
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| self::simple(state))
+                                    })
+                                  })
+                                })
+                              })
+                            })
+                        })
+                      })
+                    })
+                })
+              })
+              .or_else(|state| self::empty(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn empty(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::empty, |state| state.match_string(""))
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn hyphen(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::hyphen, |state| {
+            state.sequence(|state| {
+              self::partial(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    self::space(state)
+                      .and_then(|state| super::hidden::skip(state))
+                      .and_then(|state| {
+                        state.sequence(|state| {
+                          state.optional(|state| {
+                            self::space(state).and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| self::space(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                      })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| state.match_string("-"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    self::space(state)
+                      .and_then(|state| super::hidden::skip(state))
+                      .and_then(|state| {
+                        state.sequence(|state| {
+                          state.optional(|state| {
+                            self::space(state).and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| self::space(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                      })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn simple(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::simple, |state| {
+            self::primitive(state)
+              .or_else(|state| self::partial(state))
+              .or_else(|state| self::tilde(state))
+              .or_else(|state| self::caret(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn primitive(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::primitive, |state| {
+            state.sequence(|state| {
+              self::primitive_op(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn primitive_op(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::primitive_op, |state| {
+            state
+              .match_string("<=")
+              .or_else(|state| state.match_string(">="))
+              .or_else(|state| state.match_string(">"))
+              .or_else(|state| state.match_string("<"))
+              .or_else(|state| state.match_string("="))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn partial(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::partial, |state| {
+            state.sequence(|state| {
+              self::xr(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.optional(|state| {
+                    state.sequence(|state| {
+                      state
+                        .match_string(".")
+                        .and_then(|state| super::hidden::skip(state))
+                        .and_then(|state| self::xr(state))
+                        .and_then(|state| super::hidden::skip(state))
+                        .and_then(|state| {
+                          state.optional(|state| {
+                            state.sequence(|state| {
+                              state
+                                .match_string(".")
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::xr(state))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.optional(|state| self::qualifier(state)))
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn xr(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::xr, |state| {
+            self::xr_op(state).or_else(|state| self::nr(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn xr_op(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::xr_op, |state| {
+            state
+              .match_string("x")
+              .or_else(|state| state.match_string("X"))
+              .or_else(|state| state.match_string("*"))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn nr(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::nr, |state| {
+            state.match_string("0").or_else(|state| {
+              state.sequence(|state| {
+                state
+                  .match_range('1'..'9')
+                  .and_then(|state| super::hidden::skip(state))
+                  .and_then(|state| {
+                    state.sequence(|state| {
+                      state.optional(|state| {
+                        state.match_range('0'..'9').and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state)
+                                .and_then(|state| state.match_range('0'..'9'))
+                            })
+                          })
+                        })
+                      })
+                    })
+                  })
+              })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn tilde(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::tilde, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("~>")
+                .or_else(|state| state.match_string("~"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn caret(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::caret, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("^")
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn qualifier(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::qualifier, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("-")
+                .or_else(|state| state.match_string("+"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::parts(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn parts(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::parts, |state| {
+            state.sequence(|state| {
+              self::part(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      state
+                        .sequence(|state| {
+                          state
+                            .match_string(".")
+                            .and_then(|state| super::hidden::skip(state))
+                            .and_then(|state| self::part(state))
+                        })
+                        .and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state).and_then(|state| {
+                                state.sequence(|state| {
+                                  state
+                                    .match_string(".")
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| self::part(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn part(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::part, |state| {
+            self::nr(state).or_else(|state| {
+              state.sequence(|state| {
+                state
+                  .match_string("-")
+                  .or_else(|state| state.match_range('0'..'9'))
+                  .or_else(|state| state.match_range('A'..'Z'))
+                  .or_else(|state| state.match_range('a'..'z'))
+                  .and_then(|state| super::hidden::skip(state))
+                  .and_then(|state| {
+                    state.sequence(|state| {
+                      state.optional(|state| {
+                        state
+                          .match_string("-")
+                          .or_else(|state| state.match_range('0'..'9'))
+                          .or_else(|state| state.match_range('A'..'Z'))
+                          .or_else(|state| state.match_range('a'..'z'))
+                          .and_then(|state| {
+                            state.repeat(|state| {
+                              state.sequence(|state| {
+                                super::hidden::skip(state).and_then(|state| {
+                                  state
+                                    .match_string("-")
+                                    .or_else(|state| state.match_range('0'..'9'))
+                                    .or_else(|state| state.match_range('A'..'Z'))
+                                    .or_else(|state| state.match_range('a'..'z'))
+                                })
+                              })
+                            })
+                          })
+                      })
+                    })
+                  })
+              })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn space(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state
+            .match_string(" ")
+            .or_else(|state| state.match_string("\t"))
+        }
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn EOI(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::EOI, |state| state.end_of_input())
+        }
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn SOI(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.start_of_input()
+        }
+      }
+      pub use self::visible::*;
+    }
+    ::pest::state(input, |state| match rule {
+      Rule::range_set => rules::range_set(state),
+      Rule::logical_or => rules::logical_or(state),
+      Rule::range => rules::range(state),
+      Rule::empty => rules::empty(state),
+      Rule::hyphen => rules::hyphen(state),
+      Rule::simple => rules::simple(state),
+      Rule::primitive => rules::primitive(state),
+      Rule::primitive_op => rules::primitive_op(state),
+      Rule::partial => rules::partial(state),
+      Rule::xr => rules::xr(state),
+      Rule::xr_op => rules::xr_op(state),
+      Rule::nr => rules::nr(state),
+      Rule::tilde => rules::tilde(state),
+      Rule::caret => rules::caret(state),
+      Rule::qualifier => rules::qualifier(state),
+      Rule::parts => rules::parts(state),
+      Rule::part => rules::part(state),
+      Rule::space => rules::space(state),
+      Rule::EOI => rules::EOI(state),
+    })
+  }
+}
\ No newline at end of file
diff --git a/tests/source/performance/issue-5128.rs b/tests/source/performance/issue-5128.rs
new file mode 100644
index 00000000000..3adce49601c
--- /dev/null
+++ b/tests/source/performance/issue-5128.rs
@@ -0,0 +1,5127 @@
+
+fn takes_a_long_time_to_rustfmt() {
+    let inner_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("ranked_by_age_within_key"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from(""),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::AStar(AStar{}))
+                                        }],
+                                        location: 80
+                                    }))
+                                })),
+                                location: 80
+                            })))
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("rank_in_key"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::FuncCall(Box::new(FuncCall {
+                                        funcname: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("row_number")
+                                            }))
+                                        }],
+                                        args: vec![],
+                                        agg_order: vec![],
+                                        agg_filter: None,
+                                        agg_within_group: false,
+                                        agg_star: false,
+                                        agg_distinct: false,
+                                        func_variadic: false,
+                                        over: Some(Box::new(WindowDef {
+                                            name: String::from(""),
+                                            refname: String::from(""),
+                                            partition_clause: vec![
+                                                Node {
+                                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                                        fields: vec![Node {
+                                                            node: Some(node::Node::String(String2 {
+                                                                str: String::from("synthetic_key")
+                                                            }))
+                                                        }], location: 123
+                                                    }))
+                                                }], order_clause: vec![Node {
+                                                    node: Some(node::Node::SortBy(Box::new(SortBy {
+                                                        node: Some(Box::new(Node {
+                                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                                fields: vec![Node {
+                                                                    node: Some(node::Node::String(String2 {
+                                                                        str: String::from("logical_timestamp")
+                                                                    }))
+                                                                }], location: 156
+                                                            }))
+                                                        })),
+                                                        sortby_dir: SortByDir::SortbyDesc as i32,
+                                                        sortby_nulls: SortByNulls::SortbyNullsDefault as i32,
+                                                        use_op: vec![],
+                                                        location: -1
+                                                    })))
+                                                }], frame_options: 1058, start_offset: None, end_offset: None, location: 109
+                                            })),
+                                            location: 91
+                                        })))
+                                    })),
+                                    location: 91
+                                })))
+                            }],
+                            from_clause: vec![Node {
+                                node: Some(node::Node::RangeVar(RangeVar {
+                                    catalogname: String::from(""), schemaname: String::from("_supertables"), relname: String::from("9999-9999-9999"), inh: true, relpersistence: String::from("p"), alias: None, location: 206
+                                }))
+                            }],
+                            where_clause: Some(Box::new(Node {
+                                node: Some(node::Node::AExpr(Box::new(AExpr {
+                                    kind: AExprKind::AexprOp as i32,
+                                    name: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("<=")
+                                        }))
+                                    }],
+                                    lexpr: Some(Box::new(Node {
+                                        node: Some(node::Node::ColumnRef(ColumnRef {
+                                            fields: vec![Node {
+                                                node: Some(node::Node::String(String2 {
+                                                    str: String::from("logical_timestamp")
+                                                }))
+                                            }],
+                                            location: 250
+                                        }))
+                                    })),
+                                    rexpr: Some(Box::new(Node {
+                                        node: Some(node::Node::AConst(Box::new(AConst {
+                                            val: Some(Box::new(Node {
+                                                node: Some(node::Node::Integer(Integer {
+                                                    ival: 9000
+                                                }))
+                                            })),
+                                            location: 271
+                                        })))
+                                    })),
+                                    location: 268
+                                })))
+                            })),
+                            group_clause: vec![],
+                            having_clause: None,
+                            window_clause: vec![],
+                            values_lists: vec![],
+                            sort_clause: vec![],
+                            limit_offset: None,
+                            limit_count: None,
+                            limit_option: LimitOption::Default as i32,
+                            locking_clause: vec![],
+                            with_clause: None,
+                            op: SetOperation::SetopNone as i32,
+                            all: false,
+                            larg: None,
+                            rarg: None
+                        }))),
+            })),
+            location: 29,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let outer_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("table_name"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column1"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c1"),
+                                            })),
+                                        }],
+                                        location: 301,
+                                    })),
+                                })),
+                                location: 301,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column2"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c2"),
+                                            })),
+                                        }],
+                                        location: 324,
+                                    })),
+                                })),
+                                location: 324,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("ranked_by_age_within_key"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 347,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::BoolExpr(Box::new(BoolExpr {
+                            xpr: None,
+                            boolop: BoolExprType::AndExpr as i32,
+                            args: vec![
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(
+                                                        String2 {
+                                                            str: String::from("rank_in_key"),
+                                                        },
+                                                    )),
+                                                }],
+                                                location: 382,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::AConst(Box::new(AConst {
+                                                val: Some(Box::new(Node {
+                                                    node: Some(node::Node::Integer(
+                                                        Integer { ival: 1 },
+                                                    )),
+                                                })),
+                                                location: 396,
+                                            }))),
+                                        })),
+                                        location: 394,
+                                    }))),
+                                },
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(
+                                                        String2 {
+                                                            str: String::from("is_deleted"),
+                                                        },
+                                                    )),
+                                                }],
+                                                location: 402,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::TypeCast(Box::new(
+                                                TypeCast {
+                                                    arg: Some(Box::new(Node {
+                                                        node: Some(node::Node::AConst(
+                                                            Box::new(AConst {
+                                                                val: Some(Box::new(Node {
+                                                                    node: Some(
+                                                                        node::Node::String(
+                                                                            String2 {
+                                                                                str:
+                                                                                    String::from(
+                                                                                        "f",
+                                                                                    ),
+                                                                            },
+                                                                        ),
+                                                                    ),
+                                                                })),
+                                                                location: 415,
+                                                            }),
+                                                        )),
+                                                    })),
+                                                    type_name: Some(TypeName {
+                                                        names: vec![
+                                                            Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from(
+                                                                            "pg_catalog",
+                                                                        ),
+                                                                    },
+                                                                )),
+                                                            },
+                                                            Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from(
+                                                                            "bool",
+                                                                        ),
+                                                                    },
+                                                                )),
+                                                            },
+                                                        ],
+                                                        type_oid: 0,
+                                                        setof: false,
+                                                        pct_type: false,
+                                                        typmods: vec![],
+                                                        typemod: -1,
+                                                        array_bounds: vec![],
+                                                        location: -1,
+                                                    }),
+                                                    location: -1,
+                                                },
+                                            ))),
+                                        })),
+                                        location: 413,
+                                    }))),
+                                },
+                            ],
+                            location: 398,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: inner_cte,
+                        recursive: false,
+                        location: 24,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 5,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let expected_result = ParseResult {
+        version: 130003,
+        stmts: vec![RawStmt {
+            stmt: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+
+                    target_list: vec![Node {
+                        node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                            name: String::from(""),
+                            indirection: vec![],
+                            val: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column1"),
+                                        })),
+                                    }],
+                                    location: 430,
+                                })),
+                            })),
+                            location: 430,
+                        }))),
+                    }],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("table_name"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 443,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from(">"),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column2"),
+                                        })),
+                                    }],
+                                    location: 460,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer {
+                                            ival: 9000,
+                                        })),
+                                    })),
+                                    location: 470,
+                                }))),
+                            })),
+                            location: 468,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: outer_cte,
+                        recursive: false,
+                        location: 0,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            stmt_location: 0,
+            stmt_len: 0,
+        }],
+    };
+
+}
+#[derive(Clone, PartialEq)]
+pub struct ParseResult {
+
+    pub version: i32,
+
+    pub stmts: Vec<RawStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanResult {
+
+    pub version: i32,
+
+    pub tokens: Vec<ScanToken>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Node {
+    pub node: ::core::option::Option<node::Node>,
+}
+/// Nested message and enum types in `Node`.
+pub mod node {
+    #[derive(Clone, PartialEq)]
+    pub enum Node {
+
+        Alias(super::Alias),
+
+        RangeVar(super::RangeVar),
+
+        TableFunc(Box<super::TableFunc>),
+
+        Expr(super::Expr),
+
+        Var(Box<super::Var>),
+
+        Param(Box<super::Param>),
+
+        Aggref(Box<super::Aggref>),
+
+        GroupingFunc(Box<super::GroupingFunc>),
+
+        WindowFunc(Box<super::WindowFunc>),
+
+        SubscriptingRef(Box<super::SubscriptingRef>),
+
+        FuncExpr(Box<super::FuncExpr>),
+
+        NamedArgExpr(Box<super::NamedArgExpr>),
+
+        OpExpr(Box<super::OpExpr>),
+
+        DistinctExpr(Box<super::DistinctExpr>),
+
+        NullIfExpr(Box<super::NullIfExpr>),
+
+        ScalarArrayOpExpr(Box<super::ScalarArrayOpExpr>),
+
+        BoolExpr(Box<super::BoolExpr>),
+
+        SubLink(Box<super::SubLink>),
+
+        SubPlan(Box<super::SubPlan>),
+
+        AlternativeSubPlan(Box<super::AlternativeSubPlan>),
+
+        FieldSelect(Box<super::FieldSelect>),
+
+        FieldStore(Box<super::FieldStore>),
+
+        RelabelType(Box<super::RelabelType>),
+
+        CoerceViaIo(Box<super::CoerceViaIo>),
+
+        ArrayCoerceExpr(Box<super::ArrayCoerceExpr>),
+
+        ConvertRowtypeExpr(Box<super::ConvertRowtypeExpr>),
+
+        CollateExpr(Box<super::CollateExpr>),
+
+        CaseExpr(Box<super::CaseExpr>),
+
+        CaseWhen(Box<super::CaseWhen>),
+
+        CaseTestExpr(Box<super::CaseTestExpr>),
+
+        ArrayExpr(Box<super::ArrayExpr>),
+
+        RowExpr(Box<super::RowExpr>),
+
+        RowCompareExpr(Box<super::RowCompareExpr>),
+
+        CoalesceExpr(Box<super::CoalesceExpr>),
+
+        MinMaxExpr(Box<super::MinMaxExpr>),
+
+        SqlvalueFunction(Box<super::SqlValueFunction>),
+
+        XmlExpr(Box<super::XmlExpr>),
+
+        NullTest(Box<super::NullTest>),
+
+        BooleanTest(Box<super::BooleanTest>),
+
+        CoerceToDomain(Box<super::CoerceToDomain>),
+
+        CoerceToDomainValue(Box<super::CoerceToDomainValue>),
+
+        SetToDefault(Box<super::SetToDefault>),
+
+        CurrentOfExpr(Box<super::CurrentOfExpr>),
+
+        NextValueExpr(Box<super::NextValueExpr>),
+
+        InferenceElem(Box<super::InferenceElem>),
+
+        TargetEntry(Box<super::TargetEntry>),
+
+        RangeTblRef(super::RangeTblRef),
+
+        JoinExpr(Box<super::JoinExpr>),
+
+        FromExpr(Box<super::FromExpr>),
+
+        OnConflictExpr(Box<super::OnConflictExpr>),
+
+        IntoClause(Box<super::IntoClause>),
+
+        RawStmt(Box<super::RawStmt>),
+
+        Query(Box<super::Query>),
+
+        InsertStmt(Box<super::InsertStmt>),
+
+        DeleteStmt(Box<super::DeleteStmt>),
+
+        UpdateStmt(Box<super::UpdateStmt>),
+
+        SelectStmt(Box<super::SelectStmt>),
+
+        AlterTableStmt(super::AlterTableStmt),
+
+        AlterTableCmd(Box<super::AlterTableCmd>),
+
+        AlterDomainStmt(Box<super::AlterDomainStmt>),
+
+        SetOperationStmt(Box<super::SetOperationStmt>),
+
+        GrantStmt(super::GrantStmt),
+
+        GrantRoleStmt(super::GrantRoleStmt),
+
+        AlterDefaultPrivilegesStmt(super::AlterDefaultPrivilegesStmt),
+
+        ClosePortalStmt(super::ClosePortalStmt),
+
+        ClusterStmt(super::ClusterStmt),
+
+        CopyStmt(Box<super::CopyStmt>),
+
+        CreateStmt(super::CreateStmt),
+
+        DefineStmt(super::DefineStmt),
+
+        DropStmt(super::DropStmt),
+
+        TruncateStmt(super::TruncateStmt),
+
+        CommentStmt(Box<super::CommentStmt>),
+
+        FetchStmt(super::FetchStmt),
+
+        IndexStmt(Box<super::IndexStmt>),
+
+        CreateFunctionStmt(super::CreateFunctionStmt),
+
+        AlterFunctionStmt(super::AlterFunctionStmt),
+
+        DoStmt(super::DoStmt),
+
+        RenameStmt(Box<super::RenameStmt>),
+
+        RuleStmt(Box<super::RuleStmt>),
+
+        NotifyStmt(super::NotifyStmt),
+
+        ListenStmt(super::ListenStmt),
+
+        UnlistenStmt(super::UnlistenStmt),
+
+        TransactionStmt(super::TransactionStmt),
+
+        ViewStmt(Box<super::ViewStmt>),
+
+        LoadStmt(super::LoadStmt),
+
+        CreateDomainStmt(Box<super::CreateDomainStmt>),
+
+        CreatedbStmt(super::CreatedbStmt),
+
+        DropdbStmt(super::DropdbStmt),
+
+        VacuumStmt(super::VacuumStmt),
+
+        ExplainStmt(Box<super::ExplainStmt>),
+
+        CreateTableAsStmt(Box<super::CreateTableAsStmt>),
+
+        CreateSeqStmt(super::CreateSeqStmt),
+
+        AlterSeqStmt(super::AlterSeqStmt),
+
+        VariableSetStmt(super::VariableSetStmt),
+
+        VariableShowStmt(super::VariableShowStmt),
+
+        DiscardStmt(super::DiscardStmt),
+
+        CreateTrigStmt(Box<super::CreateTrigStmt>),
+
+        CreatePlangStmt(super::CreatePLangStmt),
+
+        CreateRoleStmt(super::CreateRoleStmt),
+
+        AlterRoleStmt(super::AlterRoleStmt),
+
+        DropRoleStmt(super::DropRoleStmt),
+
+        LockStmt(super::LockStmt),
+
+        ConstraintsSetStmt(super::ConstraintsSetStmt),
+
+        ReindexStmt(super::ReindexStmt),
+
+        CheckPointStmt(super::CheckPointStmt),
+
+        CreateSchemaStmt(super::CreateSchemaStmt),
+
+        AlterDatabaseStmt(super::AlterDatabaseStmt),
+
+        AlterDatabaseSetStmt(super::AlterDatabaseSetStmt),
+
+        AlterRoleSetStmt(super::AlterRoleSetStmt),
+
+        CreateConversionStmt(super::CreateConversionStmt),
+
+        CreateCastStmt(super::CreateCastStmt),
+
+        CreateOpClassStmt(super::CreateOpClassStmt),
+
+        CreateOpFamilyStmt(super::CreateOpFamilyStmt),
+
+        AlterOpFamilyStmt(super::AlterOpFamilyStmt),
+
+        PrepareStmt(Box<super::PrepareStmt>),
+
+        ExecuteStmt(super::ExecuteStmt),
+
+        DeallocateStmt(super::DeallocateStmt),
+
+        DeclareCursorStmt(Box<super::DeclareCursorStmt>),
+
+        CreateTableSpaceStmt(super::CreateTableSpaceStmt),
+
+        DropTableSpaceStmt(super::DropTableSpaceStmt),
+
+        AlterObjectDependsStmt(Box<super::AlterObjectDependsStmt>),
+
+        AlterObjectSchemaStmt(Box<super::AlterObjectSchemaStmt>),
+
+        AlterOwnerStmt(Box<super::AlterOwnerStmt>),
+
+        AlterOperatorStmt(super::AlterOperatorStmt),
+
+        AlterTypeStmt(super::AlterTypeStmt),
+
+        DropOwnedStmt(super::DropOwnedStmt),
+
+        ReassignOwnedStmt(super::ReassignOwnedStmt),
+
+        CompositeTypeStmt(super::CompositeTypeStmt),
+
+        CreateEnumStmt(super::CreateEnumStmt),
+
+        CreateRangeStmt(super::CreateRangeStmt),
+
+        AlterEnumStmt(super::AlterEnumStmt),
+
+        AlterTsdictionaryStmt(super::AlterTsDictionaryStmt),
+
+        AlterTsconfigurationStmt(super::AlterTsConfigurationStmt),
+
+        CreateFdwStmt(super::CreateFdwStmt),
+
+        AlterFdwStmt(super::AlterFdwStmt),
+
+        CreateForeignServerStmt(super::CreateForeignServerStmt),
+
+        AlterForeignServerStmt(super::AlterForeignServerStmt),
+
+        CreateUserMappingStmt(super::CreateUserMappingStmt),
+
+        AlterUserMappingStmt(super::AlterUserMappingStmt),
+
+        DropUserMappingStmt(super::DropUserMappingStmt),
+
+        AlterTableSpaceOptionsStmt(super::AlterTableSpaceOptionsStmt),
+
+        AlterTableMoveAllStmt(super::AlterTableMoveAllStmt),
+
+        SecLabelStmt(Box<super::SecLabelStmt>),
+
+        CreateForeignTableStmt(super::CreateForeignTableStmt),
+
+        ImportForeignSchemaStmt(super::ImportForeignSchemaStmt),
+
+        CreateExtensionStmt(super::CreateExtensionStmt),
+
+        AlterExtensionStmt(super::AlterExtensionStmt),
+
+        AlterExtensionContentsStmt(Box<super::AlterExtensionContentsStmt>),
+
+        CreateEventTrigStmt(super::CreateEventTrigStmt),
+
+        AlterEventTrigStmt(super::AlterEventTrigStmt),
+
+        RefreshMatViewStmt(super::RefreshMatViewStmt),
+
+        ReplicaIdentityStmt(super::ReplicaIdentityStmt),
+
+        AlterSystemStmt(super::AlterSystemStmt),
+
+        CreatePolicyStmt(Box<super::CreatePolicyStmt>),
+
+        AlterPolicyStmt(Box<super::AlterPolicyStmt>),
+
+        CreateTransformStmt(super::CreateTransformStmt),
+
+        CreateAmStmt(super::CreateAmStmt),
+
+        CreatePublicationStmt(super::CreatePublicationStmt),
+
+        AlterPublicationStmt(super::AlterPublicationStmt),
+
+        CreateSubscriptionStmt(super::CreateSubscriptionStmt),
+
+        AlterSubscriptionStmt(super::AlterSubscriptionStmt),
+
+        DropSubscriptionStmt(super::DropSubscriptionStmt),
+
+        CreateStatsStmt(super::CreateStatsStmt),
+
+        AlterCollationStmt(super::AlterCollationStmt),
+
+        CallStmt(Box<super::CallStmt>),
+
+        AlterStatsStmt(super::AlterStatsStmt),
+
+        AExpr(Box<super::AExpr>),
+
+        ColumnRef(super::ColumnRef),
+
+        ParamRef(super::ParamRef),
+
+        AConst(Box<super::AConst>),
+
+        FuncCall(Box<super::FuncCall>),
+
+        AStar(super::AStar),
+
+        AIndices(Box<super::AIndices>),
+
+        AIndirection(Box<super::AIndirection>),
+
+        AArrayExpr(super::AArrayExpr),
+
+        ResTarget(Box<super::ResTarget>),
+
+        MultiAssignRef(Box<super::MultiAssignRef>),
+
+        TypeCast(Box<super::TypeCast>),
+
+        CollateClause(Box<super::CollateClause>),
+
+        SortBy(Box<super::SortBy>),
+
+        WindowDef(Box<super::WindowDef>),
+
+        RangeSubselect(Box<super::RangeSubselect>),
+
+        RangeFunction(super::RangeFunction),
+
+        RangeTableSample(Box<super::RangeTableSample>),
+
+        RangeTableFunc(Box<super::RangeTableFunc>),
+
+        RangeTableFuncCol(Box<super::RangeTableFuncCol>),
+
+        TypeName(super::TypeName),
+
+        ColumnDef(Box<super::ColumnDef>),
+
+        IndexElem(Box<super::IndexElem>),
+
+        Constraint(Box<super::Constraint>),
+
+        DefElem(Box<super::DefElem>),
+
+        RangeTblEntry(Box<super::RangeTblEntry>),
+
+        RangeTblFunction(Box<super::RangeTblFunction>),
+
+        TableSampleClause(Box<super::TableSampleClause>),
+
+        WithCheckOption(Box<super::WithCheckOption>),
+
+        SortGroupClause(super::SortGroupClause),
+
+        GroupingSet(super::GroupingSet),
+
+        WindowClause(Box<super::WindowClause>),
+
+        ObjectWithArgs(super::ObjectWithArgs),
+
+        AccessPriv(super::AccessPriv),
+
+        CreateOpClassItem(super::CreateOpClassItem),
+
+        TableLikeClause(super::TableLikeClause),
+
+        FunctionParameter(Box<super::FunctionParameter>),
+
+        LockingClause(super::LockingClause),
+
+        RowMarkClause(super::RowMarkClause),
+
+        XmlSerialize(Box<super::XmlSerialize>),
+
+        WithClause(super::WithClause),
+
+        InferClause(Box<super::InferClause>),
+
+        OnConflictClause(Box<super::OnConflictClause>),
+
+        CommonTableExpr(Box<super::CommonTableExpr>),
+
+        RoleSpec(super::RoleSpec),
+
+        TriggerTransition(super::TriggerTransition),
+
+        PartitionElem(Box<super::PartitionElem>),
+
+        PartitionSpec(super::PartitionSpec),
+
+        PartitionBoundSpec(super::PartitionBoundSpec),
+
+        PartitionRangeDatum(Box<super::PartitionRangeDatum>),
+
+        PartitionCmd(super::PartitionCmd),
+
+        VacuumRelation(super::VacuumRelation),
+
+        InlineCodeBlock(super::InlineCodeBlock),
+
+        CallContext(super::CallContext),
+
+        Integer(super::Integer),
+
+        Float(super::Float),
+
+        String(super::String2),
+
+        BitString(super::BitString),
+
+        Null(super::Null),
+
+        List(super::List),
+
+        IntList(super::IntList),
+
+        OidList(super::OidList),
+    }
+}
+#[derive(Clone, PartialEq)]
+pub struct Integer {
+    /// machine integer
+
+    pub ival: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Float {
+    /// string
+
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct String2 {
+    /// string
+
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct BitString {
+    /// string
+
+    pub str: String,
+}
+/// intentionally empty
+#[derive(Clone, PartialEq)]
+pub struct Null {}
+#[derive(Clone, PartialEq)]
+pub struct List {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OidList {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntList {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Alias {
+
+    pub aliasname: String,
+
+    pub colnames: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeVar {
+
+    pub catalogname: String,
+
+    pub schemaname: String,
+
+    pub relname: String,
+
+    pub inh: bool,
+
+    pub relpersistence: String,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableFunc {
+
+    pub ns_uris: Vec<Node>,
+
+    pub ns_names: Vec<Node>,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub colnames: Vec<Node>,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub colexprs: Vec<Node>,
+
+    pub coldefexprs: Vec<Node>,
+
+    pub notnulls: Vec<u64>,
+
+    pub ordinalitycol: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Expr {}
+#[derive(Clone, PartialEq)]
+pub struct Var {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub varno: u32,
+
+    pub varattno: i32,
+
+    pub vartype: u32,
+
+    pub vartypmod: i32,
+
+    pub varcollid: u32,
+
+    pub varlevelsup: u32,
+
+    pub varnosyn: u32,
+
+    pub varattnosyn: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Param {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub paramkind: i32,
+
+    pub paramid: i32,
+
+    pub paramtype: u32,
+
+    pub paramtypmod: i32,
+
+    pub paramcollid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Aggref {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub aggfnoid: u32,
+
+    pub aggtype: u32,
+
+    pub aggcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub aggtranstype: u32,
+
+    pub aggargtypes: Vec<Node>,
+
+    pub aggdirectargs: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub aggorder: Vec<Node>,
+
+    pub aggdistinct: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub aggstar: bool,
+
+    pub aggvariadic: bool,
+
+    pub aggkind: String,
+
+    pub agglevelsup: u32,
+
+    pub aggsplit: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingFunc {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub refs: Vec<Node>,
+
+    pub cols: Vec<Node>,
+
+    pub agglevelsup: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowFunc {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub winfnoid: u32,
+
+    pub wintype: u32,
+
+    pub wincollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub winref: u32,
+
+    pub winstar: bool,
+
+    pub winagg: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubscriptingRef {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub refcontainertype: u32,
+
+    pub refelemtype: u32,
+
+    pub reftypmod: i32,
+
+    pub refcollid: u32,
+
+    pub refupperindexpr: Vec<Node>,
+
+    pub reflowerindexpr: Vec<Node>,
+
+    pub refexpr: ::core::option::Option<Box<Node>>,
+
+    pub refassgnexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub funcid: u32,
+
+    pub funcresulttype: u32,
+
+    pub funcretset: bool,
+
+    pub funcvariadic: bool,
+
+    pub funcformat: i32,
+
+    pub funccollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NamedArgExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub name: String,
+
+    pub argnumber: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OpExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DistinctExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullIfExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScalarArrayOpExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub use_or: bool,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BoolExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub boolop: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubLink {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub sub_link_id: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub oper_name: Vec<Node>,
+
+    pub subselect: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubPlan {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub param_ids: Vec<Node>,
+
+    pub plan_id: i32,
+
+    pub plan_name: String,
+
+    pub first_col_type: u32,
+
+    pub first_col_typmod: i32,
+
+    pub first_col_collation: u32,
+
+    pub use_hash_table: bool,
+
+    pub unknown_eq_false: bool,
+
+    pub parallel_safe: bool,
+
+    pub set_param: Vec<Node>,
+
+    pub par_param: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub startup_cost: f64,
+
+    pub per_call_cost: f64,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlternativeSubPlan {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub subplans: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldSelect {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub fieldnum: i32,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldStore {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub newvals: Vec<Node>,
+
+    pub fieldnums: Vec<Node>,
+
+    pub resulttype: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RelabelType {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub relabelformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceViaIo {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayCoerceExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub elemexpr: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConvertRowtypeExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub convertformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub coll_oid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub casetype: u32,
+
+    pub casecollid: u32,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub defresult: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseWhen {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub result: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseTestExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub array_typeid: u32,
+
+    pub array_collid: u32,
+
+    pub element_typeid: u32,
+
+    pub elements: Vec<Node>,
+
+    pub multidims: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub row_typeid: u32,
+
+    pub row_format: i32,
+
+    pub colnames: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowCompareExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub rctype: i32,
+
+    pub opnos: Vec<Node>,
+
+    pub opfamilies: Vec<Node>,
+
+    pub inputcollids: Vec<Node>,
+
+    pub largs: Vec<Node>,
+
+    pub rargs: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoalesceExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub coalescetype: u32,
+
+    pub coalescecollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MinMaxExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub minmaxtype: u32,
+
+    pub minmaxcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub op: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SqlValueFunction {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub name: String,
+
+    pub named_args: Vec<Node>,
+
+    pub arg_names: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub xmloption: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullTest {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub nulltesttype: i32,
+
+    pub argisrow: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BooleanTest {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub booltesttype: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomain {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coercionformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomainValue {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetToDefault {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CurrentOfExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub cvarno: u32,
+
+    pub cursor_name: String,
+
+    pub cursor_param: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NextValueExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub seqid: u32,
+
+    pub type_id: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferenceElem {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub infercollid: u32,
+
+    pub inferopclass: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TargetEntry {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub resno: i32,
+
+    pub resname: String,
+
+    pub ressortgroupref: u32,
+
+    pub resorigtbl: u32,
+
+    pub resorigcol: i32,
+
+    pub resjunk: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblRef {
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct JoinExpr {
+
+    pub jointype: i32,
+
+    pub is_natural: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub using_clause: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FromExpr {
+
+    pub fromlist: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictExpr {
+
+    pub action: i32,
+
+    pub arbiter_elems: Vec<Node>,
+
+    pub arbiter_where: ::core::option::Option<Box<Node>>,
+
+    pub constraint: u32,
+
+    pub on_conflict_set: Vec<Node>,
+
+    pub on_conflict_where: ::core::option::Option<Box<Node>>,
+
+    pub excl_rel_index: i32,
+
+    pub excl_rel_tlist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntoClause {
+
+    pub rel: ::core::option::Option<RangeVar>,
+
+    pub col_names: Vec<Node>,
+
+    pub access_method: String,
+
+    pub options: Vec<Node>,
+
+    pub on_commit: i32,
+
+    pub table_space_name: String,
+
+    pub view_query: ::core::option::Option<Box<Node>>,
+
+    pub skip_data: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RawStmt {
+
+    pub stmt: ::core::option::Option<Box<Node>>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Query {
+
+    pub command_type: i32,
+
+    pub query_source: i32,
+
+    pub can_set_tag: bool,
+
+    pub utility_stmt: ::core::option::Option<Box<Node>>,
+
+    pub result_relation: i32,
+
+    pub has_aggs: bool,
+
+    pub has_window_funcs: bool,
+
+    pub has_target_srfs: bool,
+
+    pub has_sub_links: bool,
+
+    pub has_distinct_on: bool,
+
+    pub has_recursive: bool,
+
+    pub has_modifying_cte: bool,
+
+    pub has_for_update: bool,
+
+    pub has_row_security: bool,
+
+    pub cte_list: Vec<Node>,
+
+    pub rtable: Vec<Node>,
+
+    pub jointree: ::core::option::Option<Box<FromExpr>>,
+
+    pub target_list: Vec<Node>,
+
+    pub r#override: i32,
+
+    pub on_conflict: ::core::option::Option<Box<OnConflictExpr>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub group_clause: Vec<Node>,
+
+    pub grouping_sets: Vec<Node>,
+
+    pub having_qual: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub distinct_clause: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub row_marks: Vec<Node>,
+
+    pub set_operations: ::core::option::Option<Box<Node>>,
+
+    pub constraint_deps: Vec<Node>,
+
+    pub with_check_options: Vec<Node>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InsertStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cols: Vec<Node>,
+
+    pub select_stmt: ::core::option::Option<Box<Node>>,
+
+    pub on_conflict_clause: ::core::option::Option<Box<OnConflictClause>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub r#override: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeleteStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub using_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct UpdateStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub from_clause: Vec<Node>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct SelectStmt {
+
+    pub distinct_clause: Vec<Node>,
+
+    pub into_clause: ::core::option::Option<Box<IntoClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub from_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub group_clause: Vec<Node>,
+
+    pub having_clause: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub values_lists: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub locking_clause: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<SelectStmt>>,
+
+    pub rarg: ::core::option::Option<Box<SelectStmt>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cmds: Vec<Node>,
+
+    pub relkind: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableCmd {
+
+    pub subtype: i32,
+
+    pub name: String,
+
+    pub num: i32,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDomainStmt {
+
+    pub subtype: String,
+
+    pub type_name: Vec<Node>,
+
+    pub name: String,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetOperationStmt {
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub col_types: Vec<Node>,
+
+    pub col_typmods: Vec<Node>,
+
+    pub col_collations: Vec<Node>,
+
+    pub group_clauses: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantStmt {
+
+    pub is_grant: bool,
+
+    pub targtype: i32,
+
+    pub objtype: i32,
+
+    pub objects: Vec<Node>,
+
+    pub privileges: Vec<Node>,
+
+    pub grantees: Vec<Node>,
+
+    pub grant_option: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantRoleStmt {
+
+    pub granted_roles: Vec<Node>,
+
+    pub grantee_roles: Vec<Node>,
+
+    pub is_grant: bool,
+
+    pub admin_opt: bool,
+
+    pub grantor: ::core::option::Option<RoleSpec>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDefaultPrivilegesStmt {
+
+    pub options: Vec<Node>,
+
+    pub action: ::core::option::Option<GrantStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClosePortalStmt {
+
+    pub portalname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClusterStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub indexname: String,
+
+    pub options: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CopyStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub attlist: Vec<Node>,
+
+    pub is_from: bool,
+
+    pub is_program: bool,
+
+    pub filename: String,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub table_elts: Vec<Node>,
+
+    pub inh_relations: Vec<Node>,
+
+    pub partbound: ::core::option::Option<PartitionBoundSpec>,
+
+    pub partspec: ::core::option::Option<PartitionSpec>,
+
+    pub of_typename: ::core::option::Option<TypeName>,
+
+    pub constraints: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub oncommit: i32,
+
+    pub tablespacename: String,
+
+    pub access_method: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefineStmt {
+
+    pub kind: i32,
+
+    pub oldstyle: bool,
+
+    pub defnames: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub definition: Vec<Node>,
+
+    pub if_not_exists: bool,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropStmt {
+
+    pub objects: Vec<Node>,
+
+    pub remove_type: i32,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct TruncateStmt {
+
+    pub relations: Vec<Node>,
+
+    pub restart_seqs: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommentStmt {
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub comment: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct FetchStmt {
+
+    pub direction: i32,
+
+    pub how_many: i64,
+
+    pub portalname: String,
+
+    pub ismove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexStmt {
+
+    pub idxname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub access_method: String,
+
+    pub table_space: String,
+
+    pub index_params: Vec<Node>,
+
+    pub index_including_params: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub exclude_op_names: Vec<Node>,
+
+    pub idxcomment: String,
+
+    pub index_oid: u32,
+
+    pub old_node: u32,
+
+    pub old_create_subid: u32,
+
+    pub old_first_relfilenode_subid: u32,
+
+    pub unique: bool,
+
+    pub primary: bool,
+
+    pub isconstraint: bool,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub transformed: bool,
+
+    pub concurrent: bool,
+
+    pub if_not_exists: bool,
+
+    pub reset_default_tblspc: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFunctionStmt {
+
+    pub is_procedure: bool,
+
+    pub replace: bool,
+
+    pub funcname: Vec<Node>,
+
+    pub parameters: Vec<Node>,
+
+    pub return_type: ::core::option::Option<TypeName>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFunctionStmt {
+
+    pub objtype: i32,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub actions: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DoStmt {
+
+    pub args: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RenameStmt {
+
+    pub rename_type: i32,
+
+    pub relation_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub subname: String,
+
+    pub newname: String,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RuleStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub rulename: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub event: i32,
+
+    pub instead: bool,
+
+    pub actions: Vec<Node>,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct NotifyStmt {
+
+    pub conditionname: String,
+
+    pub payload: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ListenStmt {
+
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct UnlistenStmt {
+
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct TransactionStmt {
+
+    pub kind: i32,
+
+    pub options: Vec<Node>,
+
+    pub savepoint_name: String,
+
+    pub gid: String,
+
+    pub chain: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ViewStmt {
+
+    pub view: ::core::option::Option<RangeVar>,
+
+    pub aliases: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub replace: bool,
+
+    pub options: Vec<Node>,
+
+    pub with_check_option: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct LoadStmt {
+
+    pub filename: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateDomainStmt {
+
+    pub domainname: Vec<Node>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub constraints: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatedbStmt {
+
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropdbStmt {
+
+    pub dbname: String,
+
+    pub missing_ok: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumStmt {
+
+    pub options: Vec<Node>,
+
+    pub rels: Vec<Node>,
+
+    pub is_vacuumcmd: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExplainStmt {
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableAsStmt {
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub into: ::core::option::Option<Box<IntoClause>>,
+
+    pub relkind: i32,
+
+    pub is_select_into: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSeqStmt {
+
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub owner_id: u32,
+
+    pub for_identity: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSeqStmt {
+
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub for_identity: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableSetStmt {
+
+    pub kind: i32,
+
+    pub name: String,
+
+    pub args: Vec<Node>,
+
+    pub is_local: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableShowStmt {
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DiscardStmt {
+
+    pub target: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTrigStmt {
+
+    pub trigname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub row: bool,
+
+    pub timing: i32,
+
+    pub events: i32,
+
+    pub columns: Vec<Node>,
+
+    pub when_clause: ::core::option::Option<Box<Node>>,
+
+    pub isconstraint: bool,
+
+    pub transition_rels: Vec<Node>,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub constrrel: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePLangStmt {
+
+    pub replace: bool,
+
+    pub plname: String,
+
+    pub plhandler: Vec<Node>,
+
+    pub plinline: Vec<Node>,
+
+    pub plvalidator: Vec<Node>,
+
+    pub pltrusted: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRoleStmt {
+
+    pub stmt_type: i32,
+
+    pub role: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleStmt {
+
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub options: Vec<Node>,
+
+    pub action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropRoleStmt {
+
+    pub roles: Vec<Node>,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockStmt {
+
+    pub relations: Vec<Node>,
+
+    pub mode: i32,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConstraintsSetStmt {
+
+    pub constraints: Vec<Node>,
+
+    pub deferred: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReindexStmt {
+
+    pub kind: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub name: String,
+
+    pub options: i32,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CheckPointStmt {}
+#[derive(Clone, PartialEq)]
+pub struct CreateSchemaStmt {
+
+    pub schemaname: String,
+
+    pub authrole: ::core::option::Option<RoleSpec>,
+
+    pub schema_elts: Vec<Node>,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseStmt {
+
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseSetStmt {
+
+    pub dbname: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleSetStmt {
+
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub database: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateConversionStmt {
+
+    pub conversion_name: Vec<Node>,
+
+    pub for_encoding_name: String,
+
+    pub to_encoding_name: String,
+
+    pub func_name: Vec<Node>,
+
+    pub def: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateCastStmt {
+
+    pub sourcetype: ::core::option::Option<TypeName>,
+
+    pub targettype: ::core::option::Option<TypeName>,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub context: i32,
+
+    pub inout: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassStmt {
+
+    pub opclassname: Vec<Node>,
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub datatype: ::core::option::Option<TypeName>,
+
+    pub items: Vec<Node>,
+
+    pub is_default: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpFamilyStmt {
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOpFamilyStmt {
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub is_drop: bool,
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct PrepareStmt {
+
+    pub name: String,
+
+    pub argtypes: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExecuteStmt {
+
+    pub name: String,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeallocateStmt {
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeclareCursorStmt {
+
+    pub portalname: String,
+
+    pub options: i32,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableSpaceStmt {
+
+    pub tablespacename: String,
+
+    pub owner: ::core::option::Option<RoleSpec>,
+
+    pub location: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropTableSpaceStmt {
+
+    pub tablespacename: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectDependsStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub extname: ::core::option::Option<Box<Node>>,
+
+    pub remove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectSchemaStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newschema: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOwnerStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOperatorStmt {
+
+    pub opername: ::core::option::Option<ObjectWithArgs>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTypeStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropOwnedStmt {
+
+    pub roles: Vec<Node>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReassignOwnedStmt {
+
+    pub roles: Vec<Node>,
+
+    pub newrole: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CompositeTypeStmt {
+
+    pub typevar: ::core::option::Option<RangeVar>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEnumStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub vals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRangeStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEnumStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub old_val: String,
+
+    pub new_val: String,
+
+    pub new_val_neighbor: String,
+
+    pub new_val_is_after: bool,
+
+    pub skip_if_new_val_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsDictionaryStmt {
+
+    pub dictname: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsConfigurationStmt {
+
+    pub kind: i32,
+
+    pub cfgname: Vec<Node>,
+
+    pub tokentype: Vec<Node>,
+
+    pub dicts: Vec<Node>,
+
+    pub r#override: bool,
+
+    pub replace: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFdwStmt {
+
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFdwStmt {
+
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignServerStmt {
+
+    pub servername: String,
+
+    pub servertype: String,
+
+    pub version: String,
+
+    pub fdwname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterForeignServerStmt {
+
+    pub servername: String,
+
+    pub version: String,
+
+    pub options: Vec<Node>,
+
+    pub has_version: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableSpaceOptionsStmt {
+
+    pub tablespacename: String,
+
+    pub options: Vec<Node>,
+
+    pub is_reset: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableMoveAllStmt {
+
+    pub orig_tablespacename: String,
+
+    pub objtype: i32,
+
+    pub roles: Vec<Node>,
+
+    pub new_tablespacename: String,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SecLabelStmt {
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub provider: String,
+
+    pub label: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignTableStmt {
+
+    pub base_stmt: ::core::option::Option<CreateStmt>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ImportForeignSchemaStmt {
+
+    pub server_name: String,
+
+    pub remote_schema: String,
+
+    pub local_schema: String,
+
+    pub list_type: i32,
+
+    pub table_list: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateExtensionStmt {
+
+    pub extname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionStmt {
+
+    pub extname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionContentsStmt {
+
+    pub extname: String,
+
+    pub action: i32,
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEventTrigStmt {
+
+    pub trigname: String,
+
+    pub eventname: String,
+
+    pub whenclause: Vec<Node>,
+
+    pub funcname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEventTrigStmt {
+
+    pub trigname: String,
+
+    pub tgenabled: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct RefreshMatViewStmt {
+
+    pub concurrent: bool,
+
+    pub skip_data: bool,
+
+    pub relation: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReplicaIdentityStmt {
+
+    pub identity_type: String,
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSystemStmt {
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePolicyStmt {
+
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub cmd_name: String,
+
+    pub permissive: bool,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPolicyStmt {
+
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTransformStmt {
+
+    pub replace: bool,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub lang: String,
+
+    pub fromsql: ::core::option::Option<ObjectWithArgs>,
+
+    pub tosql: ::core::option::Option<ObjectWithArgs>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateAmStmt {
+
+    pub amname: String,
+
+    pub handler_name: Vec<Node>,
+
+    pub amtype: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePublicationStmt {
+
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPublicationStmt {
+
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+
+    pub table_action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSubscriptionStmt {
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSubscriptionStmt {
+
+    pub kind: i32,
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropSubscriptionStmt {
+
+    pub subname: String,
+
+    pub missing_ok: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStatsStmt {
+
+    pub defnames: Vec<Node>,
+
+    pub stat_types: Vec<Node>,
+
+    pub exprs: Vec<Node>,
+
+    pub relations: Vec<Node>,
+
+    pub stxcomment: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterCollationStmt {
+
+    pub collname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallStmt {
+
+    pub funccall: ::core::option::Option<Box<FuncCall>>,
+
+    pub funcexpr: ::core::option::Option<Box<FuncExpr>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterStatsStmt {
+
+    pub defnames: Vec<Node>,
+
+    pub stxstattarget: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AExpr {
+
+    pub kind: i32,
+
+    pub name: Vec<Node>,
+
+    pub lexpr: ::core::option::Option<Box<Node>>,
+
+    pub rexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnRef {
+
+    pub fields: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ParamRef {
+
+    pub number: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AConst {
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncCall {
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub agg_order: Vec<Node>,
+
+    pub agg_filter: ::core::option::Option<Box<Node>>,
+
+    pub agg_within_group: bool,
+
+    pub agg_star: bool,
+
+    pub agg_distinct: bool,
+
+    pub func_variadic: bool,
+
+    pub over: ::core::option::Option<Box<WindowDef>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AStar {}
+#[derive(Clone, PartialEq)]
+pub struct AIndices {
+
+    pub is_slice: bool,
+
+    pub lidx: ::core::option::Option<Box<Node>>,
+
+    pub uidx: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AIndirection {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub indirection: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AArrayExpr {
+
+    pub elements: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ResTarget {
+
+    pub name: String,
+
+    pub indirection: Vec<Node>,
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MultiAssignRef {
+
+    pub source: ::core::option::Option<Box<Node>>,
+
+    pub colno: i32,
+
+    pub ncolumns: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeCast {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateClause {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub collname: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortBy {
+
+    pub node: ::core::option::Option<Box<Node>>,
+
+    pub sortby_dir: i32,
+
+    pub sortby_nulls: i32,
+
+    pub use_op: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowDef {
+
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeSubselect {
+
+    pub lateral: bool,
+
+    pub subquery: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeFunction {
+
+    pub lateral: bool,
+
+    pub ordinality: bool,
+
+    pub is_rowsfrom: bool,
+
+    pub functions: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableSample {
+
+    pub relation: ::core::option::Option<Box<Node>>,
+
+    pub method: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFunc {
+
+    pub lateral: bool,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub namespaces: Vec<Node>,
+
+    pub columns: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFuncCol {
+
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub for_ordinality: bool,
+
+    pub is_not_null: bool,
+
+    pub colexpr: ::core::option::Option<Box<Node>>,
+
+    pub coldefexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeName {
+
+    pub names: Vec<Node>,
+
+    pub type_oid: u32,
+
+    pub setof: bool,
+
+    pub pct_type: bool,
+
+    pub typmods: Vec<Node>,
+
+    pub typemod: i32,
+
+    pub array_bounds: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnDef {
+
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub inhcount: i32,
+
+    pub is_local: bool,
+
+    pub is_not_null: bool,
+
+    pub is_from_type: bool,
+
+    pub storage: String,
+
+    pub raw_default: ::core::option::Option<Box<Node>>,
+
+    pub cooked_default: ::core::option::Option<Box<Node>>,
+
+    pub identity: String,
+
+    pub identity_sequence: ::core::option::Option<RangeVar>,
+
+    pub generated: String,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub coll_oid: u32,
+
+    pub constraints: Vec<Node>,
+
+    pub fdwoptions: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexElem {
+
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub indexcolname: String,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub opclassopts: Vec<Node>,
+
+    pub ordering: i32,
+
+    pub nulls_ordering: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Constraint {
+
+    pub contype: i32,
+
+    pub conname: String,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub location: i32,
+
+    pub is_no_inherit: bool,
+
+    pub raw_expr: ::core::option::Option<Box<Node>>,
+
+    pub cooked_expr: String,
+
+    pub generated_when: String,
+
+    pub keys: Vec<Node>,
+
+    pub including: Vec<Node>,
+
+    pub exclusions: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub indexname: String,
+
+    pub indexspace: String,
+
+    pub reset_default_tblspc: bool,
+
+    pub access_method: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub pktable: ::core::option::Option<RangeVar>,
+
+    pub fk_attrs: Vec<Node>,
+
+    pub pk_attrs: Vec<Node>,
+
+    pub fk_matchtype: String,
+
+    pub fk_upd_action: String,
+
+    pub fk_del_action: String,
+
+    pub old_conpfeqop: Vec<Node>,
+
+    pub old_pktable_oid: u32,
+
+    pub skip_validation: bool,
+
+    pub initially_valid: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefElem {
+
+    pub defnamespace: String,
+
+    pub defname: String,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub defaction: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblEntry {
+
+    pub rtekind: i32,
+
+    pub relid: u32,
+
+    pub relkind: String,
+
+    pub rellockmode: i32,
+
+    pub tablesample: ::core::option::Option<Box<TableSampleClause>>,
+
+    pub subquery: ::core::option::Option<Box<Query>>,
+
+    pub security_barrier: bool,
+
+    pub jointype: i32,
+
+    pub joinmergedcols: i32,
+
+    pub joinaliasvars: Vec<Node>,
+
+    pub joinleftcols: Vec<Node>,
+
+    pub joinrightcols: Vec<Node>,
+
+    pub functions: Vec<Node>,
+
+    pub funcordinality: bool,
+
+    pub tablefunc: ::core::option::Option<Box<TableFunc>>,
+
+    pub values_lists: Vec<Node>,
+
+    pub ctename: String,
+
+    pub ctelevelsup: u32,
+
+    pub self_reference: bool,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub enrname: String,
+
+    pub enrtuples: f64,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub eref: ::core::option::Option<Alias>,
+
+    pub lateral: bool,
+
+    pub inh: bool,
+
+    pub in_from_cl: bool,
+
+    pub required_perms: u32,
+
+    pub check_as_user: u32,
+
+    pub selected_cols: Vec<u64>,
+
+    pub inserted_cols: Vec<u64>,
+
+    pub updated_cols: Vec<u64>,
+
+    pub extra_updated_cols: Vec<u64>,
+
+    pub security_quals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblFunction {
+
+    pub funcexpr: ::core::option::Option<Box<Node>>,
+
+    pub funccolcount: i32,
+
+    pub funccolnames: Vec<Node>,
+
+    pub funccoltypes: Vec<Node>,
+
+    pub funccoltypmods: Vec<Node>,
+
+    pub funccolcollations: Vec<Node>,
+
+    pub funcparams: Vec<u64>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableSampleClause {
+
+    pub tsmhandler: u32,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithCheckOption {
+
+    pub kind: i32,
+
+    pub relname: String,
+
+    pub polname: String,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub cascaded: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortGroupClause {
+
+    pub tle_sort_group_ref: u32,
+
+    pub eqop: u32,
+
+    pub sortop: u32,
+
+    pub nulls_first: bool,
+
+    pub hashable: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingSet {
+
+    pub kind: i32,
+
+    pub content: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowClause {
+
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub start_in_range_func: u32,
+
+    pub end_in_range_func: u32,
+
+    pub in_range_coll: u32,
+
+    pub in_range_asc: bool,
+
+    pub in_range_nulls_first: bool,
+
+    pub winref: u32,
+
+    pub copied_order: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ObjectWithArgs {
+
+    pub objname: Vec<Node>,
+
+    pub objargs: Vec<Node>,
+
+    pub args_unspecified: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AccessPriv {
+
+    pub priv_name: String,
+
+    pub cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassItem {
+
+    pub itemtype: i32,
+
+    pub name: ::core::option::Option<ObjectWithArgs>,
+
+    pub number: i32,
+
+    pub order_family: Vec<Node>,
+
+    pub class_args: Vec<Node>,
+
+    pub storedtype: ::core::option::Option<TypeName>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableLikeClause {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub options: u32,
+
+    pub relation_oid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FunctionParameter {
+
+    pub name: String,
+
+    pub arg_type: ::core::option::Option<TypeName>,
+
+    pub mode: i32,
+
+    pub defexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockingClause {
+
+    pub locked_rels: Vec<Node>,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowMarkClause {
+
+    pub rti: u32,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+
+    pub pushed_down: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlSerialize {
+
+    pub xmloption: i32,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithClause {
+
+    pub ctes: Vec<Node>,
+
+    pub recursive: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferClause {
+
+    pub index_elems: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub conname: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictClause {
+
+    pub action: i32,
+
+    pub infer: ::core::option::Option<Box<InferClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommonTableExpr {
+
+    pub ctename: String,
+
+    pub aliascolnames: Vec<Node>,
+
+    pub ctematerialized: i32,
+
+    pub ctequery: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+
+    pub cterecursive: bool,
+
+    pub cterefcount: i32,
+
+    pub ctecolnames: Vec<Node>,
+
+    pub ctecoltypes: Vec<Node>,
+
+    pub ctecoltypmods: Vec<Node>,
+
+    pub ctecolcollations: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RoleSpec {
+
+    pub roletype: i32,
+
+    pub rolename: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TriggerTransition {
+
+    pub name: String,
+
+    pub is_new: bool,
+
+    pub is_table: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionElem {
+
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionSpec {
+
+    pub strategy: String,
+
+    pub part_params: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionBoundSpec {
+
+    pub strategy: String,
+
+    pub is_default: bool,
+
+    pub modulus: i32,
+
+    pub remainder: i32,
+
+    pub listdatums: Vec<Node>,
+
+    pub lowerdatums: Vec<Node>,
+
+    pub upperdatums: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionRangeDatum {
+
+    pub kind: i32,
+
+    pub value: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionCmd {
+
+    pub name: ::core::option::Option<RangeVar>,
+
+    pub bound: ::core::option::Option<PartitionBoundSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumRelation {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub oid: u32,
+
+    pub va_cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct InlineCodeBlock {
+
+    pub source_text: String,
+
+    pub lang_oid: u32,
+
+    pub lang_is_trusted: bool,
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallContext {
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanToken {
+
+    pub start: i32,
+
+    pub end: i32,
+
+    pub token: i32,
+
+    pub keyword_kind: i32,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OverridingKind {
+    Undefined = 0,
+    OverridingNotSet = 1,
+    OverridingUserValue = 2,
+    OverridingSystemValue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum QuerySource {
+    Undefined = 0,
+    QsrcOriginal = 1,
+    QsrcParser = 2,
+    QsrcInsteadRule = 3,
+    QsrcQualInsteadRule = 4,
+    QsrcNonInsteadRule = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByDir {
+    Undefined = 0,
+    SortbyDefault = 1,
+    SortbyAsc = 2,
+    SortbyDesc = 3,
+    SortbyUsing = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByNulls {
+    Undefined = 0,
+    SortbyNullsDefault = 1,
+    SortbyNullsFirst = 2,
+    SortbyNullsLast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AExprKind {
+    Undefined = 0,
+    AexprOp = 1,
+    AexprOpAny = 2,
+    AexprOpAll = 3,
+    AexprDistinct = 4,
+    AexprNotDistinct = 5,
+    AexprNullif = 6,
+    AexprOf = 7,
+    AexprIn = 8,
+    AexprLike = 9,
+    AexprIlike = 10,
+    AexprSimilar = 11,
+    AexprBetween = 12,
+    AexprNotBetween = 13,
+    AexprBetweenSym = 14,
+    AexprNotBetweenSym = 15,
+    AexprParen = 16,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleSpecType {
+    Undefined = 0,
+    RolespecCstring = 1,
+    RolespecCurrentUser = 2,
+    RolespecSessionUser = 3,
+    RolespecPublic = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TableLikeOption {
+    Undefined = 0,
+    CreateTableLikeComments = 1,
+    CreateTableLikeConstraints = 2,
+    CreateTableLikeDefaults = 3,
+    CreateTableLikeGenerated = 4,
+    CreateTableLikeIdentity = 5,
+    CreateTableLikeIndexes = 6,
+    CreateTableLikeStatistics = 7,
+    CreateTableLikeStorage = 8,
+    CreateTableLikeAll = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DefElemAction {
+    Undefined = 0,
+    DefelemUnspec = 1,
+    DefelemSet = 2,
+    DefelemAdd = 3,
+    DefelemDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum PartitionRangeDatumKind {
+    Undefined = 0,
+    PartitionRangeDatumMinvalue = 1,
+    PartitionRangeDatumValue = 2,
+    PartitionRangeDatumMaxvalue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RteKind {
+    RtekindUndefined = 0,
+    RteRelation = 1,
+    RteSubquery = 2,
+    RteJoin = 3,
+    RteFunction = 4,
+    RteTablefunc = 5,
+    RteValues = 6,
+    RteCte = 7,
+    RteNamedtuplestore = 8,
+    RteResult = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum WcoKind {
+    WcokindUndefined = 0,
+    WcoViewCheck = 1,
+    WcoRlsInsertCheck = 2,
+    WcoRlsUpdateCheck = 3,
+    WcoRlsConflictCheck = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GroupingSetKind {
+    Undefined = 0,
+    GroupingSetEmpty = 1,
+    GroupingSetSimple = 2,
+    GroupingSetRollup = 3,
+    GroupingSetCube = 4,
+    GroupingSetSets = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CteMaterialize {
+    CtematerializeUndefined = 0,
+    Default = 1,
+    Always = 2,
+    Never = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOperation {
+    Undefined = 0,
+    SetopNone = 1,
+    SetopUnion = 2,
+    SetopIntersect = 3,
+    SetopExcept = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ObjectType {
+    Undefined = 0,
+    ObjectAccessMethod = 1,
+    ObjectAggregate = 2,
+    ObjectAmop = 3,
+    ObjectAmproc = 4,
+    ObjectAttribute = 5,
+    ObjectCast = 6,
+    ObjectColumn = 7,
+    ObjectCollation = 8,
+    ObjectConversion = 9,
+    ObjectDatabase = 10,
+    ObjectDefault = 11,
+    ObjectDefacl = 12,
+    ObjectDomain = 13,
+    ObjectDomconstraint = 14,
+    ObjectEventTrigger = 15,
+    ObjectExtension = 16,
+    ObjectFdw = 17,
+    ObjectForeignServer = 18,
+    ObjectForeignTable = 19,
+    ObjectFunction = 20,
+    ObjectIndex = 21,
+    ObjectLanguage = 22,
+    ObjectLargeobject = 23,
+    ObjectMatview = 24,
+    ObjectOpclass = 25,
+    ObjectOperator = 26,
+    ObjectOpfamily = 27,
+    ObjectPolicy = 28,
+    ObjectProcedure = 29,
+    ObjectPublication = 30,
+    ObjectPublicationRel = 31,
+    ObjectRole = 32,
+    ObjectRoutine = 33,
+    ObjectRule = 34,
+    ObjectSchema = 35,
+    ObjectSequence = 36,
+    ObjectSubscription = 37,
+    ObjectStatisticExt = 38,
+    ObjectTabconstraint = 39,
+    ObjectTable = 40,
+    ObjectTablespace = 41,
+    ObjectTransform = 42,
+    ObjectTrigger = 43,
+    ObjectTsconfiguration = 44,
+    ObjectTsdictionary = 45,
+    ObjectTsparser = 46,
+    ObjectTstemplate = 47,
+    ObjectType = 48,
+    ObjectUserMapping = 49,
+    ObjectView = 50,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DropBehavior {
+    Undefined = 0,
+    DropRestrict = 1,
+    DropCascade = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTableType {
+    Undefined = 0,
+    AtAddColumn = 1,
+    AtAddColumnRecurse = 2,
+    AtAddColumnToView = 3,
+    AtColumnDefault = 4,
+    AtCookedColumnDefault = 5,
+    AtDropNotNull = 6,
+    AtSetNotNull = 7,
+    AtDropExpression = 8,
+    AtCheckNotNull = 9,
+    AtSetStatistics = 10,
+    AtSetOptions = 11,
+    AtResetOptions = 12,
+    AtSetStorage = 13,
+    AtDropColumn = 14,
+    AtDropColumnRecurse = 15,
+    AtAddIndex = 16,
+    AtReAddIndex = 17,
+    AtAddConstraint = 18,
+    AtAddConstraintRecurse = 19,
+    AtReAddConstraint = 20,
+    AtReAddDomainConstraint = 21,
+    AtAlterConstraint = 22,
+    AtValidateConstraint = 23,
+    AtValidateConstraintRecurse = 24,
+    AtAddIndexConstraint = 25,
+    AtDropConstraint = 26,
+    AtDropConstraintRecurse = 27,
+    AtReAddComment = 28,
+    AtAlterColumnType = 29,
+    AtAlterColumnGenericOptions = 30,
+    AtChangeOwner = 31,
+    AtClusterOn = 32,
+    AtDropCluster = 33,
+    AtSetLogged = 34,
+    AtSetUnLogged = 35,
+    AtDropOids = 36,
+    AtSetTableSpace = 37,
+    AtSetRelOptions = 38,
+    AtResetRelOptions = 39,
+    AtReplaceRelOptions = 40,
+    AtEnableTrig = 41,
+    AtEnableAlwaysTrig = 42,
+    AtEnableReplicaTrig = 43,
+    AtDisableTrig = 44,
+    AtEnableTrigAll = 45,
+    AtDisableTrigAll = 46,
+    AtEnableTrigUser = 47,
+    AtDisableTrigUser = 48,
+    AtEnableRule = 49,
+    AtEnableAlwaysRule = 50,
+    AtEnableReplicaRule = 51,
+    AtDisableRule = 52,
+    AtAddInherit = 53,
+    AtDropInherit = 54,
+    AtAddOf = 55,
+    AtDropOf = 56,
+    AtReplicaIdentity = 57,
+    AtEnableRowSecurity = 58,
+    AtDisableRowSecurity = 59,
+    AtForceRowSecurity = 60,
+    AtNoForceRowSecurity = 61,
+    AtGenericOptions = 62,
+    AtAttachPartition = 63,
+    AtDetachPartition = 64,
+    AtAddIdentity = 65,
+    AtSetIdentity = 66,
+    AtDropIdentity = 67,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GrantTargetType {
+    Undefined = 0,
+    AclTargetObject = 1,
+    AclTargetAllInSchema = 2,
+    AclTargetDefaults = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum VariableSetKind {
+    Undefined = 0,
+    VarSetValue = 1,
+    VarSetDefault = 2,
+    VarSetCurrent = 3,
+    VarSetMulti = 4,
+    VarReset = 5,
+    VarResetAll = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ConstrType {
+    Undefined = 0,
+    ConstrNull = 1,
+    ConstrNotnull = 2,
+    ConstrDefault = 3,
+    ConstrIdentity = 4,
+    ConstrGenerated = 5,
+    ConstrCheck = 6,
+    ConstrPrimary = 7,
+    ConstrUnique = 8,
+    ConstrExclusion = 9,
+    ConstrForeign = 10,
+    ConstrAttrDeferrable = 11,
+    ConstrAttrNotDeferrable = 12,
+    ConstrAttrDeferred = 13,
+    ConstrAttrImmediate = 14,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ImportForeignSchemaType {
+    Undefined = 0,
+    FdwImportSchemaAll = 1,
+    FdwImportSchemaLimitTo = 2,
+    FdwImportSchemaExcept = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleStmtType {
+    Undefined = 0,
+    RolestmtRole = 1,
+    RolestmtUser = 2,
+    RolestmtGroup = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FetchDirection {
+    Undefined = 0,
+    FetchForward = 1,
+    FetchBackward = 2,
+    FetchAbsolute = 3,
+    FetchRelative = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FunctionParameterMode {
+    Undefined = 0,
+    FuncParamIn = 1,
+    FuncParamOut = 2,
+    FuncParamInout = 3,
+    FuncParamVariadic = 4,
+    FuncParamTable = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TransactionStmtKind {
+    Undefined = 0,
+    TransStmtBegin = 1,
+    TransStmtStart = 2,
+    TransStmtCommit = 3,
+    TransStmtRollback = 4,
+    TransStmtSavepoint = 5,
+    TransStmtRelease = 6,
+    TransStmtRollbackTo = 7,
+    TransStmtPrepare = 8,
+    TransStmtCommitPrepared = 9,
+    TransStmtRollbackPrepared = 10,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ViewCheckOption {
+    Undefined = 0,
+    NoCheckOption = 1,
+    LocalCheckOption = 2,
+    CascadedCheckOption = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ClusterOption {
+    Undefined = 0,
+    CluoptRecheck = 1,
+    CluoptVerbose = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DiscardMode {
+    Undefined = 0,
+    DiscardAll = 1,
+    DiscardPlans = 2,
+    DiscardSequences = 3,
+    DiscardTemp = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ReindexObjectType {
+    Undefined = 0,
+    ReindexObjectIndex = 1,
+    ReindexObjectTable = 2,
+    ReindexObjectSchema = 3,
+    ReindexObjectSystem = 4,
+    ReindexObjectDatabase = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTsConfigType {
+    AlterTsconfigTypeUndefined = 0,
+    AlterTsconfigAddMapping = 1,
+    AlterTsconfigAlterMappingForToken = 2,
+    AlterTsconfigReplaceDict = 3,
+    AlterTsconfigReplaceDictForToken = 4,
+    AlterTsconfigDropMapping = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterSubscriptionType {
+    Undefined = 0,
+    AlterSubscriptionOptions = 1,
+    AlterSubscriptionConnection = 2,
+    AlterSubscriptionPublication = 3,
+    AlterSubscriptionRefresh = 4,
+    AlterSubscriptionEnabled = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnCommitAction {
+    Undefined = 0,
+    OncommitNoop = 1,
+    OncommitPreserveRows = 2,
+    OncommitDeleteRows = 3,
+    OncommitDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ParamKind {
+    Undefined = 0,
+    ParamExtern = 1,
+    ParamExec = 2,
+    ParamSublink = 3,
+    ParamMultiexpr = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionContext {
+    Undefined = 0,
+    CoercionImplicit = 1,
+    CoercionAssignment = 2,
+    CoercionExplicit = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionForm {
+    Undefined = 0,
+    CoerceExplicitCall = 1,
+    CoerceExplicitCast = 2,
+    CoerceImplicitCast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolExprType {
+    Undefined = 0,
+    AndExpr = 1,
+    OrExpr = 2,
+    NotExpr = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SubLinkType {
+    Undefined = 0,
+    ExistsSublink = 1,
+    AllSublink = 2,
+    AnySublink = 3,
+    RowcompareSublink = 4,
+    ExprSublink = 5,
+    MultiexprSublink = 6,
+    ArraySublink = 7,
+    CteSublink = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RowCompareType {
+    Undefined = 0,
+    RowcompareLt = 1,
+    RowcompareLe = 2,
+    RowcompareEq = 3,
+    RowcompareGe = 4,
+    RowcompareGt = 5,
+    RowcompareNe = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum MinMaxOp {
+    Undefined = 0,
+    IsGreatest = 1,
+    IsLeast = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SqlValueFunctionOp {
+    SqlvalueFunctionOpUndefined = 0,
+    SvfopCurrentDate = 1,
+    SvfopCurrentTime = 2,
+    SvfopCurrentTimeN = 3,
+    SvfopCurrentTimestamp = 4,
+    SvfopCurrentTimestampN = 5,
+    SvfopLocaltime = 6,
+    SvfopLocaltimeN = 7,
+    SvfopLocaltimestamp = 8,
+    SvfopLocaltimestampN = 9,
+    SvfopCurrentRole = 10,
+    SvfopCurrentUser = 11,
+    SvfopUser = 12,
+    SvfopSessionUser = 13,
+    SvfopCurrentCatalog = 14,
+    SvfopCurrentSchema = 15,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlExprOp {
+    Undefined = 0,
+    IsXmlconcat = 1,
+    IsXmlelement = 2,
+    IsXmlforest = 3,
+    IsXmlparse = 4,
+    IsXmlpi = 5,
+    IsXmlroot = 6,
+    IsXmlserialize = 7,
+    IsDocument = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlOptionType {
+    Undefined = 0,
+    XmloptionDocument = 1,
+    XmloptionContent = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum NullTestType {
+    Undefined = 0,
+    IsNull = 1,
+    IsNotNull = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolTestType {
+    Undefined = 0,
+    IsTrue = 1,
+    IsNotTrue = 2,
+    IsFalse = 3,
+    IsNotFalse = 4,
+    IsUnknown = 5,
+    IsNotUnknown = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CmdType {
+    Undefined = 0,
+    CmdUnknown = 1,
+    CmdSelect = 2,
+    CmdUpdate = 3,
+    CmdInsert = 4,
+    CmdDelete = 5,
+    CmdUtility = 6,
+    CmdNothing = 7,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum JoinType {
+    Undefined = 0,
+    JoinInner = 1,
+    JoinLeft = 2,
+    JoinFull = 3,
+    JoinRight = 4,
+    JoinSemi = 5,
+    JoinAnti = 6,
+    JoinUniqueOuter = 7,
+    JoinUniqueInner = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggStrategy {
+    Undefined = 0,
+    AggPlain = 1,
+    AggSorted = 2,
+    AggHashed = 3,
+    AggMixed = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggSplit {
+    Undefined = 0,
+    AggsplitSimple = 1,
+    AggsplitInitialSerial = 2,
+    AggsplitFinalDeserial = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpCmd {
+    Undefined = 0,
+    SetopcmdIntersect = 1,
+    SetopcmdIntersectAll = 2,
+    SetopcmdExcept = 3,
+    SetopcmdExceptAll = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpStrategy {
+    Undefined = 0,
+    SetopSorted = 1,
+    SetopHashed = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnConflictAction {
+    Undefined = 0,
+    OnconflictNone = 1,
+    OnconflictNothing = 2,
+    OnconflictUpdate = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LimitOption {
+    Undefined = 0,
+    Default = 1,
+    Count = 2,
+    WithTies = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockClauseStrength {
+    Undefined = 0,
+    LcsNone = 1,
+    LcsForkeyshare = 2,
+    LcsForshare = 3,
+    LcsFornokeyupdate = 4,
+    LcsForupdate = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockWaitPolicy {
+    Undefined = 0,
+    LockWaitBlock = 1,
+    LockWaitSkip = 2,
+    LockWaitError = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockTupleMode {
+    Undefined = 0,
+    LockTupleKeyShare = 1,
+    LockTupleShare = 2,
+    LockTupleNoKeyExclusive = 3,
+    LockTupleExclusive = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum KeywordKind {
+    NoKeyword = 0,
+    UnreservedKeyword = 1,
+    ColNameKeyword = 2,
+    TypeFuncNameKeyword = 3,
+    ReservedKeyword = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum Token {
+    Nul = 0,
+    /// Single-character tokens that are returned 1:1 (identical with "self" list in scan.l)
+    /// Either supporting syntax, or single-character operators (some can be both)
+    /// Also see <https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-SPECIAL-CHARS>
+    ///
+    /// "%"
+    Ascii37 = 37,
+    /// "("
+    Ascii40 = 40,
+    /// ")"
+    Ascii41 = 41,
+    /// "*"
+    Ascii42 = 42,
+    /// "+"
+    Ascii43 = 43,
+    /// ","
+    Ascii44 = 44,
+    /// "-"
+    Ascii45 = 45,
+    /// "."
+    Ascii46 = 46,
+    /// "/"
+    Ascii47 = 47,
+    /// ":"
+    Ascii58 = 58,
+    /// ";"
+    Ascii59 = 59,
+    /// "<"
+    Ascii60 = 60,
+    /// "="
+    Ascii61 = 61,
+    /// ">"
+    Ascii62 = 62,
+    /// "?"
+    Ascii63 = 63,
+    /// "["
+    Ascii91 = 91,
+    /// "\"
+    Ascii92 = 92,
+    /// "]"
+    Ascii93 = 93,
+    /// "^"
+    Ascii94 = 94,
+    /// Named tokens in scan.l
+    Ident = 258,
+    Uident = 259,
+    Fconst = 260,
+    Sconst = 261,
+    Usconst = 262,
+    Bconst = 263,
+    Xconst = 264,
+    Op = 265,
+    Iconst = 266,
+    Param = 267,
+    Typecast = 268,
+    DotDot = 269,
+    ColonEquals = 270,
+    EqualsGreater = 271,
+    LessEquals = 272,
+    GreaterEquals = 273,
+    NotEquals = 274,
+    SqlComment = 275,
+    CComment = 276,
+    AbortP = 277,
+    AbsoluteP = 278,
+    Access = 279,
+    Action = 280,
+    AddP = 281,
+    Admin = 282,
+    After = 283,
+    Aggregate = 284,
+    All = 285,
+    Also = 286,
+    Alter = 287,
+    Always = 288,
+    Analyse = 289,
+    Analyze = 290,
+    And = 291,
+    Any = 292,
+    Array = 293,
+    As = 294,
+    Asc = 295,
+    Assertion = 296,
+    Assignment = 297,
+    Asymmetric = 298,
+    At = 299,
+    Attach = 300,
+    Attribute = 301,
+    Authorization = 302,
+    Backward = 303,
+    Before = 304,
+    BeginP = 305,
+    Between = 306,
+    Bigint = 307,
+    Binary = 308,
+    Bit = 309,
+    BooleanP = 310,
+    Both = 311,
+    By = 312,
+    Cache = 313,
+    Call = 314,
+    Called = 315,
+    Cascade = 316,
+    Cascaded = 317,
+    Case = 318,
+    Cast = 319,
+    CatalogP = 320,
+    Chain = 321,
+    CharP = 322,
+    Character = 323,
+    Characteristics = 324,
+    Check = 325,
+    Checkpoint = 326,
+    Class = 327,
+    Close = 328,
+    Cluster = 329,
+    Coalesce = 330,
+    Collate = 331,
+    Collation = 332,
+    Column = 333,
+    Columns = 334,
+    Comment = 335,
+    Comments = 336,
+    Commit = 337,
+    Committed = 338,
+    Concurrently = 339,
+    Configuration = 340,
+    Conflict = 341,
+    Connection = 342,
+    Constraint = 343,
+    Constraints = 344,
+    ContentP = 345,
+    ContinueP = 346,
+    ConversionP = 347,
+    Copy = 348,
+    Cost = 349,
+    Create = 350,
+    Cross = 351,
+    Csv = 352,
+    Cube = 353,
+    CurrentP = 354,
+    CurrentCatalog = 355,
+    CurrentDate = 356,
+    CurrentRole = 357,
+    CurrentSchema = 358,
+    CurrentTime = 359,
+    CurrentTimestamp = 360,
+    CurrentUser = 361,
+    Cursor = 362,
+    Cycle = 363,
+    DataP = 364,
+    Database = 365,
+    DayP = 366,
+    Deallocate = 367,
+    Dec = 368,
+    DecimalP = 369,
+    Declare = 370,
+    Default = 371,
+    Defaults = 372,
+    Deferrable = 373,
+    Deferred = 374,
+    Definer = 375,
+    DeleteP = 376,
+    Delimiter = 377,
+    Delimiters = 378,
+    Depends = 379,
+    Desc = 380,
+    Detach = 381,
+    Dictionary = 382,
+    DisableP = 383,
+    Discard = 384,
+    Distinct = 385,
+    Do = 386,
+    DocumentP = 387,
+    DomainP = 388,
+    DoubleP = 389,
+    Drop = 390,
+    Each = 391,
+    Else = 392,
+    EnableP = 393,
+    Encoding = 394,
+    Encrypted = 395,
+    EndP = 396,
+    EnumP = 397,
+    Escape = 398,
+    Event = 399,
+    Except = 400,
+    Exclude = 401,
+    Excluding = 402,
+    Exclusive = 403,
+    Execute = 404,
+    Exists = 405,
+    Explain = 406,
+    Expression = 407,
+    Extension = 408,
+    External = 409,
+    Extract = 410,
+    FalseP = 411,
+    Family = 412,
+    Fetch = 413,
+    Filter = 414,
+    FirstP = 415,
+    FloatP = 416,
+    Following = 417,
+    For = 418,
+    Force = 419,
+    Foreign = 420,
+    Forward = 421,
+    Freeze = 422,
+    From = 423,
+    Full = 424,
+    Function = 425,
+    Functions = 426,
+    Generated = 427,
+    Global = 428,
+    Grant = 429,
+    Granted = 430,
+    Greatest = 431,
+    GroupP = 432,
+    Grouping = 433,
+    Groups = 434,
+    Handler = 435,
+    Having = 436,
+    HeaderP = 437,
+    Hold = 438,
+    HourP = 439,
+    IdentityP = 440,
+    IfP = 441,
+    Ilike = 442,
+    Immediate = 443,
+    Immutable = 444,
+    ImplicitP = 445,
+    ImportP = 446,
+    InP = 447,
+    Include = 448,
+    Including = 449,
+    Increment = 450,
+    Index = 451,
+    Indexes = 452,
+    Inherit = 453,
+    Inherits = 454,
+    Initially = 455,
+    InlineP = 456,
+    InnerP = 457,
+    Inout = 458,
+    InputP = 459,
+    Insensitive = 460,
+    Insert = 461,
+    Instead = 462,
+    IntP = 463,
+    Integer = 464,
+    Intersect = 465,
+    Interval = 466,
+    Into = 467,
+    Invoker = 468,
+    Is = 469,
+    Isnull = 470,
+    Isolation = 471,
+    Join = 472,
+    Key = 473,
+    Label = 474,
+    Language = 475,
+    LargeP = 476,
+    LastP = 477,
+    LateralP = 478,
+    Leading = 479,
+    Leakproof = 480,
+    Least = 481,
+    Left = 482,
+    Level = 483,
+    Like = 484,
+    Limit = 485,
+    Listen = 486,
+    Load = 487,
+    Local = 488,
+    Localtime = 489,
+    Localtimestamp = 490,
+    Location = 491,
+    LockP = 492,
+    Locked = 493,
+    Logged = 494,
+    Mapping = 495,
+    Match = 496,
+    Materialized = 497,
+    Maxvalue = 498,
+    Method = 499,
+    MinuteP = 500,
+    Minvalue = 501,
+    Mode = 502,
+    MonthP = 503,
+    Move = 504,
+    NameP = 505,
+    Names = 506,
+    National = 507,
+    Natural = 508,
+    Nchar = 509,
+    New = 510,
+    Next = 511,
+    Nfc = 512,
+    Nfd = 513,
+    Nfkc = 514,
+    Nfkd = 515,
+    No = 516,
+    None = 517,
+    Normalize = 518,
+    Normalized = 519,
+    Not = 520,
+    Nothing = 521,
+    Notify = 522,
+    Notnull = 523,
+    Nowait = 524,
+    NullP = 525,
+    Nullif = 526,
+    NullsP = 527,
+    Numeric = 528,
+    ObjectP = 529,
+    Of = 530,
+    Off = 531,
+    Offset = 532,
+    Oids = 533,
+    Old = 534,
+    On = 535,
+    Only = 536,
+    Operator = 537,
+    Option = 538,
+    Options = 539,
+    Or = 540,
+    Order = 541,
+    Ordinality = 542,
+    Others = 543,
+    OutP = 544,
+    OuterP = 545,
+    Over = 546,
+    Overlaps = 547,
+    Overlay = 548,
+    Overriding = 549,
+    Owned = 550,
+    Owner = 551,
+    Parallel = 552,
+    Parser = 553,
+    Partial = 554,
+    Partition = 555,
+    Passing = 556,
+    Password = 557,
+    Placing = 558,
+    Plans = 559,
+    Policy = 560,
+    Position = 561,
+    Preceding = 562,
+    Precision = 563,
+    Preserve = 564,
+    Prepare = 565,
+    Prepared = 566,
+    Primary = 567,
+    Prior = 568,
+    Privileges = 569,
+    Procedural = 570,
+    Procedure = 571,
+    Procedures = 572,
+    Program = 573,
+    Publication = 574,
+    Quote = 575,
+    Range = 576,
+    Read = 577,
+    Real = 578,
+    Reassign = 579,
+    Recheck = 580,
+    Recursive = 581,
+    Ref = 582,
+    References = 583,
+    Referencing = 584,
+    Refresh = 585,
+    Reindex = 586,
+    RelativeP = 587,
+    Release = 588,
+    Rename = 589,
+    Repeatable = 590,
+    Replace = 591,
+    Replica = 592,
+    Reset = 593,
+    Restart = 594,
+    Restrict = 595,
+    Returning = 596,
+    Returns = 597,
+    Revoke = 598,
+    Right = 599,
+    Role = 600,
+    Rollback = 601,
+    Rollup = 602,
+    Routine = 603,
+    Routines = 604,
+    Row = 605,
+    Rows = 606,
+    Rule = 607,
+    Savepoint = 608,
+    Schema = 609,
+    Schemas = 610,
+    Scroll = 611,
+    Search = 612,
+    SecondP = 613,
+    Security = 614,
+    Select = 615,
+    Sequence = 616,
+    Sequences = 617,
+    Serializable = 618,
+    Server = 619,
+    Session = 620,
+    SessionUser = 621,
+    Set = 622,
+    Sets = 623,
+    Setof = 624,
+    Share = 625,
+    Show = 626,
+    Similar = 627,
+    Simple = 628,
+    Skip = 629,
+    Smallint = 630,
+    Snapshot = 631,
+    Some = 632,
+    SqlP = 633,
+    Stable = 634,
+    StandaloneP = 635,
+    Start = 636,
+    Statement = 637,
+    Statistics = 638,
+    Stdin = 639,
+    Stdout = 640,
+    Storage = 641,
+    Stored = 642,
+    StrictP = 643,
+    StripP = 644,
+    Subscription = 645,
+    Substring = 646,
+    Support = 647,
+    Symmetric = 648,
+    Sysid = 649,
+    SystemP = 650,
+    Table = 651,
+    Tables = 652,
+    Tablesample = 653,
+    Tablespace = 654,
+    Temp = 655,
+    Template = 656,
+    Temporary = 657,
+    TextP = 658,
+    Then = 659,
+    Ties = 660,
+    Time = 661,
+    Timestamp = 662,
+    To = 663,
+    Trailing = 664,
+    Transaction = 665,
+    Transform = 666,
+    Treat = 667,
+    Trigger = 668,
+    Trim = 669,
+    TrueP = 670,
+    Truncate = 671,
+    Trusted = 672,
+    TypeP = 673,
+    TypesP = 674,
+    Uescape = 675,
+    Unbounded = 676,
+    Uncommitted = 677,
+    Unencrypted = 678,
+    Union = 679,
+    Unique = 680,
+    Unknown = 681,
+    Unlisten = 682,
+    Unlogged = 683,
+    Until = 684,
+    Update = 685,
+    User = 686,
+    Using = 687,
+    Vacuum = 688,
+    Valid = 689,
+    Validate = 690,
+    Validator = 691,
+    ValueP = 692,
+    Values = 693,
+    Varchar = 694,
+    Variadic = 695,
+    Varying = 696,
+    Verbose = 697,
+    VersionP = 698,
+    View = 699,
+    Views = 700,
+    Volatile = 701,
+    When = 702,
+    Where = 703,
+    WhitespaceP = 704,
+    Window = 705,
+    With = 706,
+    Within = 707,
+    Without = 708,
+    Work = 709,
+    Wrapper = 710,
+    Write = 711,
+    XmlP = 712,
+    Xmlattributes = 713,
+    Xmlconcat = 714,
+    Xmlelement = 715,
+    Xmlexists = 716,
+    Xmlforest = 717,
+    Xmlnamespaces = 718,
+    Xmlparse = 719,
+    Xmlpi = 720,
+    Xmlroot = 721,
+    Xmlserialize = 722,
+    Xmltable = 723,
+    YearP = 724,
+    YesP = 725,
+    Zone = 726,
+    NotLa = 727,
+    NullsLa = 728,
+    WithLa = 729,
+    Postfixop = 730,
+    Uminus = 731,
+}
diff --git a/tests/target/performance/issue-4476.rs b/tests/target/performance/issue-4476.rs
new file mode 100644
index 00000000000..30567f2644b
--- /dev/null
+++ b/tests/target/performance/issue-4476.rs
@@ -0,0 +1,705 @@
+use super::SemverParser;
+
+#[allow(dead_code, non_camel_case_types)]
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub enum Rule {
+    EOI,
+    range_set,
+    logical_or,
+    range,
+    empty,
+    hyphen,
+    simple,
+    primitive,
+    primitive_op,
+    partial,
+    xr,
+    xr_op,
+    nr,
+    tilde,
+    caret,
+    qualifier,
+    parts,
+    part,
+    space,
+}
+#[allow(clippy::all)]
+impl ::pest::Parser<Rule> for SemverParser {
+    fn parse<'i>(
+        rule: Rule,
+        input: &'i str,
+    ) -> ::std::result::Result<::pest::iterators::Pairs<'i, Rule>, ::pest::error::Error<Rule>> {
+        mod rules {
+            pub mod hidden {
+                use super::super::Rule;
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn skip(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    Ok(state)
+                }
+            }
+            pub mod visible {
+                use super::super::Rule;
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn range_set(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::range_set, |state| {
+                        state.sequence(|state| {
+                            self::SOI(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::range(state))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            state
+                                                .sequence(|state| {
+                                                    self::logical_or(state)
+                                                        .and_then(|state| {
+                                                            super::hidden::skip(state)
+                                                        })
+                                                        .and_then(|state| self::range(state))
+                                                })
+                                                .and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| {
+                                                                    state.sequence(|state| {
+                                                                        self::logical_or(state)
+                                                                            .and_then(|state| {
+                                                                                super::hidden::skip(
+                                                                                    state,
+                                                                                )
+                                                                            })
+                                                                            .and_then(|state| {
+                                                                                self::range(state)
+                                                                            })
+                                                                    })
+                                                                },
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::EOI(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn logical_or(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::logical_or, |state| {
+                        state.sequence(|state| {
+                            state
+                                .sequence(|state| {
+                                    state.optional(|state| {
+                                        self::space(state).and_then(|state| {
+                                            state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                    super::hidden::skip(state)
+                                                        .and_then(|state| self::space(state))
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.match_string("||"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn range(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::range, |state| {
+                        self::hyphen(state)
+                            .or_else(|state| {
+                                state.sequence(|state| {
+                                    self::simple(state)
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                            state.sequence(|state| {
+                                                state.optional(|state| {
+                                                    state
+                                                        .sequence(|state| {
+                                                            state
+                                                                .optional(|state| {
+                                                                    state.match_string(",")
+                                                                })
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    state.sequence(|state| {
+                                                                        self::space(state)
+                                      .and_then(|state| super::hidden::skip(state))
+                                      .and_then(|state| {
+                                        state.sequence(|state| {
+                                          state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                              state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                  super::hidden::skip(state)
+                                                    .and_then(|state| self::space(state))
+                                                })
+                                              })
+                                            })
+                                          })
+                                        })
+                                      })
+                                                                    })
+                                                                })
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    self::simple(state)
+                                                                })
+                                                        })
+                                                        .and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            state.sequence(
+                                                                                |state| {
+                                                                                    state
+                                        .optional(|state| state.match_string(","))
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                          state.sequence(|state| {
+                                            self::space(state)
+                                              .and_then(|state| super::hidden::skip(state))
+                                              .and_then(|state| {
+                                                state.sequence(|state| {
+                                                  state.optional(|state| {
+                                                    self::space(state).and_then(|state| {
+                                                      state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                          super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                        })
+                                                      })
+                                                    })
+                                                  })
+                                                })
+                                              })
+                                          })
+                                        })
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| self::simple(state))
+                                                                                },
+                                                                            )
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                })
+                                            })
+                                        })
+                                })
+                            })
+                            .or_else(|state| self::empty(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn empty(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::empty, |state| state.match_string(""))
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn hyphen(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::hyphen, |state| {
+                        state.sequence(|state| {
+                            self::partial(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        self::space(state)
+                                            .and_then(|state| super::hidden::skip(state))
+                                            .and_then(|state| {
+                                                state.sequence(|state| {
+                                                    state.optional(|state| {
+                                                        self::space(state).and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            self::space(state)
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.match_string("-"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        self::space(state)
+                                            .and_then(|state| super::hidden::skip(state))
+                                            .and_then(|state| {
+                                                state.sequence(|state| {
+                                                    state.optional(|state| {
+                                                        self::space(state).and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            self::space(state)
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn simple(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::simple, |state| {
+                        self::primitive(state)
+                            .or_else(|state| self::partial(state))
+                            .or_else(|state| self::tilde(state))
+                            .or_else(|state| self::caret(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn primitive(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::primitive, |state| {
+                        state.sequence(|state| {
+                            self::primitive_op(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn primitive_op(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::primitive_op, |state| {
+                        state
+                            .match_string("<=")
+                            .or_else(|state| state.match_string(">="))
+                            .or_else(|state| state.match_string(">"))
+                            .or_else(|state| state.match_string("<"))
+                            .or_else(|state| state.match_string("="))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn partial(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::partial, |state| {
+                        state.sequence(|state| {
+                            self::xr(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.optional(|state| {
+                                        state.sequence(|state| {
+                                            state
+                                                .match_string(".")
+                                                .and_then(|state| super::hidden::skip(state))
+                                                .and_then(|state| self::xr(state))
+                                                .and_then(|state| super::hidden::skip(state))
+                                                .and_then(|state| {
+                                                    state.optional(|state| {
+                                                        state.sequence(|state| {
+                                                            state
+                                                                .match_string(".")
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| self::xr(state))
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    state.optional(|state| {
+                                                                        self::qualifier(state)
+                                                                    })
+                                                                })
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn xr(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::xr, |state| {
+                        self::xr_op(state).or_else(|state| self::nr(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn xr_op(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::xr_op, |state| {
+                        state
+                            .match_string("x")
+                            .or_else(|state| state.match_string("X"))
+                            .or_else(|state| state.match_string("*"))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn nr(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::nr, |state| {
+                        state.match_string("0").or_else(|state| {
+                            state.sequence(|state| {
+                                state
+                                    .match_range('1'..'9')
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| {
+                                        state.sequence(|state| {
+                                            state.optional(|state| {
+                                                state.match_range('0'..'9').and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| state.match_range('0'..'9'),
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                            })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn tilde(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::tilde, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("~>")
+                                .or_else(|state| state.match_string("~"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn caret(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::caret, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("^")
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn qualifier(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::qualifier, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("-")
+                                .or_else(|state| state.match_string("+"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::parts(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn parts(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::parts, |state| {
+                        state.sequence(|state| {
+                            self::part(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            state
+                                                .sequence(|state| {
+                                                    state
+                                                        .match_string(".")
+                                                        .and_then(|state| {
+                                                            super::hidden::skip(state)
+                                                        })
+                                                        .and_then(|state| self::part(state))
+                                                })
+                                                .and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| {
+                                                                    state.sequence(|state| {
+                                                                        state
+                                                                            .match_string(".")
+                                                                            .and_then(|state| {
+                                                                                super::hidden::skip(
+                                                                                    state,
+                                                                                )
+                                                                            })
+                                                                            .and_then(|state| {
+                                                                                self::part(state)
+                                                                            })
+                                                                    })
+                                                                },
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn part(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::part, |state| {
+                        self::nr(state).or_else(|state| {
+                            state.sequence(|state| {
+                                state
+                                    .match_string("-")
+                                    .or_else(|state| state.match_range('0'..'9'))
+                                    .or_else(|state| state.match_range('A'..'Z'))
+                                    .or_else(|state| state.match_range('a'..'z'))
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| {
+                                        state.sequence(|state| {
+                                            state.optional(|state| {
+                                                state
+                                                    .match_string("-")
+                                                    .or_else(|state| state.match_range('0'..'9'))
+                                                    .or_else(|state| state.match_range('A'..'Z'))
+                                                    .or_else(|state| state.match_range('a'..'z'))
+                                                    .and_then(|state| {
+                                                        state.repeat(|state| {
+                                                            state.sequence(|state| {
+                                                                super::hidden::skip(state).and_then(
+                                                                    |state| {
+                                                                        state
+                                                                            .match_string("-")
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    '0'..'9',
+                                                                                )
+                                                                            })
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    'A'..'Z',
+                                                                                )
+                                                                            })
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    'a'..'z',
+                                                                                )
+                                                                            })
+                                                                    },
+                                                                )
+                                                            })
+                                                        })
+                                                    })
+                                            })
+                                        })
+                                    })
+                            })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn space(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state
+                        .match_string(" ")
+                        .or_else(|state| state.match_string("\t"))
+                }
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn EOI(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::EOI, |state| state.end_of_input())
+                }
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn SOI(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.start_of_input()
+                }
+            }
+            pub use self::visible::*;
+        }
+        ::pest::state(input, |state| match rule {
+            Rule::range_set => rules::range_set(state),
+            Rule::logical_or => rules::logical_or(state),
+            Rule::range => rules::range(state),
+            Rule::empty => rules::empty(state),
+            Rule::hyphen => rules::hyphen(state),
+            Rule::simple => rules::simple(state),
+            Rule::primitive => rules::primitive(state),
+            Rule::primitive_op => rules::primitive_op(state),
+            Rule::partial => rules::partial(state),
+            Rule::xr => rules::xr(state),
+            Rule::xr_op => rules::xr_op(state),
+            Rule::nr => rules::nr(state),
+            Rule::tilde => rules::tilde(state),
+            Rule::caret => rules::caret(state),
+            Rule::qualifier => rules::qualifier(state),
+            Rule::parts => rules::parts(state),
+            Rule::part => rules::part(state),
+            Rule::space => rules::space(state),
+            Rule::EOI => rules::EOI(state),
+        })
+    }
+}
diff --git a/tests/target/performance/issue-4867.rs b/tests/target/performance/issue-4867.rs
new file mode 100644
index 00000000000..336dae1b64a
--- /dev/null
+++ b/tests/target/performance/issue-4867.rs
@@ -0,0 +1,13 @@
+mod modA {
+    mod modB {
+        mod modC {
+            mod modD {
+                mod modE {
+                    fn func() {
+                        state . rule (Rule :: myrule , | state | { state . sequence (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . sequence (| state | { state . optional (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) . and_then (| state | { state . repeat (| state | { state . sequence (| state | { super :: hidden :: skip (state) . and_then (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) }) }) }) }) }) }) }) }) });
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/target/performance/issue-5128.rs b/tests/target/performance/issue-5128.rs
new file mode 100644
index 00000000000..ba9ebfc6243
--- /dev/null
+++ b/tests/target/performance/issue-5128.rs
@@ -0,0 +1,4898 @@
+fn takes_a_long_time_to_rustfmt() {
+    let inner_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("ranked_by_age_within_key"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from(""),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::AStar(AStar {})),
+                                        }],
+                                        location: 80,
+                                    })),
+                                })),
+                                location: 80,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("rank_in_key"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::FuncCall(Box::new(FuncCall {
+                                        funcname: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("row_number"),
+                                            })),
+                                        }],
+                                        args: vec![],
+                                        agg_order: vec![],
+                                        agg_filter: None,
+                                        agg_within_group: false,
+                                        agg_star: false,
+                                        agg_distinct: false,
+                                        func_variadic: false,
+                                        over: Some(Box::new(WindowDef {
+                                            name: String::from(""),
+                                            refname: String::from(""),
+                                            partition_clause: vec![Node {
+                                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                                    fields: vec![Node {
+                                                        node: Some(node::Node::String(String2 {
+                                                            str: String::from("synthetic_key"),
+                                                        })),
+                                                    }],
+                                                    location: 123,
+                                                })),
+                                            }],
+                                            order_clause: vec![Node {
+                                                node: Some(node::Node::SortBy(Box::new(SortBy {
+                                                    node: Some(Box::new(Node {
+                                                        node: Some(node::Node::ColumnRef(
+                                                            ColumnRef {
+                                                                fields: vec![Node {
+                                                                    node: Some(node::Node::String(
+                                                                        String2 {
+                                                                            str: String::from(
+                                                                                "logical_timestamp",
+                                                                            ),
+                                                                        },
+                                                                    )),
+                                                                }],
+                                                                location: 156,
+                                                            },
+                                                        )),
+                                                    })),
+                                                    sortby_dir: SortByDir::SortbyDesc as i32,
+                                                    sortby_nulls: SortByNulls::SortbyNullsDefault
+                                                        as i32,
+                                                    use_op: vec![],
+                                                    location: -1,
+                                                }))),
+                                            }],
+                                            frame_options: 1058,
+                                            start_offset: None,
+                                            end_offset: None,
+                                            location: 109,
+                                        })),
+                                        location: 91,
+                                    }))),
+                                })),
+                                location: 91,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from("_supertables"),
+                            relname: String::from("9999-9999-9999"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 206,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from("<="),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("logical_timestamp"),
+                                        })),
+                                    }],
+                                    location: 250,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer { ival: 9000 })),
+                                    })),
+                                    location: 271,
+                                }))),
+                            })),
+                            location: 268,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: None,
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 29,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let outer_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("table_name"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column1"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c1"),
+                                            })),
+                                        }],
+                                        location: 301,
+                                    })),
+                                })),
+                                location: 301,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column2"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c2"),
+                                            })),
+                                        }],
+                                        location: 324,
+                                    })),
+                                })),
+                                location: 324,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("ranked_by_age_within_key"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 347,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::BoolExpr(Box::new(BoolExpr {
+                            xpr: None,
+                            boolop: BoolExprType::AndExpr as i32,
+                            args: vec![
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(String2 {
+                                                        str: String::from("rank_in_key"),
+                                                    })),
+                                                }],
+                                                location: 382,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::AConst(Box::new(AConst {
+                                                val: Some(Box::new(Node {
+                                                    node: Some(node::Node::Integer(Integer {
+                                                        ival: 1,
+                                                    })),
+                                                })),
+                                                location: 396,
+                                            }))),
+                                        })),
+                                        location: 394,
+                                    }))),
+                                },
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(String2 {
+                                                        str: String::from("is_deleted"),
+                                                    })),
+                                                }],
+                                                location: 402,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::TypeCast(Box::new(TypeCast {
+                                                arg: Some(Box::new(Node {
+                                                    node: Some(node::Node::AConst(Box::new(
+                                                        AConst {
+                                                            val: Some(Box::new(Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from("f"),
+                                                                    },
+                                                                )),
+                                                            })),
+                                                            location: 415,
+                                                        },
+                                                    ))),
+                                                })),
+                                                type_name: Some(TypeName {
+                                                    names: vec![
+                                                        Node {
+                                                            node: Some(node::Node::String(
+                                                                String2 {
+                                                                    str: String::from("pg_catalog"),
+                                                                },
+                                                            )),
+                                                        },
+                                                        Node {
+                                                            node: Some(node::Node::String(
+                                                                String2 {
+                                                                    str: String::from("bool"),
+                                                                },
+                                                            )),
+                                                        },
+                                                    ],
+                                                    type_oid: 0,
+                                                    setof: false,
+                                                    pct_type: false,
+                                                    typmods: vec![],
+                                                    typemod: -1,
+                                                    array_bounds: vec![],
+                                                    location: -1,
+                                                }),
+                                                location: -1,
+                                            }))),
+                                        })),
+                                        location: 413,
+                                    }))),
+                                },
+                            ],
+                            location: 398,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: inner_cte,
+                        recursive: false,
+                        location: 24,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 5,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let expected_result = ParseResult {
+        version: 130003,
+        stmts: vec![RawStmt {
+            stmt: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+
+                    target_list: vec![Node {
+                        node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                            name: String::from(""),
+                            indirection: vec![],
+                            val: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column1"),
+                                        })),
+                                    }],
+                                    location: 430,
+                                })),
+                            })),
+                            location: 430,
+                        }))),
+                    }],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("table_name"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 443,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from(">"),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column2"),
+                                        })),
+                                    }],
+                                    location: 460,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer { ival: 9000 })),
+                                    })),
+                                    location: 470,
+                                }))),
+                            })),
+                            location: 468,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: outer_cte,
+                        recursive: false,
+                        location: 0,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            stmt_location: 0,
+            stmt_len: 0,
+        }],
+    };
+}
+#[derive(Clone, PartialEq)]
+pub struct ParseResult {
+    pub version: i32,
+
+    pub stmts: Vec<RawStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanResult {
+    pub version: i32,
+
+    pub tokens: Vec<ScanToken>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Node {
+    pub node: ::core::option::Option<node::Node>,
+}
+/// Nested message and enum types in `Node`.
+pub mod node {
+    #[derive(Clone, PartialEq)]
+    pub enum Node {
+        Alias(super::Alias),
+
+        RangeVar(super::RangeVar),
+
+        TableFunc(Box<super::TableFunc>),
+
+        Expr(super::Expr),
+
+        Var(Box<super::Var>),
+
+        Param(Box<super::Param>),
+
+        Aggref(Box<super::Aggref>),
+
+        GroupingFunc(Box<super::GroupingFunc>),
+
+        WindowFunc(Box<super::WindowFunc>),
+
+        SubscriptingRef(Box<super::SubscriptingRef>),
+
+        FuncExpr(Box<super::FuncExpr>),
+
+        NamedArgExpr(Box<super::NamedArgExpr>),
+
+        OpExpr(Box<super::OpExpr>),
+
+        DistinctExpr(Box<super::DistinctExpr>),
+
+        NullIfExpr(Box<super::NullIfExpr>),
+
+        ScalarArrayOpExpr(Box<super::ScalarArrayOpExpr>),
+
+        BoolExpr(Box<super::BoolExpr>),
+
+        SubLink(Box<super::SubLink>),
+
+        SubPlan(Box<super::SubPlan>),
+
+        AlternativeSubPlan(Box<super::AlternativeSubPlan>),
+
+        FieldSelect(Box<super::FieldSelect>),
+
+        FieldStore(Box<super::FieldStore>),
+
+        RelabelType(Box<super::RelabelType>),
+
+        CoerceViaIo(Box<super::CoerceViaIo>),
+
+        ArrayCoerceExpr(Box<super::ArrayCoerceExpr>),
+
+        ConvertRowtypeExpr(Box<super::ConvertRowtypeExpr>),
+
+        CollateExpr(Box<super::CollateExpr>),
+
+        CaseExpr(Box<super::CaseExpr>),
+
+        CaseWhen(Box<super::CaseWhen>),
+
+        CaseTestExpr(Box<super::CaseTestExpr>),
+
+        ArrayExpr(Box<super::ArrayExpr>),
+
+        RowExpr(Box<super::RowExpr>),
+
+        RowCompareExpr(Box<super::RowCompareExpr>),
+
+        CoalesceExpr(Box<super::CoalesceExpr>),
+
+        MinMaxExpr(Box<super::MinMaxExpr>),
+
+        SqlvalueFunction(Box<super::SqlValueFunction>),
+
+        XmlExpr(Box<super::XmlExpr>),
+
+        NullTest(Box<super::NullTest>),
+
+        BooleanTest(Box<super::BooleanTest>),
+
+        CoerceToDomain(Box<super::CoerceToDomain>),
+
+        CoerceToDomainValue(Box<super::CoerceToDomainValue>),
+
+        SetToDefault(Box<super::SetToDefault>),
+
+        CurrentOfExpr(Box<super::CurrentOfExpr>),
+
+        NextValueExpr(Box<super::NextValueExpr>),
+
+        InferenceElem(Box<super::InferenceElem>),
+
+        TargetEntry(Box<super::TargetEntry>),
+
+        RangeTblRef(super::RangeTblRef),
+
+        JoinExpr(Box<super::JoinExpr>),
+
+        FromExpr(Box<super::FromExpr>),
+
+        OnConflictExpr(Box<super::OnConflictExpr>),
+
+        IntoClause(Box<super::IntoClause>),
+
+        RawStmt(Box<super::RawStmt>),
+
+        Query(Box<super::Query>),
+
+        InsertStmt(Box<super::InsertStmt>),
+
+        DeleteStmt(Box<super::DeleteStmt>),
+
+        UpdateStmt(Box<super::UpdateStmt>),
+
+        SelectStmt(Box<super::SelectStmt>),
+
+        AlterTableStmt(super::AlterTableStmt),
+
+        AlterTableCmd(Box<super::AlterTableCmd>),
+
+        AlterDomainStmt(Box<super::AlterDomainStmt>),
+
+        SetOperationStmt(Box<super::SetOperationStmt>),
+
+        GrantStmt(super::GrantStmt),
+
+        GrantRoleStmt(super::GrantRoleStmt),
+
+        AlterDefaultPrivilegesStmt(super::AlterDefaultPrivilegesStmt),
+
+        ClosePortalStmt(super::ClosePortalStmt),
+
+        ClusterStmt(super::ClusterStmt),
+
+        CopyStmt(Box<super::CopyStmt>),
+
+        CreateStmt(super::CreateStmt),
+
+        DefineStmt(super::DefineStmt),
+
+        DropStmt(super::DropStmt),
+
+        TruncateStmt(super::TruncateStmt),
+
+        CommentStmt(Box<super::CommentStmt>),
+
+        FetchStmt(super::FetchStmt),
+
+        IndexStmt(Box<super::IndexStmt>),
+
+        CreateFunctionStmt(super::CreateFunctionStmt),
+
+        AlterFunctionStmt(super::AlterFunctionStmt),
+
+        DoStmt(super::DoStmt),
+
+        RenameStmt(Box<super::RenameStmt>),
+
+        RuleStmt(Box<super::RuleStmt>),
+
+        NotifyStmt(super::NotifyStmt),
+
+        ListenStmt(super::ListenStmt),
+
+        UnlistenStmt(super::UnlistenStmt),
+
+        TransactionStmt(super::TransactionStmt),
+
+        ViewStmt(Box<super::ViewStmt>),
+
+        LoadStmt(super::LoadStmt),
+
+        CreateDomainStmt(Box<super::CreateDomainStmt>),
+
+        CreatedbStmt(super::CreatedbStmt),
+
+        DropdbStmt(super::DropdbStmt),
+
+        VacuumStmt(super::VacuumStmt),
+
+        ExplainStmt(Box<super::ExplainStmt>),
+
+        CreateTableAsStmt(Box<super::CreateTableAsStmt>),
+
+        CreateSeqStmt(super::CreateSeqStmt),
+
+        AlterSeqStmt(super::AlterSeqStmt),
+
+        VariableSetStmt(super::VariableSetStmt),
+
+        VariableShowStmt(super::VariableShowStmt),
+
+        DiscardStmt(super::DiscardStmt),
+
+        CreateTrigStmt(Box<super::CreateTrigStmt>),
+
+        CreatePlangStmt(super::CreatePLangStmt),
+
+        CreateRoleStmt(super::CreateRoleStmt),
+
+        AlterRoleStmt(super::AlterRoleStmt),
+
+        DropRoleStmt(super::DropRoleStmt),
+
+        LockStmt(super::LockStmt),
+
+        ConstraintsSetStmt(super::ConstraintsSetStmt),
+
+        ReindexStmt(super::ReindexStmt),
+
+        CheckPointStmt(super::CheckPointStmt),
+
+        CreateSchemaStmt(super::CreateSchemaStmt),
+
+        AlterDatabaseStmt(super::AlterDatabaseStmt),
+
+        AlterDatabaseSetStmt(super::AlterDatabaseSetStmt),
+
+        AlterRoleSetStmt(super::AlterRoleSetStmt),
+
+        CreateConversionStmt(super::CreateConversionStmt),
+
+        CreateCastStmt(super::CreateCastStmt),
+
+        CreateOpClassStmt(super::CreateOpClassStmt),
+
+        CreateOpFamilyStmt(super::CreateOpFamilyStmt),
+
+        AlterOpFamilyStmt(super::AlterOpFamilyStmt),
+
+        PrepareStmt(Box<super::PrepareStmt>),
+
+        ExecuteStmt(super::ExecuteStmt),
+
+        DeallocateStmt(super::DeallocateStmt),
+
+        DeclareCursorStmt(Box<super::DeclareCursorStmt>),
+
+        CreateTableSpaceStmt(super::CreateTableSpaceStmt),
+
+        DropTableSpaceStmt(super::DropTableSpaceStmt),
+
+        AlterObjectDependsStmt(Box<super::AlterObjectDependsStmt>),
+
+        AlterObjectSchemaStmt(Box<super::AlterObjectSchemaStmt>),
+
+        AlterOwnerStmt(Box<super::AlterOwnerStmt>),
+
+        AlterOperatorStmt(super::AlterOperatorStmt),
+
+        AlterTypeStmt(super::AlterTypeStmt),
+
+        DropOwnedStmt(super::DropOwnedStmt),
+
+        ReassignOwnedStmt(super::ReassignOwnedStmt),
+
+        CompositeTypeStmt(super::CompositeTypeStmt),
+
+        CreateEnumStmt(super::CreateEnumStmt),
+
+        CreateRangeStmt(super::CreateRangeStmt),
+
+        AlterEnumStmt(super::AlterEnumStmt),
+
+        AlterTsdictionaryStmt(super::AlterTsDictionaryStmt),
+
+        AlterTsconfigurationStmt(super::AlterTsConfigurationStmt),
+
+        CreateFdwStmt(super::CreateFdwStmt),
+
+        AlterFdwStmt(super::AlterFdwStmt),
+
+        CreateForeignServerStmt(super::CreateForeignServerStmt),
+
+        AlterForeignServerStmt(super::AlterForeignServerStmt),
+
+        CreateUserMappingStmt(super::CreateUserMappingStmt),
+
+        AlterUserMappingStmt(super::AlterUserMappingStmt),
+
+        DropUserMappingStmt(super::DropUserMappingStmt),
+
+        AlterTableSpaceOptionsStmt(super::AlterTableSpaceOptionsStmt),
+
+        AlterTableMoveAllStmt(super::AlterTableMoveAllStmt),
+
+        SecLabelStmt(Box<super::SecLabelStmt>),
+
+        CreateForeignTableStmt(super::CreateForeignTableStmt),
+
+        ImportForeignSchemaStmt(super::ImportForeignSchemaStmt),
+
+        CreateExtensionStmt(super::CreateExtensionStmt),
+
+        AlterExtensionStmt(super::AlterExtensionStmt),
+
+        AlterExtensionContentsStmt(Box<super::AlterExtensionContentsStmt>),
+
+        CreateEventTrigStmt(super::CreateEventTrigStmt),
+
+        AlterEventTrigStmt(super::AlterEventTrigStmt),
+
+        RefreshMatViewStmt(super::RefreshMatViewStmt),
+
+        ReplicaIdentityStmt(super::ReplicaIdentityStmt),
+
+        AlterSystemStmt(super::AlterSystemStmt),
+
+        CreatePolicyStmt(Box<super::CreatePolicyStmt>),
+
+        AlterPolicyStmt(Box<super::AlterPolicyStmt>),
+
+        CreateTransformStmt(super::CreateTransformStmt),
+
+        CreateAmStmt(super::CreateAmStmt),
+
+        CreatePublicationStmt(super::CreatePublicationStmt),
+
+        AlterPublicationStmt(super::AlterPublicationStmt),
+
+        CreateSubscriptionStmt(super::CreateSubscriptionStmt),
+
+        AlterSubscriptionStmt(super::AlterSubscriptionStmt),
+
+        DropSubscriptionStmt(super::DropSubscriptionStmt),
+
+        CreateStatsStmt(super::CreateStatsStmt),
+
+        AlterCollationStmt(super::AlterCollationStmt),
+
+        CallStmt(Box<super::CallStmt>),
+
+        AlterStatsStmt(super::AlterStatsStmt),
+
+        AExpr(Box<super::AExpr>),
+
+        ColumnRef(super::ColumnRef),
+
+        ParamRef(super::ParamRef),
+
+        AConst(Box<super::AConst>),
+
+        FuncCall(Box<super::FuncCall>),
+
+        AStar(super::AStar),
+
+        AIndices(Box<super::AIndices>),
+
+        AIndirection(Box<super::AIndirection>),
+
+        AArrayExpr(super::AArrayExpr),
+
+        ResTarget(Box<super::ResTarget>),
+
+        MultiAssignRef(Box<super::MultiAssignRef>),
+
+        TypeCast(Box<super::TypeCast>),
+
+        CollateClause(Box<super::CollateClause>),
+
+        SortBy(Box<super::SortBy>),
+
+        WindowDef(Box<super::WindowDef>),
+
+        RangeSubselect(Box<super::RangeSubselect>),
+
+        RangeFunction(super::RangeFunction),
+
+        RangeTableSample(Box<super::RangeTableSample>),
+
+        RangeTableFunc(Box<super::RangeTableFunc>),
+
+        RangeTableFuncCol(Box<super::RangeTableFuncCol>),
+
+        TypeName(super::TypeName),
+
+        ColumnDef(Box<super::ColumnDef>),
+
+        IndexElem(Box<super::IndexElem>),
+
+        Constraint(Box<super::Constraint>),
+
+        DefElem(Box<super::DefElem>),
+
+        RangeTblEntry(Box<super::RangeTblEntry>),
+
+        RangeTblFunction(Box<super::RangeTblFunction>),
+
+        TableSampleClause(Box<super::TableSampleClause>),
+
+        WithCheckOption(Box<super::WithCheckOption>),
+
+        SortGroupClause(super::SortGroupClause),
+
+        GroupingSet(super::GroupingSet),
+
+        WindowClause(Box<super::WindowClause>),
+
+        ObjectWithArgs(super::ObjectWithArgs),
+
+        AccessPriv(super::AccessPriv),
+
+        CreateOpClassItem(super::CreateOpClassItem),
+
+        TableLikeClause(super::TableLikeClause),
+
+        FunctionParameter(Box<super::FunctionParameter>),
+
+        LockingClause(super::LockingClause),
+
+        RowMarkClause(super::RowMarkClause),
+
+        XmlSerialize(Box<super::XmlSerialize>),
+
+        WithClause(super::WithClause),
+
+        InferClause(Box<super::InferClause>),
+
+        OnConflictClause(Box<super::OnConflictClause>),
+
+        CommonTableExpr(Box<super::CommonTableExpr>),
+
+        RoleSpec(super::RoleSpec),
+
+        TriggerTransition(super::TriggerTransition),
+
+        PartitionElem(Box<super::PartitionElem>),
+
+        PartitionSpec(super::PartitionSpec),
+
+        PartitionBoundSpec(super::PartitionBoundSpec),
+
+        PartitionRangeDatum(Box<super::PartitionRangeDatum>),
+
+        PartitionCmd(super::PartitionCmd),
+
+        VacuumRelation(super::VacuumRelation),
+
+        InlineCodeBlock(super::InlineCodeBlock),
+
+        CallContext(super::CallContext),
+
+        Integer(super::Integer),
+
+        Float(super::Float),
+
+        String(super::String2),
+
+        BitString(super::BitString),
+
+        Null(super::Null),
+
+        List(super::List),
+
+        IntList(super::IntList),
+
+        OidList(super::OidList),
+    }
+}
+#[derive(Clone, PartialEq)]
+pub struct Integer {
+    /// machine integer
+    pub ival: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Float {
+    /// string
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct String2 {
+    /// string
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct BitString {
+    /// string
+    pub str: String,
+}
+/// intentionally empty
+#[derive(Clone, PartialEq)]
+pub struct Null {}
+#[derive(Clone, PartialEq)]
+pub struct List {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OidList {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntList {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Alias {
+    pub aliasname: String,
+
+    pub colnames: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeVar {
+    pub catalogname: String,
+
+    pub schemaname: String,
+
+    pub relname: String,
+
+    pub inh: bool,
+
+    pub relpersistence: String,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableFunc {
+    pub ns_uris: Vec<Node>,
+
+    pub ns_names: Vec<Node>,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub colnames: Vec<Node>,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub colexprs: Vec<Node>,
+
+    pub coldefexprs: Vec<Node>,
+
+    pub notnulls: Vec<u64>,
+
+    pub ordinalitycol: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Expr {}
+#[derive(Clone, PartialEq)]
+pub struct Var {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub varno: u32,
+
+    pub varattno: i32,
+
+    pub vartype: u32,
+
+    pub vartypmod: i32,
+
+    pub varcollid: u32,
+
+    pub varlevelsup: u32,
+
+    pub varnosyn: u32,
+
+    pub varattnosyn: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Param {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub paramkind: i32,
+
+    pub paramid: i32,
+
+    pub paramtype: u32,
+
+    pub paramtypmod: i32,
+
+    pub paramcollid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Aggref {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub aggfnoid: u32,
+
+    pub aggtype: u32,
+
+    pub aggcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub aggtranstype: u32,
+
+    pub aggargtypes: Vec<Node>,
+
+    pub aggdirectargs: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub aggorder: Vec<Node>,
+
+    pub aggdistinct: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub aggstar: bool,
+
+    pub aggvariadic: bool,
+
+    pub aggkind: String,
+
+    pub agglevelsup: u32,
+
+    pub aggsplit: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingFunc {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub refs: Vec<Node>,
+
+    pub cols: Vec<Node>,
+
+    pub agglevelsup: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowFunc {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub winfnoid: u32,
+
+    pub wintype: u32,
+
+    pub wincollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub winref: u32,
+
+    pub winstar: bool,
+
+    pub winagg: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubscriptingRef {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub refcontainertype: u32,
+
+    pub refelemtype: u32,
+
+    pub reftypmod: i32,
+
+    pub refcollid: u32,
+
+    pub refupperindexpr: Vec<Node>,
+
+    pub reflowerindexpr: Vec<Node>,
+
+    pub refexpr: ::core::option::Option<Box<Node>>,
+
+    pub refassgnexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub funcid: u32,
+
+    pub funcresulttype: u32,
+
+    pub funcretset: bool,
+
+    pub funcvariadic: bool,
+
+    pub funcformat: i32,
+
+    pub funccollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NamedArgExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub name: String,
+
+    pub argnumber: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OpExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DistinctExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullIfExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScalarArrayOpExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub use_or: bool,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BoolExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub boolop: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubLink {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub sub_link_id: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub oper_name: Vec<Node>,
+
+    pub subselect: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubPlan {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub param_ids: Vec<Node>,
+
+    pub plan_id: i32,
+
+    pub plan_name: String,
+
+    pub first_col_type: u32,
+
+    pub first_col_typmod: i32,
+
+    pub first_col_collation: u32,
+
+    pub use_hash_table: bool,
+
+    pub unknown_eq_false: bool,
+
+    pub parallel_safe: bool,
+
+    pub set_param: Vec<Node>,
+
+    pub par_param: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub startup_cost: f64,
+
+    pub per_call_cost: f64,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlternativeSubPlan {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub subplans: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldSelect {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub fieldnum: i32,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldStore {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub newvals: Vec<Node>,
+
+    pub fieldnums: Vec<Node>,
+
+    pub resulttype: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RelabelType {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub relabelformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceViaIo {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayCoerceExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub elemexpr: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConvertRowtypeExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub convertformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub coll_oid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub casetype: u32,
+
+    pub casecollid: u32,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub defresult: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseWhen {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub result: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseTestExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub array_typeid: u32,
+
+    pub array_collid: u32,
+
+    pub element_typeid: u32,
+
+    pub elements: Vec<Node>,
+
+    pub multidims: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub row_typeid: u32,
+
+    pub row_format: i32,
+
+    pub colnames: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowCompareExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub rctype: i32,
+
+    pub opnos: Vec<Node>,
+
+    pub opfamilies: Vec<Node>,
+
+    pub inputcollids: Vec<Node>,
+
+    pub largs: Vec<Node>,
+
+    pub rargs: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoalesceExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub coalescetype: u32,
+
+    pub coalescecollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MinMaxExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub minmaxtype: u32,
+
+    pub minmaxcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub op: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SqlValueFunction {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub name: String,
+
+    pub named_args: Vec<Node>,
+
+    pub arg_names: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub xmloption: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullTest {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub nulltesttype: i32,
+
+    pub argisrow: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BooleanTest {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub booltesttype: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomain {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coercionformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomainValue {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetToDefault {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CurrentOfExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub cvarno: u32,
+
+    pub cursor_name: String,
+
+    pub cursor_param: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NextValueExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub seqid: u32,
+
+    pub type_id: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferenceElem {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub infercollid: u32,
+
+    pub inferopclass: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TargetEntry {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub resno: i32,
+
+    pub resname: String,
+
+    pub ressortgroupref: u32,
+
+    pub resorigtbl: u32,
+
+    pub resorigcol: i32,
+
+    pub resjunk: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblRef {
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct JoinExpr {
+    pub jointype: i32,
+
+    pub is_natural: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub using_clause: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FromExpr {
+    pub fromlist: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictExpr {
+    pub action: i32,
+
+    pub arbiter_elems: Vec<Node>,
+
+    pub arbiter_where: ::core::option::Option<Box<Node>>,
+
+    pub constraint: u32,
+
+    pub on_conflict_set: Vec<Node>,
+
+    pub on_conflict_where: ::core::option::Option<Box<Node>>,
+
+    pub excl_rel_index: i32,
+
+    pub excl_rel_tlist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntoClause {
+    pub rel: ::core::option::Option<RangeVar>,
+
+    pub col_names: Vec<Node>,
+
+    pub access_method: String,
+
+    pub options: Vec<Node>,
+
+    pub on_commit: i32,
+
+    pub table_space_name: String,
+
+    pub view_query: ::core::option::Option<Box<Node>>,
+
+    pub skip_data: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RawStmt {
+    pub stmt: ::core::option::Option<Box<Node>>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Query {
+    pub command_type: i32,
+
+    pub query_source: i32,
+
+    pub can_set_tag: bool,
+
+    pub utility_stmt: ::core::option::Option<Box<Node>>,
+
+    pub result_relation: i32,
+
+    pub has_aggs: bool,
+
+    pub has_window_funcs: bool,
+
+    pub has_target_srfs: bool,
+
+    pub has_sub_links: bool,
+
+    pub has_distinct_on: bool,
+
+    pub has_recursive: bool,
+
+    pub has_modifying_cte: bool,
+
+    pub has_for_update: bool,
+
+    pub has_row_security: bool,
+
+    pub cte_list: Vec<Node>,
+
+    pub rtable: Vec<Node>,
+
+    pub jointree: ::core::option::Option<Box<FromExpr>>,
+
+    pub target_list: Vec<Node>,
+
+    pub r#override: i32,
+
+    pub on_conflict: ::core::option::Option<Box<OnConflictExpr>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub group_clause: Vec<Node>,
+
+    pub grouping_sets: Vec<Node>,
+
+    pub having_qual: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub distinct_clause: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub row_marks: Vec<Node>,
+
+    pub set_operations: ::core::option::Option<Box<Node>>,
+
+    pub constraint_deps: Vec<Node>,
+
+    pub with_check_options: Vec<Node>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InsertStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cols: Vec<Node>,
+
+    pub select_stmt: ::core::option::Option<Box<Node>>,
+
+    pub on_conflict_clause: ::core::option::Option<Box<OnConflictClause>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub r#override: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeleteStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub using_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct UpdateStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub from_clause: Vec<Node>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct SelectStmt {
+    pub distinct_clause: Vec<Node>,
+
+    pub into_clause: ::core::option::Option<Box<IntoClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub from_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub group_clause: Vec<Node>,
+
+    pub having_clause: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub values_lists: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub locking_clause: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<SelectStmt>>,
+
+    pub rarg: ::core::option::Option<Box<SelectStmt>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cmds: Vec<Node>,
+
+    pub relkind: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableCmd {
+    pub subtype: i32,
+
+    pub name: String,
+
+    pub num: i32,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDomainStmt {
+    pub subtype: String,
+
+    pub type_name: Vec<Node>,
+
+    pub name: String,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetOperationStmt {
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub col_types: Vec<Node>,
+
+    pub col_typmods: Vec<Node>,
+
+    pub col_collations: Vec<Node>,
+
+    pub group_clauses: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantStmt {
+    pub is_grant: bool,
+
+    pub targtype: i32,
+
+    pub objtype: i32,
+
+    pub objects: Vec<Node>,
+
+    pub privileges: Vec<Node>,
+
+    pub grantees: Vec<Node>,
+
+    pub grant_option: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantRoleStmt {
+    pub granted_roles: Vec<Node>,
+
+    pub grantee_roles: Vec<Node>,
+
+    pub is_grant: bool,
+
+    pub admin_opt: bool,
+
+    pub grantor: ::core::option::Option<RoleSpec>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDefaultPrivilegesStmt {
+    pub options: Vec<Node>,
+
+    pub action: ::core::option::Option<GrantStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClosePortalStmt {
+    pub portalname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClusterStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub indexname: String,
+
+    pub options: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CopyStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub attlist: Vec<Node>,
+
+    pub is_from: bool,
+
+    pub is_program: bool,
+
+    pub filename: String,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub table_elts: Vec<Node>,
+
+    pub inh_relations: Vec<Node>,
+
+    pub partbound: ::core::option::Option<PartitionBoundSpec>,
+
+    pub partspec: ::core::option::Option<PartitionSpec>,
+
+    pub of_typename: ::core::option::Option<TypeName>,
+
+    pub constraints: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub oncommit: i32,
+
+    pub tablespacename: String,
+
+    pub access_method: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefineStmt {
+    pub kind: i32,
+
+    pub oldstyle: bool,
+
+    pub defnames: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub definition: Vec<Node>,
+
+    pub if_not_exists: bool,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropStmt {
+    pub objects: Vec<Node>,
+
+    pub remove_type: i32,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct TruncateStmt {
+    pub relations: Vec<Node>,
+
+    pub restart_seqs: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommentStmt {
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub comment: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct FetchStmt {
+    pub direction: i32,
+
+    pub how_many: i64,
+
+    pub portalname: String,
+
+    pub ismove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexStmt {
+    pub idxname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub access_method: String,
+
+    pub table_space: String,
+
+    pub index_params: Vec<Node>,
+
+    pub index_including_params: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub exclude_op_names: Vec<Node>,
+
+    pub idxcomment: String,
+
+    pub index_oid: u32,
+
+    pub old_node: u32,
+
+    pub old_create_subid: u32,
+
+    pub old_first_relfilenode_subid: u32,
+
+    pub unique: bool,
+
+    pub primary: bool,
+
+    pub isconstraint: bool,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub transformed: bool,
+
+    pub concurrent: bool,
+
+    pub if_not_exists: bool,
+
+    pub reset_default_tblspc: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFunctionStmt {
+    pub is_procedure: bool,
+
+    pub replace: bool,
+
+    pub funcname: Vec<Node>,
+
+    pub parameters: Vec<Node>,
+
+    pub return_type: ::core::option::Option<TypeName>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFunctionStmt {
+    pub objtype: i32,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub actions: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DoStmt {
+    pub args: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RenameStmt {
+    pub rename_type: i32,
+
+    pub relation_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub subname: String,
+
+    pub newname: String,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RuleStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub rulename: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub event: i32,
+
+    pub instead: bool,
+
+    pub actions: Vec<Node>,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct NotifyStmt {
+    pub conditionname: String,
+
+    pub payload: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ListenStmt {
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct UnlistenStmt {
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct TransactionStmt {
+    pub kind: i32,
+
+    pub options: Vec<Node>,
+
+    pub savepoint_name: String,
+
+    pub gid: String,
+
+    pub chain: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ViewStmt {
+    pub view: ::core::option::Option<RangeVar>,
+
+    pub aliases: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub replace: bool,
+
+    pub options: Vec<Node>,
+
+    pub with_check_option: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct LoadStmt {
+    pub filename: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateDomainStmt {
+    pub domainname: Vec<Node>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub constraints: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatedbStmt {
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropdbStmt {
+    pub dbname: String,
+
+    pub missing_ok: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumStmt {
+    pub options: Vec<Node>,
+
+    pub rels: Vec<Node>,
+
+    pub is_vacuumcmd: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExplainStmt {
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableAsStmt {
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub into: ::core::option::Option<Box<IntoClause>>,
+
+    pub relkind: i32,
+
+    pub is_select_into: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSeqStmt {
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub owner_id: u32,
+
+    pub for_identity: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSeqStmt {
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub for_identity: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableSetStmt {
+    pub kind: i32,
+
+    pub name: String,
+
+    pub args: Vec<Node>,
+
+    pub is_local: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableShowStmt {
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DiscardStmt {
+    pub target: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTrigStmt {
+    pub trigname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub row: bool,
+
+    pub timing: i32,
+
+    pub events: i32,
+
+    pub columns: Vec<Node>,
+
+    pub when_clause: ::core::option::Option<Box<Node>>,
+
+    pub isconstraint: bool,
+
+    pub transition_rels: Vec<Node>,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub constrrel: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePLangStmt {
+    pub replace: bool,
+
+    pub plname: String,
+
+    pub plhandler: Vec<Node>,
+
+    pub plinline: Vec<Node>,
+
+    pub plvalidator: Vec<Node>,
+
+    pub pltrusted: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRoleStmt {
+    pub stmt_type: i32,
+
+    pub role: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleStmt {
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub options: Vec<Node>,
+
+    pub action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropRoleStmt {
+    pub roles: Vec<Node>,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockStmt {
+    pub relations: Vec<Node>,
+
+    pub mode: i32,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConstraintsSetStmt {
+    pub constraints: Vec<Node>,
+
+    pub deferred: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReindexStmt {
+    pub kind: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub name: String,
+
+    pub options: i32,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CheckPointStmt {}
+#[derive(Clone, PartialEq)]
+pub struct CreateSchemaStmt {
+    pub schemaname: String,
+
+    pub authrole: ::core::option::Option<RoleSpec>,
+
+    pub schema_elts: Vec<Node>,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseStmt {
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseSetStmt {
+    pub dbname: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleSetStmt {
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub database: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateConversionStmt {
+    pub conversion_name: Vec<Node>,
+
+    pub for_encoding_name: String,
+
+    pub to_encoding_name: String,
+
+    pub func_name: Vec<Node>,
+
+    pub def: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateCastStmt {
+    pub sourcetype: ::core::option::Option<TypeName>,
+
+    pub targettype: ::core::option::Option<TypeName>,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub context: i32,
+
+    pub inout: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassStmt {
+    pub opclassname: Vec<Node>,
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub datatype: ::core::option::Option<TypeName>,
+
+    pub items: Vec<Node>,
+
+    pub is_default: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpFamilyStmt {
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOpFamilyStmt {
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub is_drop: bool,
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct PrepareStmt {
+    pub name: String,
+
+    pub argtypes: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExecuteStmt {
+    pub name: String,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeallocateStmt {
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeclareCursorStmt {
+    pub portalname: String,
+
+    pub options: i32,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableSpaceStmt {
+    pub tablespacename: String,
+
+    pub owner: ::core::option::Option<RoleSpec>,
+
+    pub location: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropTableSpaceStmt {
+    pub tablespacename: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectDependsStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub extname: ::core::option::Option<Box<Node>>,
+
+    pub remove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectSchemaStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newschema: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOwnerStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOperatorStmt {
+    pub opername: ::core::option::Option<ObjectWithArgs>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTypeStmt {
+    pub type_name: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropOwnedStmt {
+    pub roles: Vec<Node>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReassignOwnedStmt {
+    pub roles: Vec<Node>,
+
+    pub newrole: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CompositeTypeStmt {
+    pub typevar: ::core::option::Option<RangeVar>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEnumStmt {
+    pub type_name: Vec<Node>,
+
+    pub vals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRangeStmt {
+    pub type_name: Vec<Node>,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEnumStmt {
+    pub type_name: Vec<Node>,
+
+    pub old_val: String,
+
+    pub new_val: String,
+
+    pub new_val_neighbor: String,
+
+    pub new_val_is_after: bool,
+
+    pub skip_if_new_val_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsDictionaryStmt {
+    pub dictname: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsConfigurationStmt {
+    pub kind: i32,
+
+    pub cfgname: Vec<Node>,
+
+    pub tokentype: Vec<Node>,
+
+    pub dicts: Vec<Node>,
+
+    pub r#override: bool,
+
+    pub replace: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFdwStmt {
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFdwStmt {
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignServerStmt {
+    pub servername: String,
+
+    pub servertype: String,
+
+    pub version: String,
+
+    pub fdwname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterForeignServerStmt {
+    pub servername: String,
+
+    pub version: String,
+
+    pub options: Vec<Node>,
+
+    pub has_version: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableSpaceOptionsStmt {
+    pub tablespacename: String,
+
+    pub options: Vec<Node>,
+
+    pub is_reset: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableMoveAllStmt {
+    pub orig_tablespacename: String,
+
+    pub objtype: i32,
+
+    pub roles: Vec<Node>,
+
+    pub new_tablespacename: String,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SecLabelStmt {
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub provider: String,
+
+    pub label: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignTableStmt {
+    pub base_stmt: ::core::option::Option<CreateStmt>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ImportForeignSchemaStmt {
+    pub server_name: String,
+
+    pub remote_schema: String,
+
+    pub local_schema: String,
+
+    pub list_type: i32,
+
+    pub table_list: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateExtensionStmt {
+    pub extname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionStmt {
+    pub extname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionContentsStmt {
+    pub extname: String,
+
+    pub action: i32,
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEventTrigStmt {
+    pub trigname: String,
+
+    pub eventname: String,
+
+    pub whenclause: Vec<Node>,
+
+    pub funcname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEventTrigStmt {
+    pub trigname: String,
+
+    pub tgenabled: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct RefreshMatViewStmt {
+    pub concurrent: bool,
+
+    pub skip_data: bool,
+
+    pub relation: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReplicaIdentityStmt {
+    pub identity_type: String,
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSystemStmt {
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePolicyStmt {
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub cmd_name: String,
+
+    pub permissive: bool,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPolicyStmt {
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTransformStmt {
+    pub replace: bool,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub lang: String,
+
+    pub fromsql: ::core::option::Option<ObjectWithArgs>,
+
+    pub tosql: ::core::option::Option<ObjectWithArgs>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateAmStmt {
+    pub amname: String,
+
+    pub handler_name: Vec<Node>,
+
+    pub amtype: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePublicationStmt {
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPublicationStmt {
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+
+    pub table_action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSubscriptionStmt {
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSubscriptionStmt {
+    pub kind: i32,
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropSubscriptionStmt {
+    pub subname: String,
+
+    pub missing_ok: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStatsStmt {
+    pub defnames: Vec<Node>,
+
+    pub stat_types: Vec<Node>,
+
+    pub exprs: Vec<Node>,
+
+    pub relations: Vec<Node>,
+
+    pub stxcomment: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterCollationStmt {
+    pub collname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallStmt {
+    pub funccall: ::core::option::Option<Box<FuncCall>>,
+
+    pub funcexpr: ::core::option::Option<Box<FuncExpr>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterStatsStmt {
+    pub defnames: Vec<Node>,
+
+    pub stxstattarget: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AExpr {
+    pub kind: i32,
+
+    pub name: Vec<Node>,
+
+    pub lexpr: ::core::option::Option<Box<Node>>,
+
+    pub rexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnRef {
+    pub fields: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ParamRef {
+    pub number: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AConst {
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncCall {
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub agg_order: Vec<Node>,
+
+    pub agg_filter: ::core::option::Option<Box<Node>>,
+
+    pub agg_within_group: bool,
+
+    pub agg_star: bool,
+
+    pub agg_distinct: bool,
+
+    pub func_variadic: bool,
+
+    pub over: ::core::option::Option<Box<WindowDef>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AStar {}
+#[derive(Clone, PartialEq)]
+pub struct AIndices {
+    pub is_slice: bool,
+
+    pub lidx: ::core::option::Option<Box<Node>>,
+
+    pub uidx: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AIndirection {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub indirection: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AArrayExpr {
+    pub elements: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ResTarget {
+    pub name: String,
+
+    pub indirection: Vec<Node>,
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MultiAssignRef {
+    pub source: ::core::option::Option<Box<Node>>,
+
+    pub colno: i32,
+
+    pub ncolumns: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeCast {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateClause {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub collname: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortBy {
+    pub node: ::core::option::Option<Box<Node>>,
+
+    pub sortby_dir: i32,
+
+    pub sortby_nulls: i32,
+
+    pub use_op: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowDef {
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeSubselect {
+    pub lateral: bool,
+
+    pub subquery: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeFunction {
+    pub lateral: bool,
+
+    pub ordinality: bool,
+
+    pub is_rowsfrom: bool,
+
+    pub functions: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableSample {
+    pub relation: ::core::option::Option<Box<Node>>,
+
+    pub method: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFunc {
+    pub lateral: bool,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub namespaces: Vec<Node>,
+
+    pub columns: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFuncCol {
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub for_ordinality: bool,
+
+    pub is_not_null: bool,
+
+    pub colexpr: ::core::option::Option<Box<Node>>,
+
+    pub coldefexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeName {
+    pub names: Vec<Node>,
+
+    pub type_oid: u32,
+
+    pub setof: bool,
+
+    pub pct_type: bool,
+
+    pub typmods: Vec<Node>,
+
+    pub typemod: i32,
+
+    pub array_bounds: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnDef {
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub inhcount: i32,
+
+    pub is_local: bool,
+
+    pub is_not_null: bool,
+
+    pub is_from_type: bool,
+
+    pub storage: String,
+
+    pub raw_default: ::core::option::Option<Box<Node>>,
+
+    pub cooked_default: ::core::option::Option<Box<Node>>,
+
+    pub identity: String,
+
+    pub identity_sequence: ::core::option::Option<RangeVar>,
+
+    pub generated: String,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub coll_oid: u32,
+
+    pub constraints: Vec<Node>,
+
+    pub fdwoptions: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexElem {
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub indexcolname: String,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub opclassopts: Vec<Node>,
+
+    pub ordering: i32,
+
+    pub nulls_ordering: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Constraint {
+    pub contype: i32,
+
+    pub conname: String,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub location: i32,
+
+    pub is_no_inherit: bool,
+
+    pub raw_expr: ::core::option::Option<Box<Node>>,
+
+    pub cooked_expr: String,
+
+    pub generated_when: String,
+
+    pub keys: Vec<Node>,
+
+    pub including: Vec<Node>,
+
+    pub exclusions: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub indexname: String,
+
+    pub indexspace: String,
+
+    pub reset_default_tblspc: bool,
+
+    pub access_method: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub pktable: ::core::option::Option<RangeVar>,
+
+    pub fk_attrs: Vec<Node>,
+
+    pub pk_attrs: Vec<Node>,
+
+    pub fk_matchtype: String,
+
+    pub fk_upd_action: String,
+
+    pub fk_del_action: String,
+
+    pub old_conpfeqop: Vec<Node>,
+
+    pub old_pktable_oid: u32,
+
+    pub skip_validation: bool,
+
+    pub initially_valid: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefElem {
+    pub defnamespace: String,
+
+    pub defname: String,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub defaction: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblEntry {
+    pub rtekind: i32,
+
+    pub relid: u32,
+
+    pub relkind: String,
+
+    pub rellockmode: i32,
+
+    pub tablesample: ::core::option::Option<Box<TableSampleClause>>,
+
+    pub subquery: ::core::option::Option<Box<Query>>,
+
+    pub security_barrier: bool,
+
+    pub jointype: i32,
+
+    pub joinmergedcols: i32,
+
+    pub joinaliasvars: Vec<Node>,
+
+    pub joinleftcols: Vec<Node>,
+
+    pub joinrightcols: Vec<Node>,
+
+    pub functions: Vec<Node>,
+
+    pub funcordinality: bool,
+
+    pub tablefunc: ::core::option::Option<Box<TableFunc>>,
+
+    pub values_lists: Vec<Node>,
+
+    pub ctename: String,
+
+    pub ctelevelsup: u32,
+
+    pub self_reference: bool,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub enrname: String,
+
+    pub enrtuples: f64,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub eref: ::core::option::Option<Alias>,
+
+    pub lateral: bool,
+
+    pub inh: bool,
+
+    pub in_from_cl: bool,
+
+    pub required_perms: u32,
+
+    pub check_as_user: u32,
+
+    pub selected_cols: Vec<u64>,
+
+    pub inserted_cols: Vec<u64>,
+
+    pub updated_cols: Vec<u64>,
+
+    pub extra_updated_cols: Vec<u64>,
+
+    pub security_quals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblFunction {
+    pub funcexpr: ::core::option::Option<Box<Node>>,
+
+    pub funccolcount: i32,
+
+    pub funccolnames: Vec<Node>,
+
+    pub funccoltypes: Vec<Node>,
+
+    pub funccoltypmods: Vec<Node>,
+
+    pub funccolcollations: Vec<Node>,
+
+    pub funcparams: Vec<u64>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableSampleClause {
+    pub tsmhandler: u32,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithCheckOption {
+    pub kind: i32,
+
+    pub relname: String,
+
+    pub polname: String,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub cascaded: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortGroupClause {
+    pub tle_sort_group_ref: u32,
+
+    pub eqop: u32,
+
+    pub sortop: u32,
+
+    pub nulls_first: bool,
+
+    pub hashable: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingSet {
+    pub kind: i32,
+
+    pub content: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowClause {
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub start_in_range_func: u32,
+
+    pub end_in_range_func: u32,
+
+    pub in_range_coll: u32,
+
+    pub in_range_asc: bool,
+
+    pub in_range_nulls_first: bool,
+
+    pub winref: u32,
+
+    pub copied_order: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ObjectWithArgs {
+    pub objname: Vec<Node>,
+
+    pub objargs: Vec<Node>,
+
+    pub args_unspecified: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AccessPriv {
+    pub priv_name: String,
+
+    pub cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassItem {
+    pub itemtype: i32,
+
+    pub name: ::core::option::Option<ObjectWithArgs>,
+
+    pub number: i32,
+
+    pub order_family: Vec<Node>,
+
+    pub class_args: Vec<Node>,
+
+    pub storedtype: ::core::option::Option<TypeName>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableLikeClause {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub options: u32,
+
+    pub relation_oid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FunctionParameter {
+    pub name: String,
+
+    pub arg_type: ::core::option::Option<TypeName>,
+
+    pub mode: i32,
+
+    pub defexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockingClause {
+    pub locked_rels: Vec<Node>,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowMarkClause {
+    pub rti: u32,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+
+    pub pushed_down: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlSerialize {
+    pub xmloption: i32,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithClause {
+    pub ctes: Vec<Node>,
+
+    pub recursive: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferClause {
+    pub index_elems: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub conname: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictClause {
+    pub action: i32,
+
+    pub infer: ::core::option::Option<Box<InferClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommonTableExpr {
+    pub ctename: String,
+
+    pub aliascolnames: Vec<Node>,
+
+    pub ctematerialized: i32,
+
+    pub ctequery: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+
+    pub cterecursive: bool,
+
+    pub cterefcount: i32,
+
+    pub ctecolnames: Vec<Node>,
+
+    pub ctecoltypes: Vec<Node>,
+
+    pub ctecoltypmods: Vec<Node>,
+
+    pub ctecolcollations: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RoleSpec {
+    pub roletype: i32,
+
+    pub rolename: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TriggerTransition {
+    pub name: String,
+
+    pub is_new: bool,
+
+    pub is_table: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionElem {
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionSpec {
+    pub strategy: String,
+
+    pub part_params: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionBoundSpec {
+    pub strategy: String,
+
+    pub is_default: bool,
+
+    pub modulus: i32,
+
+    pub remainder: i32,
+
+    pub listdatums: Vec<Node>,
+
+    pub lowerdatums: Vec<Node>,
+
+    pub upperdatums: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionRangeDatum {
+    pub kind: i32,
+
+    pub value: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionCmd {
+    pub name: ::core::option::Option<RangeVar>,
+
+    pub bound: ::core::option::Option<PartitionBoundSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumRelation {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub oid: u32,
+
+    pub va_cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct InlineCodeBlock {
+    pub source_text: String,
+
+    pub lang_oid: u32,
+
+    pub lang_is_trusted: bool,
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallContext {
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanToken {
+    pub start: i32,
+
+    pub end: i32,
+
+    pub token: i32,
+
+    pub keyword_kind: i32,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OverridingKind {
+    Undefined = 0,
+    OverridingNotSet = 1,
+    OverridingUserValue = 2,
+    OverridingSystemValue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum QuerySource {
+    Undefined = 0,
+    QsrcOriginal = 1,
+    QsrcParser = 2,
+    QsrcInsteadRule = 3,
+    QsrcQualInsteadRule = 4,
+    QsrcNonInsteadRule = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByDir {
+    Undefined = 0,
+    SortbyDefault = 1,
+    SortbyAsc = 2,
+    SortbyDesc = 3,
+    SortbyUsing = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByNulls {
+    Undefined = 0,
+    SortbyNullsDefault = 1,
+    SortbyNullsFirst = 2,
+    SortbyNullsLast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AExprKind {
+    Undefined = 0,
+    AexprOp = 1,
+    AexprOpAny = 2,
+    AexprOpAll = 3,
+    AexprDistinct = 4,
+    AexprNotDistinct = 5,
+    AexprNullif = 6,
+    AexprOf = 7,
+    AexprIn = 8,
+    AexprLike = 9,
+    AexprIlike = 10,
+    AexprSimilar = 11,
+    AexprBetween = 12,
+    AexprNotBetween = 13,
+    AexprBetweenSym = 14,
+    AexprNotBetweenSym = 15,
+    AexprParen = 16,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleSpecType {
+    Undefined = 0,
+    RolespecCstring = 1,
+    RolespecCurrentUser = 2,
+    RolespecSessionUser = 3,
+    RolespecPublic = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TableLikeOption {
+    Undefined = 0,
+    CreateTableLikeComments = 1,
+    CreateTableLikeConstraints = 2,
+    CreateTableLikeDefaults = 3,
+    CreateTableLikeGenerated = 4,
+    CreateTableLikeIdentity = 5,
+    CreateTableLikeIndexes = 6,
+    CreateTableLikeStatistics = 7,
+    CreateTableLikeStorage = 8,
+    CreateTableLikeAll = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DefElemAction {
+    Undefined = 0,
+    DefelemUnspec = 1,
+    DefelemSet = 2,
+    DefelemAdd = 3,
+    DefelemDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum PartitionRangeDatumKind {
+    Undefined = 0,
+    PartitionRangeDatumMinvalue = 1,
+    PartitionRangeDatumValue = 2,
+    PartitionRangeDatumMaxvalue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RteKind {
+    RtekindUndefined = 0,
+    RteRelation = 1,
+    RteSubquery = 2,
+    RteJoin = 3,
+    RteFunction = 4,
+    RteTablefunc = 5,
+    RteValues = 6,
+    RteCte = 7,
+    RteNamedtuplestore = 8,
+    RteResult = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum WcoKind {
+    WcokindUndefined = 0,
+    WcoViewCheck = 1,
+    WcoRlsInsertCheck = 2,
+    WcoRlsUpdateCheck = 3,
+    WcoRlsConflictCheck = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GroupingSetKind {
+    Undefined = 0,
+    GroupingSetEmpty = 1,
+    GroupingSetSimple = 2,
+    GroupingSetRollup = 3,
+    GroupingSetCube = 4,
+    GroupingSetSets = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CteMaterialize {
+    CtematerializeUndefined = 0,
+    Default = 1,
+    Always = 2,
+    Never = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOperation {
+    Undefined = 0,
+    SetopNone = 1,
+    SetopUnion = 2,
+    SetopIntersect = 3,
+    SetopExcept = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ObjectType {
+    Undefined = 0,
+    ObjectAccessMethod = 1,
+    ObjectAggregate = 2,
+    ObjectAmop = 3,
+    ObjectAmproc = 4,
+    ObjectAttribute = 5,
+    ObjectCast = 6,
+    ObjectColumn = 7,
+    ObjectCollation = 8,
+    ObjectConversion = 9,
+    ObjectDatabase = 10,
+    ObjectDefault = 11,
+    ObjectDefacl = 12,
+    ObjectDomain = 13,
+    ObjectDomconstraint = 14,
+    ObjectEventTrigger = 15,
+    ObjectExtension = 16,
+    ObjectFdw = 17,
+    ObjectForeignServer = 18,
+    ObjectForeignTable = 19,
+    ObjectFunction = 20,
+    ObjectIndex = 21,
+    ObjectLanguage = 22,
+    ObjectLargeobject = 23,
+    ObjectMatview = 24,
+    ObjectOpclass = 25,
+    ObjectOperator = 26,
+    ObjectOpfamily = 27,
+    ObjectPolicy = 28,
+    ObjectProcedure = 29,
+    ObjectPublication = 30,
+    ObjectPublicationRel = 31,
+    ObjectRole = 32,
+    ObjectRoutine = 33,
+    ObjectRule = 34,
+    ObjectSchema = 35,
+    ObjectSequence = 36,
+    ObjectSubscription = 37,
+    ObjectStatisticExt = 38,
+    ObjectTabconstraint = 39,
+    ObjectTable = 40,
+    ObjectTablespace = 41,
+    ObjectTransform = 42,
+    ObjectTrigger = 43,
+    ObjectTsconfiguration = 44,
+    ObjectTsdictionary = 45,
+    ObjectTsparser = 46,
+    ObjectTstemplate = 47,
+    ObjectType = 48,
+    ObjectUserMapping = 49,
+    ObjectView = 50,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DropBehavior {
+    Undefined = 0,
+    DropRestrict = 1,
+    DropCascade = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTableType {
+    Undefined = 0,
+    AtAddColumn = 1,
+    AtAddColumnRecurse = 2,
+    AtAddColumnToView = 3,
+    AtColumnDefault = 4,
+    AtCookedColumnDefault = 5,
+    AtDropNotNull = 6,
+    AtSetNotNull = 7,
+    AtDropExpression = 8,
+    AtCheckNotNull = 9,
+    AtSetStatistics = 10,
+    AtSetOptions = 11,
+    AtResetOptions = 12,
+    AtSetStorage = 13,
+    AtDropColumn = 14,
+    AtDropColumnRecurse = 15,
+    AtAddIndex = 16,
+    AtReAddIndex = 17,
+    AtAddConstraint = 18,
+    AtAddConstraintRecurse = 19,
+    AtReAddConstraint = 20,
+    AtReAddDomainConstraint = 21,
+    AtAlterConstraint = 22,
+    AtValidateConstraint = 23,
+    AtValidateConstraintRecurse = 24,
+    AtAddIndexConstraint = 25,
+    AtDropConstraint = 26,
+    AtDropConstraintRecurse = 27,
+    AtReAddComment = 28,
+    AtAlterColumnType = 29,
+    AtAlterColumnGenericOptions = 30,
+    AtChangeOwner = 31,
+    AtClusterOn = 32,
+    AtDropCluster = 33,
+    AtSetLogged = 34,
+    AtSetUnLogged = 35,
+    AtDropOids = 36,
+    AtSetTableSpace = 37,
+    AtSetRelOptions = 38,
+    AtResetRelOptions = 39,
+    AtReplaceRelOptions = 40,
+    AtEnableTrig = 41,
+    AtEnableAlwaysTrig = 42,
+    AtEnableReplicaTrig = 43,
+    AtDisableTrig = 44,
+    AtEnableTrigAll = 45,
+    AtDisableTrigAll = 46,
+    AtEnableTrigUser = 47,
+    AtDisableTrigUser = 48,
+    AtEnableRule = 49,
+    AtEnableAlwaysRule = 50,
+    AtEnableReplicaRule = 51,
+    AtDisableRule = 52,
+    AtAddInherit = 53,
+    AtDropInherit = 54,
+    AtAddOf = 55,
+    AtDropOf = 56,
+    AtReplicaIdentity = 57,
+    AtEnableRowSecurity = 58,
+    AtDisableRowSecurity = 59,
+    AtForceRowSecurity = 60,
+    AtNoForceRowSecurity = 61,
+    AtGenericOptions = 62,
+    AtAttachPartition = 63,
+    AtDetachPartition = 64,
+    AtAddIdentity = 65,
+    AtSetIdentity = 66,
+    AtDropIdentity = 67,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GrantTargetType {
+    Undefined = 0,
+    AclTargetObject = 1,
+    AclTargetAllInSchema = 2,
+    AclTargetDefaults = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum VariableSetKind {
+    Undefined = 0,
+    VarSetValue = 1,
+    VarSetDefault = 2,
+    VarSetCurrent = 3,
+    VarSetMulti = 4,
+    VarReset = 5,
+    VarResetAll = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ConstrType {
+    Undefined = 0,
+    ConstrNull = 1,
+    ConstrNotnull = 2,
+    ConstrDefault = 3,
+    ConstrIdentity = 4,
+    ConstrGenerated = 5,
+    ConstrCheck = 6,
+    ConstrPrimary = 7,
+    ConstrUnique = 8,
+    ConstrExclusion = 9,
+    ConstrForeign = 10,
+    ConstrAttrDeferrable = 11,
+    ConstrAttrNotDeferrable = 12,
+    ConstrAttrDeferred = 13,
+    ConstrAttrImmediate = 14,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ImportForeignSchemaType {
+    Undefined = 0,
+    FdwImportSchemaAll = 1,
+    FdwImportSchemaLimitTo = 2,
+    FdwImportSchemaExcept = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleStmtType {
+    Undefined = 0,
+    RolestmtRole = 1,
+    RolestmtUser = 2,
+    RolestmtGroup = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FetchDirection {
+    Undefined = 0,
+    FetchForward = 1,
+    FetchBackward = 2,
+    FetchAbsolute = 3,
+    FetchRelative = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FunctionParameterMode {
+    Undefined = 0,
+    FuncParamIn = 1,
+    FuncParamOut = 2,
+    FuncParamInout = 3,
+    FuncParamVariadic = 4,
+    FuncParamTable = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TransactionStmtKind {
+    Undefined = 0,
+    TransStmtBegin = 1,
+    TransStmtStart = 2,
+    TransStmtCommit = 3,
+    TransStmtRollback = 4,
+    TransStmtSavepoint = 5,
+    TransStmtRelease = 6,
+    TransStmtRollbackTo = 7,
+    TransStmtPrepare = 8,
+    TransStmtCommitPrepared = 9,
+    TransStmtRollbackPrepared = 10,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ViewCheckOption {
+    Undefined = 0,
+    NoCheckOption = 1,
+    LocalCheckOption = 2,
+    CascadedCheckOption = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ClusterOption {
+    Undefined = 0,
+    CluoptRecheck = 1,
+    CluoptVerbose = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DiscardMode {
+    Undefined = 0,
+    DiscardAll = 1,
+    DiscardPlans = 2,
+    DiscardSequences = 3,
+    DiscardTemp = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ReindexObjectType {
+    Undefined = 0,
+    ReindexObjectIndex = 1,
+    ReindexObjectTable = 2,
+    ReindexObjectSchema = 3,
+    ReindexObjectSystem = 4,
+    ReindexObjectDatabase = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTsConfigType {
+    AlterTsconfigTypeUndefined = 0,
+    AlterTsconfigAddMapping = 1,
+    AlterTsconfigAlterMappingForToken = 2,
+    AlterTsconfigReplaceDict = 3,
+    AlterTsconfigReplaceDictForToken = 4,
+    AlterTsconfigDropMapping = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterSubscriptionType {
+    Undefined = 0,
+    AlterSubscriptionOptions = 1,
+    AlterSubscriptionConnection = 2,
+    AlterSubscriptionPublication = 3,
+    AlterSubscriptionRefresh = 4,
+    AlterSubscriptionEnabled = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnCommitAction {
+    Undefined = 0,
+    OncommitNoop = 1,
+    OncommitPreserveRows = 2,
+    OncommitDeleteRows = 3,
+    OncommitDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ParamKind {
+    Undefined = 0,
+    ParamExtern = 1,
+    ParamExec = 2,
+    ParamSublink = 3,
+    ParamMultiexpr = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionContext {
+    Undefined = 0,
+    CoercionImplicit = 1,
+    CoercionAssignment = 2,
+    CoercionExplicit = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionForm {
+    Undefined = 0,
+    CoerceExplicitCall = 1,
+    CoerceExplicitCast = 2,
+    CoerceImplicitCast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolExprType {
+    Undefined = 0,
+    AndExpr = 1,
+    OrExpr = 2,
+    NotExpr = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SubLinkType {
+    Undefined = 0,
+    ExistsSublink = 1,
+    AllSublink = 2,
+    AnySublink = 3,
+    RowcompareSublink = 4,
+    ExprSublink = 5,
+    MultiexprSublink = 6,
+    ArraySublink = 7,
+    CteSublink = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RowCompareType {
+    Undefined = 0,
+    RowcompareLt = 1,
+    RowcompareLe = 2,
+    RowcompareEq = 3,
+    RowcompareGe = 4,
+    RowcompareGt = 5,
+    RowcompareNe = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum MinMaxOp {
+    Undefined = 0,
+    IsGreatest = 1,
+    IsLeast = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SqlValueFunctionOp {
+    SqlvalueFunctionOpUndefined = 0,
+    SvfopCurrentDate = 1,
+    SvfopCurrentTime = 2,
+    SvfopCurrentTimeN = 3,
+    SvfopCurrentTimestamp = 4,
+    SvfopCurrentTimestampN = 5,
+    SvfopLocaltime = 6,
+    SvfopLocaltimeN = 7,
+    SvfopLocaltimestamp = 8,
+    SvfopLocaltimestampN = 9,
+    SvfopCurrentRole = 10,
+    SvfopCurrentUser = 11,
+    SvfopUser = 12,
+    SvfopSessionUser = 13,
+    SvfopCurrentCatalog = 14,
+    SvfopCurrentSchema = 15,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlExprOp {
+    Undefined = 0,
+    IsXmlconcat = 1,
+    IsXmlelement = 2,
+    IsXmlforest = 3,
+    IsXmlparse = 4,
+    IsXmlpi = 5,
+    IsXmlroot = 6,
+    IsXmlserialize = 7,
+    IsDocument = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlOptionType {
+    Undefined = 0,
+    XmloptionDocument = 1,
+    XmloptionContent = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum NullTestType {
+    Undefined = 0,
+    IsNull = 1,
+    IsNotNull = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolTestType {
+    Undefined = 0,
+    IsTrue = 1,
+    IsNotTrue = 2,
+    IsFalse = 3,
+    IsNotFalse = 4,
+    IsUnknown = 5,
+    IsNotUnknown = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CmdType {
+    Undefined = 0,
+    CmdUnknown = 1,
+    CmdSelect = 2,
+    CmdUpdate = 3,
+    CmdInsert = 4,
+    CmdDelete = 5,
+    CmdUtility = 6,
+    CmdNothing = 7,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum JoinType {
+    Undefined = 0,
+    JoinInner = 1,
+    JoinLeft = 2,
+    JoinFull = 3,
+    JoinRight = 4,
+    JoinSemi = 5,
+    JoinAnti = 6,
+    JoinUniqueOuter = 7,
+    JoinUniqueInner = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggStrategy {
+    Undefined = 0,
+    AggPlain = 1,
+    AggSorted = 2,
+    AggHashed = 3,
+    AggMixed = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggSplit {
+    Undefined = 0,
+    AggsplitSimple = 1,
+    AggsplitInitialSerial = 2,
+    AggsplitFinalDeserial = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpCmd {
+    Undefined = 0,
+    SetopcmdIntersect = 1,
+    SetopcmdIntersectAll = 2,
+    SetopcmdExcept = 3,
+    SetopcmdExceptAll = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpStrategy {
+    Undefined = 0,
+    SetopSorted = 1,
+    SetopHashed = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnConflictAction {
+    Undefined = 0,
+    OnconflictNone = 1,
+    OnconflictNothing = 2,
+    OnconflictUpdate = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LimitOption {
+    Undefined = 0,
+    Default = 1,
+    Count = 2,
+    WithTies = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockClauseStrength {
+    Undefined = 0,
+    LcsNone = 1,
+    LcsForkeyshare = 2,
+    LcsForshare = 3,
+    LcsFornokeyupdate = 4,
+    LcsForupdate = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockWaitPolicy {
+    Undefined = 0,
+    LockWaitBlock = 1,
+    LockWaitSkip = 2,
+    LockWaitError = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockTupleMode {
+    Undefined = 0,
+    LockTupleKeyShare = 1,
+    LockTupleShare = 2,
+    LockTupleNoKeyExclusive = 3,
+    LockTupleExclusive = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum KeywordKind {
+    NoKeyword = 0,
+    UnreservedKeyword = 1,
+    ColNameKeyword = 2,
+    TypeFuncNameKeyword = 3,
+    ReservedKeyword = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum Token {
+    Nul = 0,
+    /// Single-character tokens that are returned 1:1 (identical with "self" list in scan.l)
+    /// Either supporting syntax, or single-character operators (some can be both)
+    /// Also see <https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-SPECIAL-CHARS>
+    ///
+    /// "%"
+    Ascii37 = 37,
+    /// "("
+    Ascii40 = 40,
+    /// ")"
+    Ascii41 = 41,
+    /// "*"
+    Ascii42 = 42,
+    /// "+"
+    Ascii43 = 43,
+    /// ","
+    Ascii44 = 44,
+    /// "-"
+    Ascii45 = 45,
+    /// "."
+    Ascii46 = 46,
+    /// "/"
+    Ascii47 = 47,
+    /// ":"
+    Ascii58 = 58,
+    /// ";"
+    Ascii59 = 59,
+    /// "<"
+    Ascii60 = 60,
+    /// "="
+    Ascii61 = 61,
+    /// ">"
+    Ascii62 = 62,
+    /// "?"
+    Ascii63 = 63,
+    /// "["
+    Ascii91 = 91,
+    /// "\"
+    Ascii92 = 92,
+    /// "]"
+    Ascii93 = 93,
+    /// "^"
+    Ascii94 = 94,
+    /// Named tokens in scan.l
+    Ident = 258,
+    Uident = 259,
+    Fconst = 260,
+    Sconst = 261,
+    Usconst = 262,
+    Bconst = 263,
+    Xconst = 264,
+    Op = 265,
+    Iconst = 266,
+    Param = 267,
+    Typecast = 268,
+    DotDot = 269,
+    ColonEquals = 270,
+    EqualsGreater = 271,
+    LessEquals = 272,
+    GreaterEquals = 273,
+    NotEquals = 274,
+    SqlComment = 275,
+    CComment = 276,
+    AbortP = 277,
+    AbsoluteP = 278,
+    Access = 279,
+    Action = 280,
+    AddP = 281,
+    Admin = 282,
+    After = 283,
+    Aggregate = 284,
+    All = 285,
+    Also = 286,
+    Alter = 287,
+    Always = 288,
+    Analyse = 289,
+    Analyze = 290,
+    And = 291,
+    Any = 292,
+    Array = 293,
+    As = 294,
+    Asc = 295,
+    Assertion = 296,
+    Assignment = 297,
+    Asymmetric = 298,
+    At = 299,
+    Attach = 300,
+    Attribute = 301,
+    Authorization = 302,
+    Backward = 303,
+    Before = 304,
+    BeginP = 305,
+    Between = 306,
+    Bigint = 307,
+    Binary = 308,
+    Bit = 309,
+    BooleanP = 310,
+    Both = 311,
+    By = 312,
+    Cache = 313,
+    Call = 314,
+    Called = 315,
+    Cascade = 316,
+    Cascaded = 317,
+    Case = 318,
+    Cast = 319,
+    CatalogP = 320,
+    Chain = 321,
+    CharP = 322,
+    Character = 323,
+    Characteristics = 324,
+    Check = 325,
+    Checkpoint = 326,
+    Class = 327,
+    Close = 328,
+    Cluster = 329,
+    Coalesce = 330,
+    Collate = 331,
+    Collation = 332,
+    Column = 333,
+    Columns = 334,
+    Comment = 335,
+    Comments = 336,
+    Commit = 337,
+    Committed = 338,
+    Concurrently = 339,
+    Configuration = 340,
+    Conflict = 341,
+    Connection = 342,
+    Constraint = 343,
+    Constraints = 344,
+    ContentP = 345,
+    ContinueP = 346,
+    ConversionP = 347,
+    Copy = 348,
+    Cost = 349,
+    Create = 350,
+    Cross = 351,
+    Csv = 352,
+    Cube = 353,
+    CurrentP = 354,
+    CurrentCatalog = 355,
+    CurrentDate = 356,
+    CurrentRole = 357,
+    CurrentSchema = 358,
+    CurrentTime = 359,
+    CurrentTimestamp = 360,
+    CurrentUser = 361,
+    Cursor = 362,
+    Cycle = 363,
+    DataP = 364,
+    Database = 365,
+    DayP = 366,
+    Deallocate = 367,
+    Dec = 368,
+    DecimalP = 369,
+    Declare = 370,
+    Default = 371,
+    Defaults = 372,
+    Deferrable = 373,
+    Deferred = 374,
+    Definer = 375,
+    DeleteP = 376,
+    Delimiter = 377,
+    Delimiters = 378,
+    Depends = 379,
+    Desc = 380,
+    Detach = 381,
+    Dictionary = 382,
+    DisableP = 383,
+    Discard = 384,
+    Distinct = 385,
+    Do = 386,
+    DocumentP = 387,
+    DomainP = 388,
+    DoubleP = 389,
+    Drop = 390,
+    Each = 391,
+    Else = 392,
+    EnableP = 393,
+    Encoding = 394,
+    Encrypted = 395,
+    EndP = 396,
+    EnumP = 397,
+    Escape = 398,
+    Event = 399,
+    Except = 400,
+    Exclude = 401,
+    Excluding = 402,
+    Exclusive = 403,
+    Execute = 404,
+    Exists = 405,
+    Explain = 406,
+    Expression = 407,
+    Extension = 408,
+    External = 409,
+    Extract = 410,
+    FalseP = 411,
+    Family = 412,
+    Fetch = 413,
+    Filter = 414,
+    FirstP = 415,
+    FloatP = 416,
+    Following = 417,
+    For = 418,
+    Force = 419,
+    Foreign = 420,
+    Forward = 421,
+    Freeze = 422,
+    From = 423,
+    Full = 424,
+    Function = 425,
+    Functions = 426,
+    Generated = 427,
+    Global = 428,
+    Grant = 429,
+    Granted = 430,
+    Greatest = 431,
+    GroupP = 432,
+    Grouping = 433,
+    Groups = 434,
+    Handler = 435,
+    Having = 436,
+    HeaderP = 437,
+    Hold = 438,
+    HourP = 439,
+    IdentityP = 440,
+    IfP = 441,
+    Ilike = 442,
+    Immediate = 443,
+    Immutable = 444,
+    ImplicitP = 445,
+    ImportP = 446,
+    InP = 447,
+    Include = 448,
+    Including = 449,
+    Increment = 450,
+    Index = 451,
+    Indexes = 452,
+    Inherit = 453,
+    Inherits = 454,
+    Initially = 455,
+    InlineP = 456,
+    InnerP = 457,
+    Inout = 458,
+    InputP = 459,
+    Insensitive = 460,
+    Insert = 461,
+    Instead = 462,
+    IntP = 463,
+    Integer = 464,
+    Intersect = 465,
+    Interval = 466,
+    Into = 467,
+    Invoker = 468,
+    Is = 469,
+    Isnull = 470,
+    Isolation = 471,
+    Join = 472,
+    Key = 473,
+    Label = 474,
+    Language = 475,
+    LargeP = 476,
+    LastP = 477,
+    LateralP = 478,
+    Leading = 479,
+    Leakproof = 480,
+    Least = 481,
+    Left = 482,
+    Level = 483,
+    Like = 484,
+    Limit = 485,
+    Listen = 486,
+    Load = 487,
+    Local = 488,
+    Localtime = 489,
+    Localtimestamp = 490,
+    Location = 491,
+    LockP = 492,
+    Locked = 493,
+    Logged = 494,
+    Mapping = 495,
+    Match = 496,
+    Materialized = 497,
+    Maxvalue = 498,
+    Method = 499,
+    MinuteP = 500,
+    Minvalue = 501,
+    Mode = 502,
+    MonthP = 503,
+    Move = 504,
+    NameP = 505,
+    Names = 506,
+    National = 507,
+    Natural = 508,
+    Nchar = 509,
+    New = 510,
+    Next = 511,
+    Nfc = 512,
+    Nfd = 513,
+    Nfkc = 514,
+    Nfkd = 515,
+    No = 516,
+    None = 517,
+    Normalize = 518,
+    Normalized = 519,
+    Not = 520,
+    Nothing = 521,
+    Notify = 522,
+    Notnull = 523,
+    Nowait = 524,
+    NullP = 525,
+    Nullif = 526,
+    NullsP = 527,
+    Numeric = 528,
+    ObjectP = 529,
+    Of = 530,
+    Off = 531,
+    Offset = 532,
+    Oids = 533,
+    Old = 534,
+    On = 535,
+    Only = 536,
+    Operator = 537,
+    Option = 538,
+    Options = 539,
+    Or = 540,
+    Order = 541,
+    Ordinality = 542,
+    Others = 543,
+    OutP = 544,
+    OuterP = 545,
+    Over = 546,
+    Overlaps = 547,
+    Overlay = 548,
+    Overriding = 549,
+    Owned = 550,
+    Owner = 551,
+    Parallel = 552,
+    Parser = 553,
+    Partial = 554,
+    Partition = 555,
+    Passing = 556,
+    Password = 557,
+    Placing = 558,
+    Plans = 559,
+    Policy = 560,
+    Position = 561,
+    Preceding = 562,
+    Precision = 563,
+    Preserve = 564,
+    Prepare = 565,
+    Prepared = 566,
+    Primary = 567,
+    Prior = 568,
+    Privileges = 569,
+    Procedural = 570,
+    Procedure = 571,
+    Procedures = 572,
+    Program = 573,
+    Publication = 574,
+    Quote = 575,
+    Range = 576,
+    Read = 577,
+    Real = 578,
+    Reassign = 579,
+    Recheck = 580,
+    Recursive = 581,
+    Ref = 582,
+    References = 583,
+    Referencing = 584,
+    Refresh = 585,
+    Reindex = 586,
+    RelativeP = 587,
+    Release = 588,
+    Rename = 589,
+    Repeatable = 590,
+    Replace = 591,
+    Replica = 592,
+    Reset = 593,
+    Restart = 594,
+    Restrict = 595,
+    Returning = 596,
+    Returns = 597,
+    Revoke = 598,
+    Right = 599,
+    Role = 600,
+    Rollback = 601,
+    Rollup = 602,
+    Routine = 603,
+    Routines = 604,
+    Row = 605,
+    Rows = 606,
+    Rule = 607,
+    Savepoint = 608,
+    Schema = 609,
+    Schemas = 610,
+    Scroll = 611,
+    Search = 612,
+    SecondP = 613,
+    Security = 614,
+    Select = 615,
+    Sequence = 616,
+    Sequences = 617,
+    Serializable = 618,
+    Server = 619,
+    Session = 620,
+    SessionUser = 621,
+    Set = 622,
+    Sets = 623,
+    Setof = 624,
+    Share = 625,
+    Show = 626,
+    Similar = 627,
+    Simple = 628,
+    Skip = 629,
+    Smallint = 630,
+    Snapshot = 631,
+    Some = 632,
+    SqlP = 633,
+    Stable = 634,
+    StandaloneP = 635,
+    Start = 636,
+    Statement = 637,
+    Statistics = 638,
+    Stdin = 639,
+    Stdout = 640,
+    Storage = 641,
+    Stored = 642,
+    StrictP = 643,
+    StripP = 644,
+    Subscription = 645,
+    Substring = 646,
+    Support = 647,
+    Symmetric = 648,
+    Sysid = 649,
+    SystemP = 650,
+    Table = 651,
+    Tables = 652,
+    Tablesample = 653,
+    Tablespace = 654,
+    Temp = 655,
+    Template = 656,
+    Temporary = 657,
+    TextP = 658,
+    Then = 659,
+    Ties = 660,
+    Time = 661,
+    Timestamp = 662,
+    To = 663,
+    Trailing = 664,
+    Transaction = 665,
+    Transform = 666,
+    Treat = 667,
+    Trigger = 668,
+    Trim = 669,
+    TrueP = 670,
+    Truncate = 671,
+    Trusted = 672,
+    TypeP = 673,
+    TypesP = 674,
+    Uescape = 675,
+    Unbounded = 676,
+    Uncommitted = 677,
+    Unencrypted = 678,
+    Union = 679,
+    Unique = 680,
+    Unknown = 681,
+    Unlisten = 682,
+    Unlogged = 683,
+    Until = 684,
+    Update = 685,
+    User = 686,
+    Using = 687,
+    Vacuum = 688,
+    Valid = 689,
+    Validate = 690,
+    Validator = 691,
+    ValueP = 692,
+    Values = 693,
+    Varchar = 694,
+    Variadic = 695,
+    Varying = 696,
+    Verbose = 697,
+    VersionP = 698,
+    View = 699,
+    Views = 700,
+    Volatile = 701,
+    When = 702,
+    Where = 703,
+    WhitespaceP = 704,
+    Window = 705,
+    With = 706,
+    Within = 707,
+    Without = 708,
+    Work = 709,
+    Wrapper = 710,
+    Write = 711,
+    XmlP = 712,
+    Xmlattributes = 713,
+    Xmlconcat = 714,
+    Xmlelement = 715,
+    Xmlexists = 716,
+    Xmlforest = 717,
+    Xmlnamespaces = 718,
+    Xmlparse = 719,
+    Xmlpi = 720,
+    Xmlroot = 721,
+    Xmlserialize = 722,
+    Xmltable = 723,
+    YearP = 724,
+    YesP = 725,
+    Zone = 726,
+    NotLa = 727,
+    NullsLa = 728,
+    WithLa = 729,
+    Postfixop = 730,
+    Uminus = 731,
+}

From b26c86b51afa013815fc54404ef033f14541c707 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sat, 30 Apr 2022 14:07:43 -0700
Subject: [PATCH 177/195] Update GitHub Actions actions/checkout@v2 to v3

The v2 implementation uses Node 12, which is end-of-life on April 30, 2022.
See https://nodejs.org/en/about/releases/. Update to v3, which is based on
Node 16 whose support lasts until April 30, 2024.
---
 .github/workflows/integration.yml   | 2 +-
 .github/workflows/linux.yml         | 2 +-
 .github/workflows/mac.yml           | 2 +-
 .github/workflows/rustdoc_check.yml | 2 +-
 .github/workflows/upload-assets.yml | 2 +-
 .github/workflows/windows.yml       | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index b79221d0543..4d8899b434b 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -69,7 +69,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 45f63b83c05..6a3f9d89d98 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -26,7 +26,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml
index 55e1cc9539b..7dfda3142ca 100644
--- a/.github/workflows/mac.yml
+++ b/.github/workflows/mac.yml
@@ -23,7 +23,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml
index ca96d30f586..cd0c3218971 100644
--- a/.github/workflows/rustdoc_check.yml
+++ b/.github/workflows/rustdoc_check.yml
@@ -11,7 +11,7 @@ jobs:
     name: rustdoc check
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
     - name: install rustup
       run: |
diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml
index f4dd3944453..25699234a1e 100644
--- a/.github/workflows/upload-assets.yml
+++ b/.github/workflows/upload-assets.yml
@@ -31,7 +31,7 @@ jobs:
             target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
         # Run build
       - name: install rustup
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index dcb08b5412e..4ebc2963849 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -33,7 +33,7 @@ jobs:
     - name: disable git eol translation
       run: git config --global core.autocrlf false
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: Install Rustup using win.rustup.rs

From c03e1842f637e34b23297fa3a0aeeb0fcdca1c47 Mon Sep 17 00:00:00 2001
From: cuishuang <imcusg@gmail.com>
Date: Sat, 7 May 2022 23:56:21 +0800
Subject: [PATCH 178/195] fix some typos

Signed-off-by: cuishuang <imcusg@gmail.com>
---
 src/parse/session.rs  | 2 +-
 tests/rustfmt/main.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/parse/session.rs b/src/parse/session.rs
index 7571e6d078a..55050571db7 100644
--- a/src/parse/session.rs
+++ b/src/parse/session.rs
@@ -152,7 +152,7 @@ impl ParseSess {
     /// * `relative` - If Some(symbol), the symbol name is a directory relative to the dir_path.
     ///   If relative is Some, resolve the submodle at {dir_path}/{symbol}/{id}.rs
     ///   or {dir_path}/{symbol}/{id}/mod.rs. if None, resolve the module at {dir_path}/{id}.rs.
-    /// *  `dir_path` - Module resolution will occur relative to this direcotry.
+    /// *  `dir_path` - Module resolution will occur relative to this directory.
     pub(crate) fn default_submod_path(
         &self,
         id: symbol::Ident,
diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 450051d2fec..4c6d52726f3 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -143,7 +143,7 @@ fn mod_resolution_error_relative_module_not_found() {
     let args = ["tests/mod-resolver/module-not-found/relative_module/lib.rs"];
     let (_stdout, stderr) = rustfmt(&args);
     // The file `./a.rs` and directory `./a` both exist.
-    // Module resolution fails becuase we're unable to find `./a/b.rs`
+    // Module resolution fails because we're unable to find `./a/b.rs`
     #[cfg(not(windows))]
     assert!(stderr.contains("a/b.rs does not exist"));
     #[cfg(windows)]

From 3cc1f5ed5b04ea6512b710e231c147b4546f8e52 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Thu, 28 Apr 2022 23:08:22 -0400
Subject: [PATCH 179/195] Add tests for issue 4573

It's unclear which PR resolved this issue, however the behavior of
adding inline comments to the next line can't be reproduced.

These test cases should serve to prevent a regression.
---
 tests/target/issue_4573.rs | 245 +++++++++++++++++++++++++++++++++++++
 1 file changed, 245 insertions(+)
 create mode 100644 tests/target/issue_4573.rs

diff --git a/tests/target/issue_4573.rs b/tests/target/issue_4573.rs
new file mode 100644
index 00000000000..82cfe4f5359
--- /dev/null
+++ b/tests/target/issue_4573.rs
@@ -0,0 +1,245 @@
+// rustmft-version:Two
+// rustmft-use_small_heuristics:Max
+// rustmft-merge_derives:false
+// These are the same rustfmt configuration options that are used
+// in the comiler as of ce39461ca75a and 8eb7c58dbb7b
+// These are commits in https://github.com/rust-lang/rust
+
+#![no_std] // inner attribute comment
+// inner attribute comment
+#![no_implicit_prelude]
+// post inner attribute comment
+
+#[cfg(not(miri))] // inline comment
+#[no_link]
+extern crate foo;
+
+// before attributes
+#[no_link]
+// between attributes
+#[cfg(not(miri))] // inline comment
+extern crate foo as bar;
+
+#[cfg(not(miri))] // inline comment
+// between attribute and use
+use foo;
+
+#[cfg(not(miri))] // inline comment
+use foo;
+
+/* pre attributre */
+#[cfg(not(miri))]
+use foo::bar;
+
+#[cfg(not(miri))] // inline comment
+use foo::bar as FooBar;
+
+#[cfg(not(miri))] // inline comment
+#[allow(unused)]
+#[deprecated(
+    since = "5.2",  // inline inner comment
+    note = "FOO was rarely used. Users should instead use BAR"
+)]
+#[allow(unused)]
+static FOO: i32 = 42;
+
+#[used]
+#[export_name = "FOO"]
+#[cfg(not(miri))] // inline comment
+#[deprecated(
+    since = "5.2",
+    note = "FOO was rarely used. Users should instead use BAR"
+)]
+static FOO: i32 = 42;
+
+#[cfg(not(miri))] // inline comment
+#[export_name = "FOO"]
+static BAR: &'static str = "bar";
+
+#[cfg(not(miri))] // inline comment
+const BAR: i32 = 42;
+
+#[cfg(not(miri))] // inline comment
+#[no_mangle]
+#[link_section = ".example_section"]
+fn foo(bar: usize) {
+    #[cfg(not(miri))] // inline comment
+    println!("hello world!");
+}
+
+#[cfg(not(miri))] // inline comment
+mod foo {}
+
+#[cfg(not(miri))] // inline comment
+extern "C" {
+    fn my_c_function(x: i32) -> bool;
+}
+
+#[cfg(not(miri))] // inline comment
+#[link(name = "CoreFoundation", kind = "framework")]
+extern "C" {
+
+    #[link_name = "actual_symbol_name"] // inline comment
+    // between attribute and function
+    fn my_c_function(x: i32) -> bool;
+}
+
+#[cfg(not(miri))] // inline comment
+pub extern "C" fn callable_from_c(x: i32) -> bool {
+    x % 3 == 0
+}
+
+#[cfg(not(miri))] // inline comment
+/* between attribute block comment */
+#[no_mangle]
+/* between attribute and type */
+type Foo = Bar<u8>;
+
+#[no_mangle]
+#[cfg(not(miri))] // inline comment
+#[non_exhaustive] // inline comment
+enum Foo {
+    Bar,
+    Baz,
+}
+
+#[no_mangle]
+#[cfg(not(miri))] /* inline comment */
+struct Foo<A> {
+    x: A,
+}
+
+#[cfg(not(miri))] // inline comment
+union Foo<A, B> {
+    x: A,
+    y: B,
+}
+
+#[cfg(not(miri))] // inline comment
+trait Foo {}
+
+#[cfg(not(miri))] // inline comment
+trait Foo = Bar + Quux;
+
+#[cfg(not(miri))] // inline comment
+impl Foo {}
+
+#[cfg(not(miri))] // inline comment
+macro_rules! bar {
+    (3) => {};
+}
+
+mod nested {
+    #[cfg(not(miri))] // inline comment
+    // between attribute and use
+    use foo;
+
+    #[cfg(not(miri))] // inline comment
+    use foo;
+
+    #[cfg(not(miri))] // inline comment
+    use foo::bar;
+
+    #[cfg(not(miri))] // inline comment
+    use foo::bar as FooBar;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: &'static str = "bar";
+
+    #[cfg(not(miri))] // inline comment
+    const FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    fn foo(bar: usize) {
+        #[cfg(not(miri))] // inline comment
+        println!("hello world!");
+    }
+
+    #[cfg(not(miri))] // inline comment
+    mod foo {}
+
+    #[cfg(not(miri))] // inline comment
+    mod foo {}
+
+    #[cfg(not(miri))] // inline comment
+    extern "C" {
+        fn my_c_function(x: i32) -> bool;
+    }
+
+    #[cfg(not(miri))] // inline comment
+    #[link(name = "CoreFoundation", kind = "framework")]
+    extern "C" {
+
+        #[link_name = "actual_symbol_name"] // inline comment
+        // between attribute and function
+        fn my_c_function(x: i32) -> bool;
+    }
+
+    #[cfg(not(miri))] // inline comment
+    pub extern "C" fn callable_from_c(x: i32) -> bool {
+        x % 3 == 0
+    }
+
+    #[cfg(not(miri))] // inline comment
+    type Foo = Bar<u8>;
+
+    #[cfg(not(miri))] // inline comment
+    #[non_exhaustive] // inline comment
+    enum Foo {
+        // comment
+        #[attribute_1]
+        #[attribute_2] // comment
+        // comment!
+        Bar,
+        /* comment */
+        #[attribute_1]
+        #[attribute_2] /* comment */
+        #[attribute_3]
+        #[attribute_4]
+        /* comment! */
+        Baz,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    struct Foo<A> {
+        x: A,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    union Foo<A, B> {
+        #[attribute_1]
+        #[attribute_2] /* comment */
+        #[attribute_3]
+        #[attribute_4] // comment
+        x: A,
+        y: B,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    #[allow(missing_docs)]
+    trait Foo {
+        #[must_use] /* comment
+                     * that wrappes to
+                     * the next line */
+        fn bar() {}
+    }
+
+    #[allow(missing_docs)]
+    #[cfg(not(miri))] // inline comment
+    trait Foo = Bar + Quux;
+
+    #[allow(missing_docs)]
+    #[cfg(not(miri))] // inline comment
+    impl Foo {}
+
+    #[cfg(not(miri))] // inline comment
+    macro_rules! bar {
+        (3) => {};
+    }
+}

From c65ba14d692bedab306b0426c36ab8f4fe4cbab2 Mon Sep 17 00:00:00 2001
From: Pascal Seitz <pascal.seitz@gmail.com>
Date: Sun, 13 Mar 2022 10:03:50 +0800
Subject: [PATCH 180/195] Fixes #5260

Fixes #5260 by checking if it is part of a type '::'
---
 src/comment.rs             |  2 +-
 src/string.rs              | 45 ++++++++++++++++++++++++++++++++------
 tests/source/issue-5260.rs | 14 ++++++++++++
 tests/target/issue-5260.rs | 13 +++++++++++
 4 files changed, 66 insertions(+), 8 deletions(-)
 create mode 100644 tests/source/issue-5260.rs
 create mode 100644 tests/target/issue-5260.rs

diff --git a/src/comment.rs b/src/comment.rs
index f9d8a0fa70c..eb195b1f762 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -796,7 +796,7 @@ impl<'a> CommentRewrite<'a> {
         // 1) wrap_comments = true is configured
         // 2) The comment is not the start of a markdown header doc comment
         // 3) The comment width exceeds the shape's width
-        // 4) No URLS were found in the commnet
+        // 4) No URLS were found in the comment
         let should_wrap_comment = self.fmt.config.wrap_comments()
             && !is_markdown_header_doc_comment
             && unicode_str_width(line) > self.fmt.shape.width
diff --git a/src/string.rs b/src/string.rs
index b65aa5b33b2..78b72a50cb2 100644
--- a/src/string.rs
+++ b/src/string.rs
@@ -315,20 +315,21 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
         // Found a whitespace and what is on its left side is big enough.
         Some(index) if index >= MIN_STRING => break_at(index),
         // No whitespace found, try looking for a punctuation instead
-        _ => match input[0..max_width_index_in_input]
-            .iter()
-            .rposition(|grapheme| is_punctuation(grapheme))
+        _ => match (0..max_width_index_in_input)
+            .rev()
+            .skip_while(|pos| !is_valid_linebreak(input, *pos))
+            .next()
         {
             // Found a punctuation and what is on its left side is big enough.
             Some(index) if index >= MIN_STRING => break_at(index),
             // Either no boundary character was found to the left of `input[max_chars]`, or the line
             // got too small. We try searching for a boundary character to the right.
-            _ => match input[max_width_index_in_input..]
-                .iter()
-                .position(|grapheme| is_whitespace(grapheme) || is_punctuation(grapheme))
+            _ => match (max_width_index_in_input..input.len())
+                .skip_while(|pos| !is_valid_linebreak(input, *pos))
+                .next()
             {
                 // A boundary was found after the line limit
-                Some(index) => break_at(max_width_index_in_input + index),
+                Some(index) => break_at(index),
                 // No boundary to the right, the input cannot be broken
                 None => SnippetState::EndOfInput(input.concat()),
             },
@@ -336,6 +337,23 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
     }
 }
 
+fn is_valid_linebreak(input: &[&str], pos: usize) -> bool {
+    let is_whitespace = is_whitespace(input[pos]);
+    if is_whitespace {
+        return true;
+    }
+    let is_punctuation = is_punctuation(input[pos]);
+    if is_punctuation && !is_part_of_type(input, pos) {
+        return true;
+    }
+    false
+}
+
+fn is_part_of_type(input: &[&str], pos: usize) -> bool {
+    input.get(pos..=pos + 1) == Some(&[":", ":"])
+        || input.get(pos.saturating_sub(1)..=pos) == Some(&[":", ":"])
+}
+
 fn is_new_line(grapheme: &str) -> bool {
     let bytes = grapheme.as_bytes();
     bytes.starts_with(b"\n") || bytes.starts_with(b"\r\n")
@@ -369,6 +387,19 @@ mod test {
         rewrite_string("eq_", &fmt, 2);
     }
 
+    #[test]
+    fn line_break_at_valid_points_test() {
+        let string = "[TheName](Dont::break::my::type::That::would::be::very::nice) break here";
+        let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
+        assert_eq!(
+            break_string(20, false, "", &graphemes[..]),
+            SnippetState::LineEnd(
+                "[TheName](Dont::break::my::type::That::would::be::very::nice) ".to_string(),
+                62
+            )
+        );
+    }
+
     #[test]
     fn should_break_on_whitespace() {
         let string = "Placerat felis. Mauris porta ante sagittis purus.";
diff --git a/tests/source/issue-5260.rs b/tests/source/issue-5260.rs
new file mode 100644
index 00000000000..c0606817290
--- /dev/null
+++ b/tests/source/issue-5260.rs
@@ -0,0 +1,14 @@
+// rustfmt-wrap_comments: true
+
+/// [MyType](VeryLongPathToMyType::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks)
+fn documented_with_longtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
+/// VeryLongPathToMyType::JustMyType::But::VeryVery::Long::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks
+fn documented_with_verylongtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
diff --git a/tests/target/issue-5260.rs b/tests/target/issue-5260.rs
new file mode 100644
index 00000000000..171f6fa51b7
--- /dev/null
+++ b/tests/target/issue-5260.rs
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: true
+
+/// [MyType](VeryLongPathToMyType::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks)
+fn documented_with_longtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
+/// VeryLongPathToMyType::JustMyType::But::VeryVery::Long::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks
+fn documented_with_verylongtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}

From 84fd4cdd022c7a6234006100b7e547eb2b178634 Mon Sep 17 00:00:00 2001
From: PSeitz <PSeitz@users.noreply.github.com>
Date: Mon, 9 May 2022 04:54:15 +0200
Subject: [PATCH 181/195] Update CHANGELOG.md

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b233608583..0db1dffd6e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 ### Fixed
 
 - Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+- Fixes an issue where types would be incorrectly wrapped in comments [#5260](https://github.com/rust-lang/rustfmt/issues/5260)
 
 ## [1.4.38] 2021-10-20
 

From 17003ce66b5737a71d0a08832995dc11df497ee2 Mon Sep 17 00:00:00 2001
From: Josh Triplett <josh@joshtriplett.org>
Date: Mon, 9 May 2022 17:10:53 -0700
Subject: [PATCH 182/195] In the docs for `hex_literal_case`, show the default
 as a possible value

---
 Configurations.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Configurations.md b/Configurations.md
index dc8d38267a8..7afd4b5cd6a 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1065,7 +1065,7 @@ See also: [`tab_spaces`](#tab_spaces).
 Control the case of the letters in hexadecimal literal values
 
 - **Default value**: `Preserve`
-- **Possible values**: `Upper`, `Lower`
+- **Possible values**: `Preserve`, `Upper`, `Lower`
 - **Stable**: No (tracking issue: [#5081](https://github.com/rust-lang/rustfmt/issues/5081))
 
 ## `hide_parse_errors`

From 8a4c05865be17bac75b8d53eae5be18d749a0f5c Mon Sep 17 00:00:00 2001
From: Koichi ITO <koic.ito@gmail.com>
Date: Thu, 12 May 2022 00:44:25 +0900
Subject: [PATCH 183/195] Use the traits added to the Rust 2021 Edition prelude

Follow up https://github.com/rust-lang/rust/pull/96861.

This PR uses the traits added to the Rust 2021 Edition prelude.

> The `TryInto`, `TryFrom` and `FromIterator` traits are now part of the prelude.

https://doc.rust-lang.org/edition-guide/rust-2021/prelude.html
---
 src/cargo-fmt/main.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 3542536f29b..55fd75f6de9 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -10,7 +10,6 @@ use std::ffi::OsStr;
 use std::fs;
 use std::hash::{Hash, Hasher};
 use std::io::{self, Write};
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;

From b08b2daeb6da2f77be50a53cdca2098fb3bb11b2 Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Thu, 31 Mar 2022 18:15:51 -0400
Subject: [PATCH 184/195] Add test for issue 3937

Closes 3937

It's unclear which change fixed the `format_code_in_doc_comments=true`
issue brought up in this issue, however I'm unable to reproduce the
error on the current master.

The added test cases should serve to prevent a regression.
---
 tests/target/issue_3937.rs | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 tests/target/issue_3937.rs

diff --git a/tests/target/issue_3937.rs b/tests/target/issue_3937.rs
new file mode 100644
index 00000000000..80673108500
--- /dev/null
+++ b/tests/target/issue_3937.rs
@@ -0,0 +1,13 @@
+// rustfmt-format_code_in_doc_comments:true
+
+struct Foo {
+    // a: i32,
+    //
+    // b: i32,
+}
+
+struct Foo {
+    a: i32,
+    //
+    // b: i32,
+}

From 95837832f4bb89a681fd7fae57dad42fca497e23 Mon Sep 17 00:00:00 2001
From: David Lattimore <dvdlttmr@gmail.com>
Date: Sat, 30 Apr 2022 15:12:06 +1000
Subject: [PATCH 185/195] import_granularity: Don't normalize imports with
 comments

---
 src/imports.rs                             | 17 +++++++-
 tests/source/imports_granularity_crate.rs  | 28 +++++++++++++
 tests/source/imports_granularity_item.rs   | 28 +++++++++++++
 tests/source/imports_granularity_module.rs | 28 +++++++++++++
 tests/source/imports_granularity_one.rs    | 28 +++++++++++++
 tests/target/imports_granularity_crate.rs  | 31 +++++++++++++++
 tests/target/imports_granularity_item.rs   | 32 +++++++++++++++
 tests/target/imports_granularity_module.rs | 39 ++++++++++++++++--
 tests/target/imports_granularity_one.rs    | 46 ++++++++++++++++++----
 9 files changed, 264 insertions(+), 13 deletions(-)

diff --git a/src/imports.rs b/src/imports.rs
index efe4e9498c9..962f2126c66 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -181,6 +181,14 @@ impl UseSegment {
             }
         })
     }
+
+    fn contains_comment(&self) -> bool {
+        if let UseSegment::List(list) = self {
+            list.iter().any(|subtree| subtree.contains_comment())
+        } else {
+            false
+        }
+    }
 }
 
 pub(crate) fn normalize_use_trees_with_granularity(
@@ -197,7 +205,7 @@ pub(crate) fn normalize_use_trees_with_granularity(
 
     let mut result = Vec::with_capacity(use_trees.len());
     for use_tree in use_trees {
-        if use_tree.has_comment() || use_tree.attrs.is_some() {
+        if use_tree.contains_comment() || use_tree.attrs.is_some() {
             result.push(use_tree);
             continue;
         }
@@ -556,6 +564,10 @@ impl UseTree {
         self.list_item.as_ref().map_or(false, ListItem::has_comment)
     }
 
+    fn contains_comment(&self) -> bool {
+        self.has_comment() || self.path.iter().any(|path| path.contains_comment())
+    }
+
     fn same_visibility(&self, other: &UseTree) -> bool {
         match (&self.visibility, &other.visibility) {
             (
@@ -582,6 +594,7 @@ impl UseTree {
         if self.path.is_empty()
             || other.path.is_empty()
             || self.attrs.is_some()
+            || self.contains_comment()
             || !self.same_visibility(other)
         {
             false
@@ -597,7 +610,7 @@ impl UseTree {
     }
 
     fn flatten(self, import_granularity: ImportGranularity) -> Vec<UseTree> {
-        if self.path.is_empty() {
+        if self.path.is_empty() || self.contains_comment() {
             return vec![self];
         }
         match self.path.clone().last().unwrap() {
diff --git a/tests/source/imports_granularity_crate.rs b/tests/source/imports_granularity_crate.rs
index d16681b01b5..f6f7761e82e 100644
--- a/tests/source/imports_granularity_crate.rs
+++ b/tests/source/imports_granularity_crate.rs
@@ -35,3 +35,31 @@ use j::{a::{self}};
 
 use {k::{a, b}, l::{a, b}};
 use {k::{c, d}, l::{c, d}};
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/tests/source/imports_granularity_item.rs b/tests/source/imports_granularity_item.rs
index d0e94df66ae..b82c0d33caf 100644
--- a/tests/source/imports_granularity_item.rs
+++ b/tests/source/imports_granularity_item.rs
@@ -4,3 +4,31 @@ use a::{b, c, d};
 use a::{f::g, h::{i, j}};
 use a::{l::{self, m, n::o, p::*}};
 use a::q::{self};
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/tests/source/imports_granularity_module.rs b/tests/source/imports_granularity_module.rs
index 2d7bb299aaa..c7f68cea6d4 100644
--- a/tests/source/imports_granularity_module.rs
+++ b/tests/source/imports_granularity_module.rs
@@ -17,3 +17,31 @@ use bar::{
     c::d,
     e::f,
 };
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/tests/source/imports_granularity_one.rs b/tests/source/imports_granularity_one.rs
index c21707df395..4d5a4795641 100644
--- a/tests/source/imports_granularity_one.rs
+++ b/tests/source/imports_granularity_one.rs
@@ -58,3 +58,31 @@ use a::{
 };
 use b as x;
 use a::ad::ada;
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/tests/target/imports_granularity_crate.rs b/tests/target/imports_granularity_crate.rs
index d75906d30f1..36e01558ff0 100644
--- a/tests/target/imports_granularity_crate.rs
+++ b/tests/target/imports_granularity_crate.rs
@@ -26,3 +26,34 @@ use j::a::{self};
 
 use k::{a, b, c, d};
 use l::{a, b, c, d};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    c, d, e,
+    u::{a, b},
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/tests/target/imports_granularity_item.rs b/tests/target/imports_granularity_item.rs
index eace785e670..d2f5496fdac 100644
--- a/tests/target/imports_granularity_item.rs
+++ b/tests/target/imports_granularity_item.rs
@@ -11,3 +11,35 @@ use a::l::n::o;
 use a::l::p::*;
 use a::l::{self};
 use a::q::{self};
+
+use b::c;
+use b::d;
+use b::e;
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::u::a;
+use b::u::b;
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/tests/target/imports_granularity_module.rs b/tests/target/imports_granularity_module.rs
index e4e1a299e58..14f341016ff 100644
--- a/tests/target/imports_granularity_module.rs
+++ b/tests/target/imports_granularity_module.rs
@@ -17,6 +17,39 @@ use foo::e;
 #[cfg(test)]
 use foo::{a::b, c::d};
 
-use bar::a::b;
-use bar::c::d;
-use bar::e::f;
+use bar::{
+    // comment
+    a::b,
+    // more comment
+    c::d,
+    e::f,
+};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::u::{a, b};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{c, d, e};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/tests/target/imports_granularity_one.rs b/tests/target/imports_granularity_one.rs
index 78ec5e7325c..da4c6678db1 100644
--- a/tests/target/imports_granularity_one.rs
+++ b/tests/target/imports_granularity_one.rs
@@ -68,12 +68,42 @@ use {
     c::{self, ca},
 };
 
-use {
-    a::{
-        aa::{aaa, aab},
-        ab,
-        ac::aca,
-        ad::ada,
-    },
-    b as x,
+use a::{
+    // some comment
+    aa::{aaa, aab},
+    ab,
+    // another comment
+    ac::aca,
+};
+use {a::ad::ada, b as x};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    c, d, e,
+    u::{a, b},
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
 };

From 0b6659cf02fd9bbdec1c0a5a90b48d1aff1ed5f8 Mon Sep 17 00:00:00 2001
From: Alexander Pozdneev <pozdneev@users.noreply.github.com>
Date: Sun, 22 May 2022 21:41:03 +0100
Subject: [PATCH 186/195] Update Configurations.md

---
 Configurations.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Configurations.md b/Configurations.md
index 7afd4b5cd6a..5380275f8f9 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -10,7 +10,7 @@ reorder_imports = false
 ```
 
 Each configuration option is either stable or unstable.
-Stable options can be used directly, while unstable options are opt-in.
+Stable options can always be used, while unstable ones are only available on a nightly toolchain, and opt-in.
 To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or pass `--unstable-features` to rustfmt.
 
 # Configuration Options

From 37b48ca4b20fa9873297bcef9f25abf3fcdbd475 Mon Sep 17 00:00:00 2001
From: Alexander Pozdneev <pozdneev@users.noreply.github.com>
Date: Mon, 23 May 2022 10:07:19 +0100
Subject: [PATCH 187/195] Update Configurations.md

Co-authored-by: Yacin Tmimi <yacintmimi@gmail.com>
---
 Configurations.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Configurations.md b/Configurations.md
index 5380275f8f9..b3463fad19b 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -10,7 +10,7 @@ reorder_imports = false
 ```
 
 Each configuration option is either stable or unstable.
-Stable options can always be used, while unstable ones are only available on a nightly toolchain, and opt-in.
+Stable options can always be used, while unstable options are only available on a nightly toolchain and must be opted into.
 To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or pass `--unstable-features` to rustfmt.
 
 # Configuration Options

From a5cfd4d14522ae064c55ac776731b069ae91bb9c Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Sat, 9 Apr 2022 00:31:24 -0400
Subject: [PATCH 188/195] Updated Unreleased CHANGELOG entries

from revision  v1.4.38..2d9bc460
---
 CHANGELOG.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0db1dffd6e0..729c7516d1f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,62 @@
 
 ## [Unreleased]
 
+### Changed
+
+- Also apply `empty_item_single_line=true` to trait definitions to match the behavior of empty functions, struct, enums, and impls [#5047](https://github.com/rust-lang/rustfmt/issues/5047)
+
 ### Fixed
 
+- Block indent line breaks for type alias impl traits (TAITs) when `version = "Two"` [#5027](https://github.com/rust-lang/rustfmt/issues/5027)
+- Retain trailing comments in module when using `#![rustfmt::skip]` [#5033](https://github.com/rust-lang/rustfmt/issues/5033)
+- Remove trailing whitespace when formatting a where clause with an empty right hand side [#5012](https://github.com/rust-lang/rustfmt/issues/5012) [#4850](https://github.com/rust-lang/rustfmt/issues/4850)
+- Fix various module resolution issues:
+  - Handle external mods imported via external->inline load hierarchy [#5063](https://github.com/rust-lang/rustfmt/issues/5063)
+  - Resolve sub modules of integration tests [#5119](https://github.com/rust-lang/rustfmt/issues/5119)
+  - Module resolution will fallback to the current search directory if a relative directory search results in a `FileNotFound` error [#5198](https://github.com/rust-lang/rustfmt/issues/5198)
+  - Give clearer error messsaeg when a module is found in two places (e.g `x.rs` and `x/mod.rs`) [#5167](https://github.com/rust-lang/rustfmt/issues/5167)
+- Prevent rustfmt from adding an `impl Trait` definition into types [#5086](https://github.com/rust-lang/rustfmt/issues/5086)
+- Correctly format associated type in macro body [#4823](https://github.com/rust-lang/rustfmt/issues/4823)
+- Fix cases where `normalize_comments=true` would de-normalizes some comments [#4909](https://github.com/rust-lang/rustfmt/issues/4909)
+- Prevent rustfmt from wrapping reference style links [#5095](https://github.com/rust-lang/rustfmt/issues/5095) and [#4933](https://github.com/rust-lang/rustfmt/issues/4933)
+- Prevent rustfmt from always adding an empty comment line when formatting itemized blocks [#5088](https://github.com/rust-lang/rustfmt/issues/5088)
+- Don't format files annotated with an inner `#![rustfmt::skip]` attribute [PR #5094](https://github.com/rust-lang/rustfmt/pull/5094)
+- Remove duplicate comma when struct pattern ends with `..` and `trailing_comma=Always` [#5066](https://github.com/rust-lang/rustfmt/issues/5066)
+- Fix static async closure qualifier order [#5149](https://github.com/rust-lang/rustfmt/issues/5149)
+- Retain qualified path when rewriting struct literal expressions [#5151](https://github.com/rust-lang/rustfmt/issues/5151)
+- Do not flatten match arm block with leading attributes [#4109](https://github.com/rust-lang/rustfmt/issues/4109)
+- Backport json emitter and stdin changes [PR #5054](https://github.com/rust-lang/rustfmt/pull/5054)
+  - Make `--check` work when running rustfmt with input from stdin [PR #3896](https://github.com/rust-lang/rustfmt/pull/3896)
+  - Fix `--check` with the `--files-with-diff` flag [PR #3910](https://github.com/rust-lang/rustfmt/pull/3910)
+  - Produce valid JSON when using the JSON emitter [PR #3953](https://github.com/rust-lang/rustfmt/pull/3953)
+  - Fix newlines in JSON output [PR #4262](https://github.com/rust-lang/rustfmt/pull/4262)
+  - Use `<stdin>` when emitting stdin as filename [PR #4298](https://github.com/rust-lang/rustfmt/pull/4298)
+- Generate output when formatting `@generated` input via stdin [#5172](https://github.com/rust-lang/rustfmt/issues/5172)
+- Fix comment indentation in empty structs [#4854](https://github.com/rust-lang/rustfmt/issues/4854)
+- Prevent adding whitespace when rewriting `ast::Param` [#5125](https://github.com/rust-lang/rustfmt/issues/5125)
+- Prevent panic when `wrap_comments=true` and non-ascii character at comment wrap boundary [#5023](https://github.com/rust-lang/rustfmt/issues/5023)
+- Retain trailing commas in inline post comments [#5042](https://github.com/rust-lang/rustfmt/issues/5042)
+- Fix `import_granularity` option when the use tree has an alias [#5131](https://github.com/rust-lang/rustfmt/issues/5131)
+- Don't merge gereric items into their doc comments [#5122](https://github.com/rust-lang/rustfmt/issues/5122)
 - Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+- Handle markdown block quotes when `wrap_comments=true` [#5157](https://github.com/rust-lang/rustfmt/issues/5157)
+- Long markdown headers are no longer wrapped when `wrap_comments=true` [#5238](https://github.com/rust-lang/rustfmt/issues/5238)
+- Retain trailing comma when struct fields are followed by an empty line [#4791](https://github.com/rust-lang/rustfmt/issues/4791) [#4928](https://github.com/rust-lang/rustfmt/issues/4928)
+- Fix compile error when `imports_granularity=Module` and path contains self [#4681](https://github.com/rust-lang/rustfmt/issues/4681)
 - Fixes an issue where types would be incorrectly wrapped in comments [#5260](https://github.com/rust-lang/rustfmt/issues/5260)
+- Don't duplicate parts of `const` expressions when formatting generic arguments [#5273](https://github.com/rust-lang/rustfmt/issues/5273)
+- Prevent merging derives when using `#[rustfmt::skip::attributes(derive)]` [#5270](https://github.com/rust-lang/rustfmt/issues/5270)
+- Retain trailing `;` when rewriting macro call in extern block [#5281](https://github.com/rust-lang/rustfmt/issues/5281)
+- Add a newline when formatting struct fields preceeded by doc comments and inline comments [#5215](https://github.com/rust-lang/rustfmt/issues/5215)
+
+### Added
+
+- Added `One` as a new [group_imports](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#group_imports) option to create a single group for all imports [PR #4966](https://github.com/rust-lang/rustfmt/pull/4966)
+- Add [short_array_element_width_threshold](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#short_array_element_width_threshold) config option [PR #5228](https://github.com/rust-lang/rustfmt/pull/5228)
+
+### Removed
+
+- Remove rustfmt executable path from usage string [#5214](https://github.com/rust-lang/rustfmt/issues/5214)
 
 ## [1.4.38] 2021-10-20
 

From 73be264f9f8be070bd2764323911f94f1529db4d Mon Sep 17 00:00:00 2001
From: Yacin Tmimi <yacintmimi@gmail.com>
Date: Thu, 26 May 2022 16:06:46 -0400
Subject: [PATCH 189/195] Rephrase changelog entries to give more context

---
 CHANGELOG.md | 72 +++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 729c7516d1f..e729bfb8486 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,60 +4,62 @@
 
 ### Changed
 
-- Also apply `empty_item_single_line=true` to trait definitions to match the behavior of empty functions, struct, enums, and impls [#5047](https://github.com/rust-lang/rustfmt/issues/5047)
+- Also apply `empty_item_single_line=true` to trait definitions to match the behavior of empty functions, structs, enums, and impls [#5047](https://github.com/rust-lang/rustfmt/issues/5047)
 
 ### Fixed
 
-- Block indent line breaks for type alias impl traits (TAITs) when `version = "Two"` [#5027](https://github.com/rust-lang/rustfmt/issues/5027)
-- Retain trailing comments in module when using `#![rustfmt::skip]` [#5033](https://github.com/rust-lang/rustfmt/issues/5033)
-- Remove trailing whitespace when formatting a where clause with an empty right hand side [#5012](https://github.com/rust-lang/rustfmt/issues/5012) [#4850](https://github.com/rust-lang/rustfmt/issues/4850)
-- Fix various module resolution issues:
+- Prevent rustfmt from removing trailing comments at the end of files annotated with inner `#![rustfmt::skip]` attributes [#5033](https://github.com/rust-lang/rustfmt/issues/5033)
+- Fixed various `error[internal]: left behind trailing whitespace"` issues:
+  - Remove trailing whitespace when formatting a where clause who's bounds have an empty right hand side [#5012](https://github.com/rust-lang/rustfmt/issues/5012) [#4850](https://github.com/rust-lang/rustfmt/issues/4850)
+  - Prevent rustfmt from adding an empty comment line when rewriting markdown lists at the start of doc comments. This issue was triggered when `wrap_comments=true` [#5088](https://github.com/rust-lang/rustfmt/issues/5088)
+- Prevent adding a block indented newline before a function parameter with a complex type that was formatted over multiple lines [#5125](https://github.com/rust-lang/rustfmt/issues/5125)
+- Fix various module resolution issues preventing rustfmt from finding modules that should be formatted:
   - Handle external mods imported via external->inline load hierarchy [#5063](https://github.com/rust-lang/rustfmt/issues/5063)
   - Resolve sub modules of integration tests [#5119](https://github.com/rust-lang/rustfmt/issues/5119)
   - Module resolution will fallback to the current search directory if a relative directory search results in a `FileNotFound` error [#5198](https://github.com/rust-lang/rustfmt/issues/5198)
-  - Give clearer error messsaeg when a module is found in two places (e.g `x.rs` and `x/mod.rs`) [#5167](https://github.com/rust-lang/rustfmt/issues/5167)
-- Prevent rustfmt from adding an `impl Trait` definition into types [#5086](https://github.com/rust-lang/rustfmt/issues/5086)
-- Correctly format associated type in macro body [#4823](https://github.com/rust-lang/rustfmt/issues/4823)
-- Fix cases where `normalize_comments=true` would de-normalizes some comments [#4909](https://github.com/rust-lang/rustfmt/issues/4909)
-- Prevent rustfmt from wrapping reference style links [#5095](https://github.com/rust-lang/rustfmt/issues/5095) and [#4933](https://github.com/rust-lang/rustfmt/issues/4933)
-- Prevent rustfmt from always adding an empty comment line when formatting itemized blocks [#5088](https://github.com/rust-lang/rustfmt/issues/5088)
-- Don't format files annotated with an inner `#![rustfmt::skip]` attribute [PR #5094](https://github.com/rust-lang/rustfmt/pull/5094)
-- Remove duplicate comma when struct pattern ends with `..` and `trailing_comma=Always` [#5066](https://github.com/rust-lang/rustfmt/issues/5066)
-- Fix static async closure qualifier order [#5149](https://github.com/rust-lang/rustfmt/issues/5149)
-- Retain qualified path when rewriting struct literal expressions [#5151](https://github.com/rust-lang/rustfmt/issues/5151)
-- Do not flatten match arm block with leading attributes [#4109](https://github.com/rust-lang/rustfmt/issues/4109)
+- Give users a clearer error message when resolving a module who's file path is ambiguous (e.g `x.rs` and `x/mod.rs`). Before users were given a `File not found` error message which was confusing [#5167](https://github.com/rust-lang/rustfmt/issues/5167)
+- Fix various issues related to type aliases:
+  - Prevent rustfmt from adding `= impl` to associated types defined in macro bodies [#4823](https://github.com/rust-lang/rustfmt/issues/4823)
+  - Properly block indent type alias impl traits (TAITs) that wrap to the next line when `version=Two` is set. Before any trait bounds that wrapped to the next line would not be indented [#5027](https://github.com/rust-lang/rustfmt/issues/5027)
+  - Prevent rustfmt from adding an `impl Trait` definition into types [#5086](https://github.com/rust-lang/rustfmt/issues/5086)
+- Fix cases where `normalize_comments=true` would de-normalizes some comments by changing inline comments into block comments [#4909](https://github.com/rust-lang/rustfmt/issues/4909)
+- Prevent rustfmt from wrapping the content of markdown [reference-style links](https://www.markdownguide.org/basic-syntax/#reference-style-links) in doc comments [#5095](https://github.com/rust-lang/rustfmt/issues/5095) [#4933](https://github.com/rust-lang/rustfmt/issues/4933)
+- Don't format files annotated with inner `#![rustfmt::skip]` attribute [PR #5094](https://github.com/rust-lang/rustfmt/pull/5094)
+- Prevent duplicate comma when struct pattern ends with `..` and `trailing_comma=Always`. For example, `let Foo { a, .. } = b;` would become `let Foo { a,, .. } = b;` [#5066](https://github.com/rust-lang/rustfmt/issues/5066)
+- Fix the order of `static` and `async` keywords when rewriting static async closures. The correct order is `static` and then `async` (e.g `static async || {}`) [#5149](https://github.com/rust-lang/rustfmt/issues/5149)
+- Retain the fully qualified path segment when rewriting struct literals in expression position. Now `<Struct as Trait>::Type` is not rewritten as `Trait::Type` [#5151](https://github.com/rust-lang/rustfmt/issues/5151)
+- Do not remove match arm braces from a match arm with a single `ast::ExprKind::Block` that has leading attributes. Removing the braces could lead to code that does not compile. Now rustfmt will leave the outer `{}` in place when formatting `=> {#[allow(unsafe_code)]unsafe {}}` [#4109](https://github.com/rust-lang/rustfmt/issues/4109)
 - Backport json emitter and stdin changes [PR #5054](https://github.com/rust-lang/rustfmt/pull/5054)
   - Make `--check` work when running rustfmt with input from stdin [PR #3896](https://github.com/rust-lang/rustfmt/pull/3896)
   - Fix `--check` with the `--files-with-diff` flag [PR #3910](https://github.com/rust-lang/rustfmt/pull/3910)
   - Produce valid JSON when using the JSON emitter [PR #3953](https://github.com/rust-lang/rustfmt/pull/3953)
   - Fix newlines in JSON output [PR #4262](https://github.com/rust-lang/rustfmt/pull/4262)
   - Use `<stdin>` when emitting stdin as filename [PR #4298](https://github.com/rust-lang/rustfmt/pull/4298)
-- Generate output when formatting `@generated` input via stdin [#5172](https://github.com/rust-lang/rustfmt/issues/5172)
-- Fix comment indentation in empty structs [#4854](https://github.com/rust-lang/rustfmt/issues/4854)
-- Prevent adding whitespace when rewriting `ast::Param` [#5125](https://github.com/rust-lang/rustfmt/issues/5125)
-- Prevent panic when `wrap_comments=true` and non-ascii character at comment wrap boundary [#5023](https://github.com/rust-lang/rustfmt/issues/5023)
-- Retain trailing commas in inline post comments [#5042](https://github.com/rust-lang/rustfmt/issues/5042)
-- Fix `import_granularity` option when the use tree has an alias [#5131](https://github.com/rust-lang/rustfmt/issues/5131)
-- Don't merge gereric items into their doc comments [#5122](https://github.com/rust-lang/rustfmt/issues/5122)
-- Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
-- Handle markdown block quotes when `wrap_comments=true` [#5157](https://github.com/rust-lang/rustfmt/issues/5157)
-- Long markdown headers are no longer wrapped when `wrap_comments=true` [#5238](https://github.com/rust-lang/rustfmt/issues/5238)
-- Retain trailing comma when struct fields are followed by an empty line [#4791](https://github.com/rust-lang/rustfmt/issues/4791) [#4928](https://github.com/rust-lang/rustfmt/issues/4928)
-- Fix compile error when `imports_granularity=Module` and path contains self [#4681](https://github.com/rust-lang/rustfmt/issues/4681)
-- Fixes an issue where types would be incorrectly wrapped in comments [#5260](https://github.com/rust-lang/rustfmt/issues/5260)
-- Don't duplicate parts of `const` expressions when formatting generic arguments [#5273](https://github.com/rust-lang/rustfmt/issues/5273)
-- Prevent merging derives when using `#[rustfmt::skip::attributes(derive)]` [#5270](https://github.com/rust-lang/rustfmt/issues/5270)
-- Retain trailing `;` when rewriting macro call in extern block [#5281](https://github.com/rust-lang/rustfmt/issues/5281)
-- Add a newline when formatting struct fields preceeded by doc comments and inline comments [#5215](https://github.com/rust-lang/rustfmt/issues/5215)
+- Always generate some output when formatting `@generated` files via stdin even when `format_generated_files=false`. Not producing output caused rust-analyzer to delete the file content [rust-lang/rust-analyzer](https://github.com/rust-lang/rust-analyzer/issues/11285) [#5172](https://github.com/rust-lang/rustfmt/issues/5172)
+- Properly block indent multi-line comments in empty struct definitions. Previously, only the first comment line would be block indented. All other comment lines would be aligned with the struct definition [#4854](https://github.com/rust-lang/rustfmt/issues/4854)
+- Prevent rustfmt from wrapping a comment at a byte position inside a non-ascii character when `wrap_comments=true`. This prevents rustfmt from panicking when breaking on the invalid position [#5023](https://github.com/rust-lang/rustfmt/issues/5023)
+- Prevent rustfmt from removing commented out trailing separators (e.g commas) when rewriting lists. For example, remove the comma from a comment like this `// ...,` would lead to a scenario where the entire list could not be rewritten because the content of the comment changed [#5042](https://github.com/rust-lang/rustfmt/issues/5042)
+- Fix panic when `import_granularity` was set to `Module`, `One`, or `Crate` and the import use declaration contained an alias `use crate a::b as b1` [#5131](https://github.com/rust-lang/rustfmt/issues/5131)
+- Add a newline between generic parameters and their doc comments to prevent the generic parameters from being merged into their doc comments [#5122](https://github.com/rust-lang/rustfmt/issues/5122)
+- Fixes indentation issue where string literals manually broken with line continuation characters (`\`) would be incorrectly indented in macro definitions when setting `format_strings=true`[#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+- Properly wrap and format long markdown block quotes when `wrap_comments=true` [#5157](https://github.com/rust-lang/rustfmt/issues/5157)
+- Prevent rustfmt from wrapping markdown headers even when `wrap_comments=true`. Wrapping the markdown headers would prevent them from being properly rendered with rustdoc [#5238](https://github.com/rust-lang/rustfmt/issues/5238)
+- Prevent rustfmt from removing commas between struct fields when those fields were also separated by an empty line [#4791](https://github.com/rust-lang/rustfmt/issues/4791) [#4928](https://github.com/rust-lang/rustfmt/issues/4928)
+- Fix compiler error caused when formatting imports with `imports_granularity=Module` and a path containing `self`. Given the following import `use crate::lexer::{self, tokens::TokenData};`, rustfmt would transform the `self` import into `use crate::lexer::self;`. Now rustfmt produces `use crate::lexer::{self};` [#4681](https://github.com/rust-lang/rustfmt/issues/4681)
+- Prevent rustfmt from breaking long type links in doc comments on namespace qualifiers (`::`) when `wrap_comments=true`. Breaking these long type links over multiple lines prevented them from being properly rendered in rustdoc [#5260](https://github.com/rust-lang/rustfmt/issues/5260)
+- Correctly find the start of struct bodies after any generic `const` parameters. Naively searching for an opening `{` lead to issues since generic `const` parameters are also defined with `{}` (e.g. `struct Example<const N: usize = { 1048576 }> {}`) [#5273](https://github.com/rust-lang/rustfmt/issues/5273)
+- Prevent rustfmt from merging derives when using inner or outer `rustfmt::skip::attributes` attributes. For example, `#[rustfmt::skip::attributes(derive)]` [#5270](https://github.com/rust-lang/rustfmt/issues/5270)
+- Retain trailing `;` when rewriting macro calls in extern blocks. For example, `extern "C" { x!(-); }`[#5281](https://github.com/rust-lang/rustfmt/issues/5281)
+- Add a newline when formatting struct fields preceded by both doc comments and inline comments to prevent the field from being merged into the inline comment. This was not an issue when a struct was preceded by just a doc comment or just an inline comment [#5215](https://github.com/rust-lang/rustfmt/issues/5215)
 
 ### Added
 
 - Added `One` as a new [group_imports](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#group_imports) option to create a single group for all imports [PR #4966](https://github.com/rust-lang/rustfmt/pull/4966)
-- Add [short_array_element_width_threshold](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#short_array_element_width_threshold) config option [PR #5228](https://github.com/rust-lang/rustfmt/pull/5228)
+- Add [short_array_element_width_threshold](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#short_array_element_width_threshold) config option to give users more control over when `Mixed` list formatting is used [PR #5228](https://github.com/rust-lang/rustfmt/pull/5228)
 
 ### Removed
 
-- Remove rustfmt executable path from usage string [#5214](https://github.com/rust-lang/rustfmt/issues/5214)
+- Remove rustfmt binary path from the usage string when running `rustfmt --help` [#5214](https://github.com/rust-lang/rustfmt/issues/5214)
 
 ## [1.4.38] 2021-10-20
 

From 3e38399ed89da3b7ed68b062ad82bdc0f2068685 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Thu, 26 May 2022 21:56:35 -0500
Subject: [PATCH 190/195] docs: clarify imports_granularity behavior with
 comments

---
 CHANGELOG.md      | 1 +
 Configurations.md | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e729bfb8486..3664571fe64 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 
 ### Fixed
 
+- Don't change granularity of imports containing comments with `imports_granularity` if doing so could lose or misplace those comments [#5311](https://github.com/rust-lang/rustfmt/pull/5311)
 - Prevent rustfmt from removing trailing comments at the end of files annotated with inner `#![rustfmt::skip]` attributes [#5033](https://github.com/rust-lang/rustfmt/issues/5033)
 - Fixed various `error[internal]: left behind trailing whitespace"` issues:
   - Remove trailing whitespace when formatting a where clause who's bounds have an empty right hand side [#5012](https://github.com/rust-lang/rustfmt/issues/5012) [#4850](https://github.com/rust-lang/rustfmt/issues/4850)
diff --git a/Configurations.md b/Configurations.md
index b3463fad19b..669da79087c 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1705,6 +1705,8 @@ How imports should be grouped into `use` statements. Imports will be merged or s
 - **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):
 
 Do not change the granularity of any imports and preserve the original structure written by the developer.

From 4c8db8593905d09a872601c445005a594ac632dc Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 29 May 2022 21:35:12 -0500
Subject: [PATCH 191/195] feat: remove report_todo option

---
 Configurations.md            |  17 ------
 src/config/mod.rs            |   3 -
 src/formatting.rs            |   4 +-
 src/issues.rs                | 110 ++++++-----------------------------
 src/test/mod.rs              |   5 +-
 tests/config/small_tabs.toml |   1 -
 6 files changed, 20 insertions(+), 120 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 669da79087c..72499618755 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2180,23 +2180,6 @@ Warns about any comments containing `FIXME` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
 `FIXME`, `"Unnumbered"` will ignore it.
 
-See also [`report_todo`](#report_todo).
-
-
-## `report_todo`
-
-Report `TODO` items in comments.
-
-- **Default value**: `"Never"`
-- **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393))
-
-Warns about any comments containing `TODO` in them when set to `"Always"`. If
-it contains a `#X` (with `X` being a number) in parentheses following the
-`TODO`, `"Unnumbered"` will ignore it.
-
-See also [`report_fixme`](#report_fixme).
-
 ## `required_version`
 
 Require a specific version of rustfmt. If you want to make sure that the
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 18e1854612b..4c14d735689 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -164,8 +164,6 @@ create_config! {
     error_on_unformatted: bool, false, false,
         "Error if unable to get comments or string literals within max_width, \
          or they are left with trailing whitespaces";
-    report_todo: ReportTactic, ReportTactic::Never, false,
-        "Report all, none or unnumbered occurrences of TODO in source file comments";
     report_fixme: ReportTactic, ReportTactic::Never, false,
         "Report all, none or unnumbered occurrences of FIXME in source file comments";
     ignore: IgnoreList, IgnoreList::default(), false,
@@ -625,7 +623,6 @@ skip_children = false
 hide_parse_errors = false
 error_on_line_overflow = false
 error_on_unformatted = false
-report_todo = "Never"
 report_fixme = "Never"
 ignore = []
 emit_mode = "Files"
diff --git a/src/formatting.rs b/src/formatting.rs
index 281d3e4e808..8e6999643b1 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -497,7 +497,7 @@ impl<'a> FormatLines<'a> {
         skipped_range: &'a [(usize, usize)],
         config: &'a Config,
     ) -> FormatLines<'a> {
-        let issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme());
+        let issue_seeker = BadIssueSeeker::new(config.report_fixme());
         FormatLines {
             name,
             skipped_range,
@@ -537,7 +537,7 @@ impl<'a> FormatLines<'a> {
             }
 
             if self.allow_issue_seek && self.format_line {
-                // Add warnings for bad todos/ fixmes
+                // Add warnings for bad fixmes
                 if let Some(issue) = self.issue_seeker.inspect(c) {
                     self.push_err(ErrorKind::BadIssue(issue), false, false);
                 }
diff --git a/src/issues.rs b/src/issues.rs
index 33fb5522aea..3c39d813a6f 100644
--- a/src/issues.rs
+++ b/src/issues.rs
@@ -6,7 +6,6 @@ use std::fmt;
 
 use crate::config::ReportTactic;
 
-const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o'];
 const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
 
 // Enabled implementation detail is here because it is
@@ -17,7 +16,7 @@ fn is_enabled(report_tactic: ReportTactic) -> bool {
 
 #[derive(Clone, Copy)]
 enum Seeking {
-    Issue { todo_idx: usize, fixme_idx: usize },
+    Issue { fixme_idx: usize },
     Number { issue: Issue, part: NumberPart },
 }
 
@@ -40,7 +39,6 @@ pub struct Issue {
 impl fmt::Display for Issue {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         let msg = match self.issue_type {
-            IssueType::Todo => "TODO",
             IssueType::Fixme => "FIXME",
         };
         let details = if self.missing_number {
@@ -55,7 +53,6 @@ impl fmt::Display for Issue {
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 enum IssueType {
-    Todo,
     Fixme,
 }
 
@@ -67,35 +64,27 @@ enum IssueClassification {
 
 pub(crate) struct BadIssueSeeker {
     state: Seeking,
-    report_todo: ReportTactic,
     report_fixme: ReportTactic,
 }
 
 impl BadIssueSeeker {
-    pub(crate) fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
+    pub(crate) fn new(report_fixme: ReportTactic) -> BadIssueSeeker {
         BadIssueSeeker {
-            state: Seeking::Issue {
-                todo_idx: 0,
-                fixme_idx: 0,
-            },
-            report_todo,
+            state: Seeking::Issue { fixme_idx: 0 },
             report_fixme,
         }
     }
 
     pub(crate) fn is_disabled(&self) -> bool {
-        !is_enabled(self.report_todo) && !is_enabled(self.report_fixme)
+        !is_enabled(self.report_fixme)
     }
 
     // Check whether or not the current char is conclusive evidence for an
     // unnumbered TO-DO or FIX-ME.
     pub(crate) fn inspect(&mut self, c: char) -> Option<Issue> {
         match self.state {
-            Seeking::Issue {
-                todo_idx,
-                fixme_idx,
-            } => {
-                self.state = self.inspect_issue(c, todo_idx, fixme_idx);
+            Seeking::Issue { fixme_idx } => {
+                self.state = self.inspect_issue(c, fixme_idx);
             }
             Seeking::Number { issue, part } => {
                 let result = self.inspect_number(c, issue, part);
@@ -104,10 +93,7 @@ impl BadIssueSeeker {
                     return None;
                 }
 
-                self.state = Seeking::Issue {
-                    todo_idx: 0,
-                    fixme_idx: 0,
-                };
+                self.state = Seeking::Issue { fixme_idx: 0 };
 
                 if let IssueClassification::Bad(issue) = result {
                     return Some(issue);
@@ -118,21 +104,9 @@ impl BadIssueSeeker {
         None
     }
 
-    fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking {
+    fn inspect_issue(&mut self, c: char, mut fixme_idx: usize) -> Seeking {
         if let Some(lower_case_c) = c.to_lowercase().next() {
-            if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] {
-                todo_idx += 1;
-                if todo_idx == TO_DO_CHARS.len() {
-                    return Seeking::Number {
-                        issue: Issue {
-                            issue_type: IssueType::Todo,
-                            missing_number: matches!(self.report_todo, ReportTactic::Unnumbered),
-                        },
-                        part: NumberPart::OpenParen,
-                    };
-                }
-                fixme_idx = 0;
-            } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
+            if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
                 // Exploit the fact that the character sets of todo and fixme
                 // are disjoint by adding else.
                 fixme_idx += 1;
@@ -145,17 +119,12 @@ impl BadIssueSeeker {
                         part: NumberPart::OpenParen,
                     };
                 }
-                todo_idx = 0;
             } else {
-                todo_idx = 0;
                 fixme_idx = 0;
             }
         }
 
-        Seeking::Issue {
-            todo_idx,
-            fixme_idx,
-        }
+        Seeking::Issue { fixme_idx }
     }
 
     fn inspect_number(
@@ -206,7 +175,7 @@ impl BadIssueSeeker {
 #[test]
 fn find_unnumbered_issue() {
     fn check_fail(text: &str, failing_pos: usize) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
         assert_eq!(
             Some(failing_pos),
             text.find(|c| seeker.inspect(c).is_some())
@@ -214,12 +183,10 @@ fn find_unnumbered_issue() {
     }
 
     fn check_pass(text: &str) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
         assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
     }
 
-    check_fail("TODO\n", 4);
-    check_pass(" TO FIX DOME\n");
     check_fail(" \n FIXME\n", 8);
     check_fail("FIXME(\n", 6);
     check_fail("FIXME(#\n", 7);
@@ -228,71 +195,28 @@ fn find_unnumbered_issue() {
     check_pass("FIXME(#1222)\n");
     check_fail("FIXME(#12\n22)\n", 9);
     check_pass("FIXME(@maintainer, #1222, hello)\n");
-    check_fail("TODO(#22) FIXME\n", 15);
 }
 
 #[test]
 fn find_issue() {
-    fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool {
-        let mut seeker = BadIssueSeeker::new(report_todo, report_fixme);
+    fn is_bad_issue(text: &str, report_fixme: ReportTactic) -> bool {
+        let mut seeker = BadIssueSeeker::new(report_fixme);
         text.chars().any(|c| seeker.inspect(c).is_some())
     }
 
-    assert!(is_bad_issue(
-        "TODO(@maintainer, #1222, hello)\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
-
-    assert!(!is_bad_issue(
-        "TODO: no number\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(!is_bad_issue(
-        "Todo: mixed case\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(is_bad_issue(
-        "This is a FIXME(#1)\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
+    assert!(is_bad_issue("This is a FIXME(#1)\n", ReportTactic::Always));
 
     assert!(is_bad_issue(
         "This is a FixMe(#1) mixed case\n",
-        ReportTactic::Never,
         ReportTactic::Always,
     ));
 
-    assert!(!is_bad_issue(
-        "bad FIXME\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
+    assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Never));
 }
 
 #[test]
 fn issue_type() {
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
-    let expected = Some(Issue {
-        issue_type: IssueType::Todo,
-        missing_number: false,
-    });
-
-    assert_eq!(
-        expected,
-        "TODO(#100): more awesomeness"
-            .chars()
-            .map(|c| seeker.inspect(c))
-            .find(Option::is_some)
-            .unwrap()
-    );
-
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
+    let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
     let expected = Some(Issue {
         issue_type: IssueType::Fixme,
         missing_number: true,
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 4bad8e71481..0eda9e4b116 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -9,7 +9,7 @@ use std::process::{Command, Stdio};
 use std::str::Chars;
 use std::thread;
 
-use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
+use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle};
 use crate::formatting::{ReportedErrors, SourceFile};
 use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
 use crate::source_file;
@@ -688,9 +688,6 @@ fn read_config(filename: &Path) -> Config {
         }
     }
 
-    // Don't generate warnings for to-do items.
-    config.set().report_todo(ReportTactic::Never);
-
     config
 }
 
diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml
index 35c8fd86467..598edda6abe 100644
--- a/tests/config/small_tabs.toml
+++ b/tests/config/small_tabs.toml
@@ -6,7 +6,6 @@ brace_style = "SameLineWhere"
 fn_args_layout = "Tall"
 trailing_comma = "Vertical"
 indent_style = "Block"
-report_todo = "Always"
 report_fixme = "Never"
 reorder_imports = false
 format_strings = true

From 825561deb86524107f1c22b59bddb16703d2c790 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 29 May 2022 21:48:59 -0500
Subject: [PATCH 192/195] feat: remove report_fixme option

---
 Configurations.md            | 12 ------
 src/config/mod.rs            |  3 --
 src/formatting.rs            |  2 +-
 src/issues.rs                | 84 ++++++++----------------------------
 tests/config/small_tabs.toml |  1 -
 5 files changed, 19 insertions(+), 83 deletions(-)

diff --git a/Configurations.md b/Configurations.md
index 72499618755..edb2d1f7575 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2168,18 +2168,6 @@ mod sit;
 **Note** `mod` with `#[macro_export]` will not be reordered since that could change the semantics
 of the original source code.
 
-## `report_fixme`
-
-Report `FIXME` items in comments.
-
-- **Default value**: `"Never"`
-- **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: [#3394](https://github.com/rust-lang/rustfmt/issues/3394))
-
-Warns about any comments containing `FIXME` in them when set to `"Always"`. If
-it contains a `#X` (with `X` being a number) in parentheses following the
-`FIXME`, `"Unnumbered"` will ignore it.
-
 ## `required_version`
 
 Require a specific version of rustfmt. If you want to make sure that the
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 4c14d735689..fc724beae60 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -164,8 +164,6 @@ create_config! {
     error_on_unformatted: bool, false, false,
         "Error if unable to get comments or string literals within max_width, \
          or they are left with trailing whitespaces";
-    report_fixme: ReportTactic, ReportTactic::Never, false,
-        "Report all, none or unnumbered occurrences of FIXME in source file comments";
     ignore: IgnoreList, IgnoreList::default(), false,
         "Skip formatting the specified files and directories";
 
@@ -623,7 +621,6 @@ skip_children = false
 hide_parse_errors = false
 error_on_line_overflow = false
 error_on_unformatted = false
-report_fixme = "Never"
 ignore = []
 emit_mode = "Files"
 make_backup = false
diff --git a/src/formatting.rs b/src/formatting.rs
index 8e6999643b1..72bbe240f7b 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -497,7 +497,7 @@ impl<'a> FormatLines<'a> {
         skipped_range: &'a [(usize, usize)],
         config: &'a Config,
     ) -> FormatLines<'a> {
-        let issue_seeker = BadIssueSeeker::new(config.report_fixme());
+        let issue_seeker = BadIssueSeeker::new();
         FormatLines {
             name,
             skipped_range,
diff --git a/src/issues.rs b/src/issues.rs
index 3c39d813a6f..d95a80fe7fd 100644
--- a/src/issues.rs
+++ b/src/issues.rs
@@ -6,8 +6,6 @@ use std::fmt;
 
 use crate::config::ReportTactic;
 
-const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
-
 // Enabled implementation detail is here because it is
 // irrelevant outside the issues module
 fn is_enabled(report_tactic: ReportTactic) -> bool {
@@ -16,7 +14,7 @@ fn is_enabled(report_tactic: ReportTactic) -> bool {
 
 #[derive(Clone, Copy)]
 enum Seeking {
-    Issue { fixme_idx: usize },
+    Issue {},
     Number { issue: Issue, part: NumberPart },
 }
 
@@ -30,7 +28,7 @@ enum NumberPart {
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 pub struct Issue {
-    issue_type: IssueType,
+    issue_type: Option<IssueType>,
     // Indicates whether we're looking for issues with missing numbers, or
     // all issues of this type.
     missing_number: bool,
@@ -39,7 +37,7 @@ pub struct Issue {
 impl fmt::Display for Issue {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         let msg = match self.issue_type {
-            IssueType::Fixme => "FIXME",
+            _ => "",
         };
         let details = if self.missing_number {
             " without issue number"
@@ -52,9 +50,7 @@ impl fmt::Display for Issue {
 }
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
-enum IssueType {
-    Fixme,
-}
+enum IssueType {}
 
 enum IssueClassification {
     Good,
@@ -64,27 +60,25 @@ enum IssueClassification {
 
 pub(crate) struct BadIssueSeeker {
     state: Seeking,
-    report_fixme: ReportTactic,
 }
 
 impl BadIssueSeeker {
-    pub(crate) fn new(report_fixme: ReportTactic) -> BadIssueSeeker {
+    pub(crate) fn new() -> BadIssueSeeker {
         BadIssueSeeker {
-            state: Seeking::Issue { fixme_idx: 0 },
-            report_fixme,
+            state: Seeking::Issue {},
         }
     }
 
     pub(crate) fn is_disabled(&self) -> bool {
-        !is_enabled(self.report_fixme)
+        true
     }
 
     // Check whether or not the current char is conclusive evidence for an
     // unnumbered TO-DO or FIX-ME.
     pub(crate) fn inspect(&mut self, c: char) -> Option<Issue> {
         match self.state {
-            Seeking::Issue { fixme_idx } => {
-                self.state = self.inspect_issue(c, fixme_idx);
+            Seeking::Issue {} => {
+                self.state = self.inspect_issue(c, 0);
             }
             Seeking::Number { issue, part } => {
                 let result = self.inspect_number(c, issue, part);
@@ -93,7 +87,7 @@ impl BadIssueSeeker {
                     return None;
                 }
 
-                self.state = Seeking::Issue { fixme_idx: 0 };
+                self.state = Seeking::Issue {};
 
                 if let IssueClassification::Bad(issue) = result {
                     return Some(issue);
@@ -106,25 +100,10 @@ impl BadIssueSeeker {
 
     fn inspect_issue(&mut self, c: char, mut fixme_idx: usize) -> Seeking {
         if let Some(lower_case_c) = c.to_lowercase().next() {
-            if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
-                // Exploit the fact that the character sets of todo and fixme
-                // are disjoint by adding else.
-                fixme_idx += 1;
-                if fixme_idx == FIX_ME_CHARS.len() {
-                    return Seeking::Number {
-                        issue: Issue {
-                            issue_type: IssueType::Fixme,
-                            missing_number: matches!(self.report_fixme, ReportTactic::Unnumbered),
-                        },
-                        part: NumberPart::OpenParen,
-                    };
-                }
-            } else {
-                fixme_idx = 0;
-            }
+            fixme_idx = 0;
         }
 
-        Seeking::Issue { fixme_idx }
+        Seeking::Issue {}
     }
 
     fn inspect_number(
@@ -175,7 +154,7 @@ impl BadIssueSeeker {
 #[test]
 fn find_unnumbered_issue() {
     fn check_fail(text: &str, failing_pos: usize) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new();
         assert_eq!(
             Some(failing_pos),
             text.find(|c| seeker.inspect(c).is_some())
@@ -183,51 +162,24 @@ fn find_unnumbered_issue() {
     }
 
     fn check_pass(text: &str) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new();
         assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
     }
-
-    check_fail(" \n FIXME\n", 8);
-    check_fail("FIXME(\n", 6);
-    check_fail("FIXME(#\n", 7);
-    check_fail("FIXME(#1\n", 8);
-    check_fail("FIXME(#)1\n", 7);
-    check_pass("FIXME(#1222)\n");
-    check_fail("FIXME(#12\n22)\n", 9);
-    check_pass("FIXME(@maintainer, #1222, hello)\n");
 }
 
 #[test]
 fn find_issue() {
-    fn is_bad_issue(text: &str, report_fixme: ReportTactic) -> bool {
-        let mut seeker = BadIssueSeeker::new(report_fixme);
+    fn is_bad_issue(text: &str) -> bool {
+        let mut seeker = BadIssueSeeker::new();
         text.chars().any(|c| seeker.inspect(c).is_some())
     }
-
-    assert!(is_bad_issue("This is a FIXME(#1)\n", ReportTactic::Always));
-
-    assert!(is_bad_issue(
-        "This is a FixMe(#1) mixed case\n",
-        ReportTactic::Always,
-    ));
-
-    assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Never));
 }
 
 #[test]
 fn issue_type() {
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
+    let seeker = BadIssueSeeker::new();
     let expected = Some(Issue {
-        issue_type: IssueType::Fixme,
+        issue_type: None,
         missing_number: true,
     });
-
-    assert_eq!(
-        expected,
-        "Test. FIXME: bad, bad, not good"
-            .chars()
-            .map(|c| seeker.inspect(c))
-            .find(Option::is_some)
-            .unwrap()
-    );
 }
diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml
index 598edda6abe..c3cfd34317a 100644
--- a/tests/config/small_tabs.toml
+++ b/tests/config/small_tabs.toml
@@ -6,6 +6,5 @@ brace_style = "SameLineWhere"
 fn_args_layout = "Tall"
 trailing_comma = "Vertical"
 indent_style = "Block"
-report_fixme = "Never"
 reorder_imports = false
 format_strings = true

From 5e4296767fadf87cea31c22edaef1a924dfbad40 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 29 May 2022 21:54:00 -0500
Subject: [PATCH 193/195] refactor: remove code for bad issue (e.g. todo/fixme)
 reporting

---
 src/format_report_formatter.rs |   2 +-
 src/formatting.rs              |  14 ---
 src/issues.rs                  | 185 ---------------------------------
 src/lib.rs                     |   8 +-
 4 files changed, 2 insertions(+), 207 deletions(-)
 delete mode 100644 src/issues.rs

diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs
index 90406cdb95e..9809f72f5ae 100644
--- a/src/format_report_formatter.rs
+++ b/src/format_report_formatter.rs
@@ -146,6 +146,6 @@ fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationTy
         | ErrorKind::BadAttr
         | ErrorKind::InvalidGlobPattern(_)
         | ErrorKind::VersionMismatch => AnnotationType::Error,
-        ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => AnnotationType::Warning,
+        ErrorKind::DeprecatedAttr => AnnotationType::Warning,
     }
 }
diff --git a/src/formatting.rs b/src/formatting.rs
index 72bbe240f7b..869c6db647d 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -13,7 +13,6 @@ use self::newline_style::apply_newline_style;
 use crate::comment::{CharClasses, FullCodeCharKind};
 use crate::config::{Config, FileName, Verbosity};
 use crate::formatting::generated::is_generated_file;
-use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
 use crate::parse::parser::{DirectoryOwnership, Parser, ParserError};
 use crate::parse::session::ParseSess;
@@ -332,7 +331,6 @@ impl FormattingError {
             ErrorKind::LineOverflow(found, max) => (max, found - max),
             ErrorKind::TrailingWhitespace
             | ErrorKind::DeprecatedAttr
-            | ErrorKind::BadIssue(_)
             | ErrorKind::BadAttr
             | ErrorKind::LostComment
             | ErrorKind::LicenseCheck => {
@@ -483,11 +481,9 @@ struct FormatLines<'a> {
     cur_line: usize,
     newline_count: usize,
     errors: Vec<FormattingError>,
-    issue_seeker: BadIssueSeeker,
     line_buffer: String,
     current_line_contains_string_literal: bool,
     format_line: bool,
-    allow_issue_seek: bool,
     config: &'a Config,
 }
 
@@ -497,7 +493,6 @@ impl<'a> FormatLines<'a> {
         skipped_range: &'a [(usize, usize)],
         config: &'a Config,
     ) -> FormatLines<'a> {
-        let issue_seeker = BadIssueSeeker::new();
         FormatLines {
             name,
             skipped_range,
@@ -506,8 +501,6 @@ impl<'a> FormatLines<'a> {
             cur_line: 1,
             newline_count: 0,
             errors: vec![],
-            allow_issue_seek: !issue_seeker.is_disabled(),
-            issue_seeker,
             line_buffer: String::with_capacity(config.max_width() * 2),
             current_line_contains_string_literal: false,
             format_line: config.file_lines().contains_line(name, 1),
@@ -536,13 +529,6 @@ impl<'a> FormatLines<'a> {
                 continue;
             }
 
-            if self.allow_issue_seek && self.format_line {
-                // Add warnings for bad fixmes
-                if let Some(issue) = self.issue_seeker.inspect(c) {
-                    self.push_err(ErrorKind::BadIssue(issue), false, false);
-                }
-            }
-
             if c == '\n' {
                 self.new_line(kind);
             } else {
diff --git a/src/issues.rs b/src/issues.rs
deleted file mode 100644
index d95a80fe7fd..00000000000
--- a/src/issues.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-// Objects for seeking through a char stream for occurrences of TODO and FIXME.
-// Depending on the loaded configuration, may also check that these have an
-// associated issue number.
-
-use std::fmt;
-
-use crate::config::ReportTactic;
-
-// Enabled implementation detail is here because it is
-// irrelevant outside the issues module
-fn is_enabled(report_tactic: ReportTactic) -> bool {
-    report_tactic != ReportTactic::Never
-}
-
-#[derive(Clone, Copy)]
-enum Seeking {
-    Issue {},
-    Number { issue: Issue, part: NumberPart },
-}
-
-#[derive(Clone, Copy)]
-enum NumberPart {
-    OpenParen,
-    Pound,
-    Number,
-    CloseParen,
-}
-
-#[derive(PartialEq, Eq, Debug, Clone, Copy)]
-pub struct Issue {
-    issue_type: Option<IssueType>,
-    // Indicates whether we're looking for issues with missing numbers, or
-    // all issues of this type.
-    missing_number: bool,
-}
-
-impl fmt::Display for Issue {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        let msg = match self.issue_type {
-            _ => "",
-        };
-        let details = if self.missing_number {
-            " without issue number"
-        } else {
-            ""
-        };
-
-        write!(fmt, "{}{}", msg, details)
-    }
-}
-
-#[derive(PartialEq, Eq, Debug, Clone, Copy)]
-enum IssueType {}
-
-enum IssueClassification {
-    Good,
-    Bad(Issue),
-    None,
-}
-
-pub(crate) struct BadIssueSeeker {
-    state: Seeking,
-}
-
-impl BadIssueSeeker {
-    pub(crate) fn new() -> BadIssueSeeker {
-        BadIssueSeeker {
-            state: Seeking::Issue {},
-        }
-    }
-
-    pub(crate) fn is_disabled(&self) -> bool {
-        true
-    }
-
-    // Check whether or not the current char is conclusive evidence for an
-    // unnumbered TO-DO or FIX-ME.
-    pub(crate) fn inspect(&mut self, c: char) -> Option<Issue> {
-        match self.state {
-            Seeking::Issue {} => {
-                self.state = self.inspect_issue(c, 0);
-            }
-            Seeking::Number { issue, part } => {
-                let result = self.inspect_number(c, issue, part);
-
-                if let IssueClassification::None = result {
-                    return None;
-                }
-
-                self.state = Seeking::Issue {};
-
-                if let IssueClassification::Bad(issue) = result {
-                    return Some(issue);
-                }
-            }
-        }
-
-        None
-    }
-
-    fn inspect_issue(&mut self, c: char, mut fixme_idx: usize) -> Seeking {
-        if let Some(lower_case_c) = c.to_lowercase().next() {
-            fixme_idx = 0;
-        }
-
-        Seeking::Issue {}
-    }
-
-    fn inspect_number(
-        &mut self,
-        c: char,
-        issue: Issue,
-        mut part: NumberPart,
-    ) -> IssueClassification {
-        if !issue.missing_number || c == '\n' {
-            return IssueClassification::Bad(issue);
-        } else if c == ')' {
-            return if let NumberPart::CloseParen = part {
-                IssueClassification::Good
-            } else {
-                IssueClassification::Bad(issue)
-            };
-        }
-
-        match part {
-            NumberPart::OpenParen => {
-                if c != '(' {
-                    return IssueClassification::Bad(issue);
-                } else {
-                    part = NumberPart::Pound;
-                }
-            }
-            NumberPart::Pound => {
-                if c == '#' {
-                    part = NumberPart::Number;
-                }
-            }
-            NumberPart::Number => {
-                if ('0'..='9').contains(&c) {
-                    part = NumberPart::CloseParen;
-                } else {
-                    return IssueClassification::Bad(issue);
-                }
-            }
-            NumberPart::CloseParen => {}
-        }
-
-        self.state = Seeking::Number { part, issue };
-
-        IssueClassification::None
-    }
-}
-
-#[test]
-fn find_unnumbered_issue() {
-    fn check_fail(text: &str, failing_pos: usize) {
-        let mut seeker = BadIssueSeeker::new();
-        assert_eq!(
-            Some(failing_pos),
-            text.find(|c| seeker.inspect(c).is_some())
-        );
-    }
-
-    fn check_pass(text: &str) {
-        let mut seeker = BadIssueSeeker::new();
-        assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
-    }
-}
-
-#[test]
-fn find_issue() {
-    fn is_bad_issue(text: &str) -> bool {
-        let mut seeker = BadIssueSeeker::new();
-        text.chars().any(|c| seeker.inspect(c).is_some())
-    }
-}
-
-#[test]
-fn issue_type() {
-    let seeker = BadIssueSeeker::new();
-    let expected = Some(Issue {
-        issue_type: None,
-        missing_number: true,
-    });
-}
diff --git a/src/lib.rs b/src/lib.rs
index ad23b16e02e..f46a6914dd8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -39,7 +39,6 @@ use thiserror::Error;
 use crate::comment::LineClasses;
 use crate::emitter::Emitter;
 use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile};
-use crate::issues::Issue;
 use crate::modules::ModuleResolutionError;
 use crate::parse::parser::DirectoryOwnership;
 use crate::shape::Indent;
@@ -69,7 +68,6 @@ mod format_report_formatter;
 pub(crate) mod formatting;
 mod ignore_path;
 mod imports;
-mod issues;
 mod items;
 mod lists;
 mod macros;
@@ -110,9 +108,6 @@ pub enum ErrorKind {
     /// Line ends in whitespace.
     #[error("left behind trailing whitespace")]
     TrailingWhitespace,
-    /// TODO or FIXME item without an issue number.
-    #[error("found {0}")]
-    BadIssue(Issue),
     /// License check has failed.
     #[error("license check failed")]
     LicenseCheck,
@@ -236,8 +231,7 @@ impl FormatReport {
                 ErrorKind::LostComment => {
                     errs.has_unformatted_code_errors = true;
                 }
-                ErrorKind::BadIssue(_)
-                | ErrorKind::LicenseCheck
+                ErrorKind::LicenseCheck
                 | ErrorKind::DeprecatedAttr
                 | ErrorKind::BadAttr
                 | ErrorKind::VersionMismatch => {

From 79515f17ed4661da864347c90c76c51f9bf86069 Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sun, 29 May 2022 22:05:57 -0500
Subject: [PATCH 194/195] feat: remove license_template_path config option

---
 Configurations.md                             |  20 --
 src/config/config_type.rs                     |  22 --
 src/config/license.rs                         | 265 ------------------
 src/config/mod.rs                             |  32 ---
 src/format_report_formatter.rs                |   1 -
 src/formatting.rs                             |  20 +-
 src/lib.rs                                    |   8 +-
 tests/config/issue-3802.toml                  |   2 -
 tests/license-template/lt.txt                 |   2 -
 .../license-templates/empty_license_path.rs   |   5 -
 tests/source/license-templates/license.rs     |   6 -
 .../license-templates/empty_license_path.rs   |   5 -
 tests/target/license-templates/license.rs     |   6 -
 13 files changed, 3 insertions(+), 391 deletions(-)
 delete mode 100644 src/config/license.rs
 delete mode 100644 tests/config/issue-3802.toml
 delete mode 100644 tests/license-template/lt.txt
 delete mode 100644 tests/source/license-templates/empty_license_path.rs
 delete mode 100644 tests/source/license-templates/license.rs
 delete mode 100644 tests/target/license-templates/empty_license_path.rs
 delete mode 100644 tests/target/license-templates/license.rs

diff --git a/Configurations.md b/Configurations.md
index edb2d1f7575..8c84614352c 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -1473,26 +1473,6 @@ use core::slice;
 #[cfg(feature = "alloc")] use core::slice;
 ```
 
-## `license_template_path`
-
-Check whether beginnings of files match a license template.
-
-- **Default value**: `""`
-- **Possible values**: path to a license template file
-- **Stable**: No (tracking issue: [#3352](https://github.com/rust-lang/rustfmt/issues/3352))
-
-A license template is a plain text file which is matched literally against the
-beginning of each source file, except for `{}`-delimited blocks, which are
-matched as regular expressions. The following license template therefore
-matches strings like `// Copyright 2017 The Rust Project Developers.`, `//
-Copyright 2018 The Rust Project Developers.`, etc.:
-
-```
-// Copyright {\d+} The Rust Project Developers.
-```
-
-`\{`, `\}` and `\\` match literal braces / backslashes.
-
 ## `match_arm_blocks`
 
 Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator.
diff --git a/src/config/config_type.rs b/src/config/config_type.rs
index 7fc4486ddcd..e37ed798cb5 100644
--- a/src/config/config_type.rs
+++ b/src/config/config_type.rs
@@ -61,9 +61,6 @@ macro_rules! create_config {
         #[derive(Clone)]
         #[allow(unreachable_pub)]
         pub struct Config {
-            // if a license_template_path has been specified, successfully read, parsed and compiled
-            // into a regex, it will be stored here
-            pub license_template: Option<Regex>,
             // 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,
@@ -104,7 +101,6 @@ macro_rules! create_config {
                     | "struct_variant_width"
                     | "array_width"
                     | "chain_width" => self.0.set_heuristics(),
-                    "license_template_path" => self.0.set_license_template(),
                     "merge_imports" => self.0.set_merge_imports(),
                     &_ => (),
                 }
@@ -163,7 +159,6 @@ macro_rules! create_config {
                 }
             )+
                 self.set_heuristics();
-                self.set_license_template();
                 self.set_ignore(dir);
                 self.set_merge_imports();
                 self
@@ -247,7 +242,6 @@ macro_rules! create_config {
                     | "struct_variant_width"
                     | "array_width"
                     | "chain_width" => self.set_heuristics(),
-                    "license_template_path" => self.set_license_template(),
                     "merge_imports" => self.set_merge_imports(),
                     &_ => (),
                 }
@@ -386,21 +380,6 @@ macro_rules! create_config {
                 };
             }
 
-            fn set_license_template(&mut self) {
-                if self.was_set().license_template_path() {
-                    let lt_path = self.license_template_path();
-                    if lt_path.len() > 0 {
-                        match license::load_and_compile_template(&lt_path) {
-                            Ok(re) => self.license_template = Some(re),
-                            Err(msg) => eprintln!("Warning for license template file {:?}: {}",
-                                                lt_path, msg),
-                        }
-                    } else {
-                        self.license_template = None;
-                    }
-                }
-            }
-
             fn set_ignore(&mut self, dir: &Path) {
                 self.ignore.2.add_prefix(dir);
             }
@@ -437,7 +416,6 @@ macro_rules! create_config {
         impl Default for Config {
             fn default() -> Config {
                 Config {
-                    license_template: None,
                     $(
                         $i: (Cell::new(false), false, $def, $stb),
                     )+
diff --git a/src/config/license.rs b/src/config/license.rs
deleted file mode 100644
index c7feb502ea9..00000000000
--- a/src/config/license.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-use std::fmt;
-use std::fs::File;
-use std::io;
-use std::io::Read;
-
-use regex::Regex;
-
-#[derive(Debug)]
-pub(crate) enum LicenseError {
-    IO(io::Error),
-    Regex(regex::Error),
-    Parse(String),
-}
-
-impl fmt::Display for LicenseError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            LicenseError::IO(ref err) => err.fmt(f),
-            LicenseError::Regex(ref err) => err.fmt(f),
-            LicenseError::Parse(ref err) => write!(f, "parsing failed, {}", err),
-        }
-    }
-}
-
-impl From<io::Error> for LicenseError {
-    fn from(err: io::Error) -> LicenseError {
-        LicenseError::IO(err)
-    }
-}
-
-impl From<regex::Error> for LicenseError {
-    fn from(err: regex::Error) -> LicenseError {
-        LicenseError::Regex(err)
-    }
-}
-
-// the template is parsed using a state machine
-enum ParsingState {
-    Lit,
-    LitEsc,
-    // the u32 keeps track of brace nesting
-    Re(u32),
-    ReEsc(u32),
-    Abort(String),
-}
-
-use self::ParsingState::*;
-
-pub(crate) struct TemplateParser {
-    parsed: String,
-    buffer: String,
-    state: ParsingState,
-    linum: u32,
-    open_brace_line: u32,
-}
-
-impl TemplateParser {
-    fn new() -> Self {
-        Self {
-            parsed: "^".to_owned(),
-            buffer: String::new(),
-            state: Lit,
-            linum: 1,
-            // keeps track of last line on which a regex placeholder was started
-            open_brace_line: 0,
-        }
-    }
-
-    /// Converts a license template into a string which can be turned into a regex.
-    ///
-    /// The license template could use regex syntax directly, but that would require a lot of manual
-    /// escaping, which is inconvenient. It is therefore literal by default, with optional regex
-    /// subparts delimited by `{` and `}`. Additionally:
-    ///
-    /// - to insert literal `{`, `}` or `\`, escape it with `\`
-    /// - an empty regex placeholder (`{}`) is shorthand for `{.*?}`
-    ///
-    /// This function parses this input format and builds a properly escaped *string* representation
-    /// of the equivalent regular expression. It **does not** however guarantee that the returned
-    /// string is a syntactically valid regular expression.
-    ///
-    /// # Examples
-    ///
-    /// ```text
-    /// assert_eq!(
-    ///     TemplateParser::parse(
-    ///         r"
-    /// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)}
-    /// // file at the top-level directory of this distribution and at
-    /// // {}.
-    /// //
-    /// // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-    /// // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-    /// // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-    /// // option. This file may not be copied, modified, or distributed
-    /// // except according to those terms.
-    /// "
-    ///     ).unwrap(),
-    ///     r"^
-    /// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+)
-    /// // file at the top\-level directory of this distribution and at
-    /// // .*?\.
-    /// //
-    /// // Licensed under the Apache License, Version 2\.0 <LICENSE\-APACHE or
-    /// // http://www\.apache\.org/licenses/LICENSE\-2\.0> or the MIT license
-    /// // <LICENSE\-MIT or http://opensource\.org/licenses/MIT>, at your
-    /// // option\. This file may not be copied, modified, or distributed
-    /// // except according to those terms\.
-    /// "
-    /// );
-    /// ```
-    pub(crate) fn parse(template: &str) -> Result<String, LicenseError> {
-        let mut parser = Self::new();
-        for chr in template.chars() {
-            if chr == '\n' {
-                parser.linum += 1;
-            }
-            parser.state = match parser.state {
-                Lit => parser.trans_from_lit(chr),
-                LitEsc => parser.trans_from_litesc(chr),
-                Re(brace_nesting) => parser.trans_from_re(chr, brace_nesting),
-                ReEsc(brace_nesting) => parser.trans_from_reesc(chr, brace_nesting),
-                Abort(msg) => return Err(LicenseError::Parse(msg)),
-            };
-        }
-        // check if we've ended parsing in a valid state
-        match parser.state {
-            Abort(msg) => return Err(LicenseError::Parse(msg)),
-            Re(_) | ReEsc(_) => {
-                return Err(LicenseError::Parse(format!(
-                    "escape or balance opening brace on l. {}",
-                    parser.open_brace_line
-                )));
-            }
-            LitEsc => {
-                return Err(LicenseError::Parse(format!(
-                    "incomplete escape sequence on l. {}",
-                    parser.linum
-                )));
-            }
-            _ => (),
-        }
-        parser.parsed.push_str(&regex::escape(&parser.buffer));
-
-        Ok(parser.parsed)
-    }
-
-    fn trans_from_lit(&mut self, chr: char) -> ParsingState {
-        match chr {
-            '{' => {
-                self.parsed.push_str(&regex::escape(&self.buffer));
-                self.buffer.clear();
-                self.open_brace_line = self.linum;
-                Re(1)
-            }
-            '}' => Abort(format!(
-                "escape or balance closing brace on l. {}",
-                self.linum
-            )),
-            '\\' => LitEsc,
-            _ => {
-                self.buffer.push(chr);
-                Lit
-            }
-        }
-    }
-
-    fn trans_from_litesc(&mut self, chr: char) -> ParsingState {
-        self.buffer.push(chr);
-        Lit
-    }
-
-    fn trans_from_re(&mut self, chr: char, brace_nesting: u32) -> ParsingState {
-        match chr {
-            '{' => {
-                self.buffer.push(chr);
-                Re(brace_nesting + 1)
-            }
-            '}' => {
-                match brace_nesting {
-                    1 => {
-                        // default regex for empty placeholder {}
-                        if self.buffer.is_empty() {
-                            self.parsed.push_str(".*?");
-                        } else {
-                            self.parsed.push_str(&self.buffer);
-                        }
-                        self.buffer.clear();
-                        Lit
-                    }
-                    _ => {
-                        self.buffer.push(chr);
-                        Re(brace_nesting - 1)
-                    }
-                }
-            }
-            '\\' => {
-                self.buffer.push(chr);
-                ReEsc(brace_nesting)
-            }
-            _ => {
-                self.buffer.push(chr);
-                Re(brace_nesting)
-            }
-        }
-    }
-
-    fn trans_from_reesc(&mut self, chr: char, brace_nesting: u32) -> ParsingState {
-        self.buffer.push(chr);
-        Re(brace_nesting)
-    }
-}
-
-pub(crate) fn load_and_compile_template(path: &str) -> Result<Regex, LicenseError> {
-    let mut lt_file = File::open(&path)?;
-    let mut lt_str = String::new();
-    lt_file.read_to_string(&mut lt_str)?;
-    let lt_parsed = TemplateParser::parse(&lt_str)?;
-    Ok(Regex::new(&lt_parsed)?)
-}
-
-#[cfg(test)]
-mod test {
-    use super::TemplateParser;
-
-    #[test]
-    fn test_parse_license_template() {
-        assert_eq!(
-            TemplateParser::parse("literal (.*)").unwrap(),
-            r"^literal \(\.\*\)"
-        );
-        assert_eq!(
-            TemplateParser::parse(r"escaping \}").unwrap(),
-            r"^escaping \}"
-        );
-        assert!(TemplateParser::parse("unbalanced } without escape").is_err());
-        assert_eq!(
-            TemplateParser::parse(r"{\d+} place{-?}holder{s?}").unwrap(),
-            r"^\d+ place-?holders?"
-        );
-        assert_eq!(TemplateParser::parse("default {}").unwrap(), "^default .*?");
-        assert_eq!(
-            TemplateParser::parse(r"unbalanced nested braces {\{{3}}").unwrap(),
-            r"^unbalanced nested braces \{{3}"
-        );
-        assert_eq!(
-            &TemplateParser::parse("parsing error }")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, escape or balance closing brace on l. 1"
-        );
-        assert_eq!(
-            &TemplateParser::parse("parsing error {\nsecond line")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, escape or balance opening brace on l. 1"
-        );
-        assert_eq!(
-            &TemplateParser::parse(r"parsing error \")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, incomplete escape sequence on l. 1"
-        );
-    }
-}
diff --git a/src/config/mod.rs b/src/config/mod.rs
index fc724beae60..a5169528187 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -5,7 +5,6 @@ use std::io::{Error, ErrorKind, Read};
 use std::path::{Path, PathBuf};
 use std::{env, fs};
 
-use regex::Regex;
 use thiserror::Error;
 
 use crate::config::config_type::ConfigType;
@@ -22,7 +21,6 @@ pub(crate) mod config_type;
 pub(crate) mod options;
 
 pub(crate) mod file_lines;
-pub(crate) mod license;
 pub(crate) mod lists;
 
 // This macro defines configuration options used in rustfmt. Each option
@@ -63,8 +61,6 @@ create_config! {
         "Maximum length of comments. No effect unless wrap_comments = true";
     normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible";
     normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments";
-    license_template_path: String, String::default(), false,
-        "Beginning of file must match license template";
     format_strings: bool, false, false, "Format string literals where necessary";
     format_macro_matchers: bool, false, false,
         "Format the metavariable matching patterns in macros";
@@ -414,8 +410,6 @@ mod test {
         create_config! {
             // Options that are used by the generated functions
             max_width: usize, 100, true, "Maximum width of each line";
-            license_template_path: String, String::default(), false,
-                "Beginning of file must match license template";
             required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
                 "Require a specific version of rustfmt.";
             ignore: IgnoreList, IgnoreList::default(), false,
@@ -520,31 +514,6 @@ mod test {
         assert_eq!(s.contains("(unstable)"), true);
     }
 
-    #[test]
-    fn test_empty_string_license_template_path() {
-        let toml = r#"license_template_path = """#;
-        let config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_none());
-    }
-
-    #[nightly_only_test]
-    #[test]
-    fn test_valid_license_template_path() {
-        let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
-        let config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_some());
-    }
-
-    #[nightly_only_test]
-    #[test]
-    fn test_override_existing_license_with_no_license() {
-        let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
-        let mut config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_some());
-        config.override_value("license_template_path", "");
-        assert!(config.license_template.is_none());
-    }
-
     #[test]
     fn test_dump_default_config() {
         let default_config = format!(
@@ -566,7 +535,6 @@ format_code_in_doc_comments = false
 comment_width = 80
 normalize_comments = false
 normalize_doc_attributes = false
-license_template_path = ""
 format_strings = false
 format_macro_matchers = false
 format_macro_bodies = true
diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs
index 9809f72f5ae..fd536d4df41 100644
--- a/src/format_report_formatter.rs
+++ b/src/format_report_formatter.rs
@@ -142,7 +142,6 @@ fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationTy
         | ErrorKind::ModuleResolutionError(_)
         | ErrorKind::ParseError
         | ErrorKind::LostComment
-        | ErrorKind::LicenseCheck
         | ErrorKind::BadAttr
         | ErrorKind::InvalidGlobPattern(_)
         | ErrorKind::VersionMismatch => AnnotationType::Error,
diff --git a/src/formatting.rs b/src/formatting.rs
index 869c6db647d..e6995210a94 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -332,8 +332,7 @@ impl FormattingError {
             ErrorKind::TrailingWhitespace
             | ErrorKind::DeprecatedAttr
             | ErrorKind::BadAttr
-            | ErrorKind::LostComment
-            | ErrorKind::LicenseCheck => {
+            | ErrorKind::LostComment => {
                 let trailing_ws_start = self
                     .line_buffer
                     .rfind(|c: char| !c.is_whitespace())
@@ -365,7 +364,7 @@ pub(crate) struct ReportedErrors {
     // Code contains macro call that was unable to format.
     pub(crate) has_macro_format_failure: bool,
 
-    // Failed a check, such as the license check or other opt-in checking.
+    // Failed an opt-in checking.
     pub(crate) has_check_errors: bool,
 
     /// Formatted code differs from existing code (--check only).
@@ -461,7 +460,6 @@ fn format_lines(
     report: &FormatReport,
 ) {
     let mut formatter = FormatLines::new(name, skipped_range, config);
-    formatter.check_license(text);
     formatter.iterate(text);
 
     if formatter.newline_count > 1 {
@@ -508,20 +506,6 @@ impl<'a> FormatLines<'a> {
         }
     }
 
-    fn check_license(&mut self, text: &mut String) {
-        if let Some(ref license_template) = self.config.license_template {
-            if !license_template.is_match(text) {
-                self.errors.push(FormattingError {
-                    line: self.cur_line,
-                    kind: ErrorKind::LicenseCheck,
-                    is_comment: false,
-                    is_string: false,
-                    line_buffer: String::new(),
-                });
-            }
-        }
-    }
-
     // Iterate over the chars in the file map.
     fn iterate(&mut self, text: &mut String) {
         for (kind, c) in CharClasses::new(text.chars()) {
diff --git a/src/lib.rs b/src/lib.rs
index f46a6914dd8..495010a297d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -108,9 +108,6 @@ pub enum ErrorKind {
     /// Line ends in whitespace.
     #[error("left behind trailing whitespace")]
     TrailingWhitespace,
-    /// License check has failed.
-    #[error("license check failed")]
-    LicenseCheck,
     /// Used deprecated skip attribute.
     #[error("`rustfmt_skip` is deprecated; use `rustfmt::skip`")]
     DeprecatedAttr,
@@ -231,10 +228,7 @@ impl FormatReport {
                 ErrorKind::LostComment => {
                     errs.has_unformatted_code_errors = true;
                 }
-                ErrorKind::LicenseCheck
-                | ErrorKind::DeprecatedAttr
-                | ErrorKind::BadAttr
-                | ErrorKind::VersionMismatch => {
+                ErrorKind::DeprecatedAttr | ErrorKind::BadAttr | ErrorKind::VersionMismatch => {
                     errs.has_check_errors = true;
                 }
                 _ => {}
diff --git a/tests/config/issue-3802.toml b/tests/config/issue-3802.toml
deleted file mode 100644
index 74ee8b010dd..00000000000
--- a/tests/config/issue-3802.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-unstable_features = true
-license_template_path = ""
diff --git a/tests/license-template/lt.txt b/tests/license-template/lt.txt
deleted file mode 100644
index ea4390371a0..00000000000
--- a/tests/license-template/lt.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright {\d+} The rustfmt developers.
diff --git a/tests/source/license-templates/empty_license_path.rs b/tests/source/license-templates/empty_license_path.rs
deleted file mode 100644
index d3a91e4231d..00000000000
--- a/tests/source/license-templates/empty_license_path.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// rustfmt-config: issue-3802.toml
-
-fn main() {
-println!("Hello world!");
-}
diff --git a/tests/source/license-templates/license.rs b/tests/source/license-templates/license.rs
deleted file mode 100644
index 6816011c60d..00000000000
--- a/tests/source/license-templates/license.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright 2019 The rustfmt developers.
-
-fn main() {
-println!("Hello world!");
-}
diff --git a/tests/target/license-templates/empty_license_path.rs b/tests/target/license-templates/empty_license_path.rs
deleted file mode 100644
index 950f103ed39..00000000000
--- a/tests/target/license-templates/empty_license_path.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// rustfmt-config: issue-3802.toml
-
-fn main() {
-    println!("Hello world!");
-}
diff --git a/tests/target/license-templates/license.rs b/tests/target/license-templates/license.rs
deleted file mode 100644
index 7169c7b2576..00000000000
--- a/tests/target/license-templates/license.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright 2019 The rustfmt developers.
-
-fn main() {
-    println!("Hello world!");
-}

From 64f1f57a4837694cb2449d6bc1f614e60c6ff42c Mon Sep 17 00:00:00 2001
From: Caleb Cartwright <caleb.cartwright@outlook.com>
Date: Sat, 4 Jun 2022 10:08:33 -0500
Subject: [PATCH 195/195] fix: handle inner ignore attribute on stdin

---
 src/formatting.rs | 28 +++++++++++++++++++++-------
 src/test/mod.rs   | 24 ++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/src/formatting.rs b/src/formatting.rs
index e6995210a94..23d90d9e2e0 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -40,12 +40,10 @@ impl<'b, T: Write + 'b> Session<'b, T> {
         rustc_span::create_session_if_not_set_then(self.config.edition().into(), |_| {
             if self.config.disable_all_formatting() {
                 // When the input is from stdin, echo back the input.
-                if let Input::Text(ref buf) = input {
-                    if let Err(e) = io::stdout().write_all(buf.as_bytes()) {
-                        return Err(From::from(e));
-                    }
-                }
-                return Ok(FormatReport::new());
+                return match input {
+                    Input::Text(ref buf) => echo_back_stdin(buf),
+                    _ => Ok(FormatReport::new()),
+                };
             }
 
             let config = &self.config.clone();
@@ -94,6 +92,13 @@ fn should_skip_module<T: FormatHandler>(
     false
 }
 
+fn echo_back_stdin(input: &str) -> Result<FormatReport, ErrorKind> {
+    if let Err(e) = io::stdout().write_all(input.as_bytes()) {
+        return Err(From::from(e));
+    }
+    Ok(FormatReport::new())
+}
+
 // Format an entire crate (or subset of the module tree).
 fn format_project<T: FormatHandler>(
     input: Input,
@@ -136,7 +141,8 @@ fn format_project<T: FormatHandler>(
     .visit_crate(&krate)?
     .into_iter()
     .filter(|(path, module)| {
-        !should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
+        input_is_stdin
+            || !should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
     })
     .collect::<Vec<_>>();
 
@@ -146,6 +152,14 @@ fn format_project<T: FormatHandler>(
     context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
+        if input_is_stdin && contains_skip(module.attrs()) {
+            return echo_back_stdin(
+                context
+                    .parse_session
+                    .snippet_provider(module.span)
+                    .entire_snippet(),
+            );
+        }
         should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
         context.format_file(path, &module, is_macro_def)?;
     }
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 0eda9e4b116..18ec8620fac 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -578,6 +578,30 @@ fn stdin_generated_files_issue_5172() {
     );
 }
 
+#[test]
+fn stdin_handles_mod_inner_ignore_attr() {
+    // see https://github.com/rust-lang/rustfmt/issues/5368
+    init_log();
+    let input = String::from("#![rustfmt::skip]\n\nfn    main() {  }");
+    let mut child = Command::new(rustfmt().to_str().unwrap())
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()
+        .expect("failed to execute child");
+
+    {
+        let stdin = child.stdin.as_mut().expect("failed to get stdin");
+        stdin
+            .write_all(input.as_bytes())
+            .expect("failed to write stdin");
+    }
+
+    let output = child.wait_with_output().expect("failed to wait on child");
+    assert!(output.status.success());
+    assert!(output.stderr.is_empty());
+    assert_eq!(input, String::from_utf8(output.stdout).unwrap());
+}
+
 #[test]
 fn format_lines_errors_are_reported() {
     init_log();