about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Cartwright <caleb.cartwright@outlook.com>2021-12-29 20:49:39 -0600
committerCaleb Cartwright <caleb.cartwright@outlook.com>2021-12-29 20:49:39 -0600
commit521fdcbe4ddaa717be2acbeb30f8978d6378fea1 (patch)
tree5e021204c2d4503b6990f53c919f54a2f3969734
parentd331cb710f0dd969d779510a49a3bafc7f78a54e (diff)
parent4a053f206fd6799a25823c307f7d7f9d897be118 (diff)
downloadrust-521fdcbe4ddaa717be2acbeb30f8978d6378fea1.tar.gz
rust-521fdcbe4ddaa717be2acbeb30f8978d6378fea1.zip
Merge commit '4a053f206fd6799a25823c307f7d7f9d897be118' into sync-rustfmt-subtree
-rw-r--r--src/tools/rustfmt/rust-toolchain2
-rw-r--r--src/tools/rustfmt/src/bin/main.rs2
-rw-r--r--src/tools/rustfmt/src/closures.rs14
-rw-r--r--src/tools/rustfmt/src/config/file_lines.rs8
-rw-r--r--src/tools/rustfmt/src/config/options.rs14
-rw-r--r--src/tools/rustfmt/src/expr.rs23
-rw-r--r--src/tools/rustfmt/src/formatting.rs56
-rw-r--r--src/tools/rustfmt/src/items.rs10
-rw-r--r--src/tools/rustfmt/src/lib.rs5
-rw-r--r--src/tools/rustfmt/src/lists.rs4
-rw-r--r--src/tools/rustfmt/src/macros.rs258
-rw-r--r--src/tools/rustfmt/src/matches.rs6
-rw-r--r--src/tools/rustfmt/src/modules.rs4
-rw-r--r--src/tools/rustfmt/src/modules/visitor.rs6
-rw-r--r--src/tools/rustfmt/src/parse/macros/asm.rs11
-rw-r--r--src/tools/rustfmt/src/parse/macros/cfg_if.rs89
-rw-r--r--src/tools/rustfmt/src/parse/macros/lazy_static.rs50
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs231
-rw-r--r--src/tools/rustfmt/src/parse/mod.rs3
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs (renamed from src/tools/rustfmt/src/syntux/parser.rs)91
-rw-r--r--src/tools/rustfmt/src/parse/session.rs (renamed from src/tools/rustfmt/src/syntux/session.rs)2
-rw-r--r--src/tools/rustfmt/src/patterns.rs7
-rw-r--r--src/tools/rustfmt/src/rewrite.rs2
-rw-r--r--src/tools/rustfmt/src/rustfmt_diff.rs10
-rw-r--r--src/tools/rustfmt/src/source_file.rs2
-rw-r--r--src/tools/rustfmt/src/test/configuration_snippet.rs21
-rw-r--r--src/tools/rustfmt/src/test/mod_resolver.rs9
-rw-r--r--src/tools/rustfmt/src/visitor.rs27
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo.rs5
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs1
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs9
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/one.rs1
-rw-r--r--src/tools/rustfmt/tests/source/async_block.rs16
-rw-r--r--src/tools/rustfmt/tests/source/match.rs19
-rw-r--r--src/tools/rustfmt/tests/target/async_block.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs10
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_always.rs5
-rw-r--r--src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs5
-rw-r--r--src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs16
-rw-r--r--src/tools/rustfmt/tests/target/match.rs19
-rw-r--r--src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs7
44 files changed, 710 insertions, 410 deletions
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 1d2cad66751..d4cdcec2018 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-11-08"
+channel = "nightly-2021-12-29"
 components = ["rustc-dev"]
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 9d2e97c9479..4d845547cdf 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 34d73a77fd3..e688db1c39d 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -236,21 +236,21 @@ fn rewrite_closure_fn_decl(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<(String, usize)> {
-    let is_async = if asyncness.is_async() { "async " } else { "" };
-    let mover = if capture == ast::CaptureBy::Value {
-        "move "
+    let immovable = if movability == ast::Movability::Static {
+        "static "
     } else {
         ""
     };
-    let immovable = if movability == ast::Movability::Static {
-        "static "
+    let is_async = if asyncness.is_async() { "async " } else { "" };
+    let mover = if capture == ast::CaptureBy::Value {
+        "move "
     } 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/src/tools/rustfmt/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs
index 4b799780d85..7b498dc46b3 100644
--- a/src/tools/rustfmt/src/config/file_lines.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs
index bce9e5d07f2..d857c29be29 100644
--- a/src/tools/rustfmt/src/config/options.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 5fd86c1a4ea..c9c8852cd3b 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/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)),
@@ -2003,9 +2016,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/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index 7d0facb8f12..67cf1232f66 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/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;
@@ -13,9 +14,9 @@ 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::utils::count_newlines;
+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};
 
@@ -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/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index b7dd6b06ff8..babc56f86ed 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 792a1080f0e..ad23b16e02e 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/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;
@@ -40,8 +41,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 +78,7 @@ mod missed_spans;
 pub(crate) mod modules;
 mod overflow;
 mod pairs;
+mod parse;
 mod patterns;
 mod release_channel;
 mod reorder;
@@ -89,7 +91,6 @@ pub(crate) mod source_map;
 mod spanned;
 mod stmt;
 mod string;
-mod syntux;
 #[cfg(test)]
 mod test;
 mod types;
diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs
index 3515dd17251..7aa0315f18c 100644
--- a/src/tools/rustfmt/src/lists.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index a52568be9ea..f29552caf8d 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/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,8 @@ 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::{parse_expr, parse_macro_args, ParsedMacroArgs};
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::source_map::SpanUtils;
@@ -60,7 +60,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 +90,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 +177,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 +195,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 +221,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,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.trees());
 
         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,
@@ -1414,10 +1294,9 @@ 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 nested_shape = shape
         .block_indent(context.config.tab_spaces())
         .with_max_width(context.config);
@@ -1425,42 +1304,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 {}: {} =",
@@ -1476,7 +1324,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));
         }
     }
@@ -1528,65 +1376,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/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 22d23fc1cdb..85d9c5d2b9b 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 9d438a80d94..9c964b274e0 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/modules/visitor.rs b/src/tools/rustfmt/src/modules/visitor.rs
index d5acf3f1cbc..ea67977c17a 100644
--- a/src/tools/rustfmt/src/modules/visitor.rs
+++ b/src/tools/rustfmt/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::macros::cfg_if::parse_cfg_if;
+use crate::parse::session::ParseSess;
 
 pub(crate) struct ModItem {
     pub(crate) item: ast::Item,
@@ -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/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs
new file mode 100644
index 00000000000..cc9fb5072ce
--- /dev/null
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs
new file mode 100644
index 00000000000..e10fbe64bcd
--- /dev/null
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
new file mode 100644
index 00000000000..9c8651aa3fa
--- /dev/null
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
new file mode 100644
index 00000000000..2e9ce1d35f4
--- /dev/null
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -0,0 +1,231 @@
+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};
+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;
+
+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> {
+    build_stream_parser(context.parse_sess.inner(), tokens)
+}
+
+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,
+    })
+}
+
+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,
+    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/tools/rustfmt/src/parse/mod.rs b/src/tools/rustfmt/src/parse/mod.rs
new file mode 100644
index 00000000000..5e88826ea8c
--- /dev/null
+++ b/src/tools/rustfmt/src/parse/mod.rs
@@ -0,0 +1,3 @@
+pub(crate) mod macros;
+pub(crate) mod parser;
+pub(crate) mod session;
diff --git a/src/tools/rustfmt/src/syntux/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 23d065c9cc9..657217633f4 100644
--- a/src/tools/rustfmt/src/syntux/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -1,17 +1,14 @@
 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::syntux::session::ParseSess;
+use crate::parse::session::ParseSess;
 use crate::Input;
 
 pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
@@ -175,84 +172,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)
-    }
 }
diff --git a/src/tools/rustfmt/src/syntux/session.rs b/src/tools/rustfmt/src/parse/session.rs
index dd7c7352686..624fed0d2de 100644
--- a/src/tools/rustfmt/src/syntux/session.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index a80d63201f9..9b74b35f314 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs
index c8abe70141b..4a3bd129d16 100644
--- a/src/tools/rustfmt/src/rewrite.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/rustfmt_diff.rs b/src/tools/rustfmt/src/rustfmt_diff.rs
index a394ce07398..1724a0f87bf 100644
--- a/src/tools/rustfmt/src/rustfmt_diff.rs
+++ b/src/tools/rustfmt/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 {
diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs
index 853336004d8..56d4ab40038 100644
--- a/src/tools/rustfmt/src/source_file.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs
index ef7dd0ddcd1..92949ab576a 100644
--- a/src/tools/rustfmt/src/test/configuration_snippet.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/test/mod_resolver.rs b/src/tools/rustfmt/src/test/mod_resolver.rs
index ae4a0d0fccb..ec9ed0f0b8d 100644
--- a/src/tools/rustfmt/src/test/mod_resolver.rs
+++ b/src/tools/rustfmt/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/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index e4a7be742ab..0177689958a 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/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,
@@ -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 {
@@ -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/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo.rs
new file mode 100644
index 00000000000..74889acf0c3
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs
new file mode 100644
index 00000000000..3519b0ee59c
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs
new file mode 100644
index 00000000000..3122e4f220f
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/one.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/one.rs
new file mode 100644
index 00000000000..e7eb2c2d64d
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/async_block.rs b/src/tools/rustfmt/tests/source/async_block.rs
index 3de51a084d2..18cb4fb5f5c 100644
--- a/src/tools/rustfmt/tests/source/async_block.rs
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/match.rs b/src/tools/rustfmt/tests/source/match.rs
index da20517203a..b5dc9957a2c 100644
--- a/src/tools/rustfmt/tests/source/match.rs
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/async_block.rs b/src/tools/rustfmt/tests/target/async_block.rs
index 258dd937a6f..137d849c9ee 100644
--- a/src/tools/rustfmt/tests/target/async_block.rs
+++ b/src/tools/rustfmt/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(())
+    });
 }
diff --git a/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs b/src/tools/rustfmt/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/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs b/src/tools/rustfmt/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/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs
new file mode 100644
index 00000000000..3368f070386
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs
new file mode 100644
index 00000000000..cf63c4c983c
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_always.rs
new file mode 100644
index 00000000000..e20bcec9316
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs
new file mode 100644
index 00000000000..8b95bb137bc
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs
@@ -0,0 +1,5 @@
+// rustfmt-trailing_comma: Never
+
+fn main() {
+    let Foo { a, .. } = b;
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs
new file mode 100644
index 00000000000..2ed3d936e32
--- /dev/null
+++ b/src/tools/rustfmt/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 {};
+}
diff --git a/src/tools/rustfmt/tests/target/match.rs b/src/tools/rustfmt/tests/target/match.rs
index e2c522bea10..1bf3fb758ee 100644
--- a/src/tools/rustfmt/tests/target/match.rs
+++ b/src/tools/rustfmt/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 {}
+        }
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs b/src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs
new file mode 100644
index 00000000000..f85de33257c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs
@@ -0,0 +1,7 @@
+#![rustfmt::skip]
+
+fn main() {
+    println!("Hello, world!");
+}
+
+// Trailing Comment