about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Cartwright <calebcartwright@users.noreply.github.com>2024-06-17 15:47:07 -0500
committerGitHub <noreply@github.com>2024-06-17 15:47:07 -0500
commit3ffd7d46a998b0e8d0a0a15213df2f264c5bc3be (patch)
tree2c2e4e3b34f64ec4c33d52be00d665339d73b443
parent55a70266e27a85ecc0876d786480e6ec464d038f (diff)
parent306ddabe0a4e08d6692aaa35736939c4613dd095 (diff)
downloadrust-3ffd7d46a998b0e8d0a0a15213df2f264c5bc3be.tar.gz
rust-3ffd7d46a998b0e8d0a0a15213df2f264c5bc3be.zip
Merge pull request #6193 from ytmimi/subtree-push-nightly-2024-06-13
subtree-push nightly-2024-06-13
-rw-r--r--.github/workflows/integration.yml1
-rw-r--r--CHANGELOG.md11
-rw-r--r--Cargo.lock33
-rw-r--r--Cargo.toml2
-rwxr-xr-xci/integration.sh2
-rw-r--r--config_proc_macro/src/attrs.rs6
-rw-r--r--rust-toolchain2
-rw-r--r--src/attr.rs18
-rw-r--r--src/comment.rs4
-rw-r--r--src/config/style_edition.rs1
-rw-r--r--src/expr.rs21
-rw-r--r--src/formatting.rs54
-rw-r--r--src/imports.rs4
-rw-r--r--src/items.rs64
-rw-r--r--src/macros.rs6
-rw-r--r--src/matches.rs33
-rw-r--r--src/missed_spans.rs6
-rw-r--r--src/modules.rs30
-rw-r--r--src/modules/visitor.rs8
-rw-r--r--src/parse/macros/asm.rs2
-rw-r--r--src/parse/macros/cfg_if.rs10
-rw-r--r--src/parse/macros/lazy_static.rs6
-rw-r--r--src/parse/macros/mod.rs52
-rw-r--r--src/parse/parser.rs79
-rw-r--r--src/parse/session.rs147
-rw-r--r--src/patterns.rs114
-rw-r--r--src/reorder.rs4
-rw-r--r--src/rewrite.rs2
-rw-r--r--src/source_file.rs5
-rw-r--r--src/spanned.rs2
-rw-r--r--src/stmt.rs2
-rw-r--r--src/test/mod.rs18
-rw-r--r--src/test/parser.rs14
-rw-r--r--src/types.rs53
-rw-r--r--src/utils.rs12
-rw-r--r--src/visitor.rs53
-rw-r--r--tests/parser/stashed-diag.rs3
-rw-r--r--tests/parser/stashed-diag2.rs3
-rw-r--r--tests/rustfmt/main.rs3
-rw-r--r--tests/source/immovable_coroutines.rs3
-rw-r--r--tests/source/macros/rewrite-const-item.rs1
-rw-r--r--tests/source/mut_ref.rs10
-rw-r--r--tests/source/postfix-match/pf-match.rs20
-rw-r--r--tests/target/anonymous-types.rs12
-rw-r--r--tests/target/asyncness.rs3
-rw-r--r--tests/target/immovable_coroutines.rs3
-rw-r--r--tests/target/issue_6082.rs5
-rw-r--r--tests/target/issue_6159.rs3
-rw-r--r--tests/target/macros/rewrite-const-item.rs3
-rw-r--r--tests/target/mut_ref.rs10
-rw-r--r--tests/target/postfix-match/pf-match.rs20
-rw-r--r--tests/target/unsafe_attributes.rs34
52 files changed, 598 insertions, 419 deletions
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 314ce0e84c6..f0dd0cf73bb 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -19,7 +19,6 @@ jobs:
       matrix:
         integration: [
           bitflags,
-          error-chain,
           log,
           mdbook,
           packed_simd,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5897b1fb378..fdb671ad4c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,17 @@
 ## [Unreleased]
 
 - Updating `dirs 4.0.0 -> 5.0.1` and `cargo_metadata 0.15.4 -> 0.18.0` [#6033] (https://github.com/rust-lang/rustfmt/issues/6033)
+- Bumped bytecount `0.6.4` -> `0.6.8` to fix compilation issues with the `generic-simd` feature. See [bytecount#92] and [bytecount#93]
+
+[bytecount#92]: https://github.com/llogiq/bytecount/pull/92
+[bytecount#93]: https://github.com/llogiq/bytecount/pull/93
+
+- Output correct syntax for type ascription builtin [#6159](https://github.com/rust-lang/rustfmt/issues/6159)
+  ```rust
+  fn main() {
+      builtin # type_ascribe(10, usize)
+  }
+  ```
 
 ## [1.7.0] 2023-10-22
 
diff --git a/Cargo.lock b/Cargo.lock
index b5032945e7e..3d0233f4cf3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -98,12 +98,9 @@ dependencies = [
 
 [[package]]
 name = "bytecount"
-version = "0.6.4"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7"
-dependencies = [
- "packed_simd",
-]
+checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
 
 [[package]]
 name = "camino"
@@ -370,12 +367,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
 
 [[package]]
-name = "libm"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
-
-[[package]]
 name = "log"
 version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -410,16 +401,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "num-traits"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
-dependencies = [
- "autocfg",
- "libm",
-]
-
-[[package]]
 name = "once_cell"
 version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -438,16 +419,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
 
 [[package]]
-name = "packed_simd"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"
-dependencies = [
- "cfg-if",
- "num-traits",
-]
-
-[[package]]
 name = "pin-project-lite"
 version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index c98200c23d4..5cd9193166c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,7 +35,7 @@ generic-simd = ["bytecount/generic-simd"]
 [dependencies]
 annotate-snippets = { version = "0.9", features = ["color"] }
 anyhow = "1.0"
-bytecount = "0.6.4"
+bytecount = "0.6.8"
 cargo_metadata = "0.18"
 clap = { version = "4.4.2", features = ["derive"] }
 clap-cargo = "0.12.0"
diff --git a/ci/integration.sh b/ci/integration.sh
index 19d502bc5c7..ea96e4be130 100755
--- a/ci/integration.sh
+++ b/ci/integration.sh
@@ -104,7 +104,7 @@ case ${INTEGRATION} in
         check_fmt_with_all_tests
         cd -
         ;;
-    error-chain | tempdir)
+    tempdir)
         git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git
         cd ${INTEGRATION}
         show_head
diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs
index d8de9aae088..e7534b813d7 100644
--- a/config_proc_macro/src/attrs.rs
+++ b/config_proc_macro/src/attrs.rs
@@ -68,7 +68,11 @@ fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> {
     match &attr.meta {
         syn::Meta::NameValue(syn::MetaNameValue {
             path,
-            value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }),
+            value:
+                syn::Expr::Lit(syn::ExprLit {
+                    lit: syn::Lit::Str(lit_str),
+                    ..
+                }),
             ..
         }) if path.is_ident(name) => Some(lit_str.value()),
         _ => None,
diff --git a/rust-toolchain b/rust-toolchain
index aa35a7f12d5..25e3961d32a 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-12-28"
+channel = "nightly-2024-06-13"
 components = ["llvm-tools", "rustc-dev"]
diff --git a/src/attr.rs b/src/attr.rs
index 4d83547d664..433b9256202 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -26,7 +26,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
 
 pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span {
     match stmt.kind {
-        ast::StmtKind::Local(ref local) => local.span,
+        ast::StmtKind::Let(ref local) => local.span,
         ast::StmtKind::Item(ref item) => item.span,
         ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span,
         ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(),
@@ -353,10 +353,18 @@ impl Rewrite for ast::Attribute {
 
                 // 1 = `[`
                 let shape = shape.offset_left(prefix.len() + 1)?;
-                Some(
-                    meta.rewrite(context, shape)
-                        .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)),
-                )
+                Some(meta.rewrite(context, shape).map_or_else(
+                    || snippet.to_owned(),
+                    |rw| match &self.kind {
+                        ast::AttrKind::Normal(normal_attr) => match normal_attr.item.unsafety {
+                            // For #![feature(unsafe_attributes)]
+                            // See https://github.com/rust-lang/rust/issues/123757
+                            ast::Safety::Unsafe(_) => format!("{}[unsafe({})]", prefix, rw),
+                            _ => format!("{}[{}]", prefix, rw),
+                        },
+                        _ => format!("{}[{}]", prefix, rw),
+                    },
+                ))
             } else {
                 Some(snippet.to_owned())
             }
diff --git a/src/comment.rs b/src/comment.rs
index 864cba3809e..24a5a1be2c3 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -1714,10 +1714,10 @@ pub(crate) fn recover_comment_removed(
         // We missed some comments. Warn and keep the original text.
         if context.config.error_on_unformatted() {
             context.report.append(
-                context.parse_sess.span_to_filename(span),
+                context.psess.span_to_filename(span),
                 vec![FormattingError::from_span(
                     span,
-                    context.parse_sess,
+                    context.psess,
                     ErrorKind::LostComment,
                 )],
             );
diff --git a/src/config/style_edition.rs b/src/config/style_edition.rs
index 4dd5f0164fa..7b3ea3bc119 100644
--- a/src/config/style_edition.rs
+++ b/src/config/style_edition.rs
@@ -1,6 +1,7 @@
 use crate::config::StyleEdition;
 
 /// Defines the default value for the given style edition
+#[allow(dead_code)]
 pub(crate) trait StyleEditionDefault {
     type ConfigType;
     fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType;
diff --git a/src/expr.rs b/src/expr.rs
index 8e92ef03770..8266f95fd70 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -3,7 +3,7 @@ use std::cmp::min;
 
 use itertools::Itertools;
 use rustc_ast::token::{Delimiter, Lit, LitKind};
-use rustc_ast::{ast, ptr, token, ForLoopKind};
+use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind};
 use rustc_span::{BytePos, Span};
 
 use crate::chains::rewrite_chain;
@@ -180,8 +180,8 @@ pub(crate) fn format_expr(
                 }
             }
         }
-        ast::ExprKind::Match(ref cond, ref arms) => {
-            rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs)
+        ast::ExprKind::Match(ref cond, ref arms, kind) => {
+            rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind)
         }
         ast::ExprKind::Path(ref qself, ref path) => {
             rewrite_path(context, PathContext::Expr, qself, path, shape)
@@ -263,14 +263,6 @@ pub(crate) fn format_expr(
             shape,
             SeparatorPlace::Front,
         ),
-        ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair(
-            &**expr,
-            &**ty,
-            PairParts::infix(": "),
-            context,
-            shape,
-            SeparatorPlace::Back,
-        ),
         ast::ExprKind::Index(ref expr, ref index, _) => {
             rewrite_index(&**expr, &**index, context, shape)
         }
@@ -412,6 +404,7 @@ pub(crate) fn format_expr(
         }
         ast::ExprKind::Underscore => Some("_".to_owned()),
         ast::ExprKind::FormatArgs(..)
+        | ast::ExprKind::Type(..)
         | ast::ExprKind::IncludedBytes(..)
         | ast::ExprKind::OffsetOf(..) => {
             // These don't normally occur in the AST because macros aren't expanded. However,
@@ -420,7 +413,7 @@ pub(crate) fn format_expr(
             // Also, rustfmt might get passed the output from `-Zunpretty=expanded`.
             None
         }
-        ast::ExprKind::Err => None,
+        ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None,
     };
 
     expr_rw
@@ -641,7 +634,7 @@ pub(crate) fn rewrite_cond(
     shape: Shape,
 ) -> Option<String> {
     match expr.kind {
-        ast::ExprKind::Match(ref cond, _) => {
+        ast::ExprKind::Match(ref cond, _, MatchKind::Prefix) => {
             // `match `cond` {`
             let cond_shape = match context.config.indent_style() {
                 IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?,
@@ -1963,7 +1956,7 @@ fn rewrite_unary_op(
 }
 
 pub(crate) enum RhsAssignKind<'ast> {
-    Expr(&'ast ast::ExprKind, Span),
+    Expr(&'ast ast::ExprKind, #[allow(dead_code)] Span),
     Bounds,
     Ty,
 }
diff --git a/src/formatting.rs b/src/formatting.rs
index 60361505a3f..7f442230b12 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -79,7 +79,7 @@ fn should_skip_module<T: FormatHandler>(
     // FIXME(calebcartwright) - we need to determine how we'll handle the
     // `format_generated_files` option with stdin based input.
     if !input_is_stdin && !config.format_generated_files() {
-        let source_file = context.parse_session.span_to_file_contents(module.span);
+        let source_file = context.psess.span_to_file_contents(module.span);
         let src = source_file.src.as_ref().expect("SourceFile without src");
 
         if is_generated_file(src, config) {
@@ -109,15 +109,16 @@ fn format_project<T: FormatHandler>(
     let main_file = input.file_name();
     let input_is_stdin = main_file == FileName::Stdin;
 
-    let parse_session = ParseSess::new(config)?;
-    if config.skip_children() && parse_session.ignore_file(&main_file) {
+    let psess = ParseSess::new(config)?;
+    if config.skip_children() && psess.ignore_file(&main_file) {
         return Ok(FormatReport::new());
     }
 
     // Parse the crate.
     let mut report = FormatReport::new();
     let directory_ownership = input.to_directory_ownership();
-    let krate = match Parser::parse_crate(input, &parse_session) {
+
+    let krate = match Parser::parse_crate(input, &psess) {
         Ok(krate) => krate,
         // Surface parse error via Session (errors are merged there from report)
         Err(e) => {
@@ -130,9 +131,9 @@ fn format_project<T: FormatHandler>(
         }
     };
 
-    let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
+    let mut context = FormatContext::new(&krate, report, psess, config, handler);
     let files = modules::ModResolver::new(
-        &context.parse_session,
+        &context.psess,
         directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
         !input_is_stdin && !config.skip_children(),
     )
@@ -147,16 +148,11 @@ fn format_project<T: FormatHandler>(
     timer = timer.done_parsing();
 
     // Suppress error output if we have to do any further parsing.
-    context.parse_session.set_silent_emitter();
+    context.psess.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(),
-            );
+            return echo_back_stdin(context.psess.snippet_provider(module.span).entire_snippet());
         }
         should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
         context.format_file(path, &module, is_macro_def)?;
@@ -178,7 +174,7 @@ fn format_project<T: FormatHandler>(
 struct FormatContext<'a, T: FormatHandler> {
     krate: &'a ast::Crate,
     report: FormatReport,
-    parse_session: ParseSess,
+    psess: ParseSess,
     config: &'a Config,
     handler: &'a mut T,
 }
@@ -187,21 +183,21 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
     fn new(
         krate: &'a ast::Crate,
         report: FormatReport,
-        parse_session: ParseSess,
+        psess: ParseSess,
         config: &'a Config,
         handler: &'a mut T,
     ) -> Self {
         FormatContext {
             krate,
             report,
-            parse_session,
+            psess,
             config,
             handler,
         }
     }
 
     fn ignore_file(&self, path: &FileName) -> bool {
-        self.parse_session.ignore_file(path)
+        self.psess.ignore_file(path)
     }
 
     // Formats a single file/module.
@@ -211,9 +207,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
         module: &Module<'_>,
         is_macro_def: bool,
     ) -> Result<(), ErrorKind> {
-        let snippet_provider = self.parse_session.snippet_provider(module.span);
-        let mut visitor = FmtVisitor::from_parse_sess(
-            &self.parse_session,
+        let snippet_provider = self.psess.snippet_provider(module.span);
+        let mut visitor = FmtVisitor::from_psess(
+            &self.psess,
             self.config,
             &snippet_provider,
             self.report.clone(),
@@ -256,7 +252,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
             .add_non_formatted_ranges(visitor.skipped_range.borrow().clone());
 
         self.handler.handle_formatted_file(
-            &self.parse_session,
+            &self.psess,
             path,
             visitor.buffer.to_owned(),
             &mut self.report,
@@ -268,7 +264,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
 trait FormatHandler {
     fn handle_formatted_file(
         &mut self,
-        parse_session: &ParseSess,
+        psess: &ParseSess,
         path: FileName,
         result: String,
         report: &mut FormatReport,
@@ -279,14 +275,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> {
     // Called for each formatted file.
     fn handle_formatted_file(
         &mut self,
-        parse_session: &ParseSess,
+        psess: &ParseSess,
         path: FileName,
         result: String,
         report: &mut FormatReport,
     ) -> Result<(), ErrorKind> {
         if let Some(ref mut out) = self.out {
             match source_file::write_file(
-                Some(parse_session),
+                Some(psess),
                 &path,
                 &result,
                 out,
@@ -317,17 +313,13 @@ pub(crate) struct FormattingError {
 }
 
 impl FormattingError {
-    pub(crate) fn from_span(
-        span: Span,
-        parse_sess: &ParseSess,
-        kind: ErrorKind,
-    ) -> FormattingError {
+    pub(crate) fn from_span(span: Span, psess: &ParseSess, kind: ErrorKind) -> FormattingError {
         FormattingError {
-            line: parse_sess.line_of_byte_pos(span.lo()),
+            line: psess.line_of_byte_pos(span.lo()),
             is_comment: kind.is_comment(),
             kind,
             is_string: false,
-            line_buffer: parse_sess.span_to_first_line_string(span),
+            line_buffer: psess.span_to_first_line_string(span),
         }
     }
 
diff --git a/src/imports.rs b/src/imports.rs
index 05195553c08..12c178e136f 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -458,7 +458,9 @@ impl UseTree {
                     version,
                 });
             }
-            UseTreeKind::Nested(ref list) => {
+            UseTreeKind::Nested {
+                items: ref list, ..
+            } => {
                 // Extract comments between nested use items.
                 // This needs to be done before sorting use items.
                 let items = itemize_list(
diff --git a/src/items.rs b/src/items.rs
index e7ff5ff818b..46ad2ac20ce 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -247,7 +247,7 @@ fn allow_single_line_let_else_block(result: &str, block: &ast::Block) -> bool {
 #[allow(dead_code)]
 #[derive(Debug)]
 struct Item<'a> {
-    unsafety: ast::Unsafe,
+    safety: ast::Safety,
     abi: Cow<'static, str>,
     vis: Option<&'a ast::Visibility>,
     body: Vec<BodyElement<'a>>,
@@ -257,7 +257,7 @@ struct Item<'a> {
 impl<'a> Item<'a> {
     fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> {
         Item {
-            unsafety: fm.unsafety,
+            safety: fm.safety,
             abi: format_extern(
                 ast::Extern::from_abi(fm.abi, DUMMY_SP),
                 config.force_explicit_abi(),
@@ -290,7 +290,7 @@ pub(crate) struct FnSig<'a> {
     coroutine_kind: Cow<'a, Option<ast::CoroutineKind>>,
     constness: ast::Const,
     defaultness: ast::Defaultness,
-    unsafety: ast::Unsafe,
+    safety: ast::Safety,
     visibility: &'a ast::Visibility,
 }
 
@@ -301,7 +301,7 @@ impl<'a> FnSig<'a> {
         visibility: &'a ast::Visibility,
     ) -> FnSig<'a> {
         FnSig {
-            unsafety: method_sig.header.unsafety,
+            safety: method_sig.header.safety,
             coroutine_kind: Cow::Borrowed(&method_sig.header.coroutine_kind),
             constness: method_sig.header.constness,
             defaultness: ast::Defaultness::Final,
@@ -330,7 +330,7 @@ impl<'a> FnSig<'a> {
                 constness: fn_sig.header.constness,
                 coroutine_kind: Cow::Borrowed(&fn_sig.header.coroutine_kind),
                 defaultness,
-                unsafety: fn_sig.header.unsafety,
+                safety: fn_sig.header.safety,
                 visibility: vis,
             },
             _ => unreachable!(),
@@ -345,7 +345,7 @@ impl<'a> FnSig<'a> {
         result.push_str(format_constness(self.constness));
         self.coroutine_kind
             .map(|coroutine_kind| result.push_str(format_coro(&coroutine_kind)));
-        result.push_str(format_unsafety(self.unsafety));
+        result.push_str(format_safety(self.safety));
         result.push_str(&format_extern(
             self.ext,
             context.config.force_explicit_abi(),
@@ -356,7 +356,7 @@ impl<'a> FnSig<'a> {
 
 impl<'a> FmtVisitor<'a> {
     fn format_item(&mut self, item: &Item<'_>) {
-        self.buffer.push_str(format_unsafety(item.unsafety));
+        self.buffer.push_str(format_safety(item.safety));
         self.buffer.push_str(&item.abi);
 
         let snippet = self.snippet(item.span);
@@ -735,7 +735,9 @@ impl<'a> FmtVisitor<'a> {
                 (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => {
                     a.ident.as_str().cmp(b.ident.as_str())
                 }
-                (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
+                (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => {
+                    a.span.lo().cmp(&b.span.lo())
+                }
                 (Type(ty), _) if is_type(&ty.ty) => Ordering::Less,
                 (_, Type(ty)) if is_type(&ty.ty) => Ordering::Greater,
                 (Type(..), _) => Ordering::Less,
@@ -744,6 +746,8 @@ impl<'a> FmtVisitor<'a> {
                 (_, Const(..)) => Ordering::Greater,
                 (MacCall(..), _) => Ordering::Less,
                 (_, MacCall(..)) => Ordering::Greater,
+                (Delegation(..), _) | (DelegationMac(..), _) => Ordering::Less,
+                (_, Delegation(..)) | (_, DelegationMac(..)) => Ordering::Greater,
             });
             let mut prev_kind = None;
             for (buf, item) in buffer {
@@ -929,7 +933,7 @@ fn format_impl_ref_and_type(
     offset: Indent,
 ) -> Option<String> {
     let ast::Impl {
-        unsafety,
+        safety,
         polarity,
         defaultness,
         constness,
@@ -942,7 +946,7 @@ fn format_impl_ref_and_type(
 
     result.push_str(&format_visibility(context, &item.vis));
     result.push_str(format_defaultness(defaultness));
-    result.push_str(format_unsafety(unsafety));
+    result.push_str(format_safety(safety));
 
     let shape = if context.config.version() == Version::Two {
         Shape::indented(offset + last_line_width(&result), context.config)
@@ -1142,7 +1146,7 @@ pub(crate) fn format_trait(
     };
     let ast::Trait {
         is_auto,
-        unsafety,
+        safety,
         ref generics,
         ref bounds,
         ref items,
@@ -1152,7 +1156,7 @@ pub(crate) fn format_trait(
     let header = format!(
         "{}{}{}trait ",
         format_visibility(context, &item.vis),
-        format_unsafety(unsafety),
+        format_safety(safety),
         format_auto(is_auto),
     );
     result.push_str(&header);
@@ -1656,8 +1660,7 @@ struct TyAliasRewriteInfo<'c, 'g>(
     &'c RewriteContext<'c>,
     Indent,
     &'g ast::Generics,
-    (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
-    usize,
+    ast::TyAliasWhereClauses,
     symbol::Ident,
     Span,
 );
@@ -1677,7 +1680,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         ref bounds,
         ref ty,
         where_clauses,
-        where_predicates_split,
     } = *ty_alias_kind;
     let ty_opt = ty.as_ref();
     let (ident, vis) = match visitor_kind {
@@ -1685,15 +1687,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
         ForeignItem(i) => (i.ident, &i.vis),
     };
-    let rw_info = &TyAliasRewriteInfo(
-        context,
-        indent,
-        generics,
-        where_clauses,
-        where_predicates_split,
-        ident,
-        span,
-    );
+    let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, 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.
@@ -1729,19 +1723,11 @@ fn rewrite_ty<R: Rewrite>(
     vis: &ast::Visibility,
 ) -> Option<String> {
     let mut result = String::with_capacity(128);
-    let TyAliasRewriteInfo(
-        context,
-        indent,
-        generics,
-        where_clauses,
-        where_predicates_split,
-        ident,
-        span,
-    ) = *rw_info;
+    let TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span) = *rw_info;
     let (before_where_predicates, after_where_predicates) = generics
         .where_clause
         .predicates
-        .split_at(where_predicates_split);
+        .split_at(where_clauses.split);
     if !after_where_predicates.is_empty() {
         return None;
     }
@@ -1776,7 +1762,7 @@ fn rewrite_ty<R: Rewrite>(
     let where_clause_str = rewrite_where_clause(
         context,
         before_where_predicates,
-        where_clauses.0.1,
+        where_clauses.before.span,
         context.config.brace_style(),
         Shape::legacy(where_budget, indent),
         false,
@@ -1800,7 +1786,7 @@ fn rewrite_ty<R: Rewrite>(
         let comment_span = context
             .snippet_provider
             .opt_span_before(span, "=")
-            .map(|op_lo| mk_sp(where_clauses.0.1.hi(), op_lo));
+            .map(|op_lo| mk_sp(where_clauses.before.span.hi(), op_lo));
 
         let lhs = match comment_span {
             Some(comment_span)
@@ -3348,11 +3334,11 @@ impl Rewrite for ast::ForeignItem {
                     .map(|(s, _, _)| format!("{};", s))
                 }
             }
-            ast::ForeignItemKind::Static(ref ty, mutability, _) => {
+            ast::ForeignItemKind::Static(ref static_foreign_item) => {
                 // FIXME(#21): we're dropping potential comments in between the
                 // function kw here.
                 let vis = format_visibility(context, &self.vis);
-                let mut_str = format_mutability(mutability);
+                let mut_str = format_mutability(static_foreign_item.mutability);
                 let prefix = format!(
                     "{}static {}{}:",
                     vis,
@@ -3363,7 +3349,7 @@ impl Rewrite for ast::ForeignItem {
                 rewrite_assign_rhs(
                     context,
                     prefix,
-                    &**ty,
+                    &static_foreign_item.ty,
                     &RhsAssignKind::Ty,
                     shape.sub_width(1)?,
                 )
diff --git a/src/macros.rs b/src/macros.rs
index 6e114c76f26..a0582b061c0 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -137,8 +137,8 @@ fn return_macro_parse_failure_fallback(
     }
 
     context.skipped_range.borrow_mut().push((
-        context.parse_sess.line_of_byte_pos(span.lo()),
-        context.parse_sess.line_of_byte_pos(span.hi()),
+        context.psess.line_of_byte_pos(span.lo()),
+        context.psess.line_of_byte_pos(span.hi()),
     ));
 
     // Return the snippet unmodified if the macro is not block-like
@@ -1092,7 +1092,7 @@ fn next_space(tok: &TokenKind) -> SpaceState {
         | TokenKind::DotDotEq
         | TokenKind::Question => SpaceState::Punctuation,
 
-        TokenKind::ModSep
+        TokenKind::PathSep
         | TokenKind::Pound
         | TokenKind::Dollar
         | TokenKind::OpenDelim(_)
diff --git a/src/matches.rs b/src/matches.rs
index 50429cfd911..e4fa077073c 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -2,7 +2,7 @@
 
 use std::iter::repeat;
 
-use rustc_ast::{ast, ptr};
+use rustc_ast::{ast, ptr, MatchKind};
 use rustc_span::{BytePos, Span};
 
 use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented};
@@ -72,6 +72,7 @@ pub(crate) fn rewrite_match(
     shape: Shape,
     span: Span,
     attrs: &[ast::Attribute],
+    match_kind: MatchKind,
 ) -> Option<String> {
     // Do not take the rhs overhead from the upper expressions into account
     // when rewriting match condition.
@@ -135,15 +136,27 @@ pub(crate) fn rewrite_match(
         }
     } else {
         let span_after_cond = mk_sp(cond.span.hi(), span.hi());
-        Some(format!(
-            "match {}{}{{\n{}{}{}\n{}}}",
-            cond_str,
-            block_sep,
-            inner_attrs_str,
-            nested_indent_str,
-            rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
-            shape.indent.to_string(context.config),
-        ))
+
+        match match_kind {
+            MatchKind::Prefix => Some(format!(
+                "match {}{}{{\n{}{}{}\n{}}}",
+                cond_str,
+                block_sep,
+                inner_attrs_str,
+                nested_indent_str,
+                rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
+                shape.indent.to_string(context.config),
+            )),
+            MatchKind::Postfix => Some(format!(
+                "{}.match{}{{\n{}{}{}\n{}}}",
+                cond_str,
+                block_sep,
+                inner_attrs_str,
+                nested_indent_str,
+                rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
+                shape.indent.to_string(context.config),
+            )),
+        }
     }
 }
 
diff --git a/src/missed_spans.rs b/src/missed_spans.rs
index 28edcb784b4..b1a7769c21b 100644
--- a/src/missed_spans.rs
+++ b/src/missed_spans.rs
@@ -91,7 +91,7 @@ impl<'a> FmtVisitor<'a> {
         assert!(
             start < end,
             "Request to format inverted span: {}",
-            self.parse_sess.span_to_debug_info(mk_sp(start, end)),
+            self.psess.span_to_debug_info(mk_sp(start, end)),
         );
 
         self.last_pos = end;
@@ -166,8 +166,8 @@ impl<'a> FmtVisitor<'a> {
         // Trim whitespace from the right hand side of each line.
         // Annoyingly, the library functions for splitting by lines etc. are not
         // quite right, so we must do it ourselves.
-        let line = self.parse_sess.line_of_byte_pos(span.lo());
-        let file_name = &self.parse_sess.span_to_filename(span);
+        let line = self.psess.line_of_byte_pos(span.lo());
+        let file_name = &self.psess.span_to_filename(span);
         let mut status = SnippetStatus::new(line);
 
         let snippet = &*transform_missing_snippet(self.config, old_snippet);
diff --git a/src/modules.rs b/src/modules.rs
index af9a154a6ae..0590f28ee05 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -57,8 +57,8 @@ impl<'a> Module<'a> {
 }
 
 /// Maps each module to the corresponding file.
-pub(crate) struct ModResolver<'ast, 'sess> {
-    parse_sess: &'sess ParseSess,
+pub(crate) struct ModResolver<'ast, 'psess> {
+    psess: &'psess ParseSess,
     directory: Directory,
     file_map: FileModMap<'ast>,
     recursive: bool,
@@ -99,10 +99,10 @@ enum SubModKind<'a, 'ast> {
     Internal(&'a ast::Item),
 }
 
-impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
+impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
     /// Creates a new `ModResolver`.
     pub(crate) fn new(
-        parse_sess: &'sess ParseSess,
+        psess: &'psess ParseSess,
         directory_ownership: DirectoryOwnership,
         recursive: bool,
     ) -> Self {
@@ -112,7 +112,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 ownership: directory_ownership,
             },
             file_map: BTreeMap::new(),
-            parse_sess,
+            psess,
             recursive,
         }
     }
@@ -122,7 +122,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         mut self,
         krate: &'ast ast::Crate,
     ) -> Result<FileModMap<'ast>, ModuleResolutionError> {
-        let root_filename = self.parse_sess.span_to_filename(krate.spans.inner_span);
+        let root_filename = self.psess.span_to_filename(krate.spans.inner_span);
         self.directory.path = match root_filename {
             FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(),
             _ => PathBuf::new(),
@@ -133,7 +133,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             self.visit_mod_from_ast(&krate.items)?;
         }
 
-        let snippet_provider = self.parse_sess.snippet_provider(krate.spans.inner_span);
+        let snippet_provider = self.psess.snippet_provider(krate.spans.inner_span);
 
         self.file_map.insert(
             root_filename,
@@ -149,7 +149,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
 
     /// Visit `cfg_if` macro and look for module declarations.
     fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResolutionError> {
-        let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess);
+        let mut visitor = visitor::CfgIfVisitor::new(self.psess);
         visitor.visit_item(&item);
         for module_item in visitor.mods() {
             if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
@@ -338,10 +338,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             DirectoryOwnership::UnownedViaBlock => None,
         };
         if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) {
-            if self.parse_sess.is_file_parsed(&path) {
+            if self.psess.is_file_parsed(&path) {
                 return Ok(None);
             }
-            return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) {
+            return match Parser::parse_file_as_module(self.psess, &path, sub_mod.span) {
                 Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
                 Ok((attrs, items, span)) => Ok(Some(SubModKind::External(
                     path,
@@ -368,7 +368,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod);
 
         match self
-            .parse_sess
+            .psess
             .default_submod_path(mod_name, relative, &self.directory.path)
         {
             Ok(ModulePathSuccess {
@@ -380,7 +380,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 let should_insert = !mods_outside_ast
                     .iter()
                     .any(|(outside_path, _, _)| outside_path == &file_path);
-                if self.parse_sess.is_file_parsed(&file_path) {
+                if self.psess.is_file_parsed(&file_path) {
                     if outside_mods_empty {
                         return Ok(None);
                     } else {
@@ -390,7 +390,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                         return Ok(Some(SubModKind::MultiExternal(mods_outside_ast)));
                     }
                 }
-                match Parser::parse_file_as_module(self.parse_sess, &file_path, sub_mod.span) {
+                match Parser::parse_file_as_module(self.psess, &file_path, sub_mod.span) {
                     Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
                     Ok((attrs, items, span)) if outside_mods_empty => {
                         Ok(Some(SubModKind::External(
@@ -517,7 +517,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             if !actual_path.exists() {
                 continue;
             }
-            if self.parse_sess.is_file_parsed(&actual_path) {
+            if self.psess.is_file_parsed(&actual_path) {
                 // If the specified file is already parsed, then we just use that.
                 result.push((
                     actual_path,
@@ -527,7 +527,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 continue;
             }
             let (attrs, items, span) =
-                match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) {
+                match Parser::parse_file_as_module(self.psess, &actual_path, sub_mod.span) {
                     Ok((ref attrs, _, _)) if contains_skip(attrs) => continue,
                     Ok(m) => m,
                     Err(..) => continue,
diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs
index 48431693332..3e05b6d0c5d 100644
--- a/src/modules/visitor.rs
+++ b/src/modules/visitor.rs
@@ -12,15 +12,15 @@ pub(crate) struct ModItem {
 
 /// Traverse `cfg_if!` macro and fetch modules.
 pub(crate) struct CfgIfVisitor<'a> {
-    parse_sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mods: Vec<ModItem>,
 }
 
 impl<'a> CfgIfVisitor<'a> {
-    pub(crate) fn new(parse_sess: &'a ParseSess) -> CfgIfVisitor<'a> {
+    pub(crate) fn new(psess: &'a ParseSess) -> CfgIfVisitor<'a> {
         CfgIfVisitor {
             mods: vec![],
-            parse_sess,
+            psess,
         }
     }
 
@@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
             }
         };
 
-        let items = parse_cfg_if(self.parse_sess, mac)?;
+        let items = parse_cfg_if(self.psess, mac)?;
         self.mods
             .append(&mut items.into_iter().map(|item| ModItem { item }).collect());
 
diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs
index 01edfab3654..6373d0251f8 100644
--- a/src/parse/macros/asm.rs
+++ b/src/parse/macros/asm.rs
@@ -7,5 +7,5 @@ use crate::rewrite::RewriteContext;
 pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
     let ts = mac.args.tokens.clone();
     let mut parser = super::build_parser(context, ts);
-    parse_asm_args(&mut parser, context.parse_sess.inner(), mac.span(), false).ok()
+    parse_asm_args(&mut parser, mac.span(), false).ok()
 }
diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs
index bafef7b0f46..5fc988e4319 100644
--- a/src/parse/macros/cfg_if.rs
+++ b/src/parse/macros/cfg_if.rs
@@ -9,10 +9,10 @@ use crate::parse::macros::build_stream_parser;
 use crate::parse::session::ParseSess;
 
 pub(crate) fn parse_cfg_if<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mac: &'a ast::MacCall,
 ) -> Result<Vec<ast::Item>, &'static str> {
-    match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) {
+    match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(psess, mac))) {
         Ok(Ok(items)) => Ok(items),
         Ok(err @ Err(_)) => err,
         Err(..) => Err("failed to parse cfg_if!"),
@@ -20,11 +20,11 @@ pub(crate) fn parse_cfg_if<'a>(
 }
 
 fn parse_cfg_if_inner<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mac: &'a ast::MacCall,
 ) -> Result<Vec<ast::Item>, &'static str> {
     let ts = mac.args.tokens.clone();
-    let mut parser = build_stream_parser(sess.inner(), ts);
+    let mut parser = build_stream_parser(psess.inner(), ts);
 
     let mut items = vec![];
     let mut process_if_cfg = true;
@@ -67,7 +67,7 @@ fn parse_cfg_if_inner<'a>(
                 Ok(None) => continue,
                 Err(err) => {
                     err.cancel();
-                    parser.sess.dcx.reset_err_count();
+                    parser.psess.dcx.reset_err_count();
                     return Err(
                         "Expected item inside cfg_if block, but failed to parse it as an item",
                     );
diff --git a/src/parse/macros/lazy_static.rs b/src/parse/macros/lazy_static.rs
index 8b1dc6694d6..badd9569950 100644
--- a/src/parse/macros/lazy_static.rs
+++ b/src/parse/macros/lazy_static.rs
@@ -16,8 +16,8 @@ pub(crate) fn parse_lazy_static(
         ($method:ident $(,)* $($arg:expr),* $(,)*) => {
             match parser.$method($($arg,)*) {
                 Ok(val) => {
-                    if parser.sess.dcx.has_errors().is_some() {
-                        parser.sess.dcx.reset_err_count();
+                    if parser.psess.dcx.has_errors().is_some() {
+                        parser.psess.dcx.reset_err_count();
                         return None;
                     } else {
                         val
@@ -25,7 +25,7 @@ pub(crate) fn parse_lazy_static(
                 }
                 Err(err) => {
                     err.cancel();
-                    parser.sess.dcx.reset_err_count();
+                    parser.psess.dcx.reset_err_count();
                     return None;
                 }
             }
diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs
index 2dd2622174f..cbcc0b2d636 100644
--- a/src/parse/macros/mod.rs
+++ b/src/parse/macros/mod.rs
@@ -1,8 +1,8 @@
-use rustc_ast::token::{Delimiter, TokenKind};
+use rustc_ast::token::{Delimiter, NonterminalKind, 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_parse::parser::{ForceCollect, Parser, Recovery};
+use rustc_parse::MACRO_ARGUMENTS;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{self, kw};
 use rustc_span::Symbol;
@@ -14,31 +14,33 @@ 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_stream_parser<'a>(psess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
+    Parser::new(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
 }
 
 fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
-    build_stream_parser(context.parse_sess.inner(), tokens)
+    build_stream_parser(context.psess.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) => {
+        ($macro_arg:ident, $nt_kind:expr, $try_parse:expr, $then:expr) => {
             let mut cloned_parser = (*parser).clone();
-            match $parser(&mut cloned_parser) {
-                Ok(x) => {
-                    if parser.sess.dcx.has_errors().is_some() {
-                        parser.sess.dcx.reset_err_count();
-                    } else {
-                        // Parsing succeeded.
-                        *parser = cloned_parser;
-                        return Some(MacroArg::$macro_arg($f(x)?));
+            if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) {
+                match $try_parse(&mut cloned_parser) {
+                    Ok(x) => {
+                        if parser.psess.dcx.has_errors().is_some() {
+                            parser.psess.dcx.reset_err_count();
+                        } else {
+                            // Parsing succeeded.
+                            *parser = cloned_parser;
+                            return Some(MacroArg::$macro_arg($then(x)?));
+                        }
+                    }
+                    Err(e) => {
+                        e.cancel();
+                        parser.psess.dcx.reset_err_count();
                     }
-                }
-                Err(e) => {
-                    e.cancel();
-                    parser.sess.dcx.reset_err_count();
                 }
             }
         };
@@ -46,23 +48,27 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
 
     parse_macro_arg!(
         Expr,
-        |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
+        NonterminalKind::Expr,
+        |parser: &mut 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(),
+        NonterminalKind::Ty,
+        |parser: &mut 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, None),
+        NonterminalKind::PatParam { inferred: false },
+        |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, 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),
+        NonterminalKind::Item,
+        |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No),
         |x: Option<ptr::P<ast::Item>>| x
     );
 
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 6bc53159b38..6051241309d 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -3,8 +3,9 @@ use std::path::{Path, PathBuf};
 
 use rustc_ast::token::TokenKind;
 use rustc_ast::{ast, attr, ptr};
-use rustc_errors::Diagnostic;
-use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
+use rustc_errors::Diag;
+use rustc_parse::parser::Parser as RawParser;
+use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_span::{sym, Span};
 use thin_vec::ThinVec;
 
@@ -29,7 +30,7 @@ pub(crate) struct Parser<'a> {
 /// A builder for the `Parser`.
 #[derive(Default)]
 pub(crate) struct ParserBuilder<'a> {
-    sess: Option<&'a ParseSess>,
+    psess: Option<&'a ParseSess>,
     input: Option<Input>,
 }
 
@@ -39,23 +40,20 @@ impl<'a> ParserBuilder<'a> {
         self
     }
 
-    pub(crate) fn sess(mut self, sess: &'a ParseSess) -> ParserBuilder<'a> {
-        self.sess = Some(sess);
+    pub(crate) fn psess(mut self, psess: &'a ParseSess) -> ParserBuilder<'a> {
+        self.psess = Some(psess);
         self
     }
 
     pub(crate) fn build(self) -> Result<Parser<'a>, ParserError> {
-        let sess = self.sess.ok_or(ParserError::NoParseSess)?;
+        let psess = self.psess.ok_or(ParserError::NoParseSess)?;
         let input = self.input.ok_or(ParserError::NoInput)?;
 
-        let parser = match Self::parser(sess.inner(), input) {
+        let parser = match Self::parser(psess.inner(), input) {
             Ok(p) => p,
-            Err(db) => {
-                if let Some(diagnostics) = db {
-                    sess.emit_diagnostics(diagnostics);
-                    return Err(ParserError::ParserCreationError);
-                }
-                return Err(ParserError::ParsePanicError);
+            Err(diagnostics) => {
+                psess.emit_diagnostics(diagnostics);
+                return Err(ParserError::ParserCreationError);
             }
         };
 
@@ -63,20 +61,16 @@ impl<'a> ParserBuilder<'a> {
     }
 
     fn parser(
-        sess: &'a rustc_session::parse::ParseSess,
+        psess: &'a rustc_session::parse::ParseSess,
         input: Input,
-    ) -> Result<rustc_parse::parser::Parser<'a>, Option<Vec<Diagnostic>>> {
+    ) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
         match input {
-            Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || {
-                new_parser_from_file(sess, file, None)
-            }))
-            .map_err(|_| None),
-            Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str(
-                sess,
+            Input::File(ref file) => new_parser_from_file(psess, file, None),
+            Input::Text(text) => new_parser_from_source_str(
+                psess,
                 rustc_span::FileName::Custom("stdin".to_owned()),
                 text,
-            )
-            .map_err(Some),
+            ),
         }
     }
 }
@@ -106,27 +100,28 @@ impl<'a> Parser<'a> {
     }
 
     pub(crate) fn parse_file_as_module(
-        sess: &'a ParseSess,
+        psess: &'a ParseSess,
         path: &Path,
         span: Span,
     ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
+            let mut parser =
+                unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span)));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
-                Err(mut e) => {
+                Err(e) => {
                     e.emit();
-                    if sess.can_reset_errors() {
-                        sess.reset_errors();
+                    if psess.can_reset_errors() {
+                        psess.reset_errors();
                     }
                     None
                 }
             }
         }));
         match result {
-            Ok(Some(m)) if !sess.has_errors() => Ok(m),
-            Ok(Some(m)) if sess.can_reset_errors() => {
-                sess.reset_errors();
+            Ok(Some(m)) if !psess.has_errors() => Ok(m),
+            Ok(Some(m)) if psess.can_reset_errors() => {
+                psess.reset_errors();
                 Ok(m)
             }
             Ok(_) => Err(ParserError::ParseError),
@@ -137,39 +132,39 @@ impl<'a> Parser<'a> {
 
     pub(crate) fn parse_crate(
         input: Input,
-        sess: &'a ParseSess,
+        psess: &'a ParseSess,
     ) -> Result<ast::Crate, ParserError> {
-        let krate = Parser::parse_crate_inner(input, sess)?;
-        if !sess.has_errors() {
+        let krate = Parser::parse_crate_inner(input, psess)?;
+        if !psess.has_errors() {
             return Ok(krate);
         }
 
-        if sess.can_reset_errors() {
-            sess.reset_errors();
+        if psess.can_reset_errors() {
+            psess.reset_errors();
             return Ok(krate);
         }
 
         Err(ParserError::ParseError)
     }
 
-    fn parse_crate_inner(input: Input, sess: &'a ParseSess) -> Result<ast::Crate, ParserError> {
+    fn parse_crate_inner(input: Input, psess: &'a ParseSess) -> Result<ast::Crate, ParserError> {
         ParserBuilder::default()
             .input(input)
-            .sess(sess)
+            .psess(psess)
             .build()?
             .parse_crate_mod()
     }
 
     fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> {
         let mut parser = AssertUnwindSafe(&mut self.parser);
-
+        let err = Err(ParserError::ParsePanicError);
         match catch_unwind(move || parser.parse_crate_mod()) {
             Ok(Ok(k)) => Ok(k),
-            Ok(Err(mut db)) => {
+            Ok(Err(db)) => {
                 db.emit();
-                Err(ParserError::ParseError)
+                err
             }
-            Err(_) => Err(ParserError::ParsePanicError),
+            Err(_) => err,
         }
     }
 }
diff --git a/src/parse/session.rs b/src/parse/session.rs
index 5de6ee49acf..5ed2a8dbebb 100644
--- a/src/parse/session.rs
+++ b/src/parse/session.rs
@@ -2,9 +2,9 @@ use std::path::Path;
 use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
-use rustc_errors::emitter::{DynEmitter, Emitter, EmitterWriter};
+use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter};
 use rustc_errors::translation::Translate;
-use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel};
+use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
 use rustc_span::{
     source_map::{FilePathMapping, SourceMap},
@@ -22,36 +22,11 @@ use crate::{Config, ErrorKind, FileName};
 
 /// ParseSess holds structs necessary for constructing a parser.
 pub(crate) struct ParseSess {
-    parse_sess: RawParseSess,
+    raw_psess: RawParseSess,
     ignore_path_set: Lrc<IgnorePathSet>,
     can_reset_errors: Lrc<AtomicBool>,
 }
 
-/// Emitter which discards every error.
-struct SilentEmitter;
-
-impl Translate for SilentEmitter {
-    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
-        None
-    }
-
-    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
-        panic!("silent emitter attempted to translate a diagnostic");
-    }
-}
-
-impl Emitter for SilentEmitter {
-    fn source_map(&self) -> Option<&Lrc<SourceMap>> {
-        None
-    }
-
-    fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
-}
-
-fn silent_emitter() -> Box<DynEmitter> {
-    Box::new(SilentEmitter {})
-}
-
 /// Emit errors against every files expect ones specified in the `ignore_path_set`.
 struct SilentOnIgnoredFilesEmitter {
     ignore_path_set: IntoDynSyncSend<Lrc<IgnorePathSet>>,
@@ -62,10 +37,10 @@ struct SilentOnIgnoredFilesEmitter {
 }
 
 impl SilentOnIgnoredFilesEmitter {
-    fn handle_non_ignorable_error(&mut self, db: &Diagnostic) {
+    fn handle_non_ignoreable_error(&mut self, diag: DiagInner) {
         self.has_non_ignorable_parser_errors = true;
         self.can_reset.store(false, Ordering::Release);
-        self.emitter.emit_diagnostic(db);
+        self.emitter.emit_diagnostic(diag);
     }
 }
 
@@ -84,11 +59,11 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
         None
     }
 
-    fn emit_diagnostic(&mut self, db: &Diagnostic) {
-        if db.level() == DiagnosticLevel::Fatal {
-            return self.handle_non_ignorable_error(db);
+    fn emit_diagnostic(&mut self, diag: DiagInner) {
+        if diag.level() == DiagnosticLevel::Fatal {
+            return self.handle_non_ignoreable_error(diag);
         }
-        if let Some(primary_span) = &db.span.primary_span() {
+        if let Some(primary_span) = &diag.span.primary_span() {
             let file_name = self.source_map.span_to_filename(*primary_span);
             if let rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(ref path)) =
                 file_name
@@ -104,7 +79,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
                 }
             };
         }
-        self.handle_non_ignorable_error(db);
+        self.handle_non_ignoreable_error(diag);
     }
 }
 
@@ -132,16 +107,26 @@ fn default_dcx(
         ColorConfig::Never
     };
 
-    let emitter = if !show_parse_errors {
-        silent_emitter()
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+        false,
+    );
+    let emitter = Box::new(
+        HumanEmitter::new(stderr_destination(emit_color), fallback_bundle.clone())
+            .sm(Some(source_map.clone())),
+    );
+
+    let emitter: Box<DynEmitter> = if !show_parse_errors {
+        Box::new(SilentEmitter {
+            fallback_bundle,
+            fatal_dcx: DiagCtxt::new(emitter),
+            fatal_note: None,
+            emit_fatal_diagnostic: false,
+        })
     } else {
-        let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-            rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-            false,
-        );
-        Box::new(EmitterWriter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone())))
+        emitter
     };
-    DiagCtxt::with_emitter(Box::new(SilentOnIgnoredFilesEmitter {
+    DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter {
         has_non_ignorable_parser_errors: false,
         source_map,
         emitter,
@@ -166,10 +151,10 @@ impl ParseSess {
             config.show_parse_errors(),
             config.color(),
         );
-        let parse_sess = RawParseSess::with_dcx(dcx, source_map);
+        let raw_psess = RawParseSess::with_dcx(dcx, source_map);
 
         Ok(ParseSess {
-            parse_sess,
+            raw_psess,
             ignore_path_set,
             can_reset_errors,
         })
@@ -188,14 +173,14 @@ impl ParseSess {
         relative: Option<symbol::Ident>,
         dir_path: &Path,
     ) -> Result<ModulePathSuccess, ModError<'_>> {
-        rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path).or_else(
+        rustc_expand::module::default_submod_path(&self.raw_psess, id, relative, dir_path).or_else(
             |e| {
                 // If resolving 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)
+                    rustc_expand::module::default_submod_path(&self.raw_psess, id, None, dir_path)
                         .map_err(|_| e)
                 } else {
                     Err(e)
@@ -205,7 +190,7 @@ impl ParseSess {
     }
 
     pub(crate) fn is_file_parsed(&self, path: &Path) -> bool {
-        self.parse_sess
+        self.raw_psess
             .source_map()
             .get_source_file(&rustc_span::FileName::Real(
                 rustc_span::RealFileName::LocalPath(path.to_path_buf()),
@@ -218,21 +203,28 @@ impl ParseSess {
     }
 
     pub(crate) fn set_silent_emitter(&mut self) {
-        self.parse_sess.dcx = DiagCtxt::with_emitter(silent_emitter());
+        // Ideally this invocation wouldn't be necessary and the fallback bundle in
+        // `self.parse_sess.dcx` could be used, but the lock in `DiagCtxt` prevents this.
+        // See `<rustc_errors::SilentEmitter as Translate>::fallback_fluent_bundle`.
+        let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+            rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+            false,
+        );
+        self.raw_psess.dcx.make_silent(fallback_bundle, None, false);
     }
 
     pub(crate) fn span_to_filename(&self, span: Span) -> FileName {
-        self.parse_sess.source_map().span_to_filename(span).into()
+        self.raw_psess.source_map().span_to_filename(span).into()
     }
 
     pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> {
-        self.parse_sess
+        self.raw_psess
             .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();
+        let file_lines = self.raw_psess.source_map().span_to_lines(span).ok();
 
         match file_lines {
             Some(fl) => fl
@@ -244,7 +236,7 @@ impl ParseSess {
     }
 
     pub(crate) fn line_of_byte_pos(&self, pos: BytePos) -> usize {
-        self.parse_sess.source_map().lookup_char_pos(pos).line
+        self.raw_psess.source_map().lookup_char_pos(pos).line
     }
 
     // TODO(calebcartwright): Preemptive, currently unused addition
@@ -257,15 +249,15 @@ impl ParseSess {
     }
 
     pub(crate) fn span_to_debug_info(&self, span: Span) -> String {
-        self.parse_sess.source_map().span_to_diagnostic_string(span)
+        self.raw_psess.source_map().span_to_diagnostic_string(span)
     }
 
     pub(crate) fn inner(&self) -> &RawParseSess {
-        &self.parse_sess
+        &self.raw_psess
     }
 
     pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider {
-        let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file;
+        let source_file = self.raw_psess.source_map().lookup_char_pos(span.lo()).file;
         SnippetProvider::new(
             source_file.start_pos,
             source_file.end_position(),
@@ -274,7 +266,7 @@ impl ParseSess {
     }
 
     pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option<Lrc<String>> {
-        self.parse_sess
+        self.raw_psess
             .source_map()
             .get_source_file(&file_name.into())
             .and_then(|source_file| source_file.src.clone())
@@ -283,9 +275,9 @@ impl ParseSess {
 
 // Methods that should be restricted within the parse module.
 impl ParseSess {
-    pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
+    pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diag<'_>>) {
         for diagnostic in diagnostics {
-            self.parse_sess.dcx.emit_diagnostic(diagnostic);
+            diagnostic.emit();
         }
     }
 
@@ -294,23 +286,23 @@ impl ParseSess {
     }
 
     pub(super) fn has_errors(&self) -> bool {
-        self.parse_sess.dcx.has_errors().is_some()
+        self.raw_psess.dcx.has_errors().is_some()
     }
 
     pub(super) fn reset_errors(&self) {
-        self.parse_sess.dcx.reset_err_count();
+        self.raw_psess.dcx.reset_err_count();
     }
 }
 
 impl LineRangeUtils for ParseSess {
     fn lookup_line_range(&self, span: Span) -> LineRange {
         let snippet = self
-            .parse_sess
+            .raw_psess
             .source_map()
             .span_to_snippet(span)
             .unwrap_or_default();
-        let lo = self.parse_sess.source_map().lookup_line(span.lo()).unwrap();
-        let hi = self.parse_sess.source_map().lookup_line(span.hi()).unwrap();
+        let lo = self.raw_psess.source_map().lookup_line(span.lo()).unwrap();
+        let hi = self.raw_psess.source_map().lookup_line(span.hi()).unwrap();
 
         debug_assert_eq!(
             lo.sf.name, hi.sf.name,
@@ -363,13 +355,14 @@ mod tests {
                 None
             }
 
-            fn emit_diagnostic(&mut self, _db: &Diagnostic) {
+            fn emit_diagnostic(&mut self, _diag: DiagInner) {
                 self.num_emitted_errors.fetch_add(1, Ordering::Release);
             }
         }
 
-        fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {
-            let mut diag = Diagnostic::new(level, "");
+        fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> DiagInner {
+            #[allow(rustc::untranslatable_diagnostic)] // no translation needed for empty string
+            let mut diag = DiagInner::new(level, "");
             diag.messages.clear();
             if let Some(span) = span {
                 diag.span = span;
@@ -422,7 +415,7 @@ mod tests {
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
             let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span));
-            emitter.emit_diagnostic(&fatal_diagnostic);
+            emitter.emit_diagnostic(fatal_diagnostic);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
@@ -446,8 +439,8 @@ mod tests {
                 Some(ignore_list),
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
-            let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span));
-            emitter.emit_diagnostic(&non_fatal_diagnostic);
+            let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
+            emitter.emit_diagnostic(non_fatal_diagnostic);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
         }
@@ -470,8 +463,8 @@ mod tests {
                 None,
             );
             let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
-            let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span));
-            emitter.emit_diagnostic(&non_fatal_diagnostic);
+            let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
+            emitter.emit_diagnostic(non_fatal_diagnostic);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
@@ -507,12 +500,12 @@ mod tests {
             );
             let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
             let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22)));
-            let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(bar_span));
-            let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(foo_span));
+            let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span));
+            let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span));
             let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None);
-            emitter.emit_diagnostic(&bar_diagnostic);
-            emitter.emit_diagnostic(&foo_diagnostic);
-            emitter.emit_diagnostic(&fatal_diagnostic);
+            emitter.emit_diagnostic(bar_diagnostic);
+            emitter.emit_diagnostic(foo_diagnostic);
+            emitter.emit_diagnostic(fatal_diagnostic);
             assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2);
             assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
         }
diff --git a/src/patterns.rs b/src/patterns.rs
index 0fa6edaa5d7..d8cb26a20f1 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -1,6 +1,4 @@
-use rustc_ast::ast::{
-    self, BindingAnnotation, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax,
-};
+use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax};
 use rustc_ast::ptr;
 use rustc_span::{BytePos, Span};
 
@@ -40,9 +38,11 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
 
 fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
     match pat.kind {
-        ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => {
-            true
-        }
+        ast::PatKind::Rest
+        | ast::PatKind::Never
+        | ast::PatKind::Wild
+        | ast::PatKind::Err(_)
+        | ast::PatKind::Lit(_) => true,
         ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
         ast::PatKind::Struct(..)
         | ast::PatKind::MacCall(..)
@@ -53,9 +53,10 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
         ast::PatKind::TupleStruct(_, ref path, ref subpats) => {
             path.segments.len() <= 1 && subpats.len() <= 1
         }
-        ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => {
-            is_short_pattern_inner(&*p)
-        }
+        ast::PatKind::Box(ref p)
+        | PatKind::Deref(ref p)
+        | ast::PatKind::Ref(ref p, _)
+        | ast::PatKind::Paren(ref p) => is_short_pattern_inner(&*p),
         PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(p)),
     }
 }
@@ -103,19 +104,20 @@ impl Rewrite for Pat {
                 write_list(&items, &fmt)
             }
             PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
-            PatKind::Ident(BindingAnnotation(by_ref, mutability), ident, ref sub_pat) => {
-                let prefix = match by_ref {
-                    ByRef::Yes => "ref",
-                    ByRef::No => "",
+            PatKind::Ident(BindingMode(by_ref, mutability), ident, ref sub_pat) => {
+                let mut_prefix = format_mutability(mutability).trim();
+
+                let (ref_kw, mut_infix) = match by_ref {
+                    ByRef::Yes(rmutbl) => ("ref", format_mutability(rmutbl).trim()),
+                    ByRef::No => ("", ""),
                 };
-                let mut_infix = format_mutability(mutability).trim();
                 let id_str = rewrite_ident(context, ident);
                 let sub_pat = match *sub_pat {
                     Some(ref p) => {
                         // 2 - `@ `.
-                        let width = shape
-                            .width
-                            .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 2)?;
+                        let width = shape.width.checked_sub(
+                            mut_prefix.len() + ref_kw.len() + mut_infix.len() + id_str.len() + 2,
+                        )?;
                         let lo = context.snippet_provider.span_after(self.span, "@");
                         combine_strs_with_missing_comments(
                             context,
@@ -129,33 +131,55 @@ impl Rewrite for Pat {
                     None => "".to_owned(),
                 };
 
-                // combine prefix and mut
-                let (first_lo, first) = if !prefix.is_empty() && !mut_infix.is_empty() {
-                    let hi = context.snippet_provider.span_before(self.span, "mut");
-                    let lo = context.snippet_provider.span_after(self.span, "ref");
-                    (
+                // combine prefix and ref
+                let (first_lo, first) = match (mut_prefix.is_empty(), ref_kw.is_empty()) {
+                    (false, false) => {
+                        let lo = context.snippet_provider.span_after(self.span, "mut");
+                        let hi = context.snippet_provider.span_before(self.span, "ref");
+                        (
+                            context.snippet_provider.span_after(self.span, "ref"),
+                            combine_strs_with_missing_comments(
+                                context,
+                                mut_prefix,
+                                ref_kw,
+                                mk_sp(lo, hi),
+                                shape,
+                                true,
+                            )?,
+                        )
+                    }
+                    (false, true) => (
                         context.snippet_provider.span_after(self.span, "mut"),
-                        combine_strs_with_missing_comments(
-                            context,
-                            prefix,
-                            mut_infix,
-                            mk_sp(lo, hi),
-                            shape,
-                            true,
-                        )?,
-                    )
-                } else if !prefix.is_empty() {
-                    (
+                        mut_prefix.to_owned(),
+                    ),
+                    (true, false) => (
                         context.snippet_provider.span_after(self.span, "ref"),
-                        prefix.to_owned(),
-                    )
-                } else if !mut_infix.is_empty() {
-                    (
-                        context.snippet_provider.span_after(self.span, "mut"),
-                        mut_infix.to_owned(),
-                    )
-                } else {
-                    (self.span.lo(), "".to_owned())
+                        ref_kw.to_owned(),
+                    ),
+                    (true, true) => (self.span.lo(), "".to_owned()),
+                };
+
+                // combine result of above and mut
+                let (second_lo, second) = match (first.is_empty(), mut_infix.is_empty()) {
+                    (false, false) => {
+                        let lo = context.snippet_provider.span_after(self.span, "ref");
+                        let end_span = mk_sp(first_lo, self.span.hi());
+                        let hi = context.snippet_provider.span_before(end_span, "mut");
+                        (
+                            context.snippet_provider.span_after(end_span, "mut"),
+                            combine_strs_with_missing_comments(
+                                context,
+                                &first,
+                                mut_infix,
+                                mk_sp(lo, hi),
+                                shape,
+                                true,
+                            )?,
+                        )
+                    }
+                    (false, true) => (first_lo, first),
+                    (true, false) => unreachable!("mut_infix necessarily follows a ref"),
+                    (true, true) => (self.span.lo(), "".to_owned()),
                 };
 
                 let next = if !sub_pat.is_empty() {
@@ -174,9 +198,9 @@ impl Rewrite for Pat {
 
                 combine_strs_with_missing_comments(
                     context,
-                    &first,
+                    &second,
                     &next,
-                    mk_sp(first_lo, ident.span.lo()),
+                    mk_sp(second_lo, ident.span.lo()),
                     shape,
                     true,
                 )
@@ -274,6 +298,8 @@ impl Rewrite for Pat {
             PatKind::Paren(ref pat) => pat
                 .rewrite(context, shape.offset_left(1)?.sub_width(1)?)
                 .map(|inner_pat| format!("({})", inner_pat)),
+            PatKind::Err(_) => None,
+            PatKind::Deref(_) => None,
         }
     }
 }
diff --git a/src/reorder.rs b/src/reorder.rs
index 3e14f9f1272..fdbed939af5 100644
--- a/src/reorder.rs
+++ b/src/reorder.rs
@@ -263,13 +263,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         item_kind: ReorderableItemKind,
         in_group: bool,
     ) -> usize {
-        let mut last = self.parse_sess.lookup_line_range(items[0].span());
+        let mut last = self.psess.lookup_line_range(items[0].span());
         let item_length = items
             .iter()
             .take_while(|ppi| {
                 item_kind.is_same_item_kind(&***ppi)
                     && (!in_group || {
-                        let current = self.parse_sess.lookup_line_range(ppi.span());
+                        let current = self.psess.lookup_line_range(ppi.span());
                         let in_same_group = current.lo < last.hi + 2;
                         last = current;
                         in_same_group
diff --git a/src/rewrite.rs b/src/rewrite.rs
index 4a3bd129d16..e2498a3500a 100644
--- a/src/rewrite.rs
+++ b/src/rewrite.rs
@@ -26,7 +26,7 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
 
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
-    pub(crate) parse_sess: &'a ParseSess,
+    pub(crate) psess: &'a ParseSess,
     pub(crate) config: &'a Config,
     pub(crate) inside_macro: Rc<Cell<bool>>,
     // Force block indent style even if we are using visual indent style.
diff --git a/src/source_file.rs b/src/source_file.rs
index 8f66def3df3..5eea8021b32 100644
--- a/src/source_file.rs
+++ b/src/source_file.rs
@@ -49,7 +49,7 @@ where
 }
 
 pub(crate) fn write_file<T>(
-    parse_sess: Option<&ParseSess>,
+    psess: Option<&ParseSess>,
     filename: &FileName,
     formatted_text: &str,
     out: &mut T,
@@ -66,6 +66,7 @@ where
         }
     }
 
+    #[allow(non_local_definitions)]
     impl From<&FileName> for rustc_span::FileName {
         fn from(filename: &FileName) -> rustc_span::FileName {
             match filename {
@@ -89,7 +90,7 @@ where
     let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin {
         Lrc::new(fs::read_to_string(ensure_real_path(filename))?)
     } else {
-        match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) {
+        match psess.and_then(|psess| psess.get_original_snippet(filename)) {
             Some(ori) => ori,
             None => Lrc::new(fs::read_to_string(ensure_real_path(filename))?),
         }
diff --git a/src/spanned.rs b/src/spanned.rs
index 5960b144499..4aaf7fdb27f 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -61,7 +61,7 @@ implement_spanned!(ast::Local);
 impl Spanned for ast::Stmt {
     fn span(&self) -> Span {
         match self.kind {
-            ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()),
+            ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()),
             ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()),
             ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
                 mk_sp(expr.span().lo(), self.span.hi())
diff --git a/src/stmt.rs b/src/stmt.rs
index e3fe4ebca11..73a9cce416c 100644
--- a/src/stmt.rs
+++ b/src/stmt.rs
@@ -115,7 +115,7 @@ fn format_stmt(
     skip_out_of_file_lines_range!(context, stmt.span());
 
     let result = match stmt.kind {
-        ast::StmtKind::Local(ref local) => local.rewrite(context, shape),
+        ast::StmtKind::Let(ref local) => local.rewrite(context, shape),
         ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => {
             let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) {
                 ";"
diff --git a/src/test/mod.rs b/src/test/mod.rs
index d567a1b8e4e..7c563801c32 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -391,12 +391,24 @@ fn self_tests() {
         files.push(path);
     }
     // for crates that need to be included but lies outside src
-    let external_crates = vec!["check_diff"];
+    let external_crates = vec!["check_diff", "config_proc_macro"];
     for external_crate in external_crates {
         let mut path = PathBuf::from(external_crate);
         path.push("src");
-        path.push("main.rs");
-        files.push(path);
+        let directory = fs::read_dir(&path).unwrap();
+        let search_files = directory.filter_map(|file| {
+            file.ok().and_then(|f| {
+                let name = f.file_name();
+                if matches!(name.as_os_str().to_str(), Some("main.rs" | "lib.rs")) {
+                    Some(f.path())
+                } else {
+                    None
+                }
+            })
+        });
+        for file in search_files {
+            files.push(file);
+        }
     }
     files.push(PathBuf::from("src/lib.rs"));
 
diff --git a/src/test/parser.rs b/src/test/parser.rs
index ae4a4f94d92..d951c8469e6 100644
--- a/src/test/parser.rs
+++ b/src/test/parser.rs
@@ -55,3 +55,17 @@ fn crate_parsing_errors_on_unclosed_delims() {
     let filename = "tests/parser/unclosed-delims/issue_4466.rs";
     assert_parser_error(filename);
 }
+
+#[test]
+fn crate_parsing_stashed_diag() {
+    // See also https://github.com/rust-lang/rust/issues/121450
+    let filename = "tests/parser/stashed-diag.rs";
+    assert_parser_error(filename);
+}
+
+#[test]
+fn crate_parsing_stashed_diag2() {
+    // See also https://github.com/rust-lang/rust/issues/121517
+    let filename = "tests/parser/stashed-diag2.rs";
+    assert_parser_error(filename);
+}
diff --git a/src/types.rs b/src/types.rs
index 1544d2df335..fd480393584 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -142,7 +142,7 @@ pub(crate) enum SegmentParam<'a> {
     Const(&'a ast::AnonConst),
     LifeTime(&'a ast::Lifetime),
     Type(&'a ast::Ty),
-    Binding(&'a ast::AssocConstraint),
+    Binding(&'a ast::AssocItemConstraint),
 }
 
 impl<'a> SegmentParam<'a> {
@@ -177,9 +177,9 @@ impl<'a> Rewrite for SegmentParam<'a> {
     }
 }
 
-impl Rewrite for ast::AssocConstraint {
+impl Rewrite for ast::AssocItemConstraint {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        use ast::AssocConstraintKind::{Bound, Equality};
+        use ast::AssocItemConstraintKind::{Bound, Equality};
 
         let mut result = String::with_capacity(128);
         result.push_str(rewrite_ident(context, self.ident));
@@ -207,14 +207,14 @@ impl Rewrite for ast::AssocConstraint {
     }
 }
 
-impl Rewrite for ast::AssocConstraintKind {
+impl Rewrite for ast::AssocItemConstraintKind {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match self {
-            ast::AssocConstraintKind::Equality { term } => match term {
+            ast::AssocItemConstraintKind::Equality { term } => match term {
                 Term::Ty(ty) => ty.rewrite(context, shape),
                 Term::Const(c) => c.rewrite(context, shape),
             },
-            ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape),
+            ast::AssocItemConstraintKind::Bound { bounds } => bounds.rewrite(context, shape),
         }
     }
 }
@@ -539,18 +539,29 @@ impl Rewrite for ast::Lifetime {
 impl Rewrite for ast::GenericBound {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match *self {
-            ast::GenericBound::Trait(ref poly_trait_ref, modifiers) => {
+            ast::GenericBound::Trait(
+                ref poly_trait_ref,
+                ast::TraitBoundModifiers {
+                    constness,
+                    asyncness,
+                    polarity,
+                },
+            ) => {
                 let snippet = context.snippet(self.span());
                 let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
-                let mut constness = modifiers.constness.as_str().to_string();
+                let mut constness = constness.as_str().to_string();
                 if !constness.is_empty() {
                     constness.push(' ');
                 }
-                let polarity = modifiers.polarity.as_str();
+                let mut asyncness = asyncness.as_str().to_string();
+                if !asyncness.is_empty() {
+                    asyncness.push(' ');
+                }
+                let polarity = polarity.as_str();
                 let shape = shape.offset_left(constness.len() + polarity.len())?;
                 poly_trait_ref
                     .rewrite(context, shape)
-                    .map(|s| format!("{constness}{polarity}{s}"))
+                    .map(|s| format!("{constness}{asyncness}{polarity}{s}"))
                     .map(|s| if has_paren { format!("({})", s) } else { s })
             }
             ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape),
@@ -810,8 +821,8 @@ impl Rewrite for ast::Ty {
             ast::TyKind::Tup(ref items) => {
                 rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
             }
-            ast::TyKind::AnonStruct(_) => Some(context.snippet(self.span).to_owned()),
-            ast::TyKind::AnonUnion(_) => Some(context.snippet(self.span).to_owned()),
+            ast::TyKind::AnonStruct(..) => Some(context.snippet(self.span).to_owned()),
+            ast::TyKind::AnonUnion(..) => Some(context.snippet(self.span).to_owned()),
             ast::TyKind::Path(ref q_self, ref path) => {
                 rewrite_path(context, PathContext::Type, q_self, path, shape)
             }
@@ -836,7 +847,11 @@ impl Rewrite for ast::Ty {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
             }
             ast::TyKind::ImplicitSelf => Some(String::from("")),
-            ast::TyKind::ImplTrait(_, ref it) => {
+            ast::TyKind::ImplTrait(_, ref it, ref captures) => {
+                // FIXME(precise_capturing): Implement formatting.
+                if captures.is_some() {
+                    return None;
+                }
                 // Empty trait is not a parser error.
                 if it.is_empty() {
                     return Some("impl".to_owned());
@@ -852,7 +867,7 @@ impl Rewrite for ast::Ty {
                 })
             }
             ast::TyKind::CVarArgs => Some("...".to_owned()),
-            ast::TyKind::Err => Some(context.snippet(self.span).to_owned()),
+            ast::TyKind::Dummy | ast::TyKind::Err(_) => Some(context.snippet(self.span).to_owned()),
             ast::TyKind::Typeof(ref anon_const) => rewrite_call(
                 context,
                 "typeof",
@@ -860,6 +875,11 @@ impl Rewrite for ast::Ty {
                 self.span,
                 shape,
             ),
+            ast::TyKind::Pat(ref ty, ref pat) => {
+                let ty = ty.rewrite(context, shape)?;
+                let pat = pat.rewrite(context, shape)?;
+                Some(format!("{ty} is {pat}"))
+            }
         }
     }
 }
@@ -883,7 +903,7 @@ fn rewrite_bare_fn(
         result.push_str("> ");
     }
 
-    result.push_str(crate::utils::format_unsafety(bare_fn.unsafety));
+    result.push_str(crate::utils::format_safety(bare_fn.safety));
 
     result.push_str(&format_extern(
         bare_fn.ext,
@@ -1094,7 +1114,8 @@ 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),
+        // FIXME(precise_capturing): Implement support here
+        ast::TyKind::ImplTrait(_, bounds, _) => Some(bounds),
         _ => None,
     })
 }
diff --git a/src/utils.rs b/src/utils.rs
index 642b6603b1e..fd59aedadfe 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -108,10 +108,11 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str
 }
 
 #[inline]
-pub(crate) fn format_unsafety(unsafety: ast::Unsafe) -> &'static str {
+pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str {
     match unsafety {
-        ast::Unsafe::Yes(..) => "unsafe ",
-        ast::Unsafe::No => "",
+        ast::Safety::Unsafe(..) => "unsafe ",
+        ast::Safety::Safe(..) => "safe ",
+        ast::Safety::Default => "",
     }
 }
 
@@ -362,7 +363,7 @@ macro_rules! out_of_file_lines_range {
             && !$self
                 .config
                 .file_lines()
-                .intersects(&$self.parse_sess.lookup_line_range($span))
+                .intersects(&$self.psess.lookup_line_range($span))
     };
 }
 
@@ -497,7 +498,8 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
         | ast::ExprKind::Break(..)
         | ast::ExprKind::Cast(..)
         | ast::ExprKind::Continue(..)
-        | ast::ExprKind::Err
+        | ast::ExprKind::Dummy
+        | ast::ExprKind::Err(_)
         | ast::ExprKind::Field(..)
         | ast::ExprKind::IncludedBytes(..)
         | ast::ExprKind::InlineAsm(..)
diff --git a/src/visitor.rs b/src/visitor.rs
index 61e147ed8f5..1de9f5a9524 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -24,7 +24,7 @@ use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt::Stmt;
 use crate::utils::{
-    self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes,
+    self, contains_skip, count_newlines, depr_skip_annotation, format_safety, inner_attributes,
     last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr,
 };
 use crate::{ErrorKind, FormatReport, FormattingError};
@@ -71,7 +71,7 @@ impl SnippetProvider {
 
 pub(crate) struct FmtVisitor<'a> {
     parent_context: Option<&'a RewriteContext<'a>>,
-    pub(crate) parse_sess: &'a ParseSess,
+    pub(crate) psess: &'a ParseSess,
     pub(crate) buffer: String,
     pub(crate) last_pos: BytePos,
     // FIXME: use an RAII util or closure for indenting
@@ -113,10 +113,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     }
 
     fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) {
-        debug!(
-            "visit_stmt: {}",
-            self.parse_sess.span_to_debug_info(stmt.span())
-        );
+        debug!("visit_stmt: {}", self.psess.span_to_debug_info(stmt.span()));
 
         if stmt.is_empty() {
             // If the statement is empty, just skip over it. Before that, make sure any comment
@@ -153,7 +150,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 self.visit_item(item);
                 self.last_pos = stmt.span().hi();
             }
-            ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => {
+            ast::StmtKind::Let(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => {
                 let attrs = get_attrs_from_stmt(stmt.as_ast_node());
                 if contains_skip(attrs) {
                     self.push_skipped_with_span(
@@ -217,10 +214,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         inner_attrs: Option<&[ast::Attribute]>,
         has_braces: bool,
     ) {
-        debug!(
-            "visit_block: {}",
-            self.parse_sess.span_to_debug_info(b.span),
-        );
+        debug!("visit_block: {}", self.psess.span_to_debug_info(b.span));
 
         // Check if this block has braces.
         let brace_compensation = BytePos(if has_braces { 1 } else { 0 });
@@ -523,9 +517,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     self.visit_enum(item.ident, &item.vis, def, generics, item.span);
                     self.last_pos = source!(self, item.span).hi();
                 }
-                ast::ItemKind::Mod(unsafety, ref mod_kind) => {
+                ast::ItemKind::Mod(safety, ref mod_kind) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs);
+                    self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs);
                 }
                 ast::ItemKind::MacCall(ref mac) => {
                     self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
@@ -592,6 +586,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                     self.push_rewrite(item.span, rewrite);
                 }
+                ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => {
+                    // TODO: rewrite delegation items once syntax is established.
+                    // For now, leave the contents of the Span unformatted.
+                    self.push_rewrite(item.span, None)
+                }
             };
         }
         self.skip_context = skip_context_saved;
@@ -739,10 +738,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         // do not take into account the lines with attributes as part of the skipped range
         let attrs_end = attrs
             .iter()
-            .map(|attr| self.parse_sess.line_of_byte_pos(attr.span.hi()))
+            .map(|attr| self.psess.line_of_byte_pos(attr.span.hi()))
             .max()
             .unwrap_or(1);
-        let first_line = self.parse_sess.line_of_byte_pos(main_span.lo());
+        let first_line = self.psess.line_of_byte_pos(main_span.lo());
         // Statement can start after some newlines and/or spaces
         // or it can be on the same line as the last attribute.
         // So here we need to take a minimum between the two.
@@ -753,8 +752,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     }
 
     pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> {
-        let mut visitor = FmtVisitor::from_parse_sess(
-            ctx.parse_sess,
+        let mut visitor = FmtVisitor::from_psess(
+            ctx.psess,
             ctx.config,
             ctx.snippet_provider,
             ctx.report.clone(),
@@ -764,8 +763,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         visitor
     }
 
-    pub(crate) fn from_parse_sess(
-        parse_session: &'a ParseSess,
+    pub(crate) fn from_psess(
+        psess: &'a ParseSess,
         config: &'a Config,
         snippet_provider: &'a SnippetProvider,
         report: FormatReport,
@@ -781,7 +780,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         skip_context.macros.extend(macro_names);
         FmtVisitor {
             parent_context: None,
-            parse_sess: parse_session,
+            psess,
             buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
             last_pos: BytePos(0),
             block_indent: Indent::empty(),
@@ -809,12 +808,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool {
         for attr in attrs {
             if attr.has_name(depr_skip_annotation()) {
-                let file_name = self.parse_sess.span_to_filename(attr.span);
+                let file_name = self.psess.span_to_filename(attr.span);
                 self.report.append(
                     file_name,
                     vec![FormattingError::from_span(
                         attr.span,
-                        self.parse_sess,
+                        self.psess,
                         ErrorKind::DeprecatedAttr,
                     )],
                 );
@@ -823,12 +822,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     ast::AttrKind::Normal(ref normal)
                         if self.is_unknown_rustfmt_attr(&normal.item.path.segments) =>
                     {
-                        let file_name = self.parse_sess.span_to_filename(attr.span);
+                        let file_name = self.psess.span_to_filename(attr.span);
                         self.report.append(
                             file_name,
                             vec![FormattingError::from_span(
                                 attr.span,
-                                self.parse_sess,
+                                self.psess,
                                 ErrorKind::BadAttr,
                             )],
                         );
@@ -914,7 +913,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     fn format_mod(
         &mut self,
         mod_kind: &ast::ModKind,
-        unsafety: ast::Unsafe,
+        safety: ast::Safety,
         vis: &ast::Visibility,
         s: Span,
         ident: symbol::Ident,
@@ -922,7 +921,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     ) {
         let vis_str = utils::format_visibility(&self.get_context(), vis);
         self.push_str(&*vis_str);
-        self.push_str(format_unsafety(unsafety));
+        self.push_str(format_safety(safety));
         self.push_str("mod ");
         // Calling `to_owned()` to work around borrow checker.
         let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
@@ -1002,7 +1001,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
     pub(crate) fn get_context(&self) -> RewriteContext<'_> {
         RewriteContext {
-            parse_sess: self.parse_sess,
+            psess: self.psess,
             config: self.config,
             inside_macro: Rc::new(Cell::new(false)),
             use_block: Cell::new(false),
diff --git a/tests/parser/stashed-diag.rs b/tests/parser/stashed-diag.rs
new file mode 100644
index 00000000000..3b0b543e610
--- /dev/null
+++ b/tests/parser/stashed-diag.rs
@@ -0,0 +1,3 @@
+#![u={static N;}]
+
+fn main() {}
diff --git a/tests/parser/stashed-diag2.rs b/tests/parser/stashed-diag2.rs
new file mode 100644
index 00000000000..579a69def16
--- /dev/null
+++ b/tests/parser/stashed-diag2.rs
@@ -0,0 +1,3 @@
+trait Trait<'1> { s> {}
+
+fn main() {}
diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs
index 39c93c97fa6..58cf0e5e4db 100644
--- a/tests/rustfmt/main.rs
+++ b/tests/rustfmt/main.rs
@@ -180,10 +180,11 @@ fn dont_emit_ICE() {
         "tests/target/issue_5728.rs",
         "tests/target/issue_5729.rs",
         "tests/target/issue-5885.rs",
+        "tests/target/issue_6082.rs",
         "tests/target/issue_6069.rs",
         "tests/target/issue-6105.rs",
     ];
-    
+
     for file in files {
         let args = [file];
         let (_stdout, stderr) = rustfmt(&args);
diff --git a/tests/source/immovable_coroutines.rs b/tests/source/immovable_coroutines.rs
index 3b94af0c96c..539049577a0 100644
--- a/tests/source/immovable_coroutines.rs
+++ b/tests/source/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || { 
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }
diff --git a/tests/source/macros/rewrite-const-item.rs b/tests/source/macros/rewrite-const-item.rs
new file mode 100644
index 00000000000..3db2c26ab5a
--- /dev/null
+++ b/tests/source/macros/rewrite-const-item.rs
@@ -0,0 +1 @@
+m!(const N: usize = 0;);
diff --git a/tests/source/mut_ref.rs b/tests/source/mut_ref.rs
new file mode 100644
index 00000000000..18ff33a99ce
--- /dev/null
+++ b/tests/source/mut_ref.rs
@@ -0,0 +1,10 @@
+#![feature(mut_ref)]
+fn mut_ref() {
+    if let Some(mut /*a*/ ref     /*def*/  mut     /*abc*/       state)=          /*abc*/foo{
+        println!(
+"asdfasdfasdf");	}
+
+if let Some(mut /*a*/ ref     /*def*/  /*mut*/       state)=          /*abc*/foo{
+    println!(
+"asdfasdfasdf");	}
+}
diff --git a/tests/source/postfix-match/pf-match.rs b/tests/source/postfix-match/pf-match.rs
new file mode 100644
index 00000000000..b2366723631
--- /dev/null
+++ b/tests/source/postfix-match/pf-match.rs
@@ -0,0 +1,20 @@
+#![feature(postfix_match)]
+
+fn main() {
+    let val = Some(42);
+
+    val.match {
+        Some(_) => 2,
+        _ => 1
+    };
+
+    Some(2).match {
+        Some(_) => true,
+        None => false
+    }.match {
+        false => "ferris is cute",
+        true => "I turn cats in to petted cats",
+    }.match {
+        _ => (),
+    }
+}
\ No newline at end of file
diff --git a/tests/target/anonymous-types.rs b/tests/target/anonymous-types.rs
index 8e08c314ed1..e8c2d83878c 100644
--- a/tests/target/anonymous-types.rs
+++ b/tests/target/anonymous-types.rs
@@ -16,4 +16,16 @@ struct Foo {
     e: f32,
 }
 
+// Test for https://github.com/rust-lang/rust/issues/117942
+struct Foo {
+    _: union  {
+        #[rustfmt::skip]
+    f: String,
+    },
+    #[rustfmt::skip]
+    _: struct {
+    g: i32,
+    },
+}
+
 fn main() {}
diff --git a/tests/target/asyncness.rs b/tests/target/asyncness.rs
new file mode 100644
index 00000000000..d91ac960499
--- /dev/null
+++ b/tests/target/asyncness.rs
@@ -0,0 +1,3 @@
+// rustfmt-edition: 2018
+
+fn foo() -> impl async Fn() {}
diff --git a/tests/target/immovable_coroutines.rs b/tests/target/immovable_coroutines.rs
index f52cfa00f97..539049577a0 100644
--- a/tests/target/immovable_coroutines.rs
+++ b/tests/target/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || {
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }
diff --git a/tests/target/issue_6082.rs b/tests/target/issue_6082.rs
new file mode 100644
index 00000000000..58e512c710e
--- /dev/null
+++ b/tests/target/issue_6082.rs
@@ -0,0 +1,5 @@
+macro_rules! test {
+    ($T:ident, $b:lifetime) => {
+        Box<$T<$b>>
+    };
+}
diff --git a/tests/target/issue_6159.rs b/tests/target/issue_6159.rs
new file mode 100644
index 00000000000..49fd539d3ef
--- /dev/null
+++ b/tests/target/issue_6159.rs
@@ -0,0 +1,3 @@
+fn main() {
+    builtin # type_ascribe(10, usize)
+}
diff --git a/tests/target/macros/rewrite-const-item.rs b/tests/target/macros/rewrite-const-item.rs
new file mode 100644
index 00000000000..f7ebaf78277
--- /dev/null
+++ b/tests/target/macros/rewrite-const-item.rs
@@ -0,0 +1,3 @@
+m!(
+    const N: usize = 0;
+);
diff --git a/tests/target/mut_ref.rs b/tests/target/mut_ref.rs
new file mode 100644
index 00000000000..16035243791
--- /dev/null
+++ b/tests/target/mut_ref.rs
@@ -0,0 +1,10 @@
+#![feature(mut_ref)]
+fn mut_ref() {
+    if let Some(mut /*a*/ ref /*def*/ mut /*abc*/ state) = /*abc*/ foo {
+        println!("asdfasdfasdf");
+    }
+
+    if let Some(mut /*a*/ ref /*def*/  /*mut*/ state) = /*abc*/ foo {
+        println!("asdfasdfasdf");
+    }
+}
diff --git a/tests/target/postfix-match/pf-match.rs b/tests/target/postfix-match/pf-match.rs
new file mode 100644
index 00000000000..f439f272623
--- /dev/null
+++ b/tests/target/postfix-match/pf-match.rs
@@ -0,0 +1,20 @@
+#![feature(postfix_match)]
+
+fn main() {
+    let val = Some(42);
+
+    val.match {
+        Some(_) => 2,
+        _ => 1,
+    };
+
+    Some(2).match {
+        Some(_) => true,
+        None => false,
+    }.match {
+        false => "ferris is cute",
+        true => "I turn cats in to petted cats",
+    }.match {
+        _ => (),
+    }
+}
diff --git a/tests/target/unsafe_attributes.rs b/tests/target/unsafe_attributes.rs
new file mode 100644
index 00000000000..a05bedc751a
--- /dev/null
+++ b/tests/target/unsafe_attributes.rs
@@ -0,0 +1,34 @@
+#![feature(unsafe_attributes)]
+// https://github.com/rust-lang/rust/issues/123757
+//
+#![simple_ident]
+#![simple::path]
+#![simple_ident_expr = ""]
+#![simple::path::Expr = ""]
+#![simple_ident_tt(a b c)]
+#![simple_ident_tt[a b c]]
+#![simple_ident_tt{a b c}]
+#![simple::path::tt(a b c)]
+#![simple::path::tt[a b c]]
+#![simple::path::tt{a b c}]
+#![unsafe(simple_ident)]
+#![unsafe(simple::path)]
+#![unsafe(simple_ident_expr = "")]
+#![unsafe(simple::path::Expr = "")]
+#![unsafe(simple_ident_tt(a b c))]
+#![unsafe(simple_ident_tt[a b c])]
+#![unsafe(simple_ident_tt{a b c})]
+#![unsafe(simple::path::tt(a b c))]
+#![unsafe(simple::path::tt[a b c])]
+#![unsafe(simple::path::tt{a b c})]
+// I don't think `safe` attributes are a thing, but adding these formatting cases here just in case
+#![safe(simple_ident)]
+#![safe(simple::path)]
+#![safe(simple_ident_expr = "")]
+#![safe(simple::path::Expr = "")]
+#![safe(simple_ident_tt(a b c))]
+#![safe(simple_ident_tt[a b c])]
+#![safe(simple_ident_tt{a b c})]
+#![safe(simple::path::tt(a b c))]
+#![safe(simple::path::tt[a b c])]
+#![safe(simple::path::tt{a b c})]