about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-05 15:20:50 +0000
committerbors <bors@rust-lang.org>2024-04-05 15:20:50 +0000
commit1921968cc5403892739b43bdefe793a130badd15 (patch)
treef53db054de5cf0612c38d204349b32d9cfcbbe32
parent5958f5e08fa88ee95ede8c00f1b89befe0372d54 (diff)
parent9cb517aede5500e80d25a39ba9f079dcf29fb8d4 (diff)
downloadrust-1921968cc5403892739b43bdefe793a130badd15.tar.gz
rust-1921968cc5403892739b43bdefe793a130badd15.zip
Auto merge of #123497 - GuillaumeGomez:rollup-usqb4q9, r=GuillaumeGomez
Rollup of 8 pull requests

Successful merges:

 - #122334 (Vendor rustc_codegen_gcc)
 - #122894 (Move check for error in impl header outside of reporting)
 - #123149 (Port argument-non-c-like-enum to Rust)
 - #123311 (Match ergonomics: implement "`&`pat everywhere")
 - #123350 (Actually use the inferred `ClosureKind` from signature inference in coroutine-closures)
 - #123474 (Port `run-make/issue-7349` to a codegen test)
 - #123489 (handle rustc args properly in bootstrap)
 - #123496 (ping on wf changes, remove fixme)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock10
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.toml2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs91
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs50
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs9
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs56
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs9
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs20
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--src/bootstrap/bootstrap.py1
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/builder.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs14
-rw-r--r--src/tools/miri/tests/pass/async-closure-captures.rs34
-rw-r--r--src/tools/miri/tests/pass/async-closure-captures.stdout4
-rw-r--r--src/tools/run-make-support/src/cc.rs202
-rw-r--r--src/tools/run-make-support/src/lib.rs89
-rw-r--r--src/tools/run-make-support/src/run.rs21
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt2
-rw-r--r--src/tools/tidy/src/deps.rs5
-rw-r--r--tests/codegen/no-redundant-item-monomorphization.rs33
-rw-r--r--tests/run-make/arguments-non-c-like-enum/Makefile8
-rw-r--r--tests/run-make/arguments-non-c-like-enum/rmake.rs20
-rw-r--r--tests/run-make/issue-7349/Makefile11
-rw-r--r--tests/run-make/issue-7349/foo.rs22
-rw-r--r--tests/ui/async-await/async-closures/captures.rs34
-rw-r--r--tests/ui/async-await/async-closures/captures.run.stdout4
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.rs10
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.stderr49
-rw-r--r--tests/ui/coherence/skip-reporting-if-references-err.current.stderr27
-rw-r--r--tests/ui/coherence/skip-reporting-if-references-err.next.stderr14
-rw-r--r--tests/ui/coherence/skip-reporting-if-references-err.rs19
-rw-r--r--tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs14
-rw-r--r--tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr49
-rw-r--r--tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs16
-rw-r--r--tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr44
-rw-r--r--tests/ui/match/ref_pat_everywhere.rs18
-rw-r--r--triagebot.toml8
42 files changed, 910 insertions, 167 deletions
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index ab2c7ca8a47..3ecb0ef6b4d 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -79,16 +79,18 @@ dependencies = [
 
 [[package]]
 name = "gccjit"
-version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecaa4c3da2d74c1a991b4faff75d49ab1d0522d9a99d8e2614b3b04d226417ce"
 dependencies = [
  "gccjit_sys",
 ]
 
 [[package]]
 name = "gccjit_sys"
-version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "406a66fba005f1a02661f2f9443e5693dd3a667b7c58e70aa4ccc4c8b50b4758"
 dependencies = [
  "libc",
 ]
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 100c10ef1d7..c5aa2eed1e0 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -22,7 +22,7 @@ master = ["gccjit/master"]
 default = ["master"]
 
 [dependencies]
-gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
+gccjit = "2.0"
 
 # Local copy.
 #gccjit = { path = "../gccjit.rs" }
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 4c975c7b9e0..36db377f7e0 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -567,6 +567,8 @@ declare_features! (
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
     (unstable, raw_ref_op, "1.41.0", Some(64490)),
+    /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
+    (incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
     (unstable, register_tool, "1.41.0", Some(66079)),
     /// Allows the `#[repr(i128)]` attribute for enums.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 36af5394015..dbae8bfb542 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -227,11 +227,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     kind: TypeVariableOriginKind::ClosureSynthetic,
                     span: expr_span,
                 });
-                let closure_kind_ty = self.next_ty_var(TypeVariableOrigin {
-                    // FIXME(eddyb) distinguish closure kind inference variables from the rest.
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+
+                let closure_kind_ty = match expected_kind {
+                    Some(kind) => Ty::from_closure_kind(tcx, kind),
+
+                    // Create a type variable (for now) to represent the closure kind.
+                    // It will be unified during the upvar inference phase (`upvar.rs`)
+                    None => self.next_ty_var(TypeVariableOrigin {
+                        kind: TypeVariableOriginKind::ClosureSynthetic,
+                        span: expr_span,
+                    }),
+                };
+
                 let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::ClosureSynthetic,
                     span: expr_span,
@@ -262,10 +269,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
                 );
 
-                let coroutine_kind_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+                let coroutine_kind_ty = match expected_kind {
+                    Some(kind) => Ty::from_coroutine_closure_kind(tcx, kind),
+
+                    // Create a type variable (for now) to represent the closure kind.
+                    // It will be unified during the upvar inference phase (`upvar.rs`)
+                    None => self.next_ty_var(TypeVariableOrigin {
+                        kind: TypeVariableOriginKind::ClosureSynthetic,
+                        span: expr_span,
+                    }),
+                };
+
                 let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::ClosureSynthetic,
                     span: expr_span,
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 9d247c46bab..bb47f8dfba4 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -130,7 +130,14 @@ enum AdjustMode {
     /// Peel off all immediate reference types.
     Peel,
     /// Reset binding mode to the initial mode.
+    /// Used for destructuring assignment, where we don't want any match ergonomics.
     Reset,
+    /// Produced by ref patterns.
+    /// Reset the binding mode to the initial mode,
+    /// and if the old biding mode was by-reference
+    /// with mutability matching the pattern,
+    /// mark the pattern as having consumed this reference.
+    ResetAndConsumeRef(Mutability),
     /// Pass on the input binding mode and expected type.
     Pass,
 }
@@ -174,7 +181,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
-        let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
+        let (expected, def_bm, ref_pattern_already_consumed) =
+            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
         let pat_info = PatInfo {
             binding_mode: def_bm,
             top_info: ti,
@@ -211,7 +219,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
             PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
-            PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
+            PatKind::Ref(inner, mutbl) => self.check_pat_ref(
+                pat,
+                inner,
+                mutbl,
+                expected,
+                pat_info,
+                ref_pattern_already_consumed,
+            ),
             PatKind::Slice(before, slice, after) => {
                 self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
             }
@@ -264,17 +279,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Compute the new expected type and default binding mode from the old ones
     /// as well as the pattern form we are currently checking.
+    ///
+    /// Last entry is only relevant for ref patterns (`&` and `&mut`);
+    /// if `true`, then the ref pattern consumed a match ergonomics inserted reference
+    /// and so does no need to match against a reference in the scrutinee type.
     fn calc_default_binding_mode(
         &self,
         pat: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
         def_bm: BindingAnnotation,
         adjust_mode: AdjustMode,
-    ) -> (Ty<'tcx>, BindingAnnotation) {
+    ) -> (Ty<'tcx>, BindingAnnotation, bool) {
         match adjust_mode {
-            AdjustMode::Pass => (expected, def_bm),
-            AdjustMode::Reset => (expected, INITIAL_BM),
-            AdjustMode::Peel => self.peel_off_references(pat, expected, def_bm),
+            AdjustMode::Pass => (expected, def_bm, false),
+            AdjustMode::Reset => (expected, INITIAL_BM, false),
+            AdjustMode::ResetAndConsumeRef(mutbl) => {
+                (expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
+            }
+            AdjustMode::Peel => {
+                let peeled = self.peel_off_references(pat, expected, def_bm);
+                (peeled.0, peeled.1, false)
+            }
         }
     }
 
@@ -329,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // ```
             //
             // See issue #46688.
-            PatKind::Ref(..) => AdjustMode::Reset,
+            PatKind::Ref(_, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl),
             // A `_` pattern works with any expected type, so there's no need to do anything.
             PatKind::Wild
             // A malformed pattern doesn't have an expected type, so let's just accept any type.
@@ -840,8 +865,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
             && let ty::Dynamic(..) = mt.ty.kind()
         {
-            // This is "x = SomeTrait" being reduced from
-            // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
+            // This is "x = dyn SomeTrait" being reduced from
+            // "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
             let type_str = self.ty_to_string(expected);
             let mut err = struct_span_code_err!(
                 self.dcx(),
@@ -2036,6 +2061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         mutbl: Mutability,
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
+        consumed_inherited_ref: bool,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let expected = self.shallow_resolve(expected);
@@ -2051,26 +2077,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 match *expected.kind() {
                     ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
                     _ => {
-                        let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeInference,
-                            span: inner.span,
-                        });
-                        let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
-                        debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
-                        let err = self.demand_eqtype_pat_diag(
-                            pat.span,
-                            expected,
-                            ref_ty,
-                            pat_info.top_info,
-                        );
+                        if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
+                            // We already matched against a match-ergonmics inserted reference,
+                            // so we don't need to match against a reference from the original type.
+                            // Save this infor for use in lowering later
+                            self.typeck_results
+                                .borrow_mut()
+                                .skipped_ref_pats_mut()
+                                .insert(pat.hir_id);
+                            (expected, expected)
+                        } else {
+                            let inner_ty = self.next_ty_var(TypeVariableOrigin {
+                                kind: TypeVariableOriginKind::TypeInference,
+                                span: inner.span,
+                            });
+                            let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
+                            debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+                            let err = self.demand_eqtype_pat_diag(
+                                pat.span,
+                                expected,
+                                ref_ty,
+                                pat_info.top_info,
+                            );
 
-                        // Look for a case like `fn foo(&foo: u32)` and suggest
-                        // `fn foo(foo: &u32)`
-                        if let Some(mut err) = err {
-                            self.borrow_pat_suggestion(&mut err, pat);
-                            err.emit();
+                            // Look for a case like `fn foo(&foo: u32)` and suggest
+                            // `fn foo(foo: &u32)`
+                            if let Some(mut err) = err {
+                                self.borrow_pat_suggestion(&mut err, pat);
+                                err.emit();
+                            }
+                            (ref_ty, inner_ty)
                         }
-                        (ref_ty, inner_ty)
                     }
                 }
             }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 72e5b1ed95b..c987bfb9a0e 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         body_id: hir::BodyId,
         body: &'tcx hir::Body<'tcx>,
-        capture_clause: hir::CaptureBy,
+        mut capture_clause: hir::CaptureBy,
     ) {
         // Extract the type of the closure.
         let ty = self.node_ty(closure_hir_id);
@@ -259,6 +259,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
         .consume_body(body);
 
+        // If a coroutine is comes from a coroutine-closure that is `move`, but
+        // the coroutine-closure was inferred to be `FnOnce` during signature
+        // inference, then it's still possible that we try to borrow upvars from
+        // the coroutine-closure because they are not used by the coroutine body
+        // in a way that forces a move.
+        //
+        // This would lead to an impossible to satisfy situation, since `AsyncFnOnce`
+        // coroutine bodies can't borrow from their parent closure. To fix this,
+        // we force the inner coroutine to also be `move`. This only matters for
+        // coroutine-closures that are `move` since otherwise they themselves will
+        // be borrowing from the outer environment, so there's no self-borrows occuring.
+        if let UpvarArgs::Coroutine(..) = args
+            && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) =
+                self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind")
+            && let parent_hir_id =
+                self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id))
+            && let parent_ty = self.node_ty(parent_hir_id)
+            && let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty)
+        {
+            capture_clause = self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause;
+        }
+
         debug!(
             "For closure={:?}, capture_information={:#?}",
             closure_def_id, delegate.capture_information
@@ -399,16 +421,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
 
             // Additionally, we can now constrain the coroutine's kind type.
-            let ty::Coroutine(_, coroutine_args) =
-                *self.typeck_results.borrow().expr_ty(body.value).kind()
-            else {
-                bug!();
-            };
-            self.demand_eqtype(
-                span,
-                coroutine_args.as_coroutine().kind_ty(),
-                Ty::from_coroutine_closure_kind(self.tcx, closure_kind),
-            );
+            //
+            // We only do this if `infer_kind`, because if we have constrained
+            // the kind from closure signature inference, the kind inferred
+            // for the inner coroutine may actually be more restrictive.
+            if infer_kind {
+                let ty::Coroutine(_, coroutine_args) =
+                    *self.typeck_results.borrow().expr_ty(body.value).kind()
+                else {
+                    bug!();
+                };
+                self.demand_eqtype(
+                    span,
+                    coroutine_args.as_coroutine().kind_ty(),
+                    Ty::from_coroutine_closure_kind(self.tcx, closure_kind),
+                );
+            }
         }
 
         self.log_closure_min_capture_info(closure_def_id, span);
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index f4516b684c3..6604bf094c1 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -345,6 +345,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             _ => {}
         };
 
+        self.visit_skipped_ref_pats(p.hir_id);
         self.visit_pat_adjustments(p.span, p.hir_id);
 
         self.visit_node_id(p.span, p.hir_id);
@@ -674,6 +675,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
+    fn visit_skipped_ref_pats(&mut self, hir_id: hir::HirId) {
+        if self.fcx.typeck_results.borrow_mut().skipped_ref_pats_mut().remove(hir_id) {
+            debug!("node is a skipped ref pat");
+            self.typeck_results.skipped_ref_pats_mut().insert(hir_id);
+        }
+    }
+
     fn visit_liberated_fn_sigs(&mut self) {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 0d74524276f..995feeaa148 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -96,6 +96,10 @@ pub struct TypeckResults<'tcx> {
     /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
     pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
 
+    /// Set of reference patterns that match against a match-ergonomics inserted reference
+    /// (as opposed to against a reference in the scrutinee type).
+    skipped_ref_pats: ItemLocalSet,
+
     /// Records the reasons that we picked the kind of each closure;
     /// not all closures are present in the map.
     closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
@@ -228,6 +232,7 @@ impl<'tcx> TypeckResults<'tcx> {
             adjustments: Default::default(),
             pat_binding_modes: Default::default(),
             pat_adjustments: Default::default(),
+            skipped_ref_pats: Default::default(),
             closure_kind_origins: Default::default(),
             liberated_fn_sigs: Default::default(),
             fru_field_types: Default::default(),
@@ -435,6 +440,14 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
     }
 
+    pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
+        LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
+    }
+
+    pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
+        LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats }
+    }
+
     /// Does the pattern recursively contain a `ref mut` binding in it?
     ///
     /// This is used to determined whether a `deref` pattern should emit a `Deref`
@@ -629,6 +642,49 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
     }
 }
 
+#[derive(Clone, Copy, Debug)]
+pub struct LocalSetInContext<'a> {
+    hir_owner: OwnerId,
+    data: &'a ItemLocalSet,
+}
+
+impl<'a> LocalSetInContext<'a> {
+    pub fn is_empty(&self) -> bool {
+        self.data.is_empty()
+    }
+
+    pub fn contains(&self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.contains(&id.local_id)
+    }
+}
+
+#[derive(Debug)]
+pub struct LocalSetInContextMut<'a> {
+    hir_owner: OwnerId,
+    data: &'a mut ItemLocalSet,
+}
+
+impl<'a> LocalSetInContextMut<'a> {
+    pub fn is_empty(&self) -> bool {
+        self.data.is_empty()
+    }
+
+    pub fn contains(&self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.contains(&id.local_id)
+    }
+    pub fn insert(&mut self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.insert(id.local_id)
+    }
+
+    pub fn remove(&mut self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.remove(&id.local_id)
+    }
+}
+
 rustc_index::newtype_index! {
     #[derive(HashStable)]
     #[encodable]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index a4992da679e..133cf8e3349 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -65,7 +65,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
         // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
         // gets the least-dereferenced type).
-        let unadjusted_pat = self.lower_pattern_unadjusted(pat);
+        let unadjusted_pat = match pat.kind {
+            hir::PatKind::Ref(inner, _)
+                if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
+            {
+                self.lower_pattern_unadjusted(inner)
+            }
+            _ => self.lower_pattern_unadjusted(pat),
+        };
         self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
             unadjusted_pat,
             |pat: Box<_>, ref_ty| {
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 0866205dfd0..de43f9faff9 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -91,15 +91,17 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
             return;
         }
 
-        let ty::Coroutine(_, coroutine_args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
-        // We don't need to generate a by-move coroutine if the kind of the coroutine is
-        // already `FnOnce` -- that means that any upvars that the closure consumes have
-        // already been taken by-value.
-        let coroutine_kind = coroutine_args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap();
-        if coroutine_kind == ty::ClosureKind::FnOnce {
+        // We don't need to generate a by-move coroutine if the coroutine body was
+        // produced by the `CoroutineKindShim`, since it's already by-move.
+        if matches!(body.source.instance, ty::InstanceDef::CoroutineKindShim { .. }) {
             return;
         }
 
+        let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
+        let args = args.as_coroutine();
+
+        let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap();
+
         let parent_def_id = tcx.local_parent(coroutine_def_id);
         let ty::CoroutineClosure(_, parent_args) =
             *tcx.type_of(parent_def_id).instantiate_identity().kind()
@@ -128,6 +130,12 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
             // the outer closure body -- we need to change the coroutine to take the
             // upvar by value.
             if coroutine_capture.is_by_ref() && !parent_capture.is_by_ref() {
+                assert_ne!(
+                    coroutine_kind,
+                    ty::ClosureKind::FnOnce,
+                    "`FnOnce` coroutine-closures return coroutines that capture from \
+                    their body; it will always result in a borrowck error!"
+                );
                 by_ref_fields.insert(FieldIdx::from_usize(num_args + idx));
             }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a13c9c9b278..ea0f7adf6f9 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1456,6 +1456,7 @@ symbols! {
         receiver,
         recursion_limit,
         reexport_test_harness_main,
+        ref_pat_everywhere,
         ref_unwind_safe_trait,
         reference,
         reflect,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index ab8d7d31e43..46a0a4eb5ef 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -407,10 +407,6 @@ fn report_conflicting_impls<'tcx>(
         impl_span: Span,
         err: &mut Diag<'_, G>,
     ) {
-        if (overlap.trait_ref, overlap.self_ty).references_error() {
-            err.downgrade_to_delayed_bug();
-        }
-
         match tcx.span_of_impl(overlap.with_impl) {
             Ok(span) => {
                 err.span_label(span, "first implementation here");
@@ -463,6 +459,11 @@ fn report_conflicting_impls<'tcx>(
         )
     });
 
+    // Don't report overlap errors if the header references error
+    if let Err(err) = (overlap.trait_ref, overlap.self_ty).error_reported() {
+        return Err(err);
+    }
+
     match used_to_be_allowed {
         None => {
             let reported = if overlap.with_impl.is_local()
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 19ca147d3ad..a44a5ae0e6b 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -714,8 +714,6 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 // perfect and there may be ways to abuse the fact that we
                 // ignore requirements with escaping bound vars. That's a
                 // more general issue however.
-                //
-                // FIXME(eddyb) add the type to `walker` instead of recursing.
                 let fn_sig = tcx.fn_sig(did).instantiate(tcx, args);
                 fn_sig.output().skip_binder().visit_with(self);
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 30d728aa230..39add60e705 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1038,6 +1038,7 @@ class RustBuild(object):
                 sync_dirs = "--sync ./src/tools/cargo/Cargo.toml " \
                             "--sync ./src/tools/rust-analyzer/Cargo.toml " \
                             "--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \
+                            "--sync ./compiler/rustc_codegen_gcc/Cargo.toml " \
                             "--sync ./src/bootstrap/Cargo.toml "
                 eprint('ERROR: vendoring required, but vendor directory does not exist.')
                 eprint('       Run `cargo vendor {}` to initialize the '
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index ecea62140a2..b51d3e15788 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1011,6 +1011,8 @@ impl Step for PlainSourceTarball {
                 .arg("--sync")
                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
                 .arg("--sync")
+                .arg(builder.src.join("./compiler/rustc_codegen_gcc/Cargo.toml"))
+                .arg("--sync")
                 .arg(builder.src.join("./src/bootstrap/Cargo.toml"))
                 // Will read the libstd Cargo.toml
                 // which uses the unstable `public-dependency` feature.
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index c597514f170..9555be481e6 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -2102,12 +2102,10 @@ impl<'a> Builder<'a> {
             rustdocflags.arg("--cfg=parallel_compiler");
         }
 
-        // set rustc args passed from command line
-        let rustc_args =
-            self.config.cmd.rustc_args().iter().map(|s| s.to_string()).collect::<Vec<_>>();
-        if !rustc_args.is_empty() {
-            cargo.env("RUSTFLAGS", &rustc_args.join(" "));
-        }
+        // Pass the value of `--rustc-args` from test command. If it's not a test command, this won't set anything.
+        self.config.cmd.rustc_args().iter().for_each(|v| {
+            rustflags.arg(v);
+        });
 
         Cargo {
             command: cargo,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index bd2f65925bb..689fdc5dfeb 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3926,11 +3926,17 @@ impl<'test> TestCx<'test> {
             cmd.env("IS_MSVC", "1")
                 .env("IS_WINDOWS", "1")
                 .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
-                .env("CC", format!("'{}' {}", self.config.cc, cflags))
-                .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
+                // Note: we diverge from legacy run_make and don't lump `CC` the compiler and
+                // default flags together.
+                .env("CC_DEFAULT_FLAGS", &cflags)
+                .env("CC", &self.config.cc)
+                .env("CXX_DEFAULT_FLAGS", &cxxflags)
+                .env("CXX", &self.config.cxx);
         } else {
-            cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-                .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
+            cmd.env("CC_DEFAULT_FLAGS", &self.config.cflags)
+                .env("CC", &self.config.cc)
+                .env("CXX_DEFAULT_FLAGS", &self.config.cxxflags)
+                .env("CXX", &self.config.cxx)
                 .env("AR", &self.config.ar);
 
             if self.config.target.contains("windows") {
diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs
index 3e33de32efb..cac26bfe146 100644
--- a/src/tools/miri/tests/pass/async-closure-captures.rs
+++ b/src/tools/miri/tests/pass/async-closure-captures.rs
@@ -88,4 +88,38 @@ async fn async_main() {
         };
         call_once(c).await;
     }
+
+    fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
+        f
+    }
+
+    // Capture something with `move`, but infer to `AsyncFnOnce`
+    {
+        let x = Hello(6);
+        let c = force_fnonce(async move || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+
+        let x = &Hello(7);
+        let c = force_fnonce(async move || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+    }
+
+    // Capture something by-ref, but infer to `AsyncFnOnce`
+    {
+        let x = Hello(8);
+        let c = force_fnonce(async || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+
+        let x = &Hello(9);
+        let c = force_fnonce(async || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+    }
 }
diff --git a/src/tools/miri/tests/pass/async-closure-captures.stdout b/src/tools/miri/tests/pass/async-closure-captures.stdout
index a0db6d236fe..42a7999b2dc 100644
--- a/src/tools/miri/tests/pass/async-closure-captures.stdout
+++ b/src/tools/miri/tests/pass/async-closure-captures.stdout
@@ -8,3 +8,7 @@ Hello(3)
 Hello(4)
 Hello(4)
 Hello(5)
+Hello(6)
+Hello(7)
+Hello(8)
+Hello(9)
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
new file mode 100644
index 00000000000..2c9ad4f1700
--- /dev/null
+++ b/src/tools/run-make-support/src/cc.rs
@@ -0,0 +1,202 @@
+use std::env;
+use std::path::Path;
+use std::process::{Command, Output};
+
+use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname};
+
+/// Construct a new platform-specific C compiler invocation.
+///
+/// WARNING: This means that what flags are accepted by the underlying C compiler is
+/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
+pub fn cc() -> Cc {
+    Cc::new()
+}
+
+/// A platform-specific C compiler invocation builder. The specific C compiler used is
+/// passed down from compiletest.
+#[derive(Debug)]
+pub struct Cc {
+    cmd: Command,
+}
+
+impl Cc {
+    /// Construct a new platform-specific C compiler invocation.
+    ///
+    /// WARNING: This means that what flags are accepted by the underlying C compile is
+    /// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
+    pub fn new() -> Self {
+        let compiler = env::var("CC").unwrap();
+
+        let mut cmd = Command::new(compiler);
+
+        let default_cflags = env::var("CC_DEFAULT_FLAGS").unwrap();
+        for flag in default_cflags.split(char::is_whitespace) {
+            cmd.arg(flag);
+        }
+
+        Self { cmd }
+    }
+
+    /// Specify path of the input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Add a *platform-and-compiler-specific* argument. Please consult the docs for the various
+    /// possible C compilers on the various platforms to check which arguments are legal for
+    /// which compiler.
+    pub fn arg(&mut self, flag: &str) -> &mut Self {
+        self.cmd.arg(flag);
+        self
+    }
+
+    /// Add multiple *platform-and-compiler-specific* arguments. Please consult the docs for the
+    /// various possible C compilers on the various platforms to check which arguments are legal
+    /// for which compiler.
+    pub fn args(&mut self, args: &[&str]) -> &mut Self {
+        self.cmd.args(args);
+        self
+    }
+
+    /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
+    /// is under `$TMPDIR`.
+    pub fn out_exe(&mut self, name: &str) -> &mut Self {
+        // Ref: tools.mk (irrelevant lines omitted):
+        //
+        // ```makefile
+        // ifdef IS_MSVC
+        //     OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
+        //         -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
+        // else
+        //     OUT_EXE=-o $(TMPDIR)/$(1)
+        // endif
+        // ```
+
+        if is_msvc() {
+            let fe_path = cygpath_windows(tmp_dir().join(bin_name(name)));
+            let fo_path = cygpath_windows(tmp_dir().join(format!("{name}.obj")));
+            self.cmd.arg(format!("-Fe:{fe_path}"));
+            self.cmd.arg(format!("-Fo:{fo_path}"));
+        } else {
+            self.cmd.arg("-o");
+            self.cmd.arg(tmp_dir().join(name));
+        }
+
+        self
+    }
+
+    /// Run the constructed C invocation command and assert that it is successfully run.
+    #[track_caller]
+    pub fn run(&mut self) -> Output {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.cmd.output().unwrap();
+        if !output.status.success() {
+            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
+        }
+        output
+    }
+
+    /// Inspect what the underlying [`Command`] is up to the current construction.
+    pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
+        f(&self.cmd);
+        self
+    }
+}
+
+/// `EXTRACFLAGS`
+pub fn extra_c_flags() -> Vec<&'static str> {
+    // Adapted from tools.mk (trimmed):
+    //
+    // ```makefile
+    // ifdef IS_WINDOWS
+    //     ifdef IS_MSVC
+    //         EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib
+    //     else
+    //         EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization
+    //     endif
+    // else
+    //     ifeq ($(UNAME),Darwin)
+    //         EXTRACFLAGS := -lresolv
+    //     else
+    //         ifeq ($(UNAME),FreeBSD)
+    //             EXTRACFLAGS := -lm -lpthread -lgcc_s
+    //         else
+    //             ifeq ($(UNAME),SunOS)
+    //                 EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv
+    //             else
+    //                 ifeq ($(UNAME),OpenBSD)
+    //                     EXTRACFLAGS := -lm -lpthread -lc++abi
+    //                 else
+    //                     EXTRACFLAGS := -lm -lrt -ldl -lpthread
+    //                 endif
+    //             endif
+    //         endif
+    //     endif
+    // endif
+    // ```
+
+    if is_windows() {
+        if is_msvc() {
+            vec![
+                "ws2_32.lib",
+                "userenv.lib",
+                "advapi32.lib",
+                "bcrypt.lib",
+                "ntdll.lib",
+                "synchronization.lib",
+            ]
+        } else {
+            vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"]
+        }
+    } else {
+        match uname() {
+            n if n.contains("Darwin") => vec!["-lresolv"],
+            n if n.contains("FreeBSD") => vec!["-lm", "-lpthread", "-lgcc_s"],
+            n if n.contains("SunOS") => {
+                vec!["-lm", "-lpthread", "-lposix4", "-lsocket", "-lresolv"]
+            }
+            n if n.contains("OpenBSD") => vec!["-lm", "-lpthread", "-lc++abi"],
+            _ => vec!["-lm", "-lrt", "-ldl", "-lpthread"],
+        }
+    }
+}
+
+/// `EXTRACXXFLAGS`
+pub fn extra_cxx_flags() -> Vec<&'static str> {
+    // Adapted from tools.mk (trimmed):
+    //
+    // ```makefile
+    // ifdef IS_WINDOWS
+    //     ifdef IS_MSVC
+    //     else
+    //         EXTRACXXFLAGS := -lstdc++
+    //     endif
+    // else
+    //     ifeq ($(UNAME),Darwin)
+    //         EXTRACXXFLAGS := -lc++
+    //     else
+    //         ifeq ($(UNAME),FreeBSD)
+    //         else
+    //             ifeq ($(UNAME),SunOS)
+    //             else
+    //                 ifeq ($(UNAME),OpenBSD)
+    //                 else
+    //                     EXTRACXXFLAGS := -lstdc++
+    //                 endif
+    //             endif
+    //         endif
+    //     endif
+    // endif
+    // ```
+    if is_windows() {
+        if is_msvc() { vec![] } else { vec!["-lstdc++"] }
+    } else {
+        match uname() {
+            n if n.contains("Darwin") => vec!["-lc++"],
+            _ => vec!["-lstdc++"],
+        }
+    }
+}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 48fa2bbf1ac..e70acf58571 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -1,14 +1,16 @@
+pub mod cc;
 pub mod run;
 pub mod rustc;
 pub mod rustdoc;
 
 use std::env;
-use std::path::PathBuf;
-use std::process::Output;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Output};
 
 pub use object;
 pub use wasmparser;
 
+pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
 pub use run::{run, run_fail};
 pub use rustc::{aux_build, rustc, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
@@ -18,6 +20,89 @@ pub fn tmp_dir() -> PathBuf {
     env::var_os("TMPDIR").unwrap().into()
 }
 
+/// `TARGET`
+pub fn target() -> String {
+    env::var("TARGET").unwrap()
+}
+
+/// Check if target is windows-like.
+pub fn is_windows() -> bool {
+    env::var_os("IS_WINDOWS").is_some()
+}
+
+/// Check if target uses msvc.
+pub fn is_msvc() -> bool {
+    env::var_os("IS_MSVC").is_some()
+}
+
+/// Construct a path to a static library under `$TMPDIR` given the library name. This will return a
+/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
+pub fn static_lib(name: &str) -> PathBuf {
+    tmp_dir().join(static_lib_name(name))
+}
+
+/// Construct the static library name based on the platform.
+pub fn static_lib_name(name: &str) -> String {
+    // See tools.mk (irrelevant lines omitted):
+    //
+    // ```makefile
+    // ifeq ($(UNAME),Darwin)
+    //     STATICLIB = $(TMPDIR)/lib$(1).a
+    // else
+    //     ifdef IS_WINDOWS
+    //         ifdef IS_MSVC
+    //             STATICLIB = $(TMPDIR)/$(1).lib
+    //         else
+    //             STATICLIB = $(TMPDIR)/lib$(1).a
+    //         endif
+    //     else
+    //         STATICLIB = $(TMPDIR)/lib$(1).a
+    //     endif
+    // endif
+    // ```
+    assert!(!name.contains(char::is_whitespace), "name cannot contain whitespace");
+
+    if target().contains("msvc") { format!("{name}.lib") } else { format!("lib{name}.a") }
+}
+
+/// Construct the binary name based on platform.
+pub fn bin_name(name: &str) -> String {
+    if is_windows() { format!("{name}.exe") } else { name.to_string() }
+}
+
+/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
+/// available on the platform!
+#[track_caller]
+pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
+    let caller_location = std::panic::Location::caller();
+    let caller_line_number = caller_location.line();
+
+    let mut cygpath = Command::new("cygpath");
+    cygpath.arg("-w");
+    cygpath.arg(path.as_ref());
+    let output = cygpath.output().unwrap();
+    if !output.status.success() {
+        handle_failed_output(&format!("{:#?}", cygpath), output, caller_line_number);
+    }
+    let s = String::from_utf8(output.stdout).unwrap();
+    // cygpath -w can attach a newline
+    s.trim().to_string()
+}
+
+/// Run `uname`. This assumes that `uname` is available on the platform!
+#[track_caller]
+pub fn uname() -> String {
+    let caller_location = std::panic::Location::caller();
+    let caller_line_number = caller_location.line();
+
+    let mut uname = Command::new("uname");
+    let output = uname.output().unwrap();
+    if !output.status.success() {
+        handle_failed_output(&format!("{:#?}", uname), output, caller_line_number);
+    }
+    String::from_utf8(output.stdout).unwrap()
+}
+
 fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
     if output.status.success() {
         eprintln!("command incorrectly succeeded at line {caller_line_number}");
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 42dcf54da22..e33ea9d6e40 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -2,17 +2,14 @@ use std::env;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Output};
 
-use super::handle_failed_output;
+use crate::is_windows;
 
-fn run_common(bin_name: &str) -> (Command, Output) {
-    let target = env::var("TARGET").unwrap();
-
-    let bin_name =
-        if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
+use super::{bin_name, handle_failed_output};
 
+fn run_common(name: &str) -> (Command, Output) {
     let mut bin_path = PathBuf::new();
     bin_path.push(env::var("TMPDIR").unwrap());
-    bin_path.push(&bin_name);
+    bin_path.push(&bin_name(name));
     let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
     let mut cmd = Command::new(bin_path);
     cmd.env(&ld_lib_path_envvar, {
@@ -27,7 +24,7 @@ fn run_common(bin_name: &str) -> (Command, Output) {
         env::join_paths(paths.iter()).unwrap()
     });
 
-    if target.contains("windows") {
+    if is_windows() {
         let mut paths = vec![];
         for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
             paths.push(p.to_path_buf());
@@ -42,11 +39,11 @@ fn run_common(bin_name: &str) -> (Command, Output) {
 
 /// Run a built binary and make sure it succeeds.
 #[track_caller]
-pub fn run(bin_name: &str) -> Output {
+pub fn run(name: &str) -> Output {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
-    let (cmd, output) = run_common(bin_name);
+    let (cmd, output) = run_common(name);
     if !output.status.success() {
         handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
     }
@@ -55,11 +52,11 @@ pub fn run(bin_name: &str) -> Output {
 
 /// Run a built binary and make sure it fails.
 #[track_caller]
-pub fn run_fail(bin_name: &str) -> Output {
+pub fn run_fail(name: &str) -> Output {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
-    let (cmd, output) = run_common(bin_name);
+    let (cmd, output) = run_common(name);
     if output.status.success() {
         handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
     }
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 347ea1223eb..c3ed1ff6891 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -5,7 +5,6 @@ run-make/allocator-shim-circular-deps/Makefile
 run-make/allow-non-lint-warnings-cmdline/Makefile
 run-make/allow-warnings-cmdline-stability/Makefile
 run-make/archive-duplicate-names/Makefile
-run-make/arguments-non-c-like-enum/Makefile
 run-make/atomic-lock-free/Makefile
 run-make/bare-outfile/Makefile
 run-make/branch-protection-check-IBT/Makefile
@@ -131,7 +130,6 @@ run-make/issue-53964/Makefile
 run-make/issue-64153/Makefile
 run-make/issue-68794-textrel-on-minimal-lib/Makefile
 run-make/issue-69368/Makefile
-run-make/issue-7349/Makefile
 run-make/issue-83045/Makefile
 run-make/issue-83112-incr-test-moved-file/Makefile
 run-make/issue-84395-lto-embed-bitcode/Makefile
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index b74afa0d3e8..aec2856dbbc 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -56,7 +56,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
         Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
     ),
     // tidy-alphabetical-start
-    //("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None), // FIXME uncomment once all deps are vendored
+    ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None),
     //("library/backtrace", &[], None), // FIXME uncomment once rust-lang/backtrace#562 has been synced back to the rust repo
     //("library/portable-simd", &[], None), // FIXME uncomment once rust-lang/portable-simd#363 has been synced back to the rust repo
     //("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo
@@ -164,15 +164,12 @@ const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-end
 ];
 
-// FIXME uncomment once all deps are vendored
-/*
 const EXCEPTIONS_GCC: ExceptionList = &[
     // tidy-alphabetical-start
     ("gccjit", "GPL-3.0"),
     ("gccjit_sys", "GPL-3.0"),
     // tidy-alphabetical-end
 ];
-*/
 
 const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[
     ("ryu", "Apache-2.0 OR BSL-1.0"), // through serde. BSL is not acceptble, but we use it under Apache-2.0
diff --git a/tests/codegen/no-redundant-item-monomorphization.rs b/tests/codegen/no-redundant-item-monomorphization.rs
new file mode 100644
index 00000000000..466037c3770
--- /dev/null
+++ b/tests/codegen/no-redundant-item-monomorphization.rs
@@ -0,0 +1,33 @@
+// Test to make sure that inner functions within a polymorphic outer function
+// don't get re-codegened when the outer function is monomorphized. The test
+// code monomorphizes the outer functions several times, but the magic constants
+// used in the inner functions should each appear only once in the generated IR.
+
+// issue: rust-lang/rust#7349
+//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0
+
+// CHECK-COUNT-1: ret i32 8675309
+// CHECK-COUNT-1: ret i32 11235813
+
+fn outer<T>() {
+    #[allow(dead_code)]
+    fn inner() -> u32 {
+        8675309
+    }
+    inner();
+}
+
+extern "C" fn outer_foreign<T>() {
+    #[allow(dead_code)]
+    fn inner() -> u32 {
+        11235813
+    }
+    inner();
+}
+
+fn main() {
+    outer::<isize>();
+    outer::<usize>();
+    outer_foreign::<isize>();
+    outer_foreign::<usize>();
+}
diff --git a/tests/run-make/arguments-non-c-like-enum/Makefile b/tests/run-make/arguments-non-c-like-enum/Makefile
deleted file mode 100644
index 0c8d8bf3acc..00000000000
--- a/tests/run-make/arguments-non-c-like-enum/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type=staticlib nonclike.rs
-	$(CC) test.c $(call STATICLIB,nonclike) $(call OUT_EXE,test) \
-		$(EXTRACFLAGS) $(EXTRACXXFLAGS)
-	$(call RUN,test)
diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs
new file mode 100644
index 00000000000..624a7fb2251
--- /dev/null
+++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs
@@ -0,0 +1,20 @@
+//! Check that non-trivial `repr(C)` enum in Rust has valid C layout.
+//@ ignore-cross-compile
+
+extern crate run_make_support;
+
+use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib};
+
+pub fn main() {
+    use std::path::Path;
+
+    rustc().input("nonclike.rs").crate_type("staticlib").run();
+    cc().input("test.c")
+        .input(static_lib("nonclike"))
+        .out_exe("test")
+        .args(&extra_c_flags())
+        .args(&extra_cxx_flags())
+        .inspect(|cmd| eprintln!("{cmd:?}"))
+        .run();
+    run("test");
+}
diff --git a/tests/run-make/issue-7349/Makefile b/tests/run-make/issue-7349/Makefile
deleted file mode 100644
index dc073b77fe1..00000000000
--- a/tests/run-make/issue-7349/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../tools.mk
-
-# Test to make sure that inner functions within a polymorphic outer function
-# don't get re-codegened when the outer function is monomorphized.  The test
-# code monomorphizes the outer functions several times, but the magic constants
-# used in the inner functions should each appear only once in the generated IR.
-
-all:
-	$(RUSTC) foo.rs --emit=llvm-ir
-	[ "$$(grep -c 'ret i32 8675309' "$(TMPDIR)/foo.ll")" -eq "1" ]
-	[ "$$(grep -c 'ret i32 11235813' "$(TMPDIR)/foo.ll")" -eq "1" ]
diff --git a/tests/run-make/issue-7349/foo.rs b/tests/run-make/issue-7349/foo.rs
deleted file mode 100644
index 246a1259580..00000000000
--- a/tests/run-make/issue-7349/foo.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-fn outer<T>() {
-    #[allow(dead_code)]
-    fn inner() -> u32 {
-        8675309
-    }
-    inner();
-}
-
-extern "C" fn outer_foreign<T>() {
-    #[allow(dead_code)]
-    fn inner() -> u32 {
-        11235813
-    }
-    inner();
-}
-
-fn main() {
-    outer::<isize>();
-    outer::<usize>();
-    outer_foreign::<isize>();
-    outer_foreign::<usize>();
-}
diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs
index e3ab8713709..0a9d0529bf5 100644
--- a/tests/ui/async-await/async-closures/captures.rs
+++ b/tests/ui/async-await/async-closures/captures.rs
@@ -79,4 +79,38 @@ async fn async_main() {
         };
         call_once(c).await;
     }
+
+    fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
+        f
+    }
+
+    // Capture something with `move`, but infer to `AsyncFnOnce`
+    {
+        let x = Hello(6);
+        let c = force_fnonce(async move || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+
+        let x = &Hello(7);
+        let c = force_fnonce(async move || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+    }
+
+    // Capture something by-ref, but infer to `AsyncFnOnce`
+    {
+        let x = Hello(8);
+        let c = force_fnonce(async || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+
+        let x = &Hello(9);
+        let c = force_fnonce(async || {
+            println!("{x:?}");
+        });
+        call_once(c).await;
+    }
 }
diff --git a/tests/ui/async-await/async-closures/captures.run.stdout b/tests/ui/async-await/async-closures/captures.run.stdout
index a0db6d236fe..42a7999b2dc 100644
--- a/tests/ui/async-await/async-closures/captures.run.stdout
+++ b/tests/ui/async-await/async-closures/captures.run.stdout
@@ -8,3 +8,7 @@ Hello(3)
 Hello(4)
 Hello(4)
 Hello(5)
+Hello(6)
+Hello(7)
+Hello(8)
+Hello(9)
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
index 8502bb6e2d4..3d6f856874f 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
@@ -2,18 +2,22 @@
 
 #![feature(async_closure)]
 
-fn main() {
-    fn needs_async_fn(_: impl async Fn()) {}
+fn needs_async_fn(_: impl async Fn()) {}
 
+fn a() {
     let mut x = 1;
     needs_async_fn(async || {
-        //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
+        //~^ ERROR cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
         x += 1;
     });
+}
 
+fn b() {
     let x = String::new();
     needs_async_fn(move || async move {
         //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
         println!("{x}");
     });
 }
+
+fn main() {}
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
index d0f1948e48f..e56389b3202 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
@@ -1,26 +1,5 @@
-error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
-  --> $DIR/wrong-fn-kind.rs:9:20
-   |
-LL |       needs_async_fn(async || {
-   |       -------------- -^^^^^^^
-   |       |              |
-   |  _____|______________this closure implements `async FnMut`, not `async Fn`
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |         x += 1;
-   | |         - closure is `async FnMut` because it mutates the variable `x` here
-LL | |     });
-   | |_____- the requirement to implement `async Fn` derives from here
-   |
-note: required by a bound in `needs_async_fn`
-  --> $DIR/wrong-fn-kind.rs:6:31
-   |
-LL |     fn needs_async_fn(_: impl async Fn()) {}
-   |                               ^^^^^^^^^^ required by this bound in `needs_async_fn`
-
 error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
-  --> $DIR/wrong-fn-kind.rs:15:20
+  --> $DIR/wrong-fn-kind.rs:17:20
    |
 LL |       needs_async_fn(move || async move {
    |       -------------- -^^^^^^
@@ -35,11 +14,29 @@ LL | |     });
    | |_____- the requirement to implement `async Fn` derives from here
    |
 note: required by a bound in `needs_async_fn`
-  --> $DIR/wrong-fn-kind.rs:6:31
+  --> $DIR/wrong-fn-kind.rs:5:27
+   |
+LL | fn needs_async_fn(_: impl async Fn()) {}
+   |                           ^^^^^^^^^^ required by this bound in `needs_async_fn`
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/wrong-fn-kind.rs:9:29
    |
-LL |     fn needs_async_fn(_: impl async Fn()) {}
-   |                               ^^^^^^^^^^ required by this bound in `needs_async_fn`
+LL |   fn needs_async_fn(_: impl async Fn()) {}
+   |                        --------------- change this to accept `FnMut` instead of `Fn`
+...
+LL |       needs_async_fn(async || {
+   |  _____--------------_--------_^
+   | |     |              |
+   | |     |              in this closure
+   | |     expects `Fn` instead of `FnMut`
+LL | |
+LL | |         x += 1;
+   | |         - mutable borrow occurs due to use of `x` in closure
+LL | |     });
+   | |_____^ cannot borrow as mutable
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0525`.
+Some errors have detailed explanations: E0525, E0596.
+For more information about an error, try `rustc --explain E0525`.
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
new file mode 100644
index 00000000000..5eef3256b2c
--- /dev/null
+++ b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
@@ -0,0 +1,27 @@
+error[E0726]: implicit elided lifetime not allowed here
+  --> $DIR/skip-reporting-if-references-err.rs:10:9
+   |
+LL | impl<T> ToUnit for T {}
+   |         ^^^^^^ expected lifetime parameter
+   |
+help: indicate the anonymous lifetime
+   |
+LL | impl<T> ToUnit<'_> for T {}
+   |               ++++
+
+error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
+  --> $DIR/skip-reporting-if-references-err.rs:15:29
+   |
+LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
+
+error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
+  --> $DIR/skip-reporting-if-references-err.rs:15:18
+   |
+LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0726.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr
new file mode 100644
index 00000000000..5de4cf626e4
--- /dev/null
+++ b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr
@@ -0,0 +1,14 @@
+error[E0726]: implicit elided lifetime not allowed here
+  --> $DIR/skip-reporting-if-references-err.rs:10:9
+   |
+LL | impl<T> ToUnit for T {}
+   |         ^^^^^^ expected lifetime parameter
+   |
+help: indicate the anonymous lifetime
+   |
+LL | impl<T> ToUnit<'_> for T {}
+   |               ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0726`.
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs
new file mode 100644
index 00000000000..f9eaa498232
--- /dev/null
+++ b/tests/ui/coherence/skip-reporting-if-references-err.rs
@@ -0,0 +1,19 @@
+// Regression test for #121006.
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+trait ToUnit<'a> {
+    type Unit;
+}
+
+impl<T> ToUnit for T {}
+//~^ ERROR implicit elided lifetime not allowed here
+
+trait Overlap {}
+impl<U> Overlap for fn(U) {}
+impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
+//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
+//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
new file mode 100644
index 00000000000..ed5db56e0e8
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
@@ -0,0 +1,14 @@
+pub fn main() {
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &Some(Some(0)) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+}
diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr
new file mode 100644
index 00000000000..0f0051325cd
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr
@@ -0,0 +1,49 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_everywhere.rs:2:22
+   |
+LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
+   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(Some(x)) = &Some(&Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_everywhere.rs:6:17
+   |
+LL |     if let Some(&Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&_`
+   |
+   = note:   expected enum `Option<{integer}>`
+           found reference `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
+   |                      ~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs
new file mode 100644
index 00000000000..9dd7a7893ec
--- /dev/null
+++ b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs
@@ -0,0 +1,16 @@
+#![allow(incomplete_features)]
+#![feature(ref_pat_everywhere)]
+pub fn main() {
+    if let Some(&x) = Some(0) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+    if let &Some(x) = &mut Some(0) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+    if let Some(&x) = &mut Some(0) {
+        //~^ ERROR: mismatched types [E0308]
+        let _: u32 = x;
+    }
+}
diff --git a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
new file mode 100644
index 00000000000..d512ea5f957
--- /dev/null
+++ b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
@@ -0,0 +1,44 @@
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:4:17
+   |
+LL |     if let Some(&x) = Some(0) {
+   |                 ^^    ------- this expression has type `Option<{integer}>`
+   |                 |
+   |                 expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(x) = Some(0) {
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:8:12
+   |
+LL |     if let &Some(x) = &mut Some(0) {
+   |            ^^^^^^^^   ------------ this expression has type `&mut Option<{integer}>`
+   |            |
+   |            types differ in mutability
+   |
+   = note: expected mutable reference `&mut Option<{integer}>`
+                      found reference `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:12:17
+   |
+LL |     if let Some(&x) = &mut Some(0) {
+   |                 ^^    ------------ this expression has type `&mut Option<{integer}>`
+   |                 |
+   |                 expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(x) = &mut Some(0) {
+   |                 ~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere.rs b/tests/ui/match/ref_pat_everywhere.rs
new file mode 100644
index 00000000000..b3daca48409
--- /dev/null
+++ b/tests/ui/match/ref_pat_everywhere.rs
@@ -0,0 +1,18 @@
+//@ run-pass
+#![allow(incomplete_features)]
+#![feature(ref_pat_everywhere)]
+
+pub fn main() {
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &Some(Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+}
diff --git a/triagebot.toml b/triagebot.toml
index 55f0d32398f..3db0f7dc443 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -469,11 +469,11 @@ message = "Some changes occurred in need_type_info.rs"
 cc = ["@lcnr"]
 
 [mentions."compiler/rustc_middle/src/ty/relate.rs"]
-message = "Type relation code was changed"
+message = "changes to the core type system"
 cc = ["@compiler-errors", "@lcnr"]
 
 [mentions."compiler/rustc_infer/src/infer/relate"]
-message = "Type relation code was changed"
+message = "changes to the core type system"
 cc = ["@compiler-errors", "@lcnr"]
 
 [mentions."compiler/rustc_middle/src/mir/interpret"]
@@ -484,6 +484,10 @@ cc = ["@rust-lang/miri"]
 message = "Some changes occurred to MIR optimizations"
 cc = ["@rust-lang/wg-mir-opt"]
 
+[mentions."compiler/rustc_trait_selection/src/traits/wf.rs"]
+message = "changes to the core type system"
+cc = ["@compiler-errors", "@lcnr"]
+
 [mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
 message = "Some changes occurred in `const_evaluatable.rs`"
 cc = ["@BoxyUwU"]