about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs28
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs22
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs51
-rw-r--r--compiler/rustc_parse_format/src/lib.rs29
-rw-r--r--library/core/benches/char/methods.rs40
-rw-r--r--library/core/benches/num/flt2dec/strategy/dragon.rs18
-rw-r--r--library/core/benches/num/flt2dec/strategy/grisu.rs18
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py51
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md2
-rw-r--r--tests/ui/async-await/future-sizes/future-as-arg.rs16
-rw-r--r--tests/ui/async-await/future-sizes/large-arg.rs18
-rw-r--r--tests/ui/async-await/future-sizes/large-arg.stdout60
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed26
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs12
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr31
-rw-r--r--tests/ui/fmt/format-string-wrong-order.rs15
-rw-r--r--tests/ui/fmt/format-string-wrong-order.stderr54
-rw-r--r--tests/ui/parser/issues/issue-87086-colon-path-sep.rs1
-rw-r--r--tests/ui/parser/issues/issue-87086-colon-path-sep.stderr81
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.rs16
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.stderr54
21 files changed, 521 insertions, 122 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 87db08ef5b5..7901a5046ab 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -583,10 +583,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let err = FnMutError {
             span: *span,
             ty_err: match output_ty.kind() {
-                ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
                 ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
                     FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
                 }
+                _ if output_ty.contains_closure() => {
+                    FnMutReturnTypeErr::ReturnClosure { span: *span }
+                }
                 _ => FnMutReturnTypeErr::ReturnRef { span: *span },
             },
         };
@@ -997,7 +999,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
         let map = self.infcx.tcx.hir();
         let body_id = map.body_owned_by(self.mir_def_id());
-        let expr = &map.body(body_id).value;
+        let expr = &map.body(body_id).value.peel_blocks();
         let mut closure_span = None::<rustc_span::Span>;
         match expr.kind {
             hir::ExprKind::MethodCall(.., args, _) => {
@@ -1012,20 +1014,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                 }
             }
-            hir::ExprKind::Block(blk, _) => {
-                if let Some(expr) = blk.expr {
-                    // only when the block is a closure
-                    if let hir::ExprKind::Closure(hir::Closure {
-                        capture_clause: hir::CaptureBy::Ref,
-                        body,
-                        ..
-                    }) = expr.kind
-                    {
-                        let body = map.body(*body);
-                        if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
-                            closure_span = Some(expr.span.shrink_to_lo());
-                        }
-                    }
+            hir::ExprKind::Closure(hir::Closure {
+                capture_clause: hir::CaptureBy::Ref,
+                body,
+                ..
+            }) => {
+                let body = map.body(*body);
+                if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                    closure_span = Some(expr.span.shrink_to_lo());
                 }
             }
             _ => {}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 060d864389c..98d6b683563 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2043,6 +2043,28 @@ impl<'tcx> Ty<'tcx> {
         cf.is_break()
     }
 
+    /// Checks whether a type recursively contains any closure
+    ///
+    /// Example: `Option<[closure@file.rs:4:20]>` returns true
+    pub fn contains_closure(self) -> bool {
+        struct ContainsClosureVisitor;
+
+        impl<'tcx> TypeVisitor<'tcx> for ContainsClosureVisitor {
+            type BreakTy = ();
+
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                if let ty::Closure(_, _) = t.kind() {
+                    ControlFlow::Break(())
+                } else {
+                    t.super_visit_with(self)
+                }
+            }
+        }
+
+        let cf = self.visit_with(&mut ContainsClosureVisitor);
+        cf.is_break()
+    }
+
     /// Returns the type and mutability of `*ty`.
     ///
     /// The parameter `explicit` indicates if this is an *explicit* dereference.
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 16d5edfd303..cd9d85b1d91 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2405,26 +2405,42 @@ impl<'a> Parser<'a> {
         if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
             || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
         {
+            let mut snapshot_type = self.create_snapshot_for_diagnostic();
+            snapshot_type.bump(); // `:`
+            match snapshot_type.parse_ty() {
+                Err(inner_err) => {
+                    inner_err.cancel();
+                }
+                Ok(ty) => {
+                    let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else {
+                        return first_pat;
+                    };
+                    err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+                    self.restore_snapshot(snapshot_type);
+                    let span = first_pat.span.to(ty.span);
+                    first_pat = self.mk_pat(span, PatKind::Wild);
+                    err.emit();
+                }
+            }
             return first_pat;
         }
         // The pattern looks like it might be a path with a `::` -> `:` typo:
         // `match foo { bar:baz => {} }`
-        let span = self.token.span;
+        let colon_span = self.token.span;
         // We only emit "unexpected `:`" error here if we can successfully parse the
         // whole pattern correctly in that case.
-        let snapshot = self.create_snapshot_for_diagnostic();
+        let mut snapshot_pat = self.create_snapshot_for_diagnostic();
+        let mut snapshot_type = self.create_snapshot_for_diagnostic();
 
         // Create error for "unexpected `:`".
         match self.expected_one_of_not_found(&[], &[]) {
             Err(mut err) => {
-                self.bump(); // Skip the `:`.
-                match self.parse_pat_no_top_alt(expected) {
+                // Skip the `:`.
+                snapshot_pat.bump();
+                snapshot_type.bump();
+                match snapshot_pat.parse_pat_no_top_alt(expected) {
                     Err(inner_err) => {
-                        // Carry on as if we had not done anything, callers will emit a
-                        // reasonable error.
                         inner_err.cancel();
-                        err.cancel();
-                        self.restore_snapshot(snapshot);
                     }
                     Ok(mut pat) => {
                         // We've parsed the rest of the pattern.
@@ -2488,8 +2504,8 @@ impl<'a> Parser<'a> {
                             _ => {}
                         }
                         if show_sugg {
-                            err.span_suggestion(
-                                span,
+                            err.span_suggestion_verbose(
+                                colon_span.until(self.look_ahead(1, |t| t.span)),
                                 "maybe write a path separator here",
                                 "::",
                                 Applicability::MaybeIncorrect,
@@ -2497,13 +2513,24 @@ impl<'a> Parser<'a> {
                         } else {
                             first_pat = self.mk_pat(new_span, PatKind::Wild);
                         }
-                        err.emit();
+                        self.restore_snapshot(snapshot_pat);
                     }
                 }
+                match snapshot_type.parse_ty() {
+                    Err(inner_err) => {
+                        inner_err.cancel();
+                    }
+                    Ok(ty) => {
+                        err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+                        self.restore_snapshot(snapshot_type);
+                        let new_span = first_pat.span.to(ty.span);
+                        first_pat = self.mk_pat(new_span, PatKind::Wild);
+                    }
+                }
+                err.emit();
             }
             _ => {
                 // Carry on as if we had not done anything. This should be unreachable.
-                self.restore_snapshot(snapshot);
             }
         };
         first_pat
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index a6dfcd29762..088a87ca571 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -273,7 +273,13 @@ impl<'a> Iterator for Parser<'a> {
                                 );
                             }
                         } else {
-                            self.suggest_positional_arg_instead_of_captured_arg(arg);
+                            if let Some(&(_, maybe)) = self.cur.peek() {
+                                if maybe == '?' {
+                                    self.suggest_format();
+                                } else {
+                                    self.suggest_positional_arg_instead_of_captured_arg(arg);
+                                }
+                            }
                         }
                         Some(NextArgument(Box::new(arg)))
                     }
@@ -832,6 +838,27 @@ impl<'a> Parser<'a> {
         if found { Some(cur) } else { None }
     }
 
+    fn suggest_format(&mut self) {
+        if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) {
+            let word = self.word();
+            let _end = self.current_pos();
+            let pos = self.to_span_index(pos);
+            self.errors.insert(
+                0,
+                ParseError {
+                    description: "expected format parameter to occur after `:`".to_owned(),
+                    note: Some(
+                        format!("`?` comes after `:`, try `{}:{}` instead", word, "?").to_owned(),
+                    ),
+                    label: "expected `?` to occur after `:`".to_owned(),
+                    span: pos.to(pos),
+                    secondary_label: None,
+                    should_be_replaced_with_positional_argument: false,
+                },
+            );
+        }
+    }
+
     fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
         if let Some(end) = self.consume_pos('.') {
             let byte_pos = self.to_span_index(end);
diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs
index 9408f83c32f..5d4df1ac8bd 100644
--- a/library/core/benches/char/methods.rs
+++ b/library/core/benches/char/methods.rs
@@ -1,26 +1,26 @@
-use test::Bencher;
+use test::{black_box, Bencher};
 
 const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
 const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
 
 #[bench]
 fn bench_to_digit_radix_2(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_10(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_16(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_36(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min())
 }
 
 #[bench]
@@ -31,47 +31,59 @@ fn bench_to_digit_radix_var(b: &mut Bencher) {
             .cycle()
             .zip(RADIX.iter().cycle())
             .take(10_000)
-            .map(|(c, radix)| c.to_digit(*radix))
+            .map(|(c, radix)| black_box(c).to_digit(*radix))
             .min()
     })
 }
 
 #[bench]
 fn bench_to_ascii_uppercase(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min())
 }
 
 #[bench]
 fn bench_to_ascii_lowercase(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min())
 }
 
 #[bench]
 fn bench_ascii_mix_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_mix_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_char_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_char_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
 
 #[bench]
 fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs
index 319b9773e49..377c99effd0 100644
--- a/library/core/benches/num/flt2dec/strategy/dragon.rs
+++ b/library/core/benches/num/flt2dec/strategy/dragon.rs
@@ -1,14 +1,14 @@
 use super::super::*;
 use core::num::flt2dec::strategy::dragon::*;
 use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_small_shortest(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -17,7 +17,7 @@ fn bench_big_shortest(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -26,7 +26,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -35,7 +35,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -44,7 +44,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -53,7 +53,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -62,7 +62,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -71,6 +71,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs
index 8e47a046cde..6bea5e55d37 100644
--- a/library/core/benches/num/flt2dec/strategy/grisu.rs
+++ b/library/core/benches/num/flt2dec/strategy/grisu.rs
@@ -1,7 +1,7 @@
 use super::super::*;
 use core::num::flt2dec::strategy::grisu::*;
 use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -15,7 +15,7 @@ fn bench_small_shortest(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -24,7 +24,7 @@ fn bench_big_shortest(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -33,7 +33,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -42,7 +42,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -51,7 +51,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -60,7 +60,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -69,7 +69,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -78,6 +78,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index c8d1ff9aefb..a6d84a3c18a 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -19,18 +19,18 @@ import shutil
 import signal
 import subprocess
 import sys
-from typing import ClassVar, List
+from typing import ClassVar, List, Optional
 
 
 @dataclass
 class TestEnvironment:
     rust_dir: str
     sdk_dir: str
-    target_arch: str
-    package_server_pid: int = None
-    emu_addr: str = None
-    libstd_name: str = None
-    libtest_name: str = None
+    target: str
+    package_server_pid: Optional[int] = None
+    emu_addr: Optional[str] = None
+    libstd_name: Optional[str] = None
+    libtest_name: Optional[str] = None
     verbose: bool = False
 
     @staticmethod
@@ -40,6 +40,15 @@ class TestEnvironment:
             return os.path.abspath(tmp_dir)
         return os.path.join(os.path.dirname(__file__), "tmp~")
 
+    @staticmethod
+    def triple_to_arch(triple):
+        if "x86_64" in triple:
+            return "x64"
+        elif "aarch64" in triple:
+            return "arm64"
+        else:
+            raise Exception(f"Unrecognized target triple {triple}")
+
     @classmethod
     def env_file_path(cls):
         return os.path.join(cls.tmp_dir(), "test_env.json")
@@ -49,7 +58,7 @@ class TestEnvironment:
         return cls(
             os.path.abspath(args.rust),
             os.path.abspath(args.sdk),
-            args.target_arch,
+            args.target,
             verbose=args.verbose,
         )
 
@@ -60,7 +69,7 @@ class TestEnvironment:
             return cls(
                 test_env["rust_dir"],
                 test_env["sdk_dir"],
-                test_env["target_arch"],
+                test_env["target"],
                 libstd_name=test_env["libstd_name"],
                 libtest_name=test_env["libtest_name"],
                 emu_addr=test_env["emu_addr"],
@@ -68,13 +77,6 @@ class TestEnvironment:
                 verbose=test_env["verbose"],
             )
 
-    def image_name(self):
-        if self.target_arch == "x64":
-            return "qemu-x64"
-        if self.target_arch == "arm64":
-            return "qemu-arm64"
-        raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
     def write_to_file(self):
         with open(self.env_file_path(), "w", encoding="utf-8") as f:
             f.write(json.dumps(self.__dict__))
@@ -108,13 +110,6 @@ class TestEnvironment:
     def repo_dir(self):
         return os.path.join(self.tmp_dir(), self.TEST_REPO_NAME)
 
-    def rustlib_dir(self):
-        if self.target_arch == "x64":
-            return "x86_64-unknown-fuchsia"
-        if self.target_arch == "arm64":
-            return "aarch64-unknown-fuchsia"
-        raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
     def libs_dir(self):
         return os.path.join(
             self.rust_dir,
@@ -125,7 +120,7 @@ class TestEnvironment:
         return os.path.join(
             self.libs_dir(),
             "rustlib",
-            self.rustlib_dir(),
+            self.target,
             "lib",
         )
 
@@ -384,7 +379,7 @@ class TestEnvironment:
                 "--emulator-log",
                 self.emulator_log_path(),
                 "--image-name",
-                self.image_name(),
+                "qemu-" + self.triple_to_arch(self.target),
             ],
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
@@ -642,11 +637,11 @@ class TestEnvironment:
                         package_dir=package_dir,
                         package_name=package_name,
                         rust_dir=self.rust_dir,
-                        rustlib_dir=self.rustlib_dir(),
+                        rustlib_dir=self.target,
                         sdk_dir=self.sdk_dir,
                         libstd_name=self.libstd_name,
                         libtest_name=self.libtest_name,
-                        target_arch=self.target_arch,
+                        target_arch=self.triple_to_arch(self.target),
                     )
                 )
                 for shared_lib in shared_libs:
@@ -969,8 +964,8 @@ def main():
         action="store_true",
     )
     start_parser.add_argument(
-        "--target-arch",
-        help="the architecture of the image to test",
+        "--target",
+        help="the target platform to test",
         required=True,
     )
     start_parser.set_defaults(func=start)
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 29e70129a62..0f165b268ba 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -697,7 +697,7 @@ test environment with:
 src/ci/docker/scripts/fuchsia-test-runner.py start
     --rust ${RUST_SRC_PATH}/install
     --sdk ${SDK_PATH}
-    --target-arch {x64,arm64}
+    --target-triple {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}
 ```
 
 Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and
diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs
new file mode 100644
index 00000000000..93c69b05254
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/future-as-arg.rs
@@ -0,0 +1,16 @@
+// edition: 2021
+// run-pass
+
+async fn test(_arg: [u8; 16]) {}
+
+async fn use_future(fut: impl std::future::Future<Output = ()>) {
+    fut.await
+}
+
+fn main() {
+    let actual = std::mem::size_of_val(
+        &use_future(use_future(use_future(use_future(use_future(test([0; 16])))))));
+    // Not using an exact number in case it slightly changes over different commits
+    let expected = 550;
+    assert!(actual > expected, "expected: >{expected}, actual: {actual}");
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs
new file mode 100644
index 00000000000..7e7ff9d8d00
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/large-arg.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// edition: 2021
+// build-pass
+// ignore-pass
+
+pub async fn test() {
+    let _ = a([0u8; 1024]).await;
+}
+
+pub async fn a<T>(t: T) -> T {
+    b(t).await
+}
+async fn b<T>(t: T) -> T {
+    c(t).await
+}
+async fn c<T>(t: T) -> T {
+    t
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout
new file mode 100644
index 00000000000..c206d793170
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/large-arg.stdout
@@ -0,0 +1,60 @@
+print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 3075 bytes
+print-type-size         local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 3074 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.__awaitee`: 2050 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 3075 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 3075 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 3075 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 2049 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.__awaitee`: 1025 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 2050 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 2050 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 2050 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1025 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1025 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1025 bytes
+print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Ready`: 1024 bytes
+print-type-size         field `.0`: 1024 bytes
+print-type-size     variant `Pending`: 0 bytes
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed
new file mode 100644
index 00000000000..1a08470064c
--- /dev/null
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
+fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
+    None.into_iter()
+        .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
+        //~^ ERROR captured variable cannot escape `FnMut` closure body
+        //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+fn foo2(s: &str) -> impl Sized + '_ {
+    move |()| s.chars().map(move |c| format!("{}{}", c, s))
+    //~^ ERROR lifetime may not live long enough
+    //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+pub struct X;
+pub fn foo3<'a>(
+    bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+    Some(()).iter().flat_map(move |()| {
+        Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape
+        //~^ HELP consider adding 'move' keyword before the nested closure
+    })
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
index 95847d8d301..b93292e3589 100644
--- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
 fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
     None.into_iter()
         .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
@@ -11,4 +13,14 @@ fn foo2(s: &str) -> impl Sized + '_ {
     //~| HELP consider adding 'move' keyword before the nested closure
 }
 
+pub struct X;
+pub fn foo3<'a>(
+    bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+    Some(()).iter().flat_map(move |()| {
+        Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape
+        //~^ HELP consider adding 'move' keyword before the nested closure
+    })
+}
+
 fn main() {}
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
index 2eae614a2f5..776c338deac 100644
--- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
@@ -1,5 +1,5 @@
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29
    |
 LL | fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
    |         - variable defined here
@@ -7,7 +7,7 @@ LL |     None.into_iter()
 LL |         .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
    |                           - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                           | |
-   |                           | returns a reference to a captured variable which escapes the closure body
+   |                           | returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |                           | variable captured here
    |                           inferred to be a `FnMut` closure
    |
@@ -19,12 +19,12 @@ LL |         .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
    |                                           ++++
 
 error: lifetime may not live long enough
-  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15
    |
 LL |     move |()| s.chars().map(|c| format!("{}{}", c, s))
    |     --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
    |     |       |
-   |     |       return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2`
+   |     |       return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2`
    |     lifetime `'1` represents this closure's body
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure
@@ -33,5 +33,26 @@ help: consider adding 'move' keyword before the nested closure
 LL |     move |()| s.chars().map(move |c| format!("{}{}", c, s))
    |                             ++++
 
-error: aborting due to 2 previous errors
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9
+   |
+LL |     bar: &'a X,
+   |     --- variable defined here
+LL | ) -> impl Iterator<Item = ()> + 'a {
+LL |     Some(()).iter().flat_map(move |()| {
+   |                                      - inferred to be a `FnMut` closure
+LL |         Some(()).iter().map(|()| { bar; })
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^
+   |         |                          |
+   |         |                          variable captured here
+   |         returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+help: consider adding 'move' keyword before the nested closure
+   |
+LL |         Some(()).iter().map(move |()| { bar; })
+   |                             ++++
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs
new file mode 100644
index 00000000000..0bad5402396
--- /dev/null
+++ b/tests/ui/fmt/format-string-wrong-order.rs
@@ -0,0 +1,15 @@
+fn main() {
+    let bar = 3;
+    format!("{?:}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{?:bar}");
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{?:?}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{??}", bar);
+    //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+    format!("{?;bar}");
+    //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+    format!("{?:#?}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+}
diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr
new file mode 100644
index 00000000000..461af354a4e
--- /dev/null
+++ b/tests/ui/fmt/format-string-wrong-order.stderr
@@ -0,0 +1,54 @@
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:3:15
+   |
+LL |     format!("{?:}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:5:15
+   |
+LL |     format!("{?:bar}");
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `bar:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:7:15
+   |
+LL |     format!("{?:?}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected `'}'`, found `'?'`
+  --> $DIR/format-string-wrong-order.rs:9:15
+   |
+LL |     format!("{??}", bar);
+   |              -^ expected `}` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'?'`
+  --> $DIR/format-string-wrong-order.rs:11:15
+   |
+LL |     format!("{?;bar}");
+   |              -^ expected `}` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:13:15
+   |
+LL |     format!("{?:#?}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
index 0b7b67496d6..e1ea38f2795 100644
--- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
+++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
@@ -68,7 +68,6 @@ fn main() {
         Foo:Bar::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
-        //~| ERROR: failed to resolve: `Bar` is a variant, not a module
     }
     match myfoo {
         Foo::Bar => {}
diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
index 2050a16beb3..63b072ac4cd 100644
--- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
+++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
@@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:17:12
    |
 LL |         Foo:Bar => {}
-   |            ^
+   |            ^--- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar => {}
+   |            ~~
 
 error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:23:17
    |
 LL |         qux::Foo:Bar => {}
-   |                 ^
+   |                 ^--- specifying the type of a pattern isn't supported
    |                 |
    |                 expected one of 8 possible tokens
-   |                 help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Bar => {}
+   |                 ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:29:12
    |
 LL |         qux:Foo::Baz => {}
-   |            ^
+   |            ^-------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Baz => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:35:12
    |
 LL |         qux: Foo::Baz if true => {}
-   |            ^
+   |            ^ -------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Baz if true => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:40:15
    |
 LL |     if let Foo:Bar = f() {
-   |               ^
+   |               ^--- specifying the type of a pattern isn't supported
    |               |
    |               expected one of `@` or `|`
-   |               help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |     if let Foo::Bar = f() {
+   |               ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:48:16
    |
 LL |         ref qux: Foo::Baz => {}
-   |                ^
+   |                ^ -------- specifying the type of a pattern isn't supported
    |                |
    |                expected one of `@` or `|`
-   |                help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         ref qux::Foo::Baz => {}
+   |                ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:57:16
    |
 LL |         mut qux: Foo::Baz => {}
-   |                ^
+   |                ^ -------- specifying the type of a pattern isn't supported
    |                |
    |                expected one of `@` or `|`
-   |                help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         mut qux::Foo::Baz => {}
+   |                ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:68:12
    |
 LL |         Foo:Bar::Baz => {}
-   |            ^
+   |            ^-------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar::Baz => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:75:12
+  --> $DIR/issue-87086-colon-path-sep.rs:74:12
    |
 LL |         Foo:Bar => {}
-   |            ^
+   |            ^--- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
-
-error[E0433]: failed to resolve: `Bar` is a variant, not a module
-  --> $DIR/issue-87086-colon-path-sep.rs:68:13
    |
-LL |         Foo:Bar::Baz => {}
-   |             ^^^ `Bar` is a variant, not a module
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar => {}
+   |            ~~
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
-For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs
new file mode 100644
index 00000000000..fec168afba1
--- /dev/null
+++ b/tests/ui/parser/type-ascription-in-pattern.rs
@@ -0,0 +1,16 @@
+fn foo(x: bool) -> i32 {
+    match x {
+        x: i32 => x, //~ ERROR expected
+        //~^ ERROR mismatched types
+        true => 42.,
+        false => 0.333,
+    }
+}
+
+fn main() {
+    match foo(true) {
+        42: i32 => (), //~ ERROR expected
+        _: f64 => (), //~ ERROR expected
+        x: i32 => (), //~ ERROR expected
+    }
+}
diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr
new file mode 100644
index 00000000000..09190754993
--- /dev/null
+++ b/tests/ui/parser/type-ascription-in-pattern.stderr
@@ -0,0 +1,54 @@
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:3:10
+   |
+LL |         x: i32 => x,
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected one of `@` or `|`
+   |
+help: maybe write a path separator here
+   |
+LL |         x::i32 => x,
+   |          ~~
+
+error: expected one of `...`, `..=`, `..`, or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:12:11
+   |
+LL |         42: i32 => (),
+   |           ^ --- specifying the type of a pattern isn't supported
+   |           |
+   |           expected one of `...`, `..=`, `..`, or `|`
+
+error: expected `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:13:10
+   |
+LL |         _: f64 => (),
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected `|`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:14:10
+   |
+LL |         x: i32 => (),
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected one of `@` or `|`
+   |
+help: maybe write a path separator here
+   |
+LL |         x::i32 => (),
+   |          ~~
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-in-pattern.rs:3:19
+   |
+LL | fn foo(x: bool) -> i32 {
+   |                    --- expected `i32` because of return type
+LL |     match x {
+LL |         x: i32 => x,
+   |                   ^ expected `i32`, found `bool`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.