about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-22 12:29:42 +0000
committerbors <bors@rust-lang.org>2024-03-22 12:29:42 +0000
commit1447f9d38ca388ca178a544534b3cff72945fa1e (patch)
tree51b4cffdfe26ba21cda4793ce8dbe20d5f06c965
parenteff958c59e8c07ba0515e164b825c9001b242294 (diff)
parenta5de4fb2a585d0d69f62abd1f1765fef430786d9 (diff)
downloadrust-1447f9d38ca388ca178a544534b3cff72945fa1e.tar.gz
rust-1447f9d38ca388ca178a544534b3cff72945fa1e.zip
Auto merge of #122869 - matthiaskrgr:rollup-0navj4l, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #121619 (Experimental feature postfix match)
 - #122370 (Gracefully handle `AnonConst` in `diagnostic_hir_wf_check()`)
 - #122537 (interpret/allocation: fix aliasing issue in interpreter and refactor getters a bit)
 - #122542 (coverage: Clean up marker statements that aren't needed later)
 - #122800 (Add `NonNull::<[T]>::is_empty`.)
 - #122820 (Stop using `<DefId as Ord>` in various diagnostic situations)
 - #122847 (Suggest `RUST_MIN_STACK` workaround on overflow)
 - #122855 (Fix Itanium mangling usizes)
 - #122863 (add more ice tests )

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/ast.rs11
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs7
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs17
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs13
-rw-r--r--compiler/rustc_driver_impl/src/signal_handler.rs6
-rw-r--r--compiler/rustc_expand/src/build.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs10
-rw-r--r--compiler/rustc_interface/src/util.rs33
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs2
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs42
-rw-r--r--compiler/rustc_middle/src/mir/query.rs12
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs67
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs1
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs13
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs29
-rw-r--r--compiler/rustc_passes/src/check_const.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs4
-rw-r--r--library/core/src/ptr/non_null.rs19
-rw-r--r--src/doc/unstable-book/src/language-features/postfix-match.md22
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/rustfmt/src/expr.rs8
-rw-r--r--src/tools/rustfmt/src/matches.rs33
-rw-r--r--src/tools/rustfmt/tests/source/postfix-match/pf-match.rs20
-rw-r--r--src/tools/rustfmt/tests/target/postfix-match/pf-match.rs20
-rw-r--r--tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff56
-rw-r--r--tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff53
-rw-r--r--tests/mir-opt/instrument_coverage_cleanup.rs22
-rw-r--r--tests/pretty/postfix-match.rs21
-rw-r--r--tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs13
-rw-r--r--tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr19
-rw-r--r--tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs18
-rw-r--r--tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr46
-rw-r--r--tests/ui/const-generics/transmute-fail.rs75
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr91
-rw-r--r--tests/ui/const-generics/transmute.rs69
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs20
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr29
-rw-r--r--tests/ui/feature-gates/feature-gate-postfix_match.rs17
-rw-r--r--tests/ui/feature-gates/feature-gate-postfix_match.stderr23
-rw-r--r--tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs30
-rw-r--r--tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr31
-rw-r--r--tests/ui/match/postfix-match/pf-match-chain.rs16
-rw-r--r--tests/ui/match/postfix-match/pf-match-exhaustiveness.rs7
-rw-r--r--tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr21
-rw-r--r--tests/ui/match/postfix-match/pf-match-types.rs15
-rw-r--r--tests/ui/match/postfix-match/pf-match-types.stderr21
-rw-r--r--tests/ui/match/postfix-match/postfix-match.rs62
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr19
-rw-r--r--tests/ui/nll/user-annotations/adt-nullary-enums.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs52
-rw-r--r--tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr23
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs12
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr60
73 files changed, 1200 insertions, 248 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e97d29d57ee..6505aa52c4e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4236,6 +4236,7 @@ name = "rustc_middle"
 version = "0.0.0"
 dependencies = [
  "bitflags 2.4.2",
+ "derivative",
  "either",
  "field-offset",
  "gsgdt",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ea73f88dacf..915cb386075 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1437,7 +1437,7 @@ pub enum ExprKind {
     /// `'label: loop { block }`
     Loop(P<Block>, Option<Label>, Span),
     /// A `match` block.
-    Match(P<Expr>, ThinVec<Arm>),
+    Match(P<Expr>, ThinVec<Arm>, MatchKind),
     /// A closure (e.g., `move |a, b, c| a + b + c`).
     Closure(Box<Closure>),
     /// A block (`'label: { ... }`).
@@ -1762,6 +1762,15 @@ pub enum StrStyle {
     Raw(u8),
 }
 
+/// The kind of match expression
+#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
+pub enum MatchKind {
+    /// match expr { ... }
+    Prefix,
+    /// expr.match { ... }
+    Postfix,
+}
+
 /// A literal in a meta item.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MetaItemLit {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 5b22ae5f54b..7337b969242 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1425,7 +1425,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
             visit_opt(label, |label| vis.visit_label(label));
             vis.visit_span(span);
         }
-        ExprKind::Match(expr, arms) => {
+        ExprKind::Match(expr, arms, _kind) => {
             vis.visit_expr(expr);
             arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
         }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index dedf67e6a94..18986fb7504 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -923,7 +923,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
             visit_opt!(visitor, visit_label, opt_label);
             try_visit!(visitor.visit_block(block));
         }
-        ExprKind::Match(subexpression, arms) => {
+        ExprKind::Match(subexpression, arms, _kind) => {
             try_visit!(visitor.visit_expr(subexpression));
             walk_list!(visitor, visit_arm, arms);
         }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index d802dbbcb9e..389cf4e3132 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -181,10 +181,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     )
                 }),
                 ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
-                ExprKind::Match(expr, arms) => hir::ExprKind::Match(
+                ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
                     self.lower_expr(expr),
                     self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
-                    hir::MatchSource::Normal,
+                    match kind {
+                        MatchKind::Prefix => hir::MatchSource::Normal,
+                        MatchKind::Postfix => hir::MatchSource::Postfix,
+                    },
                 ),
                 ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
                 ExprKind::Closure(box Closure {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 81065fa3dce..bb83f4c0f0e 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -564,6 +564,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(generic_const_items, "generic const items are experimental");
     gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
     gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
+    gate_all!(postfix_match, "postfix match is experimental");
 
     if !visitor.features.never_patterns {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 433ef03b6e5..8bd8b6ac144 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -1,6 +1,6 @@
 use crate::pp::Breaks::Inconsistent;
 use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
-use ast::ForLoopKind;
+use ast::{ForLoopKind, MatchKind};
 use itertools::{Itertools, Position};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
@@ -589,12 +589,22 @@ impl<'a> State<'a> {
                 self.word_nbsp("loop");
                 self.print_block_with_attrs(blk, attrs);
             }
-            ast::ExprKind::Match(expr, arms) => {
+            ast::ExprKind::Match(expr, arms, match_kind) => {
                 self.cbox(0);
                 self.ibox(0);
-                self.word_nbsp("match");
-                self.print_expr_as_cond(expr);
-                self.space();
+
+                match match_kind {
+                    MatchKind::Prefix => {
+                        self.word_nbsp("match");
+                        self.print_expr_as_cond(expr);
+                        self.space();
+                    }
+                    MatchKind::Postfix => {
+                        self.print_expr_as_cond(expr);
+                        self.word_nbsp(".match");
+                    }
+                }
+
                 self.bopen();
                 self.print_inner_attributes_no_trailing_hardbreak(attrs);
                 for arm in arms {
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 56c56b2704b..92efeab08eb 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -245,7 +245,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
             ExprKind::Let(_, local_expr, _, _) => {
                 self.manage_cond_expr(local_expr);
             }
-            ExprKind::Match(local_expr, _) => {
+            ExprKind::Match(local_expr, ..) => {
                 self.manage_cond_expr(local_expr);
             }
             ExprKind::MethodCall(call) => {
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 6eccd67f8af..60dbdf8b544 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -132,7 +132,7 @@ fn cs_partial_cmp(
                 // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354
 
                 if !tag_then_data
-                    && let ExprKind::Match(_, arms) = &mut expr1.kind
+                    && let ExprKind::Match(_, arms, _) = &mut expr1.kind
                     && let Some(last) = arms.last_mut()
                     && let PatKind::Wild = last.pat.kind
                 {
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index b11a1b6cda1..108c1078eaa 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use ast::EnumDef;
-use rustc_ast::{self as ast, MetaItem};
+use rustc_ast::{self as ast, EnumDef, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 133084b7c12..54f4bc06340 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -85,14 +85,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
 
         let bx = self;
 
-        match coverage.kind {
-            // Marker statements have no effect during codegen,
-            // so return early and don't create `func_coverage`.
-            CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => return,
-            // Match exhaustively to ensure that newly-added kinds are classified correctly.
-            CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } => {}
-        }
-
         let Some(function_coverage_info) =
             bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref()
         else {
@@ -109,7 +101,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
         let Coverage { kind } = coverage;
         match *kind {
             CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!(
-                "unexpected marker statement {kind:?} should have caused an early return"
+                "marker statement {kind:?} should have been removed by CleanupPostBorrowck"
             ),
             CoverageKind::CounterIncrement { id } => {
                 func_coverage.mark_counter_id_seen(id);
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index a6ca4b2e0de..9b1d9cf932b 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1159,11 +1159,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
 
         // Side-step AllocRef and directly access the underlying bytes more efficiently.
-        // (We are staying inside the bounds here so all is good.)
+        // (We are staying inside the bounds here and all bytes do get overwritten so all is good.)
         let alloc_id = alloc_ref.alloc_id;
         let bytes = alloc_ref
             .alloc
-            .get_bytes_mut(&alloc_ref.tcx, alloc_ref.range)
+            .get_bytes_unchecked_for_overwrite(&alloc_ref.tcx, alloc_ref.range)
             .map_err(move |e| e.to_interp_error(alloc_id))?;
         // `zip` would stop when the first iterator ends; we want to definitely
         // cover all of `bytes`.
@@ -1184,6 +1184,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.mem_copy_repeatedly(src, dest, size, 1, nonoverlapping)
     }
 
+    /// Performs `num_copies` many copies of `size` many bytes from `src` to `dest + i*size` (where
+    /// `i` is the index of the copy).
+    ///
+    /// Either `nonoverlapping` must be true or `num_copies` must be 1; doing repeated copies that
+    /// may overlap is not supported.
     pub fn mem_copy_repeatedly(
         &mut self,
         src: Pointer<Option<M::Provenance>>,
@@ -1245,8 +1250,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             (dest_alloc_id, dest_prov),
             dest_range,
         )?;
+        // Yes we do overwrite all bytes in `dest_bytes`.
         let dest_bytes = dest_alloc
-            .get_bytes_mut_ptr(&tcx, dest_range)
+            .get_bytes_unchecked_for_overwrite_ptr(&tcx, dest_range)
             .map_err(|e| e.to_interp_error(dest_alloc_id))?
             .as_mut_ptr();
 
@@ -1280,6 +1286,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
             }
+            if num_copies > 1 {
+                assert!(nonoverlapping, "multi-copy only supported in non-overlapping mode");
+            }
 
             let size_in_bytes = size.bytes_usize();
             // For particularly large arrays (where this is perf-sensitive) it's common that
@@ -1292,6 +1301,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             } else if src_alloc_id == dest_alloc_id {
                 let mut dest_ptr = dest_bytes;
                 for _ in 0..num_copies {
+                    // Here we rely on `src` and `dest` being non-overlapping if there is more than
+                    // one copy.
                     ptr::copy(src_bytes, dest_ptr, size_in_bytes);
                     dest_ptr = dest_ptr.add(size_in_bytes);
                 }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 68270dab284..4bc49f90607 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_infer::traits::Reveal;
+use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
@@ -345,11 +346,21 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     self.fail(location, format!("explicit `{kind:?}` is forbidden"));
                 }
             }
+            StatementKind::Coverage(coverage) => {
+                let kind = &coverage.kind;
+                if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup)
+                    && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind
+                {
+                    self.fail(
+                        location,
+                        format!("{kind:?} should have been removed after analysis"),
+                    );
+                }
+            }
             StatementKind::Assign(..)
             | StatementKind::StorageLive(_)
             | StatementKind::StorageDead(_)
             | StatementKind::Intrinsic(_)
-            | StatementKind::Coverage(_)
             | StatementKind::ConstEvalCounter
             | StatementKind::PlaceMention(..)
             | StatementKind::Nop => {}
diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index deca1082221..441219eec90 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -1,6 +1,7 @@
 //! Signal handler for rustc
 //! Primarily used to extract a backtrace from stack overflow
 
+use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
 use std::alloc::{alloc, Layout};
 use std::{fmt, mem, ptr};
 
@@ -100,7 +101,10 @@ extern "C" fn print_stack_trace(_: libc::c_int) {
         written += 1;
     }
     raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
-    written += 1;
+    // get the current stack size WITHOUT blocking and double it
+    let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
+    raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
+    written += 2;
     if written > 24 {
         // We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
         raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index e71047f94fa..30559871b4e 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,6 +1,6 @@
 use crate::base::ExtCtxt;
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
+use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp};
 use rustc_ast::{attr, token, util::literal};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -524,7 +524,7 @@ impl<'a> ExtCtxt<'a> {
     }
 
     pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
-        self.expr(span, ast::ExprKind::Match(arg, arms))
+        self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
     }
 
     pub fn expr_if(
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 1820e172ea5..8d72f4924d6 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -559,6 +559,8 @@ declare_features! (
     (unstable, offset_of_nested, "1.77.0", Some(120140)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
+    /// Allows postfix match `expr.match { ... }`
+    (unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 87e21785c8c..162ec16fabc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2015,6 +2015,8 @@ pub enum LocalSource {
 pub enum MatchSource {
     /// A `match _ { .. }`.
     Normal,
+    /// A `expr.match { .. }`.
+    Postfix,
     /// A desugared `for _ in _ { .. }` loop.
     ForLoopDesugar,
     /// A desugared `?` operator.
@@ -2031,6 +2033,7 @@ impl MatchSource {
         use MatchSource::*;
         match self {
             Normal => "match",
+            Postfix => ".match",
             ForLoopDesugar => "for",
             TryDesugar(_) => "?",
             AwaitDesugar => ".await",
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index f932acc5e83..7014b23ff07 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -163,6 +163,16 @@ fn diagnostic_hir_wf_check<'tcx>(
                 kind: hir::GenericParamKind::Type { default: Some(ty), .. },
                 ..
             }) => vec![*ty],
+            hir::Node::AnonConst(_)
+                if let Some(const_param_id) =
+                    tcx.hir().opt_const_param_default_param_def_id(hir_id)
+                    && let hir::Node::GenericParam(hir::GenericParam {
+                        kind: hir::GenericParamKind::Const { ty, .. },
+                        ..
+                    }) = tcx.hir_node_by_def_id(const_param_id) =>
+            {
+                vec![*ty]
+            }
             ref node => bug!("Unexpected node {:?}", node),
         },
         WellFormedLoc::Param { function: _, param_idx } => {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 7d48f90db36..d09f8d7d7cf 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -48,12 +48,20 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy
     }
 }
 
-const STACK_SIZE: usize = 8 * 1024 * 1024;
-
-fn get_stack_size() -> Option<usize> {
-    // FIXME: Hacks on hacks. If the env is trying to override the stack size
-    // then *don't* set it explicitly.
-    env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
+pub static STACK_SIZE: OnceLock<usize> = OnceLock::new();
+pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024;
+
+fn init_stack_size() -> usize {
+    // Obey the environment setting or default
+    *STACK_SIZE.get_or_init(|| {
+        env::var_os("RUST_MIN_STACK")
+            .map(|os_str| os_str.to_string_lossy().into_owned())
+            // ignore if it is set to nothing
+            .filter(|s| s.trim() != "")
+            .map(|s| s.trim().parse::<usize>().unwrap())
+            // otherwise pick a consistent default
+            .unwrap_or(DEFAULT_STACK_SIZE)
+    })
 }
 
 pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
@@ -66,10 +74,7 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
     // the parallel compiler, in particular to ensure there is no accidental
     // sharing of data between the main thread and the compilation thread
     // (which might cause problems for the parallel compiler).
-    let mut builder = thread::Builder::new().name("rustc".to_string());
-    if let Some(size) = get_stack_size() {
-        builder = builder.stack_size(size);
-    }
+    let builder = thread::Builder::new().name("rustc".to_string()).stack_size(init_stack_size());
 
     // We build the session globals and run `f` on the spawned thread, because
     // `SessionGlobals` does not impl `Send` in the non-parallel compiler.
@@ -120,7 +125,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
         });
     }
 
-    let mut builder = rayon::ThreadPoolBuilder::new()
+    let builder = rayon::ThreadPoolBuilder::new()
         .thread_name(|_| "rustc".to_string())
         .acquire_thread_handler(jobserver::acquire_thread)
         .release_thread_handler(jobserver::release_thread)
@@ -144,10 +149,8 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
                     on_panic.disable();
                 })
                 .unwrap();
-        });
-    if let Some(size) = get_stack_size() {
-        builder = builder.stack_size(size);
-    }
+        })
+        .stack_size(init_stack_size());
 
     // We create the session globals on the main thread, then create the thread
     // pool. Upon creation, each worker thread created gets a copy of the
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index df77181d6f7..0b757f95a99 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -865,7 +865,7 @@ trait UnusedDelimLint {
                 (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
             }
 
-            Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
+            Match(ref head, ..) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
                 let left = e.span.lo() + rustc_span::BytePos(5);
                 (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
             }
@@ -1133,7 +1133,7 @@ impl EarlyLintPass for UnusedParens {
                 }
                 return;
             }
-            ExprKind::Match(ref _expr, ref arm) => {
+            ExprKind::Match(ref _expr, ref arm, _) => {
                 for a in arm {
                     if let Some(body) = &a.body {
                         self.check_unused_delims_expr(
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 96c58ef411b..9e8ee92b5d9 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
+derivative = "2.2.0"
 either = "1.5.0"
 field-offset = "0.3.5"
 gsgdt = "0.1.2"
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 214297b9869..02185cbeacf 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -456,7 +456,7 @@ impl<'tcx> Const<'tcx> {
 }
 
 /// An unevaluated (potentially generic) constant used in MIR.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: DefId,
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 645a417c322..588aa1f40d7 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -88,14 +88,13 @@ pub enum CoverageKind {
     /// Marks a span that might otherwise not be represented in MIR, so that
     /// coverage instrumentation can associate it with its enclosing block/BCB.
     ///
-    /// Only used by the `InstrumentCoverage` pass, and has no effect during
-    /// codegen.
+    /// Should be erased before codegen (at some point after `InstrumentCoverage`).
     SpanMarker,
 
     /// Marks its enclosing basic block with an ID that can be referred to by
     /// side data in [`BranchInfo`].
     ///
-    /// Has no effect during codegen.
+    /// Should be erased before codegen (at some point after `InstrumentCoverage`).
     BlockMarker { id: BlockMarkerId },
 
     /// Marks the point in MIR control flow represented by a coverage counter.
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 4047891d769..00faa211853 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -37,9 +37,16 @@ pub trait AllocBytes:
     /// Create a zeroed `AllocBytes` of the specified size and alignment.
     /// Returns `None` if we ran out of memory on the host.
     fn zeroed(size: Size, _align: Align) -> Option<Self>;
+
+    /// Gives direct access to the raw underlying storage.
+    ///
+    /// Crucially this pointer is compatible with:
+    /// - other pointers retunred by this method, and
+    /// - references returned from `deref()`, as long as there was no write.
+    fn as_mut_ptr(&mut self) -> *mut u8;
 }
 
-// Default `bytes` for `Allocation` is a `Box<[u8]>`.
+/// Default `bytes` for `Allocation` is a `Box<u8>`.
 impl AllocBytes for Box<[u8]> {
     fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
         Box::<[u8]>::from(slice.into())
@@ -51,6 +58,11 @@ impl AllocBytes for Box<[u8]> {
         let bytes = unsafe { bytes.assume_init() };
         Some(bytes)
     }
+
+    fn as_mut_ptr(&mut self) -> *mut u8 {
+        // Carefully avoiding any intermediate references.
+        ptr::addr_of_mut!(**self).cast()
+    }
 }
 
 /// This type represents an Allocation in the Miri/CTFE core engine.
@@ -399,10 +411,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
 
 /// Byte accessors.
 impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
-    pub fn base_addr(&self) -> *const u8 {
-        self.bytes.as_ptr()
-    }
-
     /// This is the entirely abstraction-violating way to just grab the raw bytes without
     /// caring about provenance or initialization.
     ///
@@ -452,13 +460,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         Ok(self.get_bytes_unchecked(range))
     }
 
-    /// Just calling this already marks everything as defined and removes provenance,
-    /// so be sure to actually put data there!
+    /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes.
+    /// Just calling this already marks everything as defined and removes provenance, so be sure to
+    /// actually overwrite all the data there!
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
     /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods
     /// on `InterpCx` instead.
-    pub fn get_bytes_mut(
+    pub fn get_bytes_unchecked_for_overwrite(
         &mut self,
         cx: &impl HasDataLayout,
         range: AllocRange,
@@ -469,8 +478,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()])
     }
 
-    /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
-    pub fn get_bytes_mut_ptr(
+    /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases
+    /// into this memory.
+    pub fn get_bytes_unchecked_for_overwrite_ptr(
         &mut self,
         cx: &impl HasDataLayout,
         range: AllocRange,
@@ -479,10 +489,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         self.provenance.clear(range, cx)?;
 
         assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check
+        // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
         let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize());
         let len = range.end().bytes_usize() - range.start.bytes_usize();
         Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len))
     }
+
+    /// This gives direct mutable access to the entire buffer, just exposing their internal state
+    /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if
+    /// `OFFSET_IS_ADDR` is true.
+    pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 {
+        assert!(Prov::OFFSET_IS_ADDR);
+        self.bytes.as_mut_ptr()
+    }
 }
 
 /// Reading and writing.
@@ -589,7 +608,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         };
 
         let endian = cx.data_layout().endian;
-        let dst = self.get_bytes_mut(cx, range)?;
+        // Yes we do overwrite all the bytes in `dst`.
+        let dst = self.get_bytes_unchecked_for_overwrite(cx, range)?;
         write_target_uint(endian, dst, bytes).unwrap();
 
         // See if we have to also store some provenance.
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 8bd872c1b19..731e050ca9b 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -284,8 +284,15 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
 /// order of the category, thereby influencing diagnostic output.
 ///
 /// See also `rustc_const_eval::borrow_check::constraints`.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
+#[derive(derivative::Derivative)]
+#[derivative(
+    PartialOrd,
+    Ord,
+    PartialOrd = "feature_allow_slow_enum",
+    Ord = "feature_allow_slow_enum"
+)]
 pub enum ConstraintCategory<'tcx> {
     Return(ReturnConstraint),
     Yield,
@@ -295,6 +302,7 @@ pub enum ConstraintCategory<'tcx> {
     Cast {
         /// Whether this is an unsizing cast and if yes, this contains the target type.
         /// Region variables are erased to ReErased.
+        #[derivative(PartialOrd = "ignore", Ord = "ignore")]
         unsize_to: Option<Ty<'tcx>>,
     },
 
@@ -304,7 +312,7 @@ pub enum ConstraintCategory<'tcx> {
     ClosureBounds,
 
     /// Contains the function type if available.
-    CallArgument(Option<Ty<'tcx>>),
+    CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option<Ty<'tcx>>),
     CopyBound,
     SizedBound,
     Assignment,
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 0ab797134c0..752f5845afb 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -124,6 +124,7 @@ pub enum AnalysisPhase {
     /// * [`TerminatorKind::FalseEdge`]
     /// * [`StatementKind::FakeRead`]
     /// * [`StatementKind::AscribeUserType`]
+    /// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`]
     /// * [`Rvalue::Ref`] with `BorrowKind::Fake`
     ///
     /// Furthermore, `Deref` projections must be the first projection within any place (if they
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 11fd73c9094..595ef71cc32 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_error_messages::DiagMessage;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
@@ -356,21 +356,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
                                 .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
                             return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
                         }
-                        let len = tcx.expand_abstract_consts(len);
-                        let prev = ty::Const::from_target_usize(tcx, s.bytes());
-                        let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
-                            return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
-                        };
-                        Ok(SizeSkeleton::Generic(gen_size))
+                        Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
                     }
                     SizeSkeleton::Pointer { .. } => Err(err),
-                    SizeSkeleton::Generic(g) => {
-                        let len = tcx.expand_abstract_consts(len);
-                        let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
-                            return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
-                        };
-                        Ok(SizeSkeleton::Generic(gen_size))
-                    }
+                    SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
                 }
             }
 
@@ -468,56 +457,6 @@ impl<'tcx> SizeSkeleton<'tcx> {
     }
 }
 
-/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
-/// to ensure that they have a canonical order and can be compared directly we combine all
-/// constants, and sort the other terms. This allows comparison of expressions of sizes,
-/// allowing for things like transmuting between types that depend on generic consts.
-/// This returns `None` if multiplication of constants overflows.
-fn mul_sorted_consts<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    a: ty::Const<'tcx>,
-    b: ty::Const<'tcx>,
-) -> Option<ty::Const<'tcx>> {
-    use crate::mir::BinOp::Mul;
-
-    let mut work = vec![a, b];
-    let mut done = vec![];
-    while let Some(n) = work.pop() {
-        if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() {
-            work.push(l);
-            work.push(r)
-        } else {
-            done.push(n);
-        }
-    }
-    let mut k = 1;
-    let mut overflow = false;
-    done.retain(|c| {
-        let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
-            return true;
-        };
-        let Some(next) = c.checked_mul(k) else {
-            overflow = true;
-            return false;
-        };
-        k = next;
-        false
-    });
-    if overflow {
-        return None;
-    }
-    if k != 1 {
-        done.push(ty::Const::from_target_usize(tcx, k));
-    } else if k == 0 {
-        return Some(ty::Const::from_target_usize(tcx, 0));
-    }
-    done.sort_unstable();
-
-    // create a single tree from the buffer
-    done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty()))
-}
-
 pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx(&self) -> TyCtxt<'tcx>;
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index cfa853417ca..434ed16d5c6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -481,6 +481,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
             // when the iterator is an uninhabited type. unreachable_code will trigger instead.
             hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {}
             hir::MatchSource::ForLoopDesugar
+            | hir::MatchSource::Postfix
             | hir::MatchSource::Normal
             | hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report),
             // Unreachable patterns in try and await expressions occur when one of
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 5b4bc4fa134..aaf2035fc21 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -5,15 +5,20 @@
 //!   - [`AscribeUserType`]
 //!   - [`FakeRead`]
 //!   - [`Assign`] statements with a [`Fake`] borrow
+//!   - [`Coverage`] statements of kind [`BlockMarker`] or [`SpanMarker`]
 //!
 //! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType
 //! [`Assign`]: rustc_middle::mir::StatementKind::Assign
 //! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead
 //! [`Nop`]: rustc_middle::mir::StatementKind::Nop
 //! [`Fake`]: rustc_middle::mir::BorrowKind::Fake
+//! [`Coverage`]: rustc_middle::mir::StatementKind::Coverage
+//! [`BlockMarker`]: rustc_middle::mir::coverage::CoverageKind::BlockMarker
+//! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker
 
 use crate::MirPass;
-use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind};
+use rustc_middle::mir::coverage::CoverageKind;
+use rustc_middle::mir::{Body, BorrowKind, Coverage, Rvalue, StatementKind, TerminatorKind};
 use rustc_middle::ty::TyCtxt;
 
 pub struct CleanupPostBorrowck;
@@ -25,6 +30,12 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
                 match statement.kind {
                     StatementKind::AscribeUserType(..)
                     | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _)))
+                    | StatementKind::Coverage(box Coverage {
+                        // These kinds of coverage statements are markers inserted during
+                        // MIR building, and are not needed after InstrumentCoverage.
+                        kind: CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. },
+                        ..
+                    })
                     | StatementKind::FakeRead(..) => statement.make_nop(),
                     _ => (),
                 }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index d175d1c04c8..fe17eba0d7b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -11,7 +11,7 @@ use crate::errors;
 use crate::maybe_recover_from_interpolated_ty_qpath;
 use ast::mut_visit::{noop_visit_expr, MutVisitor};
 use ast::token::IdentIsRaw;
-use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment};
+use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment};
 use core::mem;
 use core::ops::ControlFlow;
 use rustc_ast::ptr::P;
@@ -1379,6 +1379,13 @@ impl<'a> Parser<'a> {
             return Ok(self.mk_await_expr(self_arg, lo));
         }
 
+        // Post-fix match
+        if self.eat_keyword(kw::Match) {
+            let match_span = self.prev_token.span;
+            self.psess.gated_spans.gate(sym::postfix_match, match_span);
+            return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
+        }
+
         let fn_span_lo = self.token.span;
         let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
         self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
@@ -2894,8 +2901,20 @@ impl<'a> Parser<'a> {
     /// Parses a `match ... { ... }` expression (`match` token already eaten).
     fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
         let match_span = self.prev_token.span;
-        let lo = self.prev_token.span;
         let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
+
+        self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix)
+    }
+
+    /// Parses the block of a `match expr { ... }` or a `expr.match { ... }`
+    /// expression. This is after the match token and scrutinee are eaten
+    fn parse_match_block(
+        &mut self,
+        lo: Span,
+        match_span: Span,
+        scrutinee: P<Expr>,
+        match_kind: MatchKind,
+    ) -> PResult<'a, P<Expr>> {
         if let Err(mut e) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
             if self.token == token::Semi {
                 e.span_suggestion_short(
@@ -2938,7 +2957,7 @@ impl<'a> Parser<'a> {
                     });
                     return Ok(self.mk_expr_with_attrs(
                         span,
-                        ExprKind::Match(scrutinee, arms),
+                        ExprKind::Match(scrutinee, arms, match_kind),
                         attrs,
                     ));
                 }
@@ -2946,7 +2965,7 @@ impl<'a> Parser<'a> {
         }
         let hi = self.token.span;
         self.bump();
-        Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs))
+        Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs))
     }
 
     /// Attempt to recover from match arm body with statements and no surrounding braces.
@@ -3955,7 +3974,7 @@ impl MutVisitor for CondChecker<'_> {
             | ExprKind::While(_, _, _)
             | ExprKind::ForLoop { .. }
             | ExprKind::Loop(_, _, _)
-            | ExprKind::Match(_, _)
+            | ExprKind::Match(_, _, _)
             | ExprKind::Closure(_)
             | ExprKind::Block(_, _)
             | ExprKind::Gen(_, _, _)
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 8080216a252..4a1a2049083 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -48,7 +48,7 @@ impl NonConstExpr {
             Self::Match(TryDesugar(_)) => &[sym::const_try],
 
             // All other expressions are allowed.
-            Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[],
+            Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[],
         };
 
         Some(gates)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8530c6072c5..b6c07e8737f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1335,6 +1335,7 @@ symbols! {
         poll,
         poll_next,
         post_dash_lto: "post-lto",
+        postfix_match,
         powerpc_target_feature,
         powf128,
         powf16,
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 76a5d942c66..69b9fc33166 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -525,8 +525,8 @@ fn encode_ty<'tcx>(
                 "{}",
                 &len.try_to_scalar()
                     .unwrap()
-                    .to_u64()
-                    .unwrap_or_else(|_| panic!("failed to convert length to u64"))
+                    .to_target_usize(&tcx.data_layout)
+                    .expect("Array lens are defined in usize")
             );
             s.push_str(&encode_ty(tcx, *ty0, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 9c0236c172a..2ac42e20d43 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1575,6 +1575,25 @@ impl<T> NonNull<[T]> {
         self.as_ptr().len()
     }
 
+    /// Returns `true` if the non-null raw slice has a length of 0.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(slice_ptr_is_empty_nonnull)]
+    /// use std::ptr::NonNull;
+    ///
+    /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
+    /// assert!(!slice.is_empty());
+    /// ```
+    #[unstable(feature = "slice_ptr_is_empty_nonnull", issue = "71146")]
+    #[rustc_const_unstable(feature = "const_slice_ptr_is_empty_nonnull", issue = "71146")]
+    #[must_use]
+    #[inline]
+    pub const fn is_empty(self) -> bool {
+        self.len() == 0
+    }
+
     /// Returns a non-null pointer to the slice's buffer.
     ///
     /// # Examples
diff --git a/src/doc/unstable-book/src/language-features/postfix-match.md b/src/doc/unstable-book/src/language-features/postfix-match.md
new file mode 100644
index 00000000000..cd6b6a7442c
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/postfix-match.md
@@ -0,0 +1,22 @@
+# `postfix-match`
+
+`postfix-match` adds the feature for matching upon values postfix
+the expressions that generate the values.
+
+```rust,edition2021
+#![feature(postfix_match)]
+
+enum Foo {
+    Bar,
+    Baz
+}
+
+fn get_foo() -> Foo {
+    Foo::Bar
+}
+
+get_foo().match {
+    Foo::Bar => {},
+    Foo::Baz => panic!(),
+}
+```
diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs
index fb434fb7450..3bdf13dbbea 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_else.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs
@@ -105,7 +105,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor {
     fn visit_expr(&mut self, expr: &'ast Expr) {
         self.is_break = match expr.kind {
             ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) => true,
-            ExprKind::Match(_, ref arms) => arms.iter().all(|arm|
+            ExprKind::Match(_, ref arms, _) => arms.iter().all(|arm|
                 arm.body.is_none() || arm.body.as_deref().is_some_and(|body| self.check_expr(body))
             ),
             ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els),
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 60e9d262e7e..ab1b3043f0c 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -552,7 +552,7 @@ fn ident_difference_expr_with_base_location(
         | (Gen(_, _, _), Gen(_, _, _))
         | (Block(_, _), Block(_, _))
         | (Closure(_), Closure(_))
-        | (Match(_, _), Match(_, _))
+        | (Match(_, _, _), Match(_, _, _))
         | (Loop(_, _, _), Loop(_, _, _))
         | (ForLoop { .. }, ForLoop { .. })
         | (While(_, _, _), While(_, _, _))
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 3874c1169e4..f7532121aeb 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -198,7 +198,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         },
         (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
         (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
-        (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
+        (Match(ls, la, lkind), Match(rs, ra, rkind)) => (lkind == rkind) && eq_expr(ls, rs) && over(la, ra, eq_arm),
         (
             Closure(box ast::Closure {
                 binder: lb,
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index c500b30b998..053afcc52d4 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/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;
@@ -170,8 +170,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)
@@ -625,7 +625,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))?,
diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 5a00984d4c0..e68903c8715 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/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};
@@ -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.
@@ -131,15 +132,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/tools/rustfmt/tests/source/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/source/postfix-match/pf-match.rs
new file mode 100644
index 00000000000..b2366723631
--- /dev/null
+++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs
new file mode 100644
index 00000000000..f439f272623
--- /dev/null
+++ b/src/tools/rustfmt/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/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
new file mode 100644
index 00000000000..ff65ca77039
--- /dev/null
+++ b/tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
@@ -0,0 +1,56 @@
+- // MIR for `main` before CleanupPostBorrowck
++ // MIR for `main` after CleanupPostBorrowck
+  
+  fn main() -> () {
+      let mut _0: ();
+      let mut _1: bool;
+  
+      coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0)
+  
+      coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
+      coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
+      coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36;
+      coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39;
+      coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40;
+      coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2;
+      coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36;
+  
+      bb0: {
+          Coverage::CounterIncrement(0);
+-         Coverage::SpanMarker;
++         nop;
+          StorageLive(_1);
+          _1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5];
+      }
+  
+      bb1: {
+          switchInt(move _1) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb2: {
+          Coverage::CounterIncrement(1);
+-         Coverage::BlockMarker(1);
++         nop;
+          _0 = const ();
+          goto -> bb4;
+      }
+  
+      bb3: {
+          Coverage::ExpressionUsed(0);
+-         Coverage::BlockMarker(0);
++         nop;
+          _0 = const ();
+          goto -> bb4;
+      }
+  
+      bb4: {
+          Coverage::ExpressionUsed(1);
+          StorageDead(_1);
+          return;
+      }
+  
+      bb5 (cleanup): {
+          resume;
+      }
+  }
+  
diff --git a/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff
new file mode 100644
index 00000000000..8757559149a
--- /dev/null
+++ b/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff
@@ -0,0 +1,53 @@
+- // MIR for `main` before InstrumentCoverage
++ // MIR for `main` after InstrumentCoverage
+  
+  fn main() -> () {
+      let mut _0: ();
+      let mut _1: bool;
+  
+      coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0)
+  
++     coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
++     coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
++     coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36;
++     coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39;
++     coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40;
++     coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2;
++     coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36;
++ 
+      bb0: {
++         Coverage::CounterIncrement(0);
+          Coverage::SpanMarker;
+          StorageLive(_1);
+          _1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5];
+      }
+  
+      bb1: {
+          switchInt(move _1) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb2: {
++         Coverage::CounterIncrement(1);
+          Coverage::BlockMarker(1);
+          _0 = const ();
+          goto -> bb4;
+      }
+  
+      bb3: {
++         Coverage::ExpressionUsed(0);
+          Coverage::BlockMarker(0);
+          _0 = const ();
+          goto -> bb4;
+      }
+  
+      bb4: {
++         Coverage::ExpressionUsed(1);
+          StorageDead(_1);
+          return;
+      }
+  
+      bb5 (cleanup): {
+          resume;
+      }
+  }
+  
diff --git a/tests/mir-opt/instrument_coverage_cleanup.rs b/tests/mir-opt/instrument_coverage_cleanup.rs
new file mode 100644
index 00000000000..8a2fd67139b
--- /dev/null
+++ b/tests/mir-opt/instrument_coverage_cleanup.rs
@@ -0,0 +1,22 @@
+// Test that CleanupPostBorrowck cleans up the marker statements that are
+// inserted during MIR building (after InstrumentCoverage is done with them),
+// but leaves the statements that were added by InstrumentCoverage.
+//
+// Removed statement kinds: BlockMarker, SpanMarker
+// Retained statement kinds: CounterIncrement, ExpressionUsed
+
+//@ unit-test: InstrumentCoverage
+//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=branch -Zno-profiler-runtime
+//@ compile-flags: --remap-path-prefix={{src-base}}=/the/src
+
+// EMIT_MIR instrument_coverage_cleanup.main.InstrumentCoverage.diff
+// EMIT_MIR instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
+fn main() {
+    if !core::hint::black_box(true) {}
+}
+
+// CHECK-NOT: Coverage::BlockMarker
+// CHECK-NOT: Coverage::SpanMarker
+// CHECK:     Coverage::CounterIncrement
+// CHECK-NOT: Coverage::BlockMarker
+// CHECK-NOT: Coverage::SpanMarker
diff --git a/tests/pretty/postfix-match.rs b/tests/pretty/postfix-match.rs
new file mode 100644
index 00000000000..5bb54e15275
--- /dev/null
+++ b/tests/pretty/postfix-match.rs
@@ -0,0 +1,21 @@
+#![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/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs
new file mode 100644
index 00000000000..a2f8c876b5e
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs
@@ -0,0 +1,13 @@
+// test for ICE "no entry found for key" in generics_of.rs #113017
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub fn foo()
+where
+    for<const N: usize = { || {}; 1 }> ():,
+    //~^ ERROR only lifetime parameters can be used in this context
+    //~^^  ERROR defaults for generic parameters are not allowed in `for<...>` binders
+{}
+
+pub fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr
new file mode 100644
index 00000000000..edf27f58efd
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr
@@ -0,0 +1,19 @@
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:15
+   |
+LL |     for<const N: usize = { || {}; 1 }> ():,
+   |               ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:9
+   |
+LL |     for<const N: usize = { || {}; 1 }> ():,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs
new file mode 100644
index 00000000000..4ba696f4ae0
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs
@@ -0,0 +1,18 @@
+// test for ICE #119275 "no entry found for key" in predicates_of.rs
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn bug<const N: Nat>(&self)
+//~^ ERROR `self` parameter is only allowed in associated functions
+//~^^ ERROR cannot find type `Nat` in this scope
+where
+    for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+    //~^ ERROR only lifetime parameters can be used in this context
+    //~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^^^^ ERROR failed to resolve: use of undeclared type `COT`
+{
+}
+
+pub fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr
new file mode 100644
index 00000000000..ee0ec38ab06
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr
@@ -0,0 +1,46 @@
+error: `self` parameter is only allowed in associated functions
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:22
+   |
+LL | fn bug<const N: Nat>(&self)
+   |                      ^^^^^ not semantically valid as function parameter
+   |
+   = note: associated functions are those in `impl` or `trait` definitions
+
+error[E0412]: cannot find type `Nat` in this scope
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:17
+   |
+LL | fn bug<const N: Nat>(&self)
+   |                 ^^^ not found in this scope
+
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:15
+   |
+LL |     for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+   |               ^             ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:9
+   |
+LL |     for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:29
+   |
+LL |     for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+   |                             ^^^^^^^
+
+error[E0433]: failed to resolve: use of undeclared type `COT`
+  --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:43
+   |
+LL |     for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+   |                                           ^^^ use of undeclared type `COT`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0412, E0433, E0658.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs
index d7bf1b47fb5..90afd232534 100644
--- a/tests/ui/const-generics/transmute-fail.rs
+++ b/tests/ui/const-generics/transmute-fail.rs
@@ -32,4 +32,79 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777
   }
 }
 
+fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn flatten_3d<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [u32; D * W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [[u32; D * W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
+fn transpose_with_const<const W: usize, const H: usize>(
+  v: [[u32; 2 * H]; W + W]
+) -> [[u32; W + W]; 2 * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+  }
+}
+
 fn main() {}
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 397e3be768a..1b0d1ea50d0 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W)
-   = note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H)
+   = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
+   = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:16:5
@@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H]; W]` (generic size 4 * H * W)
-   = note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W)
+   = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
+   = note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:30:5
@@ -34,6 +34,87 @@ LL |     std::mem::transmute(v)
    = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
    = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
 
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:37:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
+   = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:50:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
+   = note: target type: `[u32; W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:57:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u32; H*W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:66:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
+   = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:75:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
+   = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:82:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u16; L]` (this type does not have a fixed size)
+   = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:89:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L * 2]` (this type does not have a fixed size)
+   = note: target type: `[u16; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:96:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L]` (this type does not have a fixed size)
+   = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:105:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
+   = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
+
 error[E0308]: mismatched types
   --> $DIR/transmute-fail.rs:12:53
    |
@@ -46,7 +127,7 @@ error[E0308]: mismatched types
 LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
    |                                                                   ^ expected `usize`, found `bool`
 
-error: aborting due to 6 previous errors
+error: aborting due to 15 previous errors
 
 Some errors have detailed explanations: E0308, E0512.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs
index 245fcf5670e..e8ab8637932 100644
--- a/tests/ui/const-generics/transmute.rs
+++ b/tests/ui/const-generics/transmute.rs
@@ -3,81 +3,12 @@
 #![feature(transmute_generic_consts)]
 #![allow(incomplete_features)]
 
-fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
 fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
   unsafe {
     std::mem::transmute(v)
   }
 }
 
-fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn flatten_3d<const W: usize, const H: usize, const D: usize>(
-  v: [[[u32; D]; H]; W]
-) -> [u32; D * W * H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
-  v: [[[u32; D]; H]; W]
-) -> [[u32; D * W]; H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
-fn transpose_with_const<const W: usize, const H: usize>(
-  v: [[u32; 2 * H]; W + W]
-) -> [[u32; W + W]; 2 * H] {
-  unsafe {
-    std::mem::transmute(v)
-  }
-}
-
 fn main() {
-  let _ = transpose([[0; 8]; 16]);
-  let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
   let _ = ident([[0; 8]; 16]);
-  let _ = flatten([[0; 13]; 5]);
-  let _: [[_; 5]; 13] = coagulate([0; 65]);
-  let _ = flatten_3d([[[0; 3]; 13]; 5]);
-  let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
-  let _ = known_size([16; 13]);
-  let _: [u16; 5] = condense_bytes([16u8; 10]);
-  let _ = singleton_each([16; 10]);
 }
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
new file mode 100644
index 00000000000..dc9782295c1
--- /dev/null
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
@@ -0,0 +1,20 @@
+// test for #112824 ICE type mismatching when copying!
+
+pub struct Opcode(pub u8);
+
+pub struct Opcode2(&'a S);
+//~^ ERROR use of undeclared lifetime name `'a`
+//~^^ ERROR cannot find type `S` in this scope
+
+impl Opcode2 {
+    pub const OP2: Opcode2 = Opcode2(Opcode(0x1));
+}
+
+pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
+    move |i| match msg_type {
+        Opcode2::OP2 => unimplemented!(),
+        //~^ ERROR could not evaluate constant pattern
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
new file mode 100644
index 00000000000..9442eac0cf5
--- /dev/null
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
@@ -0,0 +1,29 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-type-mismatch-when-copying-112824.rs:5:21
+   |
+LL | pub struct Opcode2(&'a S);
+   |                   - ^^ undeclared lifetime
+   |                   |
+   |                   help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0412]: cannot find type `S` in this scope
+  --> $DIR/ice-type-mismatch-when-copying-112824.rs:5:24
+   |
+LL | pub struct Opcode2(&'a S);
+   |                        ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | pub struct Opcode2<S>(&'a S);
+   |                   +++
+
+error: could not evaluate constant pattern
+  --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
+   |
+LL |         Opcode2::OP2 => unimplemented!(),
+   |         ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0261, E0412.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.rs b/tests/ui/feature-gates/feature-gate-postfix_match.rs
new file mode 100644
index 00000000000..dce7e81a9ae
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-postfix_match.rs
@@ -0,0 +1,17 @@
+// Testing that postfix match doesn't work without enabling the feature
+
+fn main() {
+    let val = Some(42);
+
+    val.match { //~ ERROR postfix match is experimental
+        Some(42) => "the answer to life, the universe, and everything",
+        _ => "might be the answer to something"
+    };
+
+    // Test that the gate works behind a cfg
+    #[cfg(FALSE)]
+    val.match { //~ ERROR postfix match is experimental
+        Some(42) => "the answer to life, the universe, and everything",
+        _ => "might be the answer to something"
+    };
+}
diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.stderr b/tests/ui/feature-gates/feature-gate-postfix_match.stderr
new file mode 100644
index 00000000000..136838788dd
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-postfix_match.stderr
@@ -0,0 +1,23 @@
+error[E0658]: postfix match is experimental
+  --> $DIR/feature-gate-postfix_match.rs:6:9
+   |
+LL |     val.match {
+   |         ^^^^^
+   |
+   = note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information
+   = help: add `#![feature(postfix_match)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: postfix match is experimental
+  --> $DIR/feature-gate-postfix_match.rs:13:9
+   |
+LL |     val.match {
+   |         ^^^^^
+   |
+   = note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information
+   = help: add `#![feature(postfix_match)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
new file mode 100644
index 00000000000..d6fa56663a3
--- /dev/null
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
@@ -0,0 +1,30 @@
+// test for ICE #112823
+// Unexpected parameter Type(Repr) when substituting in region
+
+#![feature(impl_trait_in_assoc_type)]
+
+use std::future::Future;
+
+trait Stream {}
+
+trait X {
+    type LineStream<'a, Repr>
+    where
+        Self: 'a;
+    type LineStreamFut<'a, Repr>
+    where
+        Self: 'a;
+}
+
+struct Y;
+
+impl X for Y {
+    type LineStream<'c, 'd> = impl Stream;
+    //~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
+    type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
+    fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
+    //~^ ERROR `()` is not a future
+    //~^^ method `line_stream` is not a member of trait `X`
+}
+
+pub fn main() {}
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr
new file mode 100644
index 00000000000..28a0f7461e2
--- /dev/null
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr
@@ -0,0 +1,31 @@
+error[E0407]: method `line_stream` is not a member of trait `X`
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:5
+   |
+LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
+
+error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:22:21
+   |
+LL |     type LineStream<'a, Repr>
+   |                     --  ----
+   |                     |
+   |                     expected 1 type parameter
+...
+LL |     type LineStream<'c, 'd> = impl Stream;
+   |                     ^^  ^^
+   |                     |
+   |                     found 0 type parameters
+
+error[E0277]: `()` is not a future
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:43
+   |
+LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
+   |
+   = help: the trait `Future` is not implemented for `()`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0049, E0277, E0407.
+For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/match/postfix-match/pf-match-chain.rs b/tests/ui/match/postfix-match/pf-match-chain.rs
new file mode 100644
index 00000000000..80546e1963b
--- /dev/null
+++ b/tests/ui/match/postfix-match/pf-match-chain.rs
@@ -0,0 +1,16 @@
+//@ run-pass
+
+#![feature(postfix_match)]
+
+fn main() {
+    1.match {
+        2 => Some(0),
+        _ => None,
+    }.match {
+        None => Ok(true),
+        Some(_) => Err("nope")
+    }.match {
+        Ok(_) => (),
+        Err(_) => panic!()
+    }
+}
diff --git a/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs
new file mode 100644
index 00000000000..f4cac46f7cd
--- /dev/null
+++ b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs
@@ -0,0 +1,7 @@
+#![feature(postfix_match)]
+
+fn main() {
+    Some(1).match { //~ non-exhaustive patterns
+        None => {},
+    }
+}
diff --git a/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr b/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr
new file mode 100644
index 00000000000..f458218bb5d
--- /dev/null
+++ b/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/pf-match-exhaustiveness.rs:4:5
+   |
+LL |     Some(1).match {
+   |     ^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<i32>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<i32>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         None => {},
+LL ~         Some(_) => todo!(),
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/match/postfix-match/pf-match-types.rs b/tests/ui/match/postfix-match/pf-match-types.rs
new file mode 100644
index 00000000000..af205926fb6
--- /dev/null
+++ b/tests/ui/match/postfix-match/pf-match-types.rs
@@ -0,0 +1,15 @@
+#![feature(postfix_match)]
+
+fn main() {
+    Some(10).match {
+    //~^ NOTE `match` arms have incompatible types
+        Some(5) => false,
+        //~^ NOTE this is found to be of type `bool`
+        Some(2) => true,
+        //~^ NOTE this is found to be of type `bool`
+        None    => (),
+        //~^ ERROR `match` arms have incompatible types
+        //~| NOTE expected `bool`, found `()`
+        _       => true
+    }
+}
diff --git a/tests/ui/match/postfix-match/pf-match-types.stderr b/tests/ui/match/postfix-match/pf-match-types.stderr
new file mode 100644
index 00000000000..0cfc1363d5f
--- /dev/null
+++ b/tests/ui/match/postfix-match/pf-match-types.stderr
@@ -0,0 +1,21 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/pf-match-types.rs:10:20
+   |
+LL | /     Some(10).match {
+LL | |
+LL | |         Some(5) => false,
+   | |                    ----- this is found to be of type `bool`
+LL | |
+LL | |         Some(2) => true,
+   | |                    ---- this is found to be of type `bool`
+LL | |
+LL | |         None    => (),
+   | |                    ^^ expected `bool`, found `()`
+...  |
+LL | |         _       => true
+LL | |     }
+   | |_____- `match` arms have incompatible types
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/postfix-match/postfix-match.rs b/tests/ui/match/postfix-match/postfix-match.rs
new file mode 100644
index 00000000000..03c4e8ab545
--- /dev/null
+++ b/tests/ui/match/postfix-match/postfix-match.rs
@@ -0,0 +1,62 @@
+//@ run-pass
+
+#![feature(postfix_match)]
+
+struct Bar {
+    foo: u8,
+    baz: u8,
+}
+
+pub fn main() {
+    let thing = Some("thing");
+
+    thing.match {
+        Some("nothing") => {},
+        Some(text) if text.eq_ignore_ascii_case("tapir")  => {},
+        Some("true") | Some("false") => {},
+        Some("thing") => {},
+        Some(_) => {},
+        None => {}
+    };
+
+    let num = 2u8;
+
+    num.match {
+        0 => {},
+        1..=5 => {},
+        _ => {},
+    };
+
+    let slic = &[1, 2, 3, 4][..];
+
+    slic.match {
+        [1] => {},
+        [2, _tail @ ..] => {},
+        [1, _] => {},
+        _ => {},
+    };
+
+    slic[0].match {
+        1 => 0,
+        i => i,
+    };
+
+    let out = (1, 2).match {
+        (1, 3) => 0,
+        (_, 1) => 0,
+        (1, i) => i,
+        _ => 3,
+    };
+    assert!(out == 2);
+
+    let strct = Bar {
+        foo: 3,
+        baz: 4
+    };
+
+    strct.match {
+        Bar { foo: 1, .. } => {},
+        Bar { baz: 2, .. } => {},
+        _ => (),
+    };
+}
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 9feb2a7320d..d7933a39eaa 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -53,17 +53,16 @@ LL | fn case2() {
 error[E0597]: `a` does not live long enough
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
    |
-LL |       let a = 0;
-   |           - binding `a` declared here
-LL |       let cell = Cell::new(&a);
-   |                            ^^ borrowed value does not live long enough
+LL |     let a = 0;
+   |         - binding `a` declared here
+LL |     let cell = Cell::new(&a);
+   |                ----------^^-
+   |                |         |
+   |                |         borrowed value does not live long enough
+   |                argument requires that `a` is borrowed for `'static`
 ...
-LL | /     foo(cell, |cell_a, cell_x| {
-LL | |         cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
-LL | |     })
-   | |______- argument requires that `a` is borrowed for `'static`
-LL |   }
-   |   - `a` dropped here while still borrowed
+LL | }
+   | - `a` dropped here while still borrowed
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
index 5b385feeedc..644fc94f730 100644
--- a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
+++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
@@ -1,16 +1,17 @@
 error[E0597]: `c` does not live long enough
   --> $DIR/adt-nullary-enums.rs:33:41
    |
-LL |       let c = 66;
-   |           - binding `c` declared here
-LL | /     combine(
-LL | |         SomeEnum::SomeVariant(Cell::new(&c)),
-   | |                                         ^^ borrowed value does not live long enough
-LL | |         SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
-LL | |     );
-   | |_____- argument requires that `c` is borrowed for `'static`
-LL |   }
-   |   - `c` dropped here while still borrowed
+LL |     let c = 66;
+   |         - binding `c` declared here
+LL |     combine(
+LL |         SomeEnum::SomeVariant(Cell::new(&c)),
+   |                               ----------^^-
+   |                               |         |
+   |                               |         borrowed value does not live long enough
+   |                               argument requires that `c` is borrowed for `'static`
+...
+LL | }
+   | - `c` dropped here while still borrowed
 
 error[E0597]: `c` does not live long enough
   --> $DIR/adt-nullary-enums.rs:41:41
diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs
new file mode 100644
index 00000000000..fc71d0d61ff
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs
@@ -0,0 +1,52 @@
+// test for #110696
+// failed to resolve instance for <Scope<()> as MyIndex<()>>::my_index
+// ignore-tidy-linelength
+
+#![feature(type_alias_impl_trait)]
+
+use std::marker::PhantomData;
+
+
+trait MyIndex<T> {
+    type O;
+    fn my_index(self) -> Self::O;
+}
+trait MyFrom<T>: Sized {
+    type Error;
+    fn my_from(value: T) -> Result<Self, Self::Error>;
+}
+
+
+trait F {}
+impl F for () {}
+type DummyT<T> = impl F;
+fn _dummy_t<T>() -> DummyT<T> {}
+
+struct Phantom1<T>(PhantomData<T>);
+struct Phantom2<T>(PhantomData<T>);
+struct Scope<T>(Phantom2<DummyT<T>>);
+
+impl<T> Scope<T> {
+    fn new() -> Self {
+        unimplemented!()
+    }
+}
+
+impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
+    type Error = ();
+    fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
+        unimplemented!()
+    }
+}
+
+impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
+    //~^ ERROR the type parameter `T` is not constrained by the impl
+    type O = T;
+    fn my_index(self) -> Self::O {
+        MyFrom::my_from(self.0).ok().unwrap()
+    }
+}
+
+fn main() {
+    let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
+}
diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
new file mode 100644
index 00000000000..a39f77ce17f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:42:6
+   |
+LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
+   |      ^ unconstrained type parameter
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs
new file mode 100644
index 00000000000..37e0d89efc7
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs
@@ -0,0 +1,16 @@
+// test for ICE #121472 index out of bounds un_derefer.rs
+#![feature(type_alias_impl_trait)]
+
+trait T {}
+
+type Alias<'a> = impl T;
+
+struct S;
+impl<'a> T for &'a S {}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {}
+
+fn main() {
+    with_positive(|&n| ());
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr
new file mode 100644
index 00000000000..a224bab0705
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/underef-index-out-of-bounds-121472.rs:14:20
+   |
+LL | type Alias<'a> = impl T;
+   |                  ------ the expected opaque type
+...
+LL |     with_positive(|&n| ());
+   |                    ^^
+   |                    |
+   |                    expected opaque type, found `&_`
+   |                    expected due to this
+   |
+   = note: expected opaque type `Alias<'_>`
+                found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     with_positive(|&n| ());
+LL +     with_positive(|n| ());
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
new file mode 100644
index 00000000000..107cfbb9ff6
--- /dev/null
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
@@ -0,0 +1,12 @@
+trait Trait<const N: Trait = bar> {
+//~^ ERROR cannot find value `bar` in this scope
+//~| ERROR cycle detected when computing type of `Trait::N`
+//~| ERROR cycle detected when computing type of `Trait::N`
+//~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    fn fnc(&self) {
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
new file mode 100644
index 00000000000..2d5a0ede962
--- /dev/null
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
@@ -0,0 +1,60 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:30
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                              ^^^ not found in this scope
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is an object-safe trait, use `dyn`
+   |
+LL | trait Trait<const N: dyn Trait = bar> {
+   |                      +++
+
+error[E0391]: cycle detected when computing type of `Trait::N`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+   = note: ...which immediately requires computing type of `Trait::N` again
+note: cycle used when computing explicit predicates of trait `Trait`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
+   |
+LL | trait Trait<const N: Trait = bar> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error[E0391]: cycle detected when computing type of `Trait::N`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which immediately requires computing type of `Trait::N` again
+note: cycle used when computing explicit predicates of trait `Trait`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
+   |
+LL | trait Trait<const N: Trait = bar> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0391, E0425.
+For more information about an error, try `rustc --explain E0391`.