about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_ast/src/ast.rs6
-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.rs51
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs63
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs2
-rw-r--r--compiler/rustc_borrowck/messages.ftl4
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs18
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs11
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/lib.rs106
-rw-r--r--compiler/rustc_borrowck/src/nll.rs30
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/accesses.rs10
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/facts.rs42
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs10
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs10
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/location.rs8
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/mod.rs20
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs53
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs49
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs34
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh1
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/build.rs2
-rw-r--r--compiler/rustc_expand/src/config.rs17
-rw-r--r--compiler/rustc_hir/src/hir.rs49
-rw-r--r--compiler/rustc_hir/src/intravisit.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs42
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs20
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs90
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs70
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs22
-rw-r--r--compiler/rustc_lint/src/builtin.rs11
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs14
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs39
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs179
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs23
-rw-r--r--compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs7
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs12
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs6
-rw-r--r--compiler/rustc_passes/src/input_stats.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs4
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs35
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs32
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs106
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/core/src/ptr/non_null.rs48
-rw-r--r--library/std/src/thread/mod.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs43
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs43
-rw-r--r--src/bootstrap/src/core/builder/mod.rs4
-rw-r--r--src/doc/rustc/src/SUMMARY.md19
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/win7-windows-gnu.md48
-rw-r--r--src/doc/rustc/src/platform-support/win7-windows-msvc.md8
-rw-r--r--src/etc/installer/msi/rust.wxs41
-rw-r--r--src/librustdoc/clean/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/equatable_if_let.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_range_patterns.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_bool.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/needless_match.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/string_patterns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs35
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs59
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs46
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/tests/ui/author/if.stdout4
-rw-r--r--src/tools/clippy/tests/ui/author/loop.stdout4
-rw-r--r--src/tools/clippy/tests/ui/author/matches.stdout8
-rw-r--r--src/tools/clippy/tests/ui/author/struct.stdout8
-rw-r--r--src/tools/replace-version-placeholder/src/main.rs7
-rw-r--r--src/tools/rustfmt/src/patterns.rs6
-rw-r--r--tests/assembly/targets/targets-pe.rs6
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff6
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff6
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff6
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff6
-rw-r--r--tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff340
-rw-r--r--tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff340
-rw-r--r--tests/mir-opt/gvn.rs102
-rw-r--r--tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-abort.diff115
-rw-r--r--tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-unwind.diff115
-rw-r--r--tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff74
-rw-r--r--tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff74
-rw-r--r--tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff87
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir2
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir2
-rw-r--r--tests/mir-opt/inline/unsized_argument.caller.Inline.diff2
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff83
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.keep_transparent_transmute.InstSimplify-after-simplifycfg.diff30
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.rs25
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir182
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir132
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir116
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir116
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir130
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir130
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir46
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir46
-rw-r--r--tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir1
-rw-r--r--tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir1
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr93
-rw-r--r--tests/ui/consts/promoted_const_call.stderr4
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs51
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr52
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order.rs1
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order.stderr27
-rw-r--r--tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr4
-rw-r--r--tests/ui/drop/tail_expr_drop_order-on-recursive-boxed-fut.rs13
-rw-r--r--tests/ui/drop/tail_expr_drop_order-on-thread-local.rs56
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr19
-rw-r--r--tests/ui/invalid-compile-flags/crate-type-flag.rs1
-rw-r--r--tests/ui/macros/stringify.rs2
-rw-r--r--tests/ui/pattern/patkind-litrange-no-expr.rs2
-rw-r--r--tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs10
-rw-r--r--tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr34
-rw-r--r--tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs9
-rw-r--r--tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr14
-rw-r--r--tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs70
-rw-r--r--tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr124
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.rs3
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.stderr17
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.precise.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.stock.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.rs7
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.rs4
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout4
-rw-r--r--tests/ui/unpretty/unpretty-expr-fn-arg.stdout2
-rw-r--r--triagebot.toml13
179 files changed, 3723 insertions, 1435 deletions
diff --git a/RELEASES.md b/RELEASES.md
index fe557a08a9d..7c2c2406e90 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -37,7 +37,7 @@ Libraries
 - [Move `<float>::copysign`, `<float>::abs`, `<float>::signum` to `core`](https://github.com/rust-lang/rust/pull/131304)
 - [Add `LowerExp` and `UpperExp` implementations to `NonZero`](https://github.com/rust-lang/rust/pull/131377)
 - [Implement `FromStr` for `CString` and `TryFrom<CString>` for `String`](https://github.com/rust-lang/rust/pull/130608)
-- [`std::os::darwin` has been made public](https://github.com/rust-lang/rust/pull/130635)
+- [`std::os::darwin` has been made public](https://github.com/rust-lang/rust/pull/123723)
 
 <a id="1.84.0-Stabilized-APIs"></a>
 
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 3a81b93d157..8e73df63ef5 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -623,7 +623,7 @@ impl Pat {
             PatKind::Wild
             | PatKind::Rest
             | PatKind::Never
-            | PatKind::Lit(_)
+            | PatKind::Expr(_)
             | PatKind::Range(..)
             | PatKind::Ident(..)
             | PatKind::Path(..)
@@ -801,8 +801,8 @@ pub enum PatKind {
     /// A reference pattern (e.g., `&mut (a, b)`).
     Ref(P<Pat>, Mutability),
 
-    /// A literal.
-    Lit(P<Expr>),
+    /// A literal, const block or path.
+    Expr(P<Expr>),
 
     /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
     Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 04cdfc93dcb..aa88e8369d5 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1512,7 +1512,7 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
             vis.visit_ident(ident);
             visit_opt(sub, |sub| vis.visit_pat(sub));
         }
-        PatKind::Lit(e) => vis.visit_expr(e),
+        PatKind::Expr(e) => vis.visit_expr(e),
         PatKind::TupleStruct(qself, path, elems) => {
             vis.visit_qself(qself);
             vis.visit_path(path);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e99fc7b604e..1d6d7330757 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -680,7 +680,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
             try_visit!(visitor.visit_ident(ident));
             visit_opt!(visitor, visit_pat, optional_subpattern);
         }
-        PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)),
+        PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)),
         PatKind::Range(lower_bound, upper_bound, _end) => {
             visit_opt!(visitor, visit_expr, lower_bound);
             visit_opt!(visitor, visit_expr, upper_bound);
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index d16a3ce390d..a76ca6772e5 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -102,17 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
-                ExprKind::ConstBlock(c) => {
-                    let c = self.with_new_scopes(c.value.span, |this| {
-                        let def_id = this.local_def_id(c.id);
-                        hir::ConstBlock {
-                            def_id,
-                            hir_id: this.lower_node_id(c.id),
-                            body: this.lower_const_body(c.value.span, Some(&c.value)),
-                        }
-                    });
-                    hir::ExprKind::ConstBlock(c)
-                }
+                ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
                 ExprKind::Repeat(expr, count) => {
                     let expr = self.lower_expr(expr);
                     let count = self.lower_array_length_to_const_arg(count);
@@ -153,18 +143,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::Unary(op, ohs)
                 }
-                ExprKind::Lit(token_lit) => {
-                    let lit_kind = match LitKind::from_token_lit(*token_lit) {
-                        Ok(lit_kind) => lit_kind,
-                        Err(err) => {
-                            let guar =
-                                report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span);
-                            LitKind::Err(guar)
-                        }
-                    };
-                    let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
-                    hir::ExprKind::Lit(lit)
-                }
+                ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
                 ExprKind::IncludedBytes(bytes) => {
                     let lit = self.arena.alloc(respan(
                         self.lower_span(e.span),
@@ -403,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
+        self.with_new_scopes(c.value.span, |this| {
+            let def_id = this.local_def_id(c.id);
+            hir::ConstBlock {
+                def_id,
+                hir_id: this.lower_node_id(c.id),
+                body: this.lower_const_body(c.value.span, Some(&c.value)),
+            }
+        })
+    }
+
+    pub(crate) fn lower_lit(
+        &mut self,
+        token_lit: &token::Lit,
+        span: Span,
+    ) -> &'hir Spanned<LitKind> {
+        let lit_kind = match LitKind::from_token_lit(*token_lit) {
+            Ok(lit_kind) => lit_kind,
+            Err(err) => {
+                let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);
+                LitKind::Err(guar)
+            }
+        };
+        self.arena.alloc(respan(self.lower_span(span), lit_kind))
+    }
+
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
         match u {
             UnOp::Deref => hir::UnOp::Deref,
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index c3ff7b4b897..29d4fb9ef25 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -209,6 +209,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
+    fn visit_pat_expr(&mut self, expr: &'hir PatExpr<'hir>) {
+        self.insert(expr.span, expr.hir_id, Node::PatExpr(expr));
+
+        self.with_parent(expr.hir_id, |this| {
+            intravisit::walk_pat_expr(this, expr);
+        });
+    }
+
     fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) {
         self.insert(field.span, field.hir_id, Node::PatField(field));
         self.with_parent(field.hir_id, |this| {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index fe2d5a594f3..0e28590bd66 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -35,6 +35,7 @@
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![warn(unreachable_pub)]
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 40e7d6430fd..abd314ae74c 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -1,9 +1,12 @@
+use std::sync::Arc;
+
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_span::source_map::Spanned;
+use rustc_middle::span_bug;
+use rustc_span::source_map::{Spanned, respan};
 use rustc_span::{Ident, Span};
 
 use super::errors::{
@@ -35,8 +38,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             lower_sub,
                         );
                     }
-                    PatKind::Lit(e) => {
-                        break hir::PatKind::Lit(self.lower_expr_within_pat(e, false));
+                    PatKind::Expr(e) => {
+                        break hir::PatKind::Expr(self.lower_expr_within_pat(e, false));
                     }
                     PatKind::TupleStruct(qself, path, pats) => {
                         let qpath = self.lower_qpath(
@@ -367,24 +370,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     // }
     // m!(S);
     // ```
-    fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> {
-        match &expr.kind {
-            ExprKind::Lit(..)
-            | ExprKind::ConstBlock(..)
-            | ExprKind::IncludedBytes(..)
-            | ExprKind::Err(_)
-            | ExprKind::Dummy => {}
-            ExprKind::Path(..) if allow_paths => {}
-            ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
+    fn lower_expr_within_pat(
+        &mut self,
+        expr: &Expr,
+        allow_paths: bool,
+    ) -> &'hir hir::PatExpr<'hir> {
+        let err = |guar| hir::PatExprKind::Lit {
+            lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))),
+            negated: false,
+        };
+        let kind = match &expr.kind {
+            ExprKind::Lit(lit) => {
+                hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false }
+            }
+            ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
+            ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit {
+                lit: self.arena.alloc(respan(
+                    self.lower_span(expr.span),
+                    LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
+                )),
+                negated: false,
+            },
+            ExprKind::Err(guar) => err(*guar),
+            ExprKind::Dummy => span_bug!(expr.span, "lowered ExprKind::Dummy"),
+            ExprKind::Path(qself, path) if allow_paths => hir::PatExprKind::Path(self.lower_qpath(
+                expr.id,
+                qself,
+                path,
+                ParamMode::Optional,
+                AllowReturnTypeNotation::No,
+                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                None,
+            )),
+            ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => {
+                hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: true }
+            }
             _ => {
                 let pattern_from_macro = expr.is_approximately_pattern();
                 let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
                     span: expr.span,
                     pattern_from_macro_note: pattern_from_macro,
                 });
-                return self.arena.alloc(self.expr_err(expr.span, guar));
+                err(guar)
             }
-        }
-        self.lower_expr(expr)
+        };
+        self.arena.alloc(hir::PatExpr {
+            hir_id: self.lower_node_id(expr.id),
+            span: expr.span,
+            kind,
+        })
     }
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 172df102929..9b958ed6b0d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1701,7 +1701,7 @@ impl<'a> State<'a> {
                     self.print_pat(inner);
                 }
             }
-            PatKind::Lit(e) => self.print_expr(e, FixupContext::default()),
+            PatKind::Expr(e) => self.print_expr(e, FixupContext::default()),
             PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => {
                 if let Some(e) = begin {
                     self.print_expr(e, FixupContext::default());
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index ee4b2f95cb1..ada20e5c614 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -213,6 +213,10 @@ borrowck_suggest_create_fresh_reborrow =
 borrowck_suggest_iterate_over_slice =
     consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
 
+borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024
+    .label = this temporary value will be dropped at the end of the block
+    .note = consider using a `let` binding to ensure the value will live long enough
+
 borrowck_ty_no_impl_copy =
     {$is_partial_move ->
         [true] partial move
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 7e8c48a1551..5a89f7c351c 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -11,8 +11,8 @@ pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_a
 pub use super::place_ext::PlaceExt;
 pub use super::places_conflict::{PlaceConflictBias, places_conflict};
 pub use super::polonius::legacy::{
-    AllFacts as PoloniusInput, LocationTable, PoloniusOutput, PoloniusRegionVid, RichLocation,
-    RustcFacts,
+    PoloniusFacts as PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid,
+    RichLocation, RustcFacts,
 };
 pub use super::region_infer::RegionInferenceContext;
 
@@ -33,7 +33,7 @@ pub enum ConsumerOptions {
     /// without significant slowdowns.
     ///
     /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
-    /// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that
+    /// and additionally retrieve the [`PoloniusLocationTable`] and [`PoloniusInput`] that
     /// would be given to Polonius. Critically, this does not run Polonius, which
     /// one may want to avoid due to performance issues on large bodies.
     PoloniusInputFacts,
@@ -71,7 +71,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
     /// The table that maps Polonius points to locations in the table.
     /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
     /// or [`ConsumerOptions::PoloniusOutputFacts`].
-    pub location_table: Option<LocationTable>,
+    pub location_table: Option<PoloniusLocationTable>,
     /// Polonius input facts.
     /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
     /// or [`ConsumerOptions::PoloniusOutputFacts`].
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 48f28f3f1de..a52dc447d76 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -5,7 +5,7 @@
 
 use std::assert_matches::assert_matches;
 
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_infer::infer::NllRegionVariableOrigin;
@@ -61,10 +61,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
     pub(crate) fn is_explained(&self) -> bool {
         !matches!(self, BorrowExplanation::Unexplained)
     }
-    pub(crate) fn add_explanation_to_diagnostic(
+    pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
         &self,
         cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
         multiple_borrow_span: Option<(Span, Span)>,
@@ -346,10 +346,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
         }
     }
 
-    fn add_object_lifetime_default_note(
+    fn add_object_lifetime_default_note<G: EmissionGuarantee>(
         &self,
         tcx: TyCtxt<'tcx>,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         unsize_ty: Ty<'tcx>,
     ) {
         if let ty::Adt(def, args) = unsize_ty.kind() {
@@ -403,9 +403,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
         }
     }
 
-    fn add_lifetime_bound_suggestion_to_diagnostic(
+    fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         category: &ConstraintCategory<'tcx>,
         span: Span,
         region_name: &RegionName,
@@ -432,14 +432,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
     }
 }
 
-fn suggest_rewrite_if_let(
+fn suggest_rewrite_if_let<G: EmissionGuarantee>(
     tcx: TyCtxt<'_>,
     expr: &hir::Expr<'_>,
     pat: &str,
     init: &hir::Expr<'_>,
     conseq: &hir::Expr<'_>,
     alt: Option<&hir::Expr<'_>>,
-    err: &mut Diag<'_>,
+    err: &mut Diag<'_, G>,
 ) {
     let source_map = tcx.sess.source_map();
     err.span_note(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0286ea6cd9d..d9d9ea75994 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
 
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{Applicability, Diag, MultiSpan};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::{self as hir, CoroutineKind, LangItem};
 use rustc_index::IndexSlice;
@@ -626,9 +626,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     /// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
     /// implicitly introduce an "outlives `'static`" constraint.
-    fn add_placeholder_from_predicate_note(
+    fn add_placeholder_from_predicate_note<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         path: &[OutlivesConstraint<'tcx>],
     ) {
         let predicate_span = path.iter().find_map(|constraint| {
@@ -651,9 +651,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     /// Add a label to region errors and borrow explanations when outlives constraints arise from
     /// proving a type implements `Sized` or `Copy`.
-    fn add_sized_or_copy_bound_info(
+    fn add_sized_or_copy_bound_info<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         blamed_category: ConstraintCategory<'tcx>,
         path: &[OutlivesConstraint<'tcx>],
     ) {
@@ -1042,6 +1042,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 kind,
             };
         }
+
         normal_ret
     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index bdb880b2bce..9349b46ec5b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -5,7 +5,7 @@ use std::fmt::{self, Display};
 use std::iter;
 
 use rustc_data_structures::fx::IndexEntry;
-use rustc_errors::Diag;
+use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::print::RegionHighlightMode;
@@ -108,7 +108,7 @@ impl RegionName {
         }
     }
 
-    pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_>) {
+    pub(crate) fn highlight_region_name<G: EmissionGuarantee>(&self, diag: &mut Diag<'_, G>) {
         match &self.source {
             RegionNameSource::NamedLateParamRegion(span)
             | RegionNameSource::NamedEarlyParamRegion(span) => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 88d0933d8ce..4f46a2cef7c 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -16,6 +16,7 @@
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
+use std::borrow::Cow;
 use std::cell::RefCell;
 use std::marker::PhantomData;
 use std::ops::{ControlFlow, Deref};
@@ -23,7 +24,9 @@ use std::ops::{ControlFlow, Deref};
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
+use rustc_errors::LintDiagnostic;
 use rustc_hir as hir;
+use rustc_hir::CRATE_HIR_ID;
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::{BitSet, MixedBitSet};
 use rustc_index::{IndexSlice, IndexVec};
@@ -43,7 +46,7 @@ use rustc_mir_dataflow::move_paths::{
     InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
 };
 use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
-use rustc_session::lint::builtin::UNUSED_MUT;
+use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
 use rustc_span::{Span, Symbol};
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
@@ -57,7 +60,7 @@ use crate::diagnostics::{
 use crate::path_utils::*;
 use crate::place_ext::PlaceExt;
 use crate::places_conflict::{PlaceConflictBias, places_conflict};
-use crate::polonius::legacy::{LocationTable, PoloniusOutput};
+use crate::polonius::legacy::{PoloniusLocationTable, PoloniusOutput};
 use crate::prefixes::PrefixSet;
 use crate::region_infer::RegionInferenceContext;
 use crate::renumber::RegionCtxt;
@@ -176,7 +179,7 @@ fn do_mir_borrowck<'tcx>(
         infcx.register_predefined_opaques_for_next_solver(def);
     }
 
-    let location_table = LocationTable::new(body);
+    let location_table = PoloniusLocationTable::new(body);
 
     let move_data = MoveData::gather_moves(body, tcx, |_| true);
     let promoted_move_data = promoted
@@ -247,7 +250,8 @@ fn do_mir_borrowck<'tcx>(
             infcx: &infcx,
             body: promoted_body,
             move_data: &move_data,
-            location_table: &location_table, // no need to create a real one for the promoted, it is not used
+            // no need to create a real location table for the promoted, it is not used
+            location_table: &location_table,
             movable_coroutine,
             fn_self_span_reported: Default::default(),
             locals_are_invalidated_at_exit,
@@ -513,7 +517,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
 
     /// Map from MIR `Location` to `LocationIndex`; created
     /// when MIR borrowck begins.
-    location_table: &'a LocationTable,
+    location_table: &'a PoloniusLocationTable,
 
     movable_coroutine: bool,
     /// This keeps track of whether local variables are free-ed when the function
@@ -636,9 +640,11 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
             | StatementKind::Coverage(..)
             // These do not actually affect borrowck
             | StatementKind::ConstEvalCounter
-            // This do not affect borrowck
-            | StatementKind::BackwardIncompatibleDropHint { .. }
             | StatementKind::StorageLive(..) => {}
+            // This does not affect borrowck
+            StatementKind::BackwardIncompatibleDropHint { place, reason: BackwardIncompatibleDropReason::Edition2024 } => {
+                self.check_backward_incompatible_drop(location, (**place, span), state);
+            }
             StatementKind::StorageDead(local) => {
                 self.access_place(
                     location,
@@ -1007,6 +1013,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         }
     }
 
+    fn borrows_in_scope<'s>(
+        &self,
+        location: Location,
+        state: &'s BorrowckDomain,
+    ) -> Cow<'s, BitSet<BorrowIndex>> {
+        if let Some(polonius) = &self.polonius_output {
+            // Use polonius output if it has been enabled.
+            let location = self.location_table.start_index(location);
+            let mut polonius_output = BitSet::new_empty(self.borrow_set.len());
+            for &idx in polonius.errors_at(location) {
+                polonius_output.insert(idx);
+            }
+            Cow::Owned(polonius_output)
+        } else {
+            Cow::Borrowed(&state.borrows)
+        }
+    }
+
     #[instrument(level = "debug", skip(self, state))]
     fn check_access_for_conflict(
         &mut self,
@@ -1018,18 +1042,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
     ) -> bool {
         let mut error_reported = false;
 
-        // Use polonius output if it has been enabled.
-        let mut polonius_output;
-        let borrows_in_scope = if let Some(polonius) = &self.polonius_output {
-            let location = self.location_table.start_index(location);
-            polonius_output = BitSet::new_empty(self.borrow_set.len());
-            for &idx in polonius.errors_at(location) {
-                polonius_output.insert(idx);
-            }
-            &polonius_output
-        } else {
-            &state.borrows
-        };
+        let borrows_in_scope = self.borrows_in_scope(location, state);
 
         each_borrow_involving_path(
             self,
@@ -1149,6 +1162,61 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         error_reported
     }
 
+    /// Through #123739, backward incompatible drops (BIDs) are introduced.
+    /// We would like to emit lints whether borrow checking fails at these future drop locations.
+    #[instrument(level = "debug", skip(self, state))]
+    fn check_backward_incompatible_drop(
+        &mut self,
+        location: Location,
+        (place, place_span): (Place<'tcx>, Span),
+        state: &BorrowckDomain,
+    ) {
+        let tcx = self.infcx.tcx;
+        // If this type does not need `Drop`, then treat it like a `StorageDead`.
+        // This is needed because we track the borrows of refs to thread locals,
+        // and we'll ICE because we don't track borrows behind shared references.
+        let sd = if place.ty(self.body, tcx).ty.needs_drop(tcx, self.body.typing_env(tcx)) {
+            AccessDepth::Drop
+        } else {
+            AccessDepth::Shallow(None)
+        };
+
+        let borrows_in_scope = self.borrows_in_scope(location, state);
+
+        // This is a very simplified version of `Self::check_access_for_conflict`.
+        // We are here checking on BIDs and specifically still-live borrows of data involving the BIDs.
+        each_borrow_involving_path(
+            self,
+            self.infcx.tcx,
+            self.body,
+            (sd, place),
+            self.borrow_set,
+            |borrow_index| borrows_in_scope.contains(borrow_index),
+            |this, _borrow_index, borrow| {
+                if matches!(borrow.kind, BorrowKind::Fake(_)) {
+                    return ControlFlow::Continue(());
+                }
+                let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
+                let explain = this.explain_why_borrow_contains_point(
+                    location,
+                    borrow,
+                    Some((WriteKind::StorageDeadOrDrop, place)),
+                );
+                this.infcx.tcx.node_span_lint(
+                    TAIL_EXPR_DROP_ORDER,
+                    CRATE_HIR_ID,
+                    borrowed,
+                    |diag| {
+                        session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
+                        explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
+                    },
+                );
+                // We may stop at the first case
+                ControlFlow::Break(())
+            },
+        );
+    }
+
     fn mutate_place(
         &mut self,
         location: Location,
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 7ae1df9522f..aa0bfd72147 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -28,7 +28,9 @@ use crate::borrow_set::BorrowSet;
 use crate::consumers::ConsumerOptions;
 use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
 use crate::polonius::LocalizedOutlivesConstraintSet;
-use crate::polonius::legacy::{AllFacts, AllFactsExt, LocationTable, PoloniusOutput};
+use crate::polonius::legacy::{
+    PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
+};
 use crate::region_infer::RegionInferenceContext;
 use crate::type_check::{self, MirTypeckResults};
 use crate::universal_regions::UniversalRegions;
@@ -39,7 +41,7 @@ use crate::{BorrowckInferCtxt, polonius, renumber};
 pub(crate) struct NllOutput<'tcx> {
     pub regioncx: RegionInferenceContext<'tcx>,
     pub opaque_type_values: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-    pub polonius_input: Option<Box<AllFacts>>,
+    pub polonius_input: Option<Box<PoloniusFacts>>,
     pub polonius_output: Option<Box<PoloniusOutput>>,
     pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
     pub nll_errors: RegionErrors<'tcx>,
@@ -80,7 +82,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
@@ -91,10 +93,10 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         || is_polonius_legacy_enabled;
     let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
         || is_polonius_legacy_enabled;
-    let mut all_facts =
-        (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
+    let mut polonius_facts =
+        (polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default());
 
-    let elements = Rc::new(DenseLocationMap::new(body));
+    let location_map = Rc::new(DenseLocationMap::new(body));
 
     // Run the MIR type-checker.
     let MirTypeckResults {
@@ -109,10 +111,10 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         universal_regions,
         location_table,
         borrow_set,
-        &mut all_facts,
+        &mut polonius_facts,
         flow_inits,
         move_data,
-        Rc::clone(&elements),
+        Rc::clone(&location_map),
     );
 
     // Create the region inference context, taking ownership of the
@@ -122,7 +124,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
 
     // If requested, emit legacy polonius facts.
     polonius::legacy::emit_facts(
-        &mut all_facts,
+        &mut polonius_facts,
         infcx.tcx,
         location_table,
         body,
@@ -137,7 +139,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         var_infos,
         constraints,
         universal_region_relations,
-        elements,
+        location_map,
     );
 
     // If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives
@@ -147,13 +149,13 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     });
 
     // If requested: dump NLL facts, and run legacy polonius analysis.
-    let polonius_output = all_facts.as_ref().and_then(|all_facts| {
+    let polonius_output = polonius_facts.as_ref().and_then(|polonius_facts| {
         if infcx.tcx.sess.opts.unstable_opts.nll_facts {
             let def_id = body.source.def_id();
             let def_path = infcx.tcx.def_path(def_id);
             let dir_path = PathBuf::from(&infcx.tcx.sess.opts.unstable_opts.nll_facts_dir)
                 .join(def_path.to_filename_friendly_no_crate());
-            all_facts.write_to_dir(dir_path, location_table).unwrap();
+            polonius_facts.write_to_dir(dir_path, location_table).unwrap();
         }
 
         if polonius_output {
@@ -162,7 +164,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
             debug!("compute_regions: using polonius algorithm {:?}", algorithm);
             let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
-            Some(Box::new(Output::compute(all_facts, algorithm, false)))
+            Some(Box::new(Output::compute(polonius_facts, algorithm, false)))
         } else {
             None
         }
@@ -182,7 +184,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     NllOutput {
         regioncx,
         opaque_type_values: remapped_opaque_tys,
-        polonius_input: all_facts.map(Box::new),
+        polonius_input: polonius_facts.map(Box::new),
         polonius_output,
         opt_closure_req: closure_region_requirements,
         nll_errors,
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
index 4a0c8d9b4b4..edd7ca578b7 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
@@ -4,16 +4,16 @@ use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
 use tracing::debug;
 
-use super::{AllFacts, LocationIndex, LocationTable};
+use super::{LocationIndex, PoloniusFacts, PoloniusLocationTable};
 use crate::def_use::{self, DefUse};
 use crate::universal_regions::UniversalRegions;
 
 /// Emit polonius facts for variable defs, uses, drops, and path accesses.
 pub(crate) fn emit_access_facts<'tcx>(
     tcx: TyCtxt<'tcx>,
-    facts: &mut AllFacts,
+    facts: &mut PoloniusFacts,
     body: &Body<'tcx>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     move_data: &MoveData<'tcx>,
     universal_regions: &UniversalRegions<'tcx>,
 ) {
@@ -31,9 +31,9 @@ pub(crate) fn emit_access_facts<'tcx>(
 
 /// MIR visitor extracting point-wise facts about accesses.
 struct AccessFactsExtractor<'a, 'tcx> {
-    facts: &'a mut AllFacts,
+    facts: &'a mut PoloniusFacts,
     move_data: &'a MoveData<'tcx>,
-    location_table: &'a LocationTable,
+    location_table: &'a PoloniusLocationTable,
 }
 
 impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/facts.rs b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs
index 42c4e733218..64389b11a65 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/facts.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs
@@ -4,13 +4,13 @@ use std::fs::{self, File};
 use std::io::Write;
 use std::path::Path;
 
-use polonius_engine::{AllFacts as PoloniusFacts, Atom, Output};
+use polonius_engine::{AllFacts, Atom, Output};
 use rustc_macros::extension;
 use rustc_middle::mir::Local;
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::move_paths::MovePathIndex;
 
-use super::{LocationIndex, LocationTable};
+use super::{LocationIndex, PoloniusLocationTable};
 use crate::BorrowIndex;
 
 #[derive(Copy, Clone, Debug)]
@@ -49,11 +49,11 @@ impl polonius_engine::FactTypes for RustcFacts {
     type Path = MovePathIndex;
 }
 
-pub type AllFacts = PoloniusFacts<RustcFacts>;
+pub type PoloniusFacts = AllFacts<RustcFacts>;
 
-#[extension(pub(crate) trait AllFactsExt)]
-impl AllFacts {
-    /// Returns `true` if there is a need to gather `AllFacts` given the
+#[extension(pub(crate) trait PoloniusFactsExt)]
+impl PoloniusFacts {
+    /// Returns `true` if there is a need to gather `PoloniusFacts` given the
     /// current `-Z` flags.
     fn enabled(tcx: TyCtxt<'_>) -> bool {
         tcx.sess.opts.unstable_opts.nll_facts
@@ -63,7 +63,7 @@ impl AllFacts {
     fn write_to_dir(
         &self,
         dir: impl AsRef<Path>,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>> {
         let dir: &Path = dir.as_ref();
         fs::create_dir_all(dir)?;
@@ -119,7 +119,7 @@ impl Atom for LocationIndex {
 }
 
 struct FactWriter<'w> {
-    location_table: &'w LocationTable,
+    location_table: &'w PoloniusLocationTable,
     dir: &'w Path,
 }
 
@@ -141,7 +141,7 @@ trait FactRow {
     fn write(
         &self,
         out: &mut dyn Write,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>>;
 }
 
@@ -149,7 +149,7 @@ impl FactRow for PoloniusRegionVid {
     fn write(
         &self,
         out: &mut dyn Write,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[self])
     }
@@ -163,7 +163,7 @@ where
     fn write(
         &self,
         out: &mut dyn Write,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1])
     }
@@ -178,7 +178,7 @@ where
     fn write(
         &self,
         out: &mut dyn Write,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1, &self.2])
     }
@@ -194,7 +194,7 @@ where
     fn write(
         &self,
         out: &mut dyn Write,
-        location_table: &LocationTable,
+        location_table: &PoloniusLocationTable,
     ) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
     }
@@ -202,7 +202,7 @@ where
 
 fn write_row(
     out: &mut dyn Write,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     columns: &[&dyn FactCell],
 ) -> Result<(), Box<dyn Error>> {
     for (index, c) in columns.iter().enumerate() {
@@ -213,41 +213,41 @@ fn write_row(
 }
 
 trait FactCell {
-    fn to_string(&self, location_table: &LocationTable) -> String;
+    fn to_string(&self, location_table: &PoloniusLocationTable) -> String;
 }
 
 impl FactCell for BorrowIndex {
-    fn to_string(&self, _location_table: &LocationTable) -> String {
+    fn to_string(&self, _location_table: &PoloniusLocationTable) -> String {
         format!("{self:?}")
     }
 }
 
 impl FactCell for Local {
-    fn to_string(&self, _location_table: &LocationTable) -> String {
+    fn to_string(&self, _location_table: &PoloniusLocationTable) -> String {
         format!("{self:?}")
     }
 }
 
 impl FactCell for MovePathIndex {
-    fn to_string(&self, _location_table: &LocationTable) -> String {
+    fn to_string(&self, _location_table: &PoloniusLocationTable) -> String {
         format!("{self:?}")
     }
 }
 
 impl FactCell for PoloniusRegionVid {
-    fn to_string(&self, _location_table: &LocationTable) -> String {
+    fn to_string(&self, _location_table: &PoloniusLocationTable) -> String {
         format!("{self:?}")
     }
 }
 
 impl FactCell for RegionVid {
-    fn to_string(&self, _location_table: &LocationTable) -> String {
+    fn to_string(&self, _location_table: &PoloniusLocationTable) -> String {
         format!("{self:?}")
     }
 }
 
 impl FactCell for LocationIndex {
-    fn to_string(&self, location_table: &LocationTable) -> String {
+    fn to_string(&self, location_table: &PoloniusLocationTable) -> String {
         format!("{:?}", location_table.to_rich_location(*self))
     }
 }
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
index 3c3b93cdc0d..0ad91ae51a3 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::TyCtxt;
 use tracing::debug;
 
-use super::{AllFacts, LocationTable};
+use super::{PoloniusFacts, PoloniusLocationTable};
 use crate::borrow_set::BorrowSet;
 use crate::path_utils::*;
 use crate::{
@@ -22,9 +22,9 @@ use crate::{
 /// Emit `loan_invalidated_at` facts.
 pub(super) fn emit_loan_invalidations<'tcx>(
     tcx: TyCtxt<'tcx>,
-    facts: &mut AllFacts,
+    facts: &mut PoloniusFacts,
     body: &Body<'tcx>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     let dominators = body.basic_blocks.dominators();
@@ -35,9 +35,9 @@ pub(super) fn emit_loan_invalidations<'tcx>(
 
 struct LoanInvalidationsGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    facts: &'a mut AllFacts,
+    facts: &'a mut PoloniusFacts,
     body: &'a Body<'tcx>,
-    location_table: &'a LocationTable,
+    location_table: &'a PoloniusLocationTable,
     dominators: &'a Dominators<BasicBlock>,
     borrow_set: &'a BorrowSet<'tcx>,
 }
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
index 0148e0b2869..098c922bf7b 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
@@ -6,16 +6,16 @@ use rustc_middle::mir::{
 use rustc_middle::ty::TyCtxt;
 use tracing::debug;
 
-use super::{AllFacts, LocationTable};
+use super::{PoloniusFacts, PoloniusLocationTable};
 use crate::borrow_set::BorrowSet;
 use crate::places_conflict;
 
 /// Emit `loan_killed_at` and `cfg_edge` facts at the same time.
 pub(super) fn emit_loan_kills<'tcx>(
     tcx: TyCtxt<'tcx>,
-    facts: &mut AllFacts,
+    facts: &mut PoloniusFacts,
     body: &Body<'tcx>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, facts, body };
@@ -26,8 +26,8 @@ pub(super) fn emit_loan_kills<'tcx>(
 
 struct LoanKillsGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    facts: &'a mut AllFacts,
-    location_table: &'a LocationTable,
+    facts: &'a mut PoloniusFacts,
+    location_table: &'a PoloniusLocationTable,
     borrow_set: &'a BorrowSet<'tcx>,
     body: &'a Body<'tcx>,
 }
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/location.rs b/compiler/rustc_borrowck/src/polonius/legacy/location.rs
index 4cb1202033c..5f816bb9bbd 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/location.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/location.rs
@@ -13,7 +13,7 @@ use tracing::debug;
 /// granularity through outlives relations; however, the rich location
 /// table serves another purpose: it compresses locations from
 /// multiple words into a single u32.
-pub struct LocationTable {
+pub struct PoloniusLocationTable {
     num_points: usize,
     statements_before_block: IndexVec<BasicBlock, usize>,
 }
@@ -30,7 +30,7 @@ pub enum RichLocation {
     Mid(Location),
 }
 
-impl LocationTable {
+impl PoloniusLocationTable {
     pub(crate) fn new(body: &Body<'_>) -> Self {
         let mut num_points = 0;
         let statements_before_block = body
@@ -43,8 +43,8 @@ impl LocationTable {
             })
             .collect();
 
-        debug!("LocationTable(statements_before_block={:#?})", statements_before_block);
-        debug!("LocationTable: num_points={:#?}", num_points);
+        debug!("PoloniusLocationTable(statements_before_block={:#?})", statements_before_block);
+        debug!("PoloniusLocationTable: num_points={:#?}", num_points);
 
         Self { num_points, statements_before_block }
     }
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
index 45bdbd1e999..95820c07a02 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
@@ -36,16 +36,16 @@ pub use self::facts::*;
 ///
 /// The rest of the facts are emitted during typeck and liveness.
 pub(crate) fn emit_facts<'tcx>(
-    all_facts: &mut Option<AllFacts>,
+    facts: &mut Option<PoloniusFacts>,
     tcx: TyCtxt<'tcx>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     body: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     move_data: &MoveData<'tcx>,
     universal_region_relations: &UniversalRegionRelations<'tcx>,
     constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
-    let Some(facts) = all_facts else {
+    let Some(facts) = facts else {
         // We don't do anything if there are no facts to fill.
         return;
     };
@@ -67,9 +67,9 @@ pub(crate) fn emit_facts<'tcx>(
 
 /// Emit facts needed for move/init analysis: moves and assignments.
 fn emit_move_facts(
-    facts: &mut AllFacts,
+    facts: &mut PoloniusFacts,
     body: &Body<'_>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     move_data: &MoveData<'_>,
 ) {
     facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
@@ -139,7 +139,7 @@ fn emit_move_facts(
 
 /// Emit universal regions facts, and their relations.
 fn emit_universal_region_facts(
-    facts: &mut AllFacts,
+    facts: &mut PoloniusFacts,
     borrow_set: &BorrowSet<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
@@ -187,10 +187,10 @@ pub(crate) fn emit_drop_facts<'tcx>(
     local: Local,
     kind: &GenericArg<'tcx>,
     universal_regions: &UniversalRegions<'tcx>,
-    all_facts: &mut Option<AllFacts>,
+    facts: &mut Option<PoloniusFacts>,
 ) {
     debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
-    let Some(facts) = all_facts.as_mut() else { return };
+    let Some(facts) = facts.as_mut() else { return };
     let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
     tcx.for_each_free_region(kind, |drop_live_region| {
         let region_vid = universal_regions.to_region_vid(drop_live_region);
@@ -201,8 +201,8 @@ pub(crate) fn emit_drop_facts<'tcx>(
 /// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive
 /// closure.
 fn emit_outlives_facts<'tcx>(
-    facts: &mut AllFacts,
-    location_table: &LocationTable,
+    facts: &mut PoloniusFacts,
+    location_table: &PoloniusLocationTable,
     constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
     facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map(
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 59189082f6f..c177538ee17 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -392,7 +392,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         var_infos: VarInfos,
         constraints: MirTypeckRegionConstraints<'tcx>,
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-        elements: Rc<DenseLocationMap>,
+        location_map: Rc<DenseLocationMap>,
     ) -> Self {
         let universal_regions = &universal_region_relations.universal_regions;
         let MirTypeckRegionConstraints {
@@ -436,7 +436,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         let mut scc_values =
-            RegionValues::new(elements, universal_regions.len(), placeholder_indices);
+            RegionValues::new(location_map, universal_regions.len(), placeholder_indices);
 
         for region in liveness_constraints.regions() {
             let scc = constraint_sccs.scc(region);
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 75aef8b303b..11fb125ca22 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -38,7 +38,7 @@ pub(crate) enum RegionElement {
 /// an interval matrix storing liveness ranges for each region-vid.
 pub(crate) struct LivenessValues {
     /// The map from locations to points.
-    elements: Rc<DenseLocationMap>,
+    location_map: Rc<DenseLocationMap>,
 
     /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and
     /// currently only used for validating promoteds (which don't care about more precise tracking).
@@ -77,11 +77,11 @@ impl LiveLoans {
 
 impl LivenessValues {
     /// Create an empty map of regions to locations where they're live.
-    pub(crate) fn with_specific_points(elements: Rc<DenseLocationMap>) -> Self {
+    pub(crate) fn with_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
         LivenessValues {
             live_regions: None,
-            points: Some(SparseIntervalMatrix::new(elements.num_points())),
-            elements,
+            points: Some(SparseIntervalMatrix::new(location_map.num_points())),
+            location_map,
             loans: None,
         }
     }
@@ -90,11 +90,11 @@ impl LivenessValues {
     ///
     /// Unlike `with_specific_points`, does not track exact locations where something is live, only
     /// which regions are live.
-    pub(crate) fn without_specific_points(elements: Rc<DenseLocationMap>) -> Self {
+    pub(crate) fn without_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
         LivenessValues {
             live_regions: Some(Default::default()),
             points: None,
-            elements,
+            location_map,
             loans: None,
         }
     }
@@ -122,11 +122,11 @@ impl LivenessValues {
 
     /// Records `region` as being live at the given `location`.
     pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
-        let point = self.elements.point_from_location(location);
+        let point = self.location_map.point_from_location(location);
         debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
         if let Some(points) = &mut self.points {
             points.insert(region, point);
-        } else if self.elements.point_in_range(point) {
+        } else if self.location_map.point_in_range(point) {
             self.live_regions.as_mut().unwrap().insert(region);
         }
 
@@ -143,7 +143,7 @@ impl LivenessValues {
         debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
         if let Some(this) = &mut self.points {
             this.union_row(region, points);
-        } else if points.iter().any(|point| self.elements.point_in_range(point)) {
+        } else if points.iter().any(|point| self.location_map.point_in_range(point)) {
             self.live_regions.as_mut().unwrap().insert(region);
         }
 
@@ -170,7 +170,7 @@ impl LivenessValues {
 
     /// Returns whether `region` is marked live at the given `location`.
     pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
-        let point = self.elements.point_from_location(location);
+        let point = self.location_map.point_from_location(location);
         if let Some(points) = &self.points {
             points.row(region).is_some_and(|r| r.contains(point))
         } else {
@@ -191,25 +191,26 @@ impl LivenessValues {
             .row(region)
             .into_iter()
             .flat_map(|set| set.iter())
-            .take_while(|&p| self.elements.point_in_range(p))
+            .take_while(|&p| self.location_map.point_in_range(p))
     }
 
     /// For debugging purposes, returns a pretty-printed string of the points where the `region` is
     /// live.
     pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
         pretty_print_region_elements(
-            self.live_points(region).map(|p| RegionElement::Location(self.elements.to_location(p))),
+            self.live_points(region)
+                .map(|p| RegionElement::Location(self.location_map.to_location(p))),
         )
     }
 
     #[inline]
     pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
-        self.elements.point_from_location(location)
+        self.location_map.point_from_location(location)
     }
 
     #[inline]
     pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
-        self.elements.to_location(point)
+        self.location_map.to_location(point)
     }
 
     /// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
@@ -272,7 +273,7 @@ impl PlaceholderIndices {
 /// because (since it is returned) it must live for at least `'a`. But
 /// it would also contain various points from within the function.
 pub(crate) struct RegionValues<N: Idx> {
-    elements: Rc<DenseLocationMap>,
+    location_map: Rc<DenseLocationMap>,
     placeholder_indices: PlaceholderIndices,
     points: SparseIntervalMatrix<N, PointIndex>,
     free_regions: SparseBitMatrix<N, RegionVid>,
@@ -287,14 +288,14 @@ impl<N: Idx> RegionValues<N> {
     /// Each of the regions in num_region_variables will be initialized with an
     /// empty set of points and no causal information.
     pub(crate) fn new(
-        elements: Rc<DenseLocationMap>,
+        location_map: Rc<DenseLocationMap>,
         num_universal_regions: usize,
         placeholder_indices: PlaceholderIndices,
     ) -> Self {
-        let num_points = elements.num_points();
+        let num_points = location_map.num_points();
         let num_placeholders = placeholder_indices.len();
         Self {
-            elements,
+            location_map,
             points: SparseIntervalMatrix::new(num_points),
             placeholder_indices,
             free_regions: SparseBitMatrix::new(num_universal_regions),
@@ -336,7 +337,7 @@ impl<N: Idx> RegionValues<N> {
         end: usize,
     ) -> Option<usize> {
         let row = self.points.row(r)?;
-        let block = self.elements.entry_point(block);
+        let block = self.location_map.entry_point(block);
         let start = block.plus(start);
         let end = block.plus(end);
         let first_unset = row.first_unset_in(start..=end)?;
@@ -375,8 +376,8 @@ impl<N: Idx> RegionValues<N> {
     pub(crate) fn locations_outlived_by<'a>(&'a self, r: N) -> impl Iterator<Item = Location> + 'a {
         self.points.row(r).into_iter().flat_map(move |set| {
             set.iter()
-                .take_while(move |&p| self.elements.point_in_range(p))
-                .map(move |p| self.elements.to_location(p))
+                .take_while(move |&p| self.location_map.point_in_range(p))
+                .map(move |p| self.location_map.to_location(p))
         })
     }
 
@@ -430,12 +431,12 @@ pub(crate) trait ToElementIndex: Debug + Copy {
 
 impl ToElementIndex for Location {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
-        let index = values.elements.point_from_location(self);
+        let index = values.location_map.point_from_location(self);
         values.points.insert(row, index)
     }
 
     fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
-        let index = values.elements.point_from_location(self);
+        let index = values.location_map.point_from_location(self);
         values.points.contains(row, index)
     }
 }
@@ -464,14 +465,14 @@ impl ToElementIndex for ty::PlaceholderRegion {
 
 /// For debugging purposes, returns a pretty-printed string of the given points.
 pub(crate) fn pretty_print_points(
-    elements: &DenseLocationMap,
+    location_map: &DenseLocationMap,
     points: impl IntoIterator<Item = PointIndex>,
 ) -> String {
     pretty_print_region_elements(
         points
             .into_iter()
-            .take_while(|&p| elements.point_in_range(p))
-            .map(|p| elements.to_location(p))
+            .take_while(|&p| location_map.point_in_range(p))
+            .map(|p| location_map.to_location(p))
             .map(RegionElement::Location),
     )
 }
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 627444a4ce5..4be5d0dbf42 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -480,3 +480,10 @@ pub(crate) struct SimdIntrinsicArgConst {
     pub arg: usize,
     pub intrinsic: String,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(borrowck_tail_expr_drop_order)]
+pub(crate) struct TailExprDropOrder {
+    #[label]
+    pub borrowed: Span,
+}
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 695a1cdac0d..6182b68f6f4 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -82,7 +82,7 @@ impl<'a> Iterator for AppearancesIter<'a> {
 impl LocalUseMap {
     pub(crate) fn build(
         live_locals: &[Local],
-        elements: &DenseLocationMap,
+        location_map: &DenseLocationMap,
         body: &Body<'_>,
     ) -> Self {
         let nones = IndexVec::from_elem(None, &body.local_decls);
@@ -101,7 +101,7 @@ impl LocalUseMap {
             IndexVec::from_elem(false, &body.local_decls);
         live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
 
-        LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data }
+        LocalUseMapBuild { local_use_map: &mut local_use_map, location_map, locals_with_use_data }
             .visit_body(body);
 
         local_use_map
@@ -125,7 +125,7 @@ impl LocalUseMap {
 
 struct LocalUseMapBuild<'me> {
     local_use_map: &'me mut LocalUseMap,
-    elements: &'me DenseLocationMap,
+    location_map: &'me DenseLocationMap,
 
     // Vector used in `visit_local` to signal which `Local`s do we need
     // def/use/drop information on, constructed from `live_locals` (that
@@ -147,7 +147,7 @@ impl Visitor<'_> for LocalUseMapBuild<'_> {
                 DefUse::Use => &mut self.local_use_map.first_use_at[local],
                 DefUse::Drop => &mut self.local_use_map.first_drop_at[local],
             };
-            let point_index = self.elements.point_from_location(location);
+            let point_index = self.location_map.point_from_location(location);
             let appearance_index = self
                 .local_use_map
                 .appearances
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 3e9900cce5f..f23602d0358 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -32,7 +32,7 @@ mod trace;
 pub(super) fn generate<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
-    elements: &DenseLocationMap,
+    location_map: &DenseLocationMap,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
@@ -49,7 +49,7 @@ pub(super) fn generate<'a, 'tcx>(
     trace::trace(
         typeck,
         body,
-        elements,
+        location_map,
         flow_inits,
         move_data,
         relevant_live_locals,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index c7a2d32b31d..7fce49fd16b 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -37,13 +37,13 @@ use crate::type_check::{NormalizeLocation, TypeChecker};
 pub(super) fn trace<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
-    elements: &DenseLocationMap,
+    location_map: &DenseLocationMap,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
 ) {
-    let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);
+    let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, body);
 
     // When using `-Zpolonius=next`, compute the set of loans that can reach a given region.
     if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
@@ -79,7 +79,7 @@ pub(super) fn trace<'a, 'tcx>(
         typeck,
         body,
         flow_inits,
-        elements,
+        location_map,
         local_use_map,
         move_data,
         drop_data: FxIndexMap::default(),
@@ -100,7 +100,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
     typeck: &'a mut TypeChecker<'typeck, 'tcx>,
 
     /// Defines the `PointIndex` mapping
-    elements: &'a DenseLocationMap,
+    location_map: &'a DenseLocationMap,
 
     /// MIR we are analyzing.
     body: &'a Body<'tcx>,
@@ -149,7 +149,7 @@ struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
 
 impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self {
-        let num_points = cx.elements.num_points();
+        let num_points = cx.location_map.num_points();
         LivenessResults {
             cx,
             defs: BitSet::new_empty(num_points),
@@ -213,14 +213,14 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) {
         // This collect is more necessary than immediately apparent
         // because these facts go into `add_drop_live_facts_for()`,
-        // which also writes to `all_facts`, and so this is genuinely
+        // which also writes to `polonius_facts`, and so this is genuinely
         // a simultaneous overlapping mutable borrow.
         // FIXME for future hackers: investigate whether this is
         // actually necessary; these facts come from Polonius
         // and probably maybe plausibly does not need to go back in.
         // It may be necessary to just pick out the parts of
         // `add_drop_live_facts_for()` that make sense.
-        let Some(facts) = self.cx.typeck.all_facts.as_ref() else { return };
+        let Some(facts) = self.cx.typeck.polonius_facts.as_ref() else { return };
         let facts_to_add: Vec<_> = {
             let relevant_live_locals: FxIndexSet<_> =
                 relevant_live_locals.iter().copied().collect();
@@ -240,7 +240,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                 .collect()
         };
 
-        let live_at = IntervalSet::new(self.cx.elements.num_points());
+        let live_at = IntervalSet::new(self.cx.location_map.num_points());
         for (local, local_ty, location) in facts_to_add {
             self.cx.add_drop_live_facts_for(local, local_ty, &[location], &live_at);
         }
@@ -279,7 +279,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
             //  * Inclusively, the block start
             //  * Exclusively, the previous definition (if it's in this block)
             //  * Exclusively, the previous live_at setting (an optimization)
-            let block_start = self.cx.elements.to_block_start(p);
+            let block_start = self.cx.location_map.to_block_start(p);
             let previous_defs = self.defs.last_set_in(block_start..=p);
             let previous_live_at = self.use_live_at.last_set_in(block_start..=p);
 
@@ -303,12 +303,12 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                 // terminators of predecessor basic blocks. Push those onto the
                 // stack so that the next iteration(s) will process them.
 
-                let block = self.cx.elements.to_location(block_start).block;
+                let block = self.cx.location_map.to_location(block_start).block;
                 self.stack.extend(
                     self.cx.body.basic_blocks.predecessors()[block]
                         .iter()
                         .map(|&pred_bb| self.cx.body.terminator_loc(pred_bb))
-                        .map(|pred_loc| self.cx.elements.point_from_location(pred_loc)),
+                        .map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)),
                 );
             }
         }
@@ -331,7 +331,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
 
         // Find the drops where `local` is initialized.
         for drop_point in self.cx.local_use_map.drops(local) {
-            let location = self.cx.elements.to_location(drop_point);
+            let location = self.cx.location_map.to_location(drop_point);
             debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
 
             if self.cx.initialized_at_terminator(location.block, mpi)
@@ -367,7 +367,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
         debug!(
             "compute_drop_live_points_for_block(mpi={:?}, term_point={:?})",
             self.cx.move_data.move_paths[mpi].place,
-            self.cx.elements.to_location(term_point),
+            self.cx.location_map.to_location(term_point),
         );
 
         // We are only invoked with terminators where `mpi` is
@@ -377,12 +377,15 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
         // Otherwise, scan backwards through the statements in the
         // block. One of them may be either a definition or use
         // live point.
-        let term_location = self.cx.elements.to_location(term_point);
+        let term_location = self.cx.location_map.to_location(term_point);
         debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,);
         let block = term_location.block;
-        let entry_point = self.cx.elements.entry_point(term_location.block);
+        let entry_point = self.cx.location_map.entry_point(term_location.block);
         for p in (entry_point..term_point).rev() {
-            debug!("compute_drop_live_points_for_block: p = {:?}", self.cx.elements.to_location(p));
+            debug!(
+                "compute_drop_live_points_for_block: p = {:?}",
+                self.cx.location_map.to_location(p)
+            );
 
             if self.defs.contains(p) {
                 debug!("compute_drop_live_points_for_block: def site");
@@ -428,7 +431,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
             }
 
             let pred_term_loc = self.cx.body.terminator_loc(pred_block);
-            let pred_term_point = self.cx.elements.point_from_location(pred_term_loc);
+            let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc);
 
             // If the terminator of this predecessor either *assigns*
             // our value or is a "normal use", then stop.
@@ -523,7 +526,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// points `live_at`.
     fn add_use_live_facts_for(&mut self, value: Ty<'tcx>, live_at: &IntervalSet<PointIndex>) {
         debug!("add_use_live_facts_for(value={:?})", value);
-        Self::make_all_regions_live(self.elements, self.typeck, value, live_at);
+        Self::make_all_regions_live(self.location_map, self.typeck, value, live_at);
     }
 
     /// Some variable with type `live_ty` is "drop live" at `location`
@@ -547,7 +550,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             dropped_local,
             dropped_ty,
             drop_locations,
-            values::pretty_print_points(self.elements, live_at.iter()),
+            values::pretty_print_points(self.location_map, live_at.iter()),
         );
 
         let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
@@ -574,19 +577,19 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         // All things in the `outlives` array may be touched by
         // the destructor and must be live at this point.
         for &kind in &drop_data.dropck_result.kinds {
-            Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
+            Self::make_all_regions_live(self.location_map, self.typeck, kind, live_at);
             polonius::legacy::emit_drop_facts(
                 self.typeck.tcx(),
                 dropped_local,
                 &kind,
                 self.typeck.universal_regions,
-                self.typeck.all_facts,
+                self.typeck.polonius_facts,
             );
         }
     }
 
     fn make_all_regions_live(
-        elements: &DenseLocationMap,
+        location_map: &DenseLocationMap,
         typeck: &mut TypeChecker<'_, 'tcx>,
         value: impl TypeVisitable<TyCtxt<'tcx>> + Relate<TyCtxt<'tcx>>,
         live_at: &IntervalSet<PointIndex>,
@@ -594,7 +597,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         debug!("make_all_regions_live(value={:?})", value);
         debug!(
             "make_all_regions_live: live_at={}",
-            values::pretty_print_points(elements, live_at.iter()),
+            values::pretty_print_points(location_map, live_at.iter()),
         );
 
         value.visit_with(&mut for_liveness::FreeRegionsVisitor {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 1eb471968b2..889b5684a21 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -49,7 +49,7 @@ use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
 use crate::diagnostics::UniverseInfo;
 use crate::member_constraints::MemberConstraintSet;
 use crate::polonius::PoloniusContext;
-use crate::polonius::legacy::{AllFacts, LocationTable};
+use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
 use crate::region_infer::TypeTest;
 use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
 use crate::renumber::RegionCtxt;
@@ -98,29 +98,29 @@ mod relate_tys;
 /// - `body` -- MIR body to type-check
 /// - `promoted` -- map of promoted constants within `body`
 /// - `universal_regions` -- the universal regions from `body`s function signature
-/// - `location_table` -- MIR location map of `body`
+/// - `location_table` -- for datalog polonius, the map between `Location`s and `RichLocation`s
 /// - `borrow_set` -- information about borrows occurring in `body`
-/// - `all_facts` -- when using Polonius, this is the generated set of Polonius facts
+/// - `polonius_facts` -- when using Polonius, this is the generated set of Polonius facts
 /// - `flow_inits` -- results of a maybe-init dataflow analysis
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
-/// - `elements` -- MIR region map
+/// - `location_map` -- map between MIR `Location` and `PointIndex`
 pub(crate) fn type_check<'a, 'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
     universal_regions: UniversalRegions<'tcx>,
-    location_table: &LocationTable,
+    location_table: &PoloniusLocationTable,
     borrow_set: &BorrowSet<'tcx>,
-    all_facts: &mut Option<AllFacts>,
+    polonius_facts: &mut Option<PoloniusFacts>,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
-    elements: Rc<DenseLocationMap>,
+    location_map: Rc<DenseLocationMap>,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
-        liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&elements)),
+        liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&location_map)),
         outlives_constraints: OutlivesConstraintSet::default(),
         member_constraints: MemberConstraintSet::default(),
         type_tests: Vec::default(),
@@ -165,7 +165,7 @@ pub(crate) fn type_check<'a, 'tcx>(
         reported_errors: Default::default(),
         universal_regions: &universal_region_relations.universal_regions,
         location_table,
-        all_facts,
+        polonius_facts,
         borrow_set,
         constraints: &mut constraints,
         polonius_context: &mut polonius_context,
@@ -180,7 +180,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
     typeck.check_signature_annotation(body);
 
-    liveness::generate(&mut typeck, body, &elements, flow_inits, move_data);
+    liveness::generate(&mut typeck, body, &location_map, flow_inits, move_data);
 
     let opaque_type_values =
         opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
@@ -495,14 +495,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         // Use new sets of constraints and closure bounds so that we can
         // modify their locations.
-        let all_facts = &mut None;
+        let polonius_facts = &mut None;
         let mut constraints = Default::default();
         let mut liveness_constraints =
             LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
         // Don't try to add borrow_region facts for the promoted MIR
 
         let mut swap_constraints = |this: &mut Self| {
-            mem::swap(this.typeck.all_facts, all_facts);
+            mem::swap(this.typeck.polonius_facts, polonius_facts);
             mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
             mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
         };
@@ -560,8 +560,8 @@ struct TypeChecker<'a, 'tcx> {
     implicit_region_bound: ty::Region<'tcx>,
     reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
     universal_regions: &'a UniversalRegions<'tcx>,
-    location_table: &'a LocationTable,
-    all_facts: &'a mut Option<AllFacts>,
+    location_table: &'a PoloniusLocationTable,
+    polonius_facts: &'a mut Option<PoloniusFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
     /// When using `-Zpolonius=next`, the helper data used to create polonius constraints.
@@ -2341,18 +2341,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         borrowed_place: &Place<'tcx>,
     ) {
         // These constraints are only meaningful during borrowck:
-        let Self { borrow_set, location_table, all_facts, constraints, .. } = self;
+        let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self;
 
         // In Polonius mode, we also push a `loan_issued_at` fact
         // linking the loan to the region (in some cases, though,
         // there is no loan associated with this borrow expression --
         // that occurs when we are borrowing an unsafe place, for
         // example).
-        if let Some(all_facts) = all_facts {
+        if let Some(polonius_facts) = polonius_facts {
             let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             if let Some(borrow_index) = borrow_set.get_index_of(&location) {
                 let region_vid = borrow_region.as_var();
-                all_facts.loan_issued_at.push((
+                polonius_facts.loan_issued_at.push((
                     region_vid.into(),
                     borrow_index,
                     location_table.mid_index(location),
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 442d61c6ade..e569da90cf7 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -123,7 +123,6 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
 rm tests/ui/consts/issue-33537.rs # same
 rm tests/ui/consts/const-mut-refs-crate.rs # same
 rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift
-rm tests/ui/invalid-compile-flags/crate-type-flag.rs # warning about proc-macros and panic=abort
 
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e6adbc0f0ac..43feab94c01 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -522,7 +522,7 @@ impl MacResult for MacEager {
                 return Some(P(ast::Pat {
                     id: ast::DUMMY_NODE_ID,
                     span: e.span,
-                    kind: PatKind::Lit(e),
+                    kind: PatKind::Expr(e),
                     tokens: None,
                 }));
             }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 22bfda34cc0..8bf09cf96b3 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -486,7 +486,7 @@ impl<'a> ExtCtxt<'a> {
         self.pat(span, PatKind::Wild)
     }
     pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
-        self.pat(span, PatKind::Lit(expr))
+        self.pat(span, PatKind::Expr(expr))
     }
     pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
         self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 91624c7554c..3e3f35332e0 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -18,7 +18,7 @@ use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::validate_attr;
 use rustc_session::Session;
 use rustc_session::parse::feature_err;
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
 use thin_vec::ThinVec;
 use tracing::instrument;
 
@@ -107,14 +107,11 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
 
             // If the enabled feature is unstable, record it.
             if UNSTABLE_LANG_FEATURES.iter().find(|f| name == f.name).is_some() {
-                // When the ICE comes from core, alloc or std (approximation of the standard
-                // library), there's a chance that the person hitting the ICE may be using
-                // -Zbuild-std or similar with an untested target. The bug is probably in the
-                // standard library and not the compiler in that case, but that doesn't really
-                // matter - we want a bug report.
-                if features.internal(name)
-                    && ![sym::core, sym::alloc, sym::std].contains(&crate_name)
-                {
+                // When the ICE comes a standard library crate, there's a chance that the person
+                // hitting the ICE may be using -Zbuild-std or similar with an untested target.
+                // The bug is probably in the standard library and not the compiler in that case,
+                // but that doesn't really matter - we want a bug report.
+                if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
                     sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
                 }
 
@@ -133,7 +130,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
 
             // Similar to above, detect internal lib features to suppress
             // the ICE message that asks for a report.
-            if features.internal(name) && ![sym::core, sym::alloc, sym::std].contains(&crate_name) {
+            if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
                 sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
             }
         }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 2e4b6748731..dd96b30fefc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -7,7 +7,7 @@ use rustc_ast::token::CommentKind;
 use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
 use rustc_ast::{
     self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
-    IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
+    IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
 };
 pub use rustc_ast::{
     BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
@@ -1386,7 +1386,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
+            Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
             Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
@@ -1413,7 +1413,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
+            Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
             Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@@ -1520,6 +1520,26 @@ impl fmt::Debug for DotDotPos {
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct PatExpr<'hir> {
+    pub hir_id: HirId,
+    pub span: Span,
+    pub kind: PatExprKind<'hir>,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum PatExprKind<'hir> {
+    Lit {
+        lit: &'hir Lit,
+        // FIXME: move this into `Lit` and handle negated literal expressions
+        // once instead of matching on unop neg expressions everywhere.
+        negated: bool,
+    },
+    ConstBlock(ConstBlock),
+    /// A path pattern for a unit struct/variant or a (maybe-associated) constant.
+    Path(QPath<'hir>),
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum PatKind<'hir> {
     /// Represents a wildcard pattern (i.e., `_`).
     Wild,
@@ -1563,14 +1583,14 @@ pub enum PatKind<'hir> {
     /// A reference pattern (e.g., `&mut (a, b)`).
     Ref(&'hir Pat<'hir>, Mutability),
 
-    /// A literal.
-    Lit(&'hir Expr<'hir>),
+    /// A literal, const block or path.
+    Expr(&'hir PatExpr<'hir>),
 
     /// A guard pattern (e.g., `x if guard(x)`).
     Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
 
     /// A range pattern (e.g., `1..=2` or `1..2`).
-    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
+    Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd),
 
     /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
     ///
@@ -2074,6 +2094,18 @@ impl Expr<'_> {
         }
     }
 
+    /// Check if expression is an integer literal that can be used
+    /// where `usize` is expected.
+    pub fn is_size_lit(&self) -> bool {
+        matches!(
+            self.kind,
+            ExprKind::Lit(Lit {
+                node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
+                ..
+            })
+        )
+    }
+
     /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
     /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
     /// silent, only signaling the ownership system. By doing this, suggestions that check the
@@ -4144,6 +4176,10 @@ pub enum Node<'hir> {
     OpaqueTy(&'hir OpaqueTy<'hir>),
     Pat(&'hir Pat<'hir>),
     PatField(&'hir PatField<'hir>),
+    /// Needed as its own node with its own HirId for tracking
+    /// the unadjusted type of literals within patterns
+    /// (e.g. byte str literals not being of slice type).
+    PatExpr(&'hir PatExpr<'hir>),
     Arm(&'hir Arm<'hir>),
     Block(&'hir Block<'hir>),
     LetStmt(&'hir LetStmt<'hir>),
@@ -4200,6 +4236,7 @@ impl<'hir> Node<'hir> {
             | Node::Block(..)
             | Node::Ctor(..)
             | Node::Pat(..)
+            | Node::PatExpr(..)
             | Node::Arm(..)
             | Node::LetStmt(..)
             | Node::Crate(..)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index f0480afd139..ef863aca090 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -342,6 +342,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
         walk_pat_field(self, f)
     }
+    fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
+        walk_pat_expr(self, expr)
+    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
@@ -685,10 +688,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
             try_visit!(visitor.visit_ident(ident));
             visit_opt!(visitor, visit_pat, optional_subpattern);
         }
-        PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
+        PatKind::Expr(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visit_opt!(visitor, visit_expr, lower_bound);
-            visit_opt!(visitor, visit_expr, upper_bound);
+            visit_opt!(visitor, visit_pat_expr, lower_bound);
+            visit_opt!(visitor, visit_pat_expr, upper_bound);
         }
         PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
@@ -710,6 +713,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
     visitor.visit_pat(field.pat)
 }
 
+pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(expr.hir_id));
+    match &expr.kind {
+        PatExprKind::Lit { .. } => V::Result::output(),
+        PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
+        PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
+    }
+}
+
 pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
     try_visit!(visitor.visit_id(constant.hir_id));
     visitor.visit_nested_body(constant.body)
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index ffc0657eebf..e5f98bdfb7f 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -704,7 +704,7 @@ fn resolve_local<'tcx>(
             | PatKind::Wild
             | PatKind::Never
             | PatKind::Path(_)
-            | PatKind::Lit(_)
+            | PatKind::Expr(_)
             | PatKind::Range(_, _, _)
             | PatKind::Err(_) => false,
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 81a5e9ee90d..dd6adb17c5e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1120,7 +1120,7 @@ fn check_type_defn<'tcx>(
                     } else {
                         // Evaluate the constant proactively, to emit an error if the constant has
                         // an unconditional error. We only do so if the const has no type params.
-                        let _ = tcx.const_eval_poly(def_id.into());
+                        let _ = tcx.const_eval_poly(def_id);
                     }
                 }
                 let field_id = field.did.expect_local();
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 2154568c512..0a41dad0dd8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2449,17 +2449,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         Ty::new_error(tcx, err)
                     }
                     hir::PatKind::Range(start, end, include_end) => {
-                        let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
-                            let (expr, neg) = match expr.kind {
-                                hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
-                                    (negated, Some((expr.hir_id, expr.span)))
-                                }
-                                _ => (expr, None),
-                            };
-                            let (c, c_ty) = match &expr.kind {
-                                hir::ExprKind::Lit(lit) => {
+                        let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> {
+                            let (c, c_ty) = match expr.kind {
+                                hir::PatExprKind::Lit { lit, negated } => {
                                     let lit_input =
-                                        LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
+                                        LitToConstInput { lit: &lit.node, ty, neg: negated };
                                     let ct = match tcx.lit_to_const(lit_input) {
                                         Ok(c) => c,
                                         Err(LitToConstError::Reported(err)) => {
@@ -2470,23 +2464,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                     (ct, ty)
                                 }
 
-                                hir::ExprKind::Path(hir::QPath::Resolved(
+                                hir::PatExprKind::Path(hir::QPath::Resolved(
                                     _,
                                     path @ &hir::Path {
                                         res: Res::Def(DefKind::ConstParam, def_id),
                                         ..
                                     },
                                 )) => {
-                                    let _ = self.prohibit_generic_args(
+                                    match self.prohibit_generic_args(
                                         path.segments.iter(),
                                         GenericsArgsErrExtend::Param(def_id),
-                                    );
-                                    let ty = tcx
-                                        .type_of(def_id)
-                                        .no_bound_vars()
-                                        .expect("const parameter types cannot be generic");
-                                    let ct = self.lower_const_param(def_id, expr.hir_id);
-                                    (ct, ty)
+                                    ) {
+                                        Ok(()) => {
+                                            let ty = tcx
+                                                .type_of(def_id)
+                                                .no_bound_vars()
+                                                .expect("const parameter types cannot be generic");
+                                            let ct = self.lower_const_param(def_id, expr.hir_id);
+                                            (ct, ty)
+                                        }
+                                        Err(guar) => (
+                                            ty::Const::new_error(tcx, guar),
+                                            Ty::new_error(tcx, guar),
+                                        ),
+                                    }
                                 }
 
                                 _ => {
@@ -2497,9 +2498,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 }
                             };
                             self.record_ty(expr.hir_id, c_ty, expr.span);
-                            if let Some((id, span)) = neg {
-                                self.record_ty(id, c_ty, span);
-                            }
                             c
                         };
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 16bb0dd328c..39b6823cf0e 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -199,6 +199,7 @@ impl<'a> State<'a> {
             Node::OpaqueTy(o) => self.print_opaque_ty(o),
             Node::Pat(a) => self.print_pat(a),
             Node::PatField(a) => self.print_patfield(a),
+            Node::PatExpr(a) => self.print_pat_expr(a),
             Node::Arm(a) => self.print_arm(a),
             Node::Infer(_) => self.word("_"),
             Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
@@ -1849,6 +1850,19 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) {
+        match &expr.kind {
+            hir::PatExprKind::Lit { lit, negated } => {
+                if *negated {
+                    self.word("-");
+                }
+                self.print_literal(lit);
+            }
+            hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
+            hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
+        }
+    }
+
     fn print_pat(&mut self, pat: &hir::Pat<'_>) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
@@ -1966,17 +1980,17 @@ impl<'a> State<'a> {
                     self.pclose();
                 }
             }
-            PatKind::Lit(e) => self.print_expr(e),
+            PatKind::Expr(e) => self.print_pat_expr(e),
             PatKind::Range(begin, end, end_kind) => {
                 if let Some(expr) = begin {
-                    self.print_expr(expr);
+                    self.print_pat_expr(expr);
                 }
                 match end_kind {
                     RangeEnd::Included => self.word("..."),
                     RangeEnd::Excluded => self.word(".."),
                 }
                 if let Some(expr) = end {
-                    self.print_expr(expr);
+                    self.print_pat_expr(expr);
                 }
             }
             PatKind::Slice(before, slice, after) => {
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index a93da52b270..0f424a39840 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -165,6 +165,8 @@ hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this ret
 hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it
 hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon
 
+hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr}
+
 hir_typeck_return_stmt_outside_of_fn_body =
     {$statement_kind} statement outside of function body
     .encl_body_label = the {$statement_kind} is part of this body...
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index e51323fc5c8..56f7a2c1150 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -30,7 +30,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if expr_ty == expected {
             return;
         }
-
         self.annotate_alternative_method_deref(err, expr, error);
         self.explain_self_literal(err, expr, expected, expr_ty);
 
@@ -39,6 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
             || self.suggest_remove_last_method_call(err, expr, expected)
             || self.suggest_associated_const(err, expr, expected)
+            || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
             || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
             || self.suggest_option_to_bool(err, expr, expr_ty, expected)
             || self.suggest_compatible_variants(err, expr, expected, expr_ty)
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ff09583cc65..4eed2bc1238 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -846,3 +846,16 @@ pub(crate) struct PassFnItemToVariadicFunction {
     pub sugg_span: Span,
     pub replace: String,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    hir_typeck_replace_comma_with_semicolon,
+    applicability = "machine-applicable",
+    style = "verbose",
+    code = "; "
+)]
+pub(crate) struct ReplaceCommaWithSemicolon {
+    #[primary_span]
+    pub comma_span: Span,
+    pub descr: &'static str,
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 8c8a8d6d922..3bb518e7f97 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -430,6 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | hir::Node::AssocItemConstraint(_)
             | hir::Node::TraitRef(_)
             | hir::Node::PatField(_)
+            | hir::Node::PatExpr(_)
             | hir::Node::LetStmt(_)
             | hir::Node::Synthetic
             | hir::Node::Err(_)
@@ -484,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | hir::PatKind::Box(_)
             | hir::PatKind::Ref(_, _)
             | hir::PatKind::Deref(_)
-            | hir::PatKind::Lit(_)
+            | hir::PatKind::Expr(_)
             | hir::PatKind::Range(_, _, _)
             | hir::PatKind::Slice(_, _, _)
             | hir::PatKind::Err(_) => true,
@@ -837,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // We always require that the type provided as the value for
         // a type parameter outlives the moment of instantiation.
         let args = self.typeck_results.borrow().node_args(expr.hir_id);
-        self.add_wf_bounds(args, expr);
+        self.add_wf_bounds(args, expr.span);
 
         ty
     }
@@ -1796,7 +1797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn check_expr_const_block(
+    pub(super) fn check_expr_const_block(
         &self,
         block: &'tcx hir::ConstBlock,
         expected: Expectation<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index ad764e5563b..1f48b703e4a 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -595,7 +595,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                         let place_ty = place.place.ty();
                         needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span);
                     }
-                    PatKind::Lit(_) | PatKind::Range(..) => {
+                    PatKind::Expr(_) | PatKind::Range(..) => {
                         // If the PatKind is a Lit or a Range then we want
                         // to borrow discr.
                         needs_to_be_read = true;
@@ -1803,7 +1803,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
 
             PatKind::Path(_)
             | PatKind::Binding(.., None)
-            | PatKind::Lit(..)
+            | PatKind::Expr(..)
             | PatKind::Range(..)
             | PatKind::Never
             | PatKind::Wild
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2f6e50c8014..4130f0c11dd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -577,11 +577,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Registers obligations that all `args` are well-formed.
-    pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) {
+    pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) {
         for arg in args.iter().filter(|arg| {
             matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
         }) {
-            self.register_wf_obligation(arg, expr.span, ObligationCauseCode::WellFormed(None));
+            self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None));
         }
     }
 
@@ -1039,6 +1039,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 def_id,
                 span,
             ),
+            Res::Err => {
+                return (
+                    Ty::new_error(
+                        tcx,
+                        tcx.dcx().span_delayed_bug(span, "could not resolve path {:?}"),
+                    ),
+                    res,
+                );
+            }
             _ => bug!("instantiate_value_path on {:?}", res),
         };
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 3756f6339a4..39511ca30e0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1320,14 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let span = expr.span.shrink_to_hi();
                 let subdiag = if self.type_is_copy_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Copied { span, def_path }
-                } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
-                    && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
-                        self,
-                        self.param_env,
-                        ty,
-                        clone_did,
-                    )
-                {
+                } else if self.type_is_clone_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Cloned { span, def_path }
                 } else {
                     return false;
@@ -2182,6 +2175,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Suggest replacing comma with semicolon in incorrect repeat expressions
+    /// like `["_", 10]` or `vec![String::new(), 10]`.
+    pub(crate) fn suggest_semicolon_in_repeat_expr(
+        &self,
+        err: &mut Diag<'_>,
+        expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+    ) -> bool {
+        // Check if `expr` is contained in array of two elements
+        if let hir::Node::Expr(array_expr) = self.tcx.parent_hir_node(expr.hir_id)
+            && let hir::ExprKind::Array(elements) = array_expr.kind
+            && let [first, second] = &elements[..]
+            && second.hir_id == expr.hir_id
+        {
+            // Span between the two elements of the array
+            let comma_span = first.span.between(second.span);
+
+            // Check if `expr` is a constant value of type `usize`.
+            // This can only detect const variable declarations and
+            // calls to const functions.
+
+            // Checking this here instead of rustc_hir::hir because
+            // this check needs access to `self.tcx` but rustc_hir
+            // has no access to `TyCtxt`.
+            let expr_is_const_usize = expr_ty.is_usize()
+                && match expr.kind {
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        Path { res: Res::Def(DefKind::Const, _), .. },
+                    )) => true,
+                    ExprKind::Call(
+                        Expr {
+                            kind:
+                                ExprKind::Path(QPath::Resolved(
+                                    None,
+                                    Path { res: Res::Def(DefKind::Fn, fn_def_id), .. },
+                                )),
+                            ..
+                        },
+                        _,
+                    ) => self.tcx.is_const_fn(*fn_def_id),
+                    _ => false,
+                };
+
+            // Type of the first element is guaranteed to be checked
+            // when execution reaches here because `mismatched types`
+            // error occurs only when type of second element of array
+            // is not the same as type of first element.
+            let first_ty = self.typeck_results.borrow().expr_ty(first);
+
+            // `array_expr` is from a macro `vec!["a", 10]` if
+            // 1. array expression's span is imported from a macro
+            // 2. first element of array implements `Clone` trait
+            // 3. second element is an integer literal or is an expression of `usize` like type
+            if self.tcx.sess.source_map().is_imported(array_expr.span)
+                && self.type_is_clone_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_ty.is_usize_like())
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "a vector",
+                });
+                return true;
+            }
+
+            // `array_expr` is from an array `["a", 10]` if
+            // 1. first element of array implements `Copy` trait
+            // 2. second element is an integer literal or is a const value of type `usize`
+            if self.type_is_copy_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_is_const_usize)
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "an array",
+                });
+                return true;
+            }
+        }
+        false
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     pub(crate) fn suggest_compatible_variants(
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 0c93c9817b4..f549ced9dc3 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -611,7 +611,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         // this is a projection from a trait reference, so we have to
         // make sure that the trait reference inputs are well-formed.
-        self.add_wf_bounds(all_args, self.call_expr);
+        self.add_wf_bounds(all_args, self.call_expr.span);
 
         // the function type must also be well-formed (this is not
         // implied by the args being well-formed because of inherent
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 5ccfcf93f69..69d7a6c97cb 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -8,7 +8,7 @@ use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::lint::builtin::{RUST_2021_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS};
-use rustc_span::{Ident, Span, kw, sym};
+use rustc_span::{Ident, STDLIB_STABLE_CRATES, Span, kw, sym};
 use rustc_trait_selection::infer::InferCtxtExt;
 use tracing::debug;
 
@@ -76,7 +76,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // No need to lint if method came from std/core, as that will now be in the prelude
-        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
+        if STDLIB_STABLE_CRATES.contains(&self.tcx.crate_name(pick.item.def_id.krate)) {
             return;
         }
 
@@ -252,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // No need to lint if method came from std/core, as that will now be in the prelude
-        if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
+        if STDLIB_STABLE_CRATES.contains(&self.tcx.crate_name(pick.item.def_id.krate)) {
             return;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index b4f1dcfb9cc..72a1e4af9bf 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -170,6 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 ..
             })
+            | hir::Node::PatExpr(&hir::PatExpr {
+                kind: hir::PatExprKind::Path(QPath::TypeRelative(rcvr, segment)),
+                span,
+                ..
+            })
             | hir::Node::Pat(&hir::Pat {
                 kind:
                     hir::PatKind::Path(QPath::TypeRelative(rcvr, segment))
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 4870e6193c3..36094657eaf 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -30,6 +30,7 @@ use tracing::{debug, instrument, trace};
 use ty::VariantDef;
 
 use super::report_unexpected_variant_res;
+use crate::expectation::Expectation;
 use crate::gather_locals::DeclOrigin;
 use crate::{FnCtxt, LoweredTy, errors};
 
@@ -270,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PatKind::Wild | PatKind::Err(_) => expected,
             // We allow any type here; we ensure that the type is uninhabited during match checking.
             PatKind::Never => expected,
-            PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
+            PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
             PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
             PatKind::Binding(ba, var_id, ident, sub) => {
                 self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
@@ -279,7 +280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
             }
             PatKind::Path(ref qpath) => {
-                self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
+                self.check_pat_path(pat.hir_id, pat.span, qpath, path_res.unwrap(), expected, ti)
             }
             PatKind::Struct(ref qpath, fields, has_rest_pat) => {
                 self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
@@ -398,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
             //
             // Call `resolve_vars_if_possible` here for inline const blocks.
-            PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
+            PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
                 ty::Ref(..) => AdjustMode::Pass,
                 _ => AdjustMode::Peel,
             },
@@ -493,10 +494,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         (expected, def_br, max_ref_mutbl)
     }
 
+    fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
+        let ty = match &lt.kind {
+            rustc_hir::PatExprKind::Lit { lit, .. } => {
+                self.check_expr_lit(lit, Expectation::NoExpectation)
+            }
+            rustc_hir::PatExprKind::ConstBlock(c) => {
+                self.check_expr_const_block(c, Expectation::NoExpectation)
+            }
+            rustc_hir::PatExprKind::Path(qpath) => {
+                let (res, opt_ty, segments) =
+                    self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
+                self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0
+            }
+        };
+        self.write_ty(lt.hir_id, ty);
+        ty
+    }
+
     fn check_pat_lit(
         &self,
         span: Span,
-        lt: &hir::Expr<'tcx>,
+        lt: &hir::PatExpr<'tcx>,
         expected: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
@@ -507,7 +526,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
         let mut pat_ty = ty;
-        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
+        if let hir::PatExprKind::Lit {
+            lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
+        } = lt.kind
+        {
             let expected = self.structurally_resolve_type(span, expected);
             if let ty::Ref(_, inner_ty, _) = *expected.kind()
                 && self.try_structurally_resolve_type(span, inner_ty).is_slice()
@@ -524,7 +546,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if self.tcx.features().string_deref_patterns()
-            && let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind
+            && let hir::PatExprKind::Lit {
+                lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
+            } = lt.kind
         {
             let tcx = self.tcx;
             let expected = self.resolve_vars_if_possible(expected);
@@ -565,15 +589,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_range(
         &self,
         span: Span,
-        lhs: Option<&'tcx hir::Expr<'tcx>>,
-        rhs: Option<&'tcx hir::Expr<'tcx>>,
+        lhs: Option<&'tcx hir::PatExpr<'tcx>>,
+        rhs: Option<&'tcx hir::PatExpr<'tcx>>,
         expected: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
-        let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
+        let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr {
             None => None,
             Some(expr) => {
-                let ty = self.check_expr(expr);
+                let ty = self.check_pat_expr_unadjusted(expr);
                 // Check that the end-point is possibly of numeric or char type.
                 // The early check here is not for correctness, but rather better
                 // diagnostics (e.g. when `&str` is being matched, `expected` will
@@ -919,7 +943,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | PatKind::Box(..)
                         | PatKind::Deref(_)
                         | PatKind::Ref(..)
-                        | PatKind::Lit(..)
+                        | PatKind::Expr(..)
                         | PatKind::Range(..)
                         | PatKind::Err(_) => break 'block None,
                     },
@@ -1053,7 +1077,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     fn check_pat_path(
         &self,
-        pat: &Pat<'tcx>,
+        hir_id: HirId,
+        span: Span,
         qpath: &hir::QPath<'_>,
         path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
         expected: Ty<'tcx>,
@@ -1072,8 +1097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
-                let e =
-                    report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0533, expected);
+                let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
                 return Ty::new_error(tcx, e);
             }
             Res::SelfCtor(def_id) => {
@@ -1088,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res,
                         None,
                         qpath,
-                        pat.span,
+                        span,
                         E0533,
                         "unit struct",
                     );
@@ -1107,11 +1131,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the path.
         let (pat_ty, pat_res) =
-            self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
+            self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id);
         if let Err(err) =
-            self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
+            self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
         {
-            self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
+            self.emit_bad_pat_path(err, hir_id, span, res, pat_res, pat_ty, segments);
         }
         pat_ty
     }
@@ -1154,13 +1178,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn emit_bad_pat_path(
         &self,
         mut e: Diag<'_>,
-        pat: &hir::Pat<'tcx>,
+        hir_id: HirId,
+        pat_span: Span,
         res: Res,
         pat_res: Res,
         pat_ty: Ty<'tcx>,
         segments: &'tcx [hir::PathSegment<'tcx>],
     ) {
-        let pat_span = pat.span;
         if let Some(span) = self.tcx.hir().res_span(pat_res) {
             e.span_label(span, format!("{} defined here", res.descr()));
             if let [hir::PathSegment { ident, .. }] = &*segments {
@@ -1173,7 +1197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res.descr(),
                     ),
                 );
-                match self.tcx.parent_hir_node(pat.hir_id) {
+                match self.tcx.parent_hir_node(hir_id) {
                     hir::Node::PatField(..) => {
                         e.span_suggestion_verbose(
                             ident.span.shrink_to_hi(),
@@ -1813,9 +1837,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 } else if inexistent_fields.len() == 1 {
                     match pat_field.pat.kind {
-                        PatKind::Lit(expr)
+                        PatKind::Expr(_)
                             if !self.may_coerce(
-                                self.typeck_results.borrow().expr_ty(expr),
+                                self.typeck_results.borrow().node_type(pat_field.pat.hir_id),
                                 self.field_ty(field.span, field_def, args),
                             ) => {}
                         _ => {
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 53993ba8d6c..cac891c4e4c 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -147,15 +147,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
                 self.visit_body(body);
                 self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
             }
-            hir::ExprKind::ConstBlock(anon_const) => {
-                let body = self.fcx.tcx.hir().body(anon_const.body);
-                self.visit_body(body);
-            }
             _ => {}
         }
 
         intravisit::walk_expr(self, expr);
     }
+
+    fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
+        let body = self.fcx.tcx.hir().body(c.body);
+        self.visit_body(body);
+    }
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 5612aa75aae..f63a0b17964 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -246,6 +246,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             }
         }
     }
+
+    fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) {
+        self.visit_node_id(span, anon_const.hir_id);
+
+        let body = self.tcx().hir().body(anon_const.body);
+        self.visit_body(body);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -275,11 +282,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
                 self.visit_field_id(e.hir_id);
             }
-            hir::ExprKind::ConstBlock(anon_const) => {
-                self.visit_node_id(e.span, anon_const.hir_id);
-
-                let body = self.tcx().hir().body(anon_const.body);
-                self.visit_body(body);
+            hir::ExprKind::ConstBlock(ref anon_const) => {
+                self.visit_const_block(e.span, anon_const);
             }
             _ => {}
         }
@@ -335,6 +339,14 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
         intravisit::walk_pat(self, p);
     }
 
+    fn visit_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) {
+        self.visit_node_id(expr.span, expr.hir_id);
+        if let hir::PatExprKind::ConstBlock(c) = &expr.kind {
+            self.visit_const_block(expr.span, c);
+        }
+        intravisit::walk_pat_expr(self, expr);
+    }
+
     fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) {
         intravisit::walk_local(self, l);
         let var_ty = self.fcx.local_ty(l.span, l.hir_id);
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index e74fb9d92e9..fb3cf5afad0 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1271,9 +1271,8 @@ declare_lint! {
     /// `pub(crate)` visibility is recommended to be used instead. This more clearly expresses the
     /// intent that the item is only visible within its own crate.
     ///
-    /// This lint is "allow" by default because it will trigger for a large
-    /// amount of existing Rust code, and has some false-positives. Eventually it
-    /// is desired for this to become warn-by-default.
+    /// This lint is "allow" by default because it will trigger for a large amount of existing Rust code.
+    /// Eventually it is desired for this to become warn-by-default.
     ///
     /// [`unnameable_types`]: #unnameable-types
     pub UNREACHABLE_PUB,
@@ -1304,9 +1303,9 @@ impl UnreachablePub {
                 cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| {
                     effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable)
                 })
-                && let parent_parent = cx.tcx.parent_module_from_def_id(
-                    cx.tcx.parent_module_from_def_id(def_id.into()).into(),
-                )
+                && let parent_parent = cx
+                    .tcx
+                    .parent_module_from_def_id(cx.tcx.parent_module_from_def_id(def_id).into())
                 && *restricted_did == parent_parent.to_local_def_id()
                 && !restricted_did.to_def_id().is_crate_root()
             {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 8b1526bc747..3059adb3fda 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1220,7 +1220,7 @@ impl EarlyLintPass for UnusedParens {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
             // The other cases do not contain sub-patterns.
-            | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
+            | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                 self.check_unused_parens_pat(cx, p, false, false, keep_space);
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index dee4c424387..632935eefeb 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -938,6 +938,7 @@ impl<'hir> Map<'hir> {
             Node::OpaqueTy(op) => op.span,
             Node::Pat(pat) => pat.span,
             Node::PatField(field) => field.span,
+            Node::PatExpr(lit) => lit.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
             Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
@@ -1209,6 +1210,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Node::OpaqueTy(_) => node_str("opaque type"),
         Node::Pat(_) => node_str("pat"),
         Node::PatField(_) => node_str("pattern field"),
+        Node::PatExpr(_) => node_str("pattern literal"),
         Node::Param(_) => node_str("param"),
         Node::Arm(_) => node_str("arm"),
         Node::Block(_) => node_str("block"),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5e929fbec0b..2d69386176b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `arg` is
     /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).instantiate(tcx, arg)
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).instantiate(tcx, args)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 92b3632c8ac..2980964898c 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -27,7 +27,7 @@ use crate::infer::canonical::Canonical;
 use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
-    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
 };
 
 // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
@@ -1017,6 +1017,18 @@ impl<'tcx> Ty<'tcx> {
         }
     }
 
+    /// Check if type is an `usize`.
+    #[inline]
+    pub fn is_usize(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize))
+    }
+
+    /// Check if type is an `usize` or an integral type variable.
+    #[inline]
+    pub fn is_usize_like(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
+    }
+
     #[inline]
     pub fn is_never(self) -> bool {
         matches!(self.kind(), Never)
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 35c98037827..20441530a47 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -1131,15 +1131,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Schedule emission of a backwards incompatible drop lint hint.
     /// Applicable only to temporary values for now.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn schedule_backwards_incompatible_drop(
         &mut self,
         span: Span,
         region_scope: region::Scope,
         local: Local,
     ) {
-        if !self.local_decls[local].ty.has_significant_drop(self.tcx, self.typing_env()) {
-            return;
-        }
+        // Note that we are *not* gating BIDs here on whether they have significant destructor.
+        // We need to know all of them so that we can capture potential borrow-checking errors.
         for scope in self.scopes.scopes.iter_mut().rev() {
             // Since we are inserting linting MIR statement, we have to invalidate the caches
             scope.invalidate_cache();
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 54510faf2e1..242b62dfa8d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -154,7 +154,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
     fn lower_pattern_range_endpoint(
         &mut self,
-        expr: Option<&'tcx hir::Expr<'tcx>>,
+        expr: Option<&'tcx hir::PatExpr<'tcx>>,
     ) -> Result<
         (Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
         ErrorGuaranteed,
@@ -200,13 +200,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// This is only called when the range is already known to be malformed.
     fn error_on_literal_overflow(
         &self,
-        expr: Option<&'tcx hir::Expr<'tcx>>,
+        expr: Option<&'tcx hir::PatExpr<'tcx>>,
         ty: Ty<'tcx>,
     ) -> Result<(), ErrorGuaranteed> {
-        use hir::{ExprKind, UnOp};
         use rustc_ast::ast::LitKind;
 
-        let Some(mut expr) = expr else {
+        let Some(expr) = expr else {
             return Ok(());
         };
         let span = expr.span;
@@ -214,12 +213,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // We need to inspect the original expression, because if we only inspect the output of
         // `eval_bits`, an overflowed value has already been wrapped around.
         // We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
-        let mut negated = false;
-        if let ExprKind::Unary(UnOp::Neg, sub_expr) = expr.kind {
-            negated = true;
-            expr = sub_expr;
-        }
-        let ExprKind::Lit(lit) = expr.kind else {
+        let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
             return Ok(());
         };
         let LitKind::Int(lit_val, _) = lit.node else {
@@ -248,8 +242,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
     fn lower_pattern_range(
         &mut self,
-        lo_expr: Option<&'tcx hir::Expr<'tcx>>,
-        hi_expr: Option<&'tcx hir::Expr<'tcx>>,
+        lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
+        hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
         end: RangeEnd,
         ty: Ty<'tcx>,
         span: Span,
@@ -330,7 +324,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
             hir::PatKind::Never => PatKind::Never,
 
-            hir::PatKind::Lit(value) => self.lower_lit(value),
+            hir::PatKind::Expr(value) => self.lower_lit(value),
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
                 let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
@@ -662,25 +656,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// The special case for negation exists to allow things like `-128_i8`
     /// which would overflow if we tried to evaluate `128_i8` and then negate
     /// afterwards.
-    fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
-        let (lit, neg) = match expr.kind {
-            hir::ExprKind::Path(ref qpath) => {
+    fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
+        let (lit, neg) = match &expr.kind {
+            hir::PatExprKind::Path(qpath) => {
                 return self.lower_path(qpath, expr.hir_id, expr.span).kind;
             }
-            hir::ExprKind::ConstBlock(ref anon_const) => {
+            hir::PatExprKind::ConstBlock(anon_const) => {
                 return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
             }
-            hir::ExprKind::Lit(ref lit) => (lit, false),
-            hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
-                let hir::ExprKind::Lit(ref lit) = expr.kind else {
-                    span_bug!(expr.span, "not a literal: {:?}", expr);
-                };
-                (lit, true)
-            }
-            _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+            hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
         };
 
-        let ct_ty = self.typeck_results.expr_ty(expr);
+        let ct_ty = self.typeck_results.node_type(expr.hir_id);
         let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
         match self.tcx.at(expr.span).lit_to_const(lit_input) {
             Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 283ed94b615..71bec38c405 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1366,57 +1366,108 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             return self.new_opaque();
         }
 
-        let mut was_updated = false;
-
-        // If that cast just casts away the metadata again,
-        if let PtrToPtr = kind
-            && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
-                self.get(value)
-            && let ty::RawPtr(to_pointee, _) = to.kind()
-            && to_pointee.is_sized(self.tcx, self.typing_env())
-        {
-            from = *data_pointer_ty;
-            value = fields[0];
-            was_updated = true;
-            if *data_pointer_ty == to {
-                return Some(fields[0]);
+        let mut was_ever_updated = false;
+        loop {
+            let mut was_updated_this_iteration = false;
+
+            // Transmuting between raw pointers is just a pointer cast so long as
+            // they have the same metadata type (like `*const i32` <=> `*mut u64`
+            // or `*mut [i32]` <=> `*const [u64]`), including the common special
+            // case of `*const T` <=> `*mut T`.
+            if let Transmute = kind
+                && from.is_unsafe_ptr()
+                && to.is_unsafe_ptr()
+                && self.pointers_have_same_metadata(from, to)
+            {
+                *kind = PtrToPtr;
+                was_updated_this_iteration = true;
             }
-        }
 
-        // PtrToPtr-then-PtrToPtr can skip the intermediate step
-        if let PtrToPtr = kind
-            && let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
-                *self.get(value)
-            && let PtrToPtr = inner_kind
-        {
-            from = inner_from;
-            value = inner_value;
-            was_updated = true;
-            if inner_from == to {
-                return Some(inner_value);
+            // If a cast just casts away the metadata again, then we can get it by
+            // casting the original thin pointer passed to `from_raw_parts`
+            if let PtrToPtr = kind
+                && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
+                    self.get(value)
+                && let ty::RawPtr(to_pointee, _) = to.kind()
+                && to_pointee.is_sized(self.tcx, self.typing_env())
+            {
+                from = *data_pointer_ty;
+                value = fields[0];
+                was_updated_this_iteration = true;
+                if *data_pointer_ty == to {
+                    return Some(fields[0]);
+                }
             }
-        }
 
-        // PtrToPtr-then-Transmute can just transmute the original, so long as the
-        // PtrToPtr didn't change metadata (and thus the size of the pointer)
-        if let Transmute = kind
-            && let Value::Cast {
-                kind: PtrToPtr,
+            // Aggregate-then-Transmute can just transmute the original field value,
+            // so long as the bytes of a value from only from a single field.
+            if let Transmute = kind
+                && let Value::Aggregate(_aggregate_ty, variant_idx, field_values) = self.get(value)
+                && let Some((field_idx, field_ty)) =
+                    self.value_is_all_in_one_field(from, *variant_idx)
+            {
+                from = field_ty;
+                value = field_values[field_idx.as_usize()];
+                was_updated_this_iteration = true;
+                if field_ty == to {
+                    return Some(value);
+                }
+            }
+
+            // Various cast-then-cast cases can be simplified.
+            if let Value::Cast {
+                kind: inner_kind,
                 value: inner_value,
                 from: inner_from,
                 to: inner_to,
             } = *self.get(value)
-            && self.pointers_have_same_metadata(inner_from, inner_to)
-        {
-            from = inner_from;
-            value = inner_value;
-            was_updated = true;
-            if inner_from == to {
-                return Some(inner_value);
+            {
+                let new_kind = match (inner_kind, *kind) {
+                    // Even if there's a narrowing cast in here that's fine, because
+                    // things like `*mut [i32] -> *mut i32 -> *const i32` and
+                    // `*mut [i32] -> *const [i32] -> *const i32` can skip the middle in MIR.
+                    (PtrToPtr, PtrToPtr) => Some(PtrToPtr),
+                    // PtrToPtr-then-Transmute is fine so long as the pointer cast is identity:
+                    // `*const T -> *mut T -> NonNull<T>` is fine, but we need to check for narrowing
+                    // to skip things like `*const [i32] -> *const i32 -> NonNull<T>`.
+                    (PtrToPtr, Transmute)
+                        if self.pointers_have_same_metadata(inner_from, inner_to) =>
+                    {
+                        Some(Transmute)
+                    }
+                    // Similarly, for Transmute-then-PtrToPtr. Note that we need to check different
+                    // variables for their metadata, and thus this can't merge with the previous arm.
+                    (Transmute, PtrToPtr) if self.pointers_have_same_metadata(from, to) => {
+                        Some(Transmute)
+                    }
+                    // If would be legal to always do this, but we don't want to hide information
+                    // from the backend that it'd otherwise be able to use for optimizations.
+                    (Transmute, Transmute)
+                        if !self.type_may_have_niche_of_interest_to_backend(inner_to) =>
+                    {
+                        Some(Transmute)
+                    }
+                    _ => None,
+                };
+                if let Some(new_kind) = new_kind {
+                    *kind = new_kind;
+                    from = inner_from;
+                    value = inner_value;
+                    was_updated_this_iteration = true;
+                    if inner_from == to {
+                        return Some(inner_value);
+                    }
+                }
+            }
+
+            if was_updated_this_iteration {
+                was_ever_updated = true;
+            } else {
+                break;
             }
         }
 
-        if was_updated && let Some(op) = self.try_as_operand(value, location) {
+        if was_ever_updated && let Some(op) = self.try_as_operand(value, location) {
             *operand = op;
         }
 
@@ -1438,6 +1489,54 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             false
         }
     }
+
+    /// Returns `false` if we know for sure that this type has no interesting niche,
+    /// and thus we can skip transmuting through it without worrying.
+    ///
+    /// The backend will emit `assume`s when transmuting between types with niches,
+    /// so we want to preserve `i32 -> char -> u32` so that that data is around,
+    /// but it's fine to skip whole-range-is-value steps like `A -> u32 -> B`.
+    fn type_may_have_niche_of_interest_to_backend(&self, ty: Ty<'tcx>) -> bool {
+        let Ok(layout) = self.ecx.layout_of(ty) else {
+            // If it's too generic or something, then assume it might be interesting later.
+            return true;
+        };
+
+        match layout.backend_repr {
+            BackendRepr::Uninhabited => true,
+            BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx),
+            BackendRepr::ScalarPair(a, b) => {
+                !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx)
+            }
+            BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => false,
+        }
+    }
+
+    fn value_is_all_in_one_field(
+        &self,
+        ty: Ty<'tcx>,
+        variant: VariantIdx,
+    ) -> Option<(FieldIdx, Ty<'tcx>)> {
+        if let Ok(layout) = self.ecx.layout_of(ty)
+            && let abi::Variants::Single { index } = layout.variants
+            && index == variant
+            && let Some((field_idx, field_layout)) = layout.non_1zst_field(&self.ecx)
+            && layout.size == field_layout.size
+        {
+            // We needed to check the variant to avoid trying to read the tag
+            // field from an enum where no fields have variants, since that tag
+            // field isn't in the `Aggregate` from which we're getting values.
+            Some((FieldIdx::from_usize(field_idx), field_layout.ty))
+        } else if let ty::Adt(adt, args) = ty.kind()
+            && adt.is_struct()
+            && adt.repr().transparent()
+            && let [single_field] = adt.non_enum_variant().fields.raw.as_slice()
+        {
+            Some((FieldIdx::ZERO, single_field.ty(self.tcx, args)))
+        } else {
+            None
+        }
+    }
 }
 
 fn op_to_prop_const<'tcx>(
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 1a65affe812..9e024508c58 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -173,29 +173,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
                     *kind = CastKind::IntToInt;
                     return;
                 }
-
-                // Transmuting a transparent struct/union to a field's type is a projection
-                if let ty::Adt(adt_def, args) = operand_ty.kind()
-                    && adt_def.repr().transparent()
-                    && (adt_def.is_struct() || adt_def.is_union())
-                    && let Some(place) = operand.place()
-                {
-                    let variant = adt_def.non_enum_variant();
-                    for (i, field) in variant.fields.iter_enumerated() {
-                        let field_ty = field.ty(self.tcx, args);
-                        if field_ty == *cast_ty {
-                            let place = place
-                                .project_deeper(&[ProjectionElem::Field(i, *cast_ty)], self.tcx);
-                            let operand = if operand.is_move() {
-                                Operand::Move(place)
-                            } else {
-                                Operand::Copy(place)
-                            };
-                            *rvalue = Rvalue::Use(operand);
-                            return;
-                        }
-                    }
-                }
             }
         }
     }
diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
index e5a183bc75c..6590702118c 100644
--- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
+++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
@@ -351,6 +351,11 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
     {
         return;
     }
+
+    // FIXME(typing_env): This should be able to reveal the opaques local to the
+    // body using the typeck results.
+    let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
+
     // ## About BIDs in blocks ##
     // Track the set of blocks that contain a backwards-incompatible drop (BID)
     // and, for each block, the vector of locations.
@@ -358,7 +363,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
     // We group them per-block because they tend to scheduled in the same drop ladder block.
     let mut bid_per_block = IndexMap::default();
     let mut bid_places = UnordSet::new();
-    let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
+
     let mut ty_dropped_components = UnordMap::default();
     for (block, data) in body.basic_blocks.iter_enumerated() {
         for (statement_index, stmt) in data.statements.iter().enumerate() {
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7da4f5e0107..3c5d9b95e77 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
     }
 }
 
+// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
+// the old solver, for as long as that exists.
 pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
     cx: I,
     self_ty: I::Ty,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 5ad3da2196f..64bcb1a5a36 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -656,14 +656,14 @@ impl<'a> Parser<'a> {
             fn visit_pat(&mut self, p: &'a Pat) -> Self::Result {
                 match &p.kind {
                     // Base expression
-                    PatKind::Err(_) | PatKind::Lit(_) => {
+                    PatKind::Err(_) | PatKind::Expr(_) => {
                         self.maybe_add_suggestions_then_emit(p.span, p.span, false)
                     }
 
                     // Sub-patterns
                     // FIXME: this doesn't work with recursive subpats (`&mut &mut <err>`)
                     PatKind::Box(subpat) | PatKind::Ref(subpat, _)
-                        if matches!(subpat.kind, PatKind::Err(_) | PatKind::Lit(_)) =>
+                        if matches!(subpat.kind, PatKind::Err(_) | PatKind::Expr(_)) =>
                     {
                         self.maybe_add_suggestions_then_emit(subpat.span, p.span, false)
                     }
@@ -766,7 +766,7 @@ impl<'a> Parser<'a> {
             if let Some(re) = self.parse_range_end() {
                 self.parse_pat_range_begin_with(const_expr, re)?
             } else {
-                PatKind::Lit(const_expr)
+                PatKind::Expr(const_expr)
             }
         } else if self.is_builtin() {
             self.parse_pat_builtin()?
@@ -833,7 +833,7 @@ impl<'a> Parser<'a> {
                         .struct_span_err(self_.token.span, msg)
                         .with_span_label(self_.token.span, format!("expected {expected}"))
                 });
-            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
+            PatKind::Expr(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
@@ -845,7 +845,7 @@ impl<'a> Parser<'a> {
 
                     match self.parse_range_end() {
                         Some(form) => self.parse_pat_range_begin_with(begin, form)?,
-                        None => PatKind::Lit(begin),
+                        None => PatKind::Expr(begin),
                     }
                 }
                 Err(err) => return self.fatal_unexpected_non_pat(err, expected),
@@ -989,7 +989,7 @@ impl<'a> Parser<'a> {
 
             match &pat.kind {
                 // recover ranges with parentheses around the `(start)..`
-                PatKind::Lit(begin)
+                PatKind::Expr(begin)
                     if self.may_recover()
                         && let Some(form) = self.parse_range_end() =>
                 {
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index c222aaa9a86..655ab822359 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2366,8 +2366,7 @@ fn string_to_tts_1() {
                         token::Ident(sym::i32, IdentIsRaw::No),
                         sp(8, 11),
                     ),
-                ])
-                .into(),
+                ]),
             ),
             TokenTree::Delimited(
                 DelimSpan::from_pair(sp(13, 14), sp(18, 19)),
@@ -2383,8 +2382,7 @@ fn string_to_tts_1() {
                     ),
                     // `Alone` because the `;` is followed by whitespace.
                     TokenTree::token_alone(token::Semi, sp(16, 17)),
-                ])
-                .into(),
+                ]),
             ),
         ]);
 
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 88d69eb3678..6617cf2f723 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -304,7 +304,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
             Box,
             Deref,
             Ref,
-            Lit,
+            Expr,
             Guard,
             Range,
             Slice,
@@ -587,7 +587,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
             Box,
             Deref,
             Ref,
-            Lit,
+            Expr,
             Range,
             Slice,
             Rest,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c47c3f64bf6..2936d722aa7 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1130,7 +1130,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         let None = following_seg else { return };
         for rib in self.ribs[ValueNS].iter().rev() {
             for (def_id, spans) in &rib.patterns_with_skipped_bindings {
-                if let Some(fields) = self.r.field_idents(*def_id) {
+                if let DefKind::Struct | DefKind::Variant = self.r.tcx.def_kind(*def_id)
+                    && let Some(fields) = self.r.field_idents(*def_id)
+                {
                     for field in fields {
                         if field.name == segment.ident.name {
                             if spans.iter().all(|(_, had_error)| had_error.is_err()) {
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index d5c2a337b4c..51cfbf59471 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -67,7 +67,7 @@ mod span_encoding;
 pub use span_encoding::{DUMMY_SP, Span};
 
 pub mod symbol;
-pub use symbol::{Ident, MacroRulesNormalizedIdent, Symbol, kw, sym};
+pub use symbol::{Ident, MacroRulesNormalizedIdent, STDLIB_STABLE_CRATES, Symbol, kw, sym};
 
 mod analyze_source_file;
 pub mod fatal_error;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0dcf38e3493..ef1e2c20978 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2240,6 +2240,10 @@ symbols! {
     }
 }
 
+/// Symbols for crates that are part of the stable standard library: `std`, `core`, `alloc`, and
+/// `proc_macro`.
+pub const STDLIB_STABLE_CRATES: &[Symbol] = &[sym::std, sym::core, sym::alloc, sym::proc_macro];
+
 #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
 pub struct Ident {
     pub name: Symbol,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0dc1d795a8e..a149f682c56 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1812,9 +1812,11 @@ supported_targets! {
     ("aarch64-unknown-illumos", aarch64_unknown_illumos),
 
     ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
+    ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
+    ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
     ("i686-pc-windows-gnu", i686_pc_windows_gnu),
     ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
-    ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
+    ("i686-win7-windows-gnu", i686_win7_windows_gnu),
 
     ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
     ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
new file mode 100644
index 00000000000..086a799a68c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
@@ -0,0 +1,35 @@
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::windows_gnu::opts();
+    base.vendor = "win7".into();
+    base.cpu = "pentium4".into();
+    base.max_atomic_width = Some(64);
+    base.frame_pointer = FramePointer::Always; // Required for backtraces
+    base.linker = Some("i686-w64-mingw32-gcc".into());
+
+    // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+    // space available to x86 Windows binaries on x86_64.
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
+        "-m",
+        "i386pe",
+        "--large-address-aware",
+    ]);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,--large-address-aware"]);
+
+    Target {
+        llvm_target: "i686-pc-windows-gnu".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("32-bit MinGW (Windows 7+)".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 32,
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
+            .into(),
+        arch: "x86".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
new file mode 100644
index 00000000000..d40df5a3e7d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
@@ -0,0 +1,32 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::windows_gnu::opts();
+    base.vendor = "win7".into();
+    base.cpu = "x86-64".into();
+    base.plt_by_default = false;
+    // Use high-entropy 64 bit address space for ASLR
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
+        "-m",
+        "i386pep",
+        "--high-entropy-va",
+    ]);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
+    base.max_atomic_width = Some(64);
+    base.linker = Some("x86_64-w64-mingw32-gcc".into());
+
+    Target {
+        llvm_target: "x86_64-pc-windows-gnu".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("64-bit MinGW (Windows 7+)".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout:
+            "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 7ba87e180d0..405c26b5b3b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{
     self, ToPolyTraitRef, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast,
 };
 use rustc_middle::{bug, span_bug};
-use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, sym};
+use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};
 use tracing::{debug, instrument};
 
 use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
@@ -520,7 +520,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
                                 Some(macro_def_id) => {
                                     let crate_name = tcx.crate_name(macro_def_id.krate);
-                                    crate_name == sym::std || crate_name == sym::core
+                                    STDLIB_STABLE_CRATES.contains(&crate_name)
                                 }
                                 None => false,
                             };
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index ee708564a80..f373706b296 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -47,6 +47,12 @@ impl<'tcx> InferCtxt<'tcx> {
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
     }
 
+    fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+        let ty = self.resolve_vars_if_possible(ty);
+        let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, None);
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id)
+    }
+
     fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 15eb5d74cbf..446f9eaa348 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -79,7 +79,7 @@ pub fn is_const_evaluatable<'tcx>(
                     Err(
                         EvaluateConstErr::EvaluationFailure(e)
                         | EvaluateConstErr::InvalidConstParamTy(e),
-                    ) => Err(NotConstEvaluatable::Error(e.into())),
+                    ) => Err(NotConstEvaluatable::Error(e)),
                     Ok(_) => Ok(()),
                 }
             }
@@ -140,7 +140,7 @@ pub fn is_const_evaluatable<'tcx>(
             }
             Err(
                 EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e),
-            ) => Err(NotConstEvaluatable::Error(e.into())),
+            ) => Err(NotConstEvaluatable::Error(e)),
             Ok(_) => Ok(()),
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 0ac24eb54e7..b32909efe0b 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,4 +1,4 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::traits::{
     ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
@@ -48,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
         Err(EvaluationFailure::NoSolution) => {}
     }
 
+    match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
     match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
         Ok(result) => return Ok(result),
         Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -228,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
     }
 }
 
+fn evaluate_host_effect_from_builtin_impls<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
+        Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+        _ => Err(EvaluationFailure::NoSolution),
+    }
+}
+
+// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
+fn evaluate_host_effect_for_destruct_goal<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
+    let self_ty = obligation.predicate.self_ty();
+
+    let const_conditions = match *self_ty.kind() {
+        // An ADT is `~const Destruct` only if all of the fields are,
+        // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
+        ty::Adt(adt_def, args) => {
+            let mut const_conditions: ThinVec<_> = adt_def
+                .all_fields()
+                .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
+                .collect();
+            match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+                // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
+                Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
+                // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
+                Some(hir::Constness::Const) => {
+                    let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
+                    let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
+                    const_conditions.push(drop_trait_ref);
+                }
+                // No `Drop` impl, no need to require anything else.
+                None => {}
+            }
+            const_conditions
+        }
+
+        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
+            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
+        }
+
+        ty::Tuple(tys) => {
+            tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
+        }
+
+        // Trivially implement `~const Destruct`
+        ty::Bool
+        | ty::Char
+        | ty::Int(..)
+        | ty::Uint(..)
+        | ty::Float(..)
+        | ty::Str
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(..)
+        | ty::Never
+        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+        | ty::Error(_) => thin_vec![],
+
+        // Coroutines and closures could implement `~const Drop`,
+        // but they don't really need to right now.
+        ty::Closure(_, _)
+        | ty::CoroutineClosure(_, _)
+        | ty::Coroutine(_, _)
+        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+
+        // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
+        // if their inner type implements it.
+        ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
+
+        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
+
+        ty::Bound(..)
+        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            panic!("unexpected type `{self_ty:?}`")
+        }
+    };
+
+    Ok(const_conditions
+        .into_iter()
+        .map(|trait_ref| {
+            obligation.with(
+                tcx,
+                ty::Binder::dummy(trait_ref)
+                    .to_host_effect_clause(tcx, obligation.predicate.constness),
+            )
+        })
+        .collect())
+}
+
 fn evaluate_host_effect_from_selection_candiate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &HostEffectObligation<'tcx>,
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index e014404eff3..08a7b325798 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1789,7 +1789,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
     /// let x: Rc<&str> = Rc::new("Hello, world!");
     /// {
     ///     let s = String::from("Oh, no!");
-    ///     let mut y: Rc<&str> = x.clone().into();
+    ///     let mut y: Rc<&str> = x.clone();
     ///     unsafe {
     ///         // this is Undefined Behavior, because x's inner type
     ///         // is &'long str, not &'short str
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index b34a6d3f660..30761739dbf 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2468,7 +2468,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// let x: Arc<&str> = Arc::new("Hello, world!");
     /// {
     ///     let s = String::from("Oh, no!");
-    ///     let mut y: Arc<&str> = x.clone().into();
+    ///     let mut y: Arc<&str> = x.clone();
     ///     unsafe {
     ///         // this is Undefined Behavior, because x's inner type
     ///         // is &'long str, not &'short str
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 7af26d521b3..2c9131254f7 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -85,6 +85,20 @@ impl<T: ?Sized> !Send for NonNull<T> {}
 impl<T: ?Sized> !Sync for NonNull<T> {}
 
 impl<T: Sized> NonNull<T> {
+    /// Creates a pointer with the given address and no [provenance][crate::ptr#provenance].
+    ///
+    /// For more details, see the equivalent method on a raw pointer, [`ptr::without_provenance_mut`].
+    ///
+    /// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
+    #[unstable(feature = "nonnull_provenance", issue = "135243")]
+    pub const fn without_provenance(addr: NonZero<usize>) -> Self {
+        // SAFETY: we know `addr` is non-zero.
+        unsafe {
+            let ptr = crate::ptr::without_provenance_mut(addr.get());
+            NonNull::new_unchecked(ptr)
+        }
+    }
+
     /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
@@ -116,6 +130,21 @@ impl<T: Sized> NonNull<T> {
         }
     }
 
+    /// Converts an address back to a mutable pointer, picking up some previously 'exposed'
+    /// [provenance][crate::ptr#provenance].
+    ///
+    /// For more details, see the equivalent method on a raw pointer, [`ptr::with_exposed_provenance_mut`].
+    ///
+    /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
+    #[unstable(feature = "nonnull_provenance", issue = "135243")]
+    pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self {
+        // SAFETY: we know `addr` is non-zero.
+        unsafe {
+            let ptr = crate::ptr::with_exposed_provenance_mut(addr.get());
+            NonNull::new_unchecked(ptr)
+        }
+    }
+
     /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require
     /// that the value has to be initialized.
     ///
@@ -282,7 +311,7 @@ impl<T: ?Sized> NonNull<T> {
 
     /// Gets the "address" portion of the pointer.
     ///
-    /// For more details see the equivalent method on a raw pointer, [`pointer::addr`].
+    /// For more details, see the equivalent method on a raw pointer, [`pointer::addr`].
     ///
     /// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
     #[must_use]
@@ -294,10 +323,23 @@ impl<T: ?Sized> NonNull<T> {
         unsafe { NonZero::new_unchecked(self.as_ptr().addr()) }
     }
 
+    /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in
+    /// [`with_exposed_provenance`][NonNull::with_exposed_provenance] and returns the "address" portion.
+    ///
+    /// For more details, see the equivalent method on a raw pointer, [`pointer::expose_provenance`].
+    ///
+    /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
+    #[unstable(feature = "nonnull_provenance", issue = "135243")]
+    pub fn expose_provenance(self) -> NonZero<usize> {
+        // SAFETY: The pointer is guaranteed by the type to be non-null,
+        // meaning that the address will be non-zero.
+        unsafe { NonZero::new_unchecked(self.as_ptr().expose_provenance()) }
+    }
+
     /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of
     /// `self`.
     ///
-    /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`].
+    /// For more details, see the equivalent method on a raw pointer, [`pointer::with_addr`].
     ///
     /// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
     #[must_use]
@@ -311,7 +353,7 @@ impl<T: ?Sized> NonNull<T> {
     /// Creates a new pointer by mapping `self`'s address to a new one, preserving the
     /// [provenance][crate::ptr#provenance] of `self`.
     ///
-    /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`].
+    /// For more details, see the equivalent method on a raw pointer, [`pointer::map_addr`].
     ///
     /// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
     #[must_use]
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 85ee369ca2b..b6ee00a253a 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -502,7 +502,7 @@ impl Builder {
 
         let id = ThreadId::new();
         let my_thread = match name {
-            Some(name) => Thread::new(id, name.into()),
+            Some(name) => Thread::new(id, name),
             None => Thread::new_unnamed(id),
         };
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 29bc0cbf58a..6f7f8442800 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1592,15 +1592,9 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-std");
             prepare("rust-analysis");
-
-            for tool in &[
-                "clippy",
-                "rustfmt",
-                "rust-analyzer",
-                "rust-docs",
-                "miri",
-                "rustc-codegen-cranelift",
-            ] {
+            prepare("clippy");
+            prepare("rust-analyzer");
+            for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1640,8 +1634,6 @@ impl Step for Extended {
                     "rust-analyzer-preview".to_string()
                 } else if name == "clippy" {
                     "clippy-preview".to_string()
-                } else if name == "rustfmt" {
-                    "rustfmt-preview".to_string()
                 } else if name == "miri" {
                     "miri-preview".to_string()
                 } else if name == "rustc-codegen-cranelift" {
@@ -1661,7 +1653,7 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-analysis");
             prepare("rust-std");
-            for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
+            for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1779,24 +1771,6 @@ impl Step for Extended {
                     .arg(etc.join("msi/remove-duplicates.xsl"))
                     .run(builder);
             }
-            if built_tools.contains("rustfmt") {
-                command(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("rustfmt")
-                    .args(heat_flags)
-                    .arg("-cg")
-                    .arg("RustFmtGroup")
-                    .arg("-dr")
-                    .arg("RustFmt")
-                    .arg("-var")
-                    .arg("var.RustFmtDir")
-                    .arg("-out")
-                    .arg(exe.join("RustFmtGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl"))
-                    .run(builder);
-            }
             if built_tools.contains("miri") {
                 command(&heat)
                     .current_dir(&exe)
@@ -1868,9 +1842,6 @@ impl Step for Extended {
                 if built_tools.contains("clippy") {
                     cmd.arg("-dClippyDir=clippy");
                 }
-                if built_tools.contains("rustfmt") {
-                    cmd.arg("-dRustFmtDir=rustfmt");
-                }
                 if built_tools.contains("rust-docs") {
                     cmd.arg("-dDocsDir=rust-docs");
                 }
@@ -1897,9 +1868,6 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 candle("ClippyGroup.wxs".as_ref());
             }
-            if built_tools.contains("rustfmt") {
-                candle("RustFmtGroup.wxs".as_ref());
-            }
             if built_tools.contains("miri") {
                 candle("MiriGroup.wxs".as_ref());
             }
@@ -1938,9 +1906,6 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 cmd.arg("ClippyGroup.wixobj");
             }
-            if built_tools.contains("rustfmt") {
-                cmd.arg("RustFmtGroup.wixobj");
-            }
             if built_tools.contains("miri") {
                 cmd.arg("MiriGroup.wixobj");
             }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dc6dbbac9d2..914260e38d1 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -31,6 +31,7 @@ use crate::{CLang, DocTests, GitRepo, Mode, PathSet, envify};
 
 const ADB_TEST_DIR: &str = "/data/local/tmp/work";
 
+/// Runs `cargo test` on various internal tools used by bootstrap.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateBootstrap {
     path: PathBuf,
@@ -43,13 +44,21 @@ impl Step for CrateBootstrap {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        // This step is responsible for several different tool paths. By default
+        // it will test all of them, but requesting specific tools on the
+        // command-line (e.g. `./x test suggest-tests`) will test only the
+        // specified tools.
         run.path("src/tools/jsondoclint")
             .path("src/tools/suggest-tests")
             .path("src/tools/replace-version-placeholder")
+            // We want `./x test tidy` to _run_ the tidy tool, not its tests.
+            // So we need a separate alias to test the tidy tool itself.
             .alias("tidyselftest")
     }
 
     fn make_run(run: RunConfig<'_>) {
+        // Create and ensure a separate instance of this step for each path
+        // that was selected on the command-line (or selected by default).
         for path in run.paths {
             let path = path.assert_single_path().path.clone();
             run.builder.ensure(CrateBootstrap { host: run.target, path });
@@ -60,6 +69,8 @@ impl Step for CrateBootstrap {
         let bootstrap_host = builder.config.build;
         let compiler = builder.compiler(0, bootstrap_host);
         let mut path = self.path.to_str().unwrap();
+
+        // Map alias `tidyselftest` back to the actual crate path of tidy.
         if path == "tidyselftest" {
             path = "src/tools/tidy";
         }
@@ -212,6 +223,9 @@ impl Step for HtmlCheck {
     }
 }
 
+/// Builds cargo and then runs the `src/tools/cargotest` tool, which checks out
+/// some representative crate repositories and runs `cargo test` on them, in
+/// order to test cargo.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargotest {
     stage: u32,
@@ -257,6 +271,7 @@ impl Step for Cargotest {
     }
 }
 
+/// Runs `cargo test` for cargo itself.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargo {
     stage: u32,
@@ -385,6 +400,7 @@ impl Step for RustAnalyzer {
     }
 }
 
+/// Runs `cargo test` for rustfmt.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Rustfmt {
     stage: u32,
@@ -589,6 +605,8 @@ impl Step for Miri {
     }
 }
 
+/// Runs `cargo miri test` to demonstrate that `src/tools/miri/cargo-miri`
+/// works and that libtest works under miri.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CargoMiri {
     target: TargetSelection,
@@ -1020,6 +1038,10 @@ impl Step for RustdocGUI {
     }
 }
 
+/// Runs `src/tools/tidy` and `cargo fmt --check` to detect various style
+/// problems in the repository.
+///
+/// (To run the tidy tool's internal tests, use the alias "tidyselftest" instead.)
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Tidy;
 
@@ -1230,6 +1252,8 @@ impl Step for RunMakeSupport {
     }
 }
 
+/// Runs `cargo test` on the `src/tools/run-make-support` crate.
+/// That crate is used by run-make tests.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateRunMakeSupport {
     host: TargetSelection,
@@ -2466,6 +2490,10 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
     }
 }
 
+/// Runs `cargo test` for the compiler crates in `compiler/`.
+///
+/// (This step does not test `rustc_codegen_cranelift` or `rustc_codegen_gcc`,
+/// which have their own separate test steps.)
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateLibrustc {
     compiler: Compiler,
@@ -2494,6 +2522,7 @@ impl Step for CrateLibrustc {
     fn run(self, builder: &Builder<'_>) {
         builder.ensure(compile::Std::new(self.compiler, self.target));
 
+        // To actually run the tests, delegate to a copy of the `Crate` step.
         builder.ensure(Crate {
             compiler: self.compiler,
             target: self.target,
@@ -2619,6 +2648,13 @@ fn prepare_cargo_test(
     cargo
 }
 
+/// Runs `cargo test` for standard library crates.
+///
+/// (Also used internally to run `cargo test` for compiler crates.)
+///
+/// FIXME(Zalathar): Try to split this into two separate steps: a user-visible
+/// step for testing standard library crates, and an internal step used for both
+/// library crates and compiler crates.
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Crate {
     pub compiler: Compiler,
@@ -3552,6 +3588,10 @@ impl Step for CodegenGCC {
     }
 }
 
+/// Test step that does two things:
+/// - Runs `cargo test` for the `src/etc/test-float-parse` tool.
+/// - Invokes the `test-float-parse` tool to test the standard library's
+///   float parsing routines.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct TestFloatParse {
     path: PathBuf,
@@ -3625,6 +3665,9 @@ impl Step for TestFloatParse {
     }
 }
 
+/// Runs the tool `src/tools/collect-license-metadata` in `ONLY_CHECK=1` mode,
+/// which verifies that `license-metadata.json` is up-to-date and therefore
+/// running the tool normally would not update anything.
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct CollectLicenseMetadata;
 
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 3d01647aacc..17de1762427 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1,5 +1,3 @@
-mod cargo;
-
 use std::any::{Any, type_name};
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
@@ -25,6 +23,8 @@ use crate::utils::exec::{BootstrapCommand, command};
 use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
 use crate::{Build, Crate};
 
+mod cargo;
+
 #[cfg(test)]
 mod tests;
 
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index d7e368cc87f..670e4bd1be6 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -70,8 +70,8 @@
     - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
     - [powerpc64-ibm-aix](platform-support/aix.md)
     - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md)
-    - [riscv32e*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
-    - [riscv32i*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
+    - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
+    - [riscv32i\*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
     - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
@@ -80,14 +80,14 @@
     - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [sparcv9-sun-solaris](platform-support/solaris.md)
-    - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
+    - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
-    - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
-    - [*-unknown-hermit](platform-support/hermit.md)
-    - [*-unknown-freebsd](platform-support/freebsd.md)
+    - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
+    - [\*-unknown-hermit](platform-support/hermit.md)
+    - [\*-unknown-freebsd](platform-support/freebsd.md)
     - [\*-unknown-netbsd\*](platform-support/netbsd.md)
-    - [*-unknown-openbsd](platform-support/openbsd.md)
-    - [*-unknown-redox](platform-support/redox.md)
+    - [\*-unknown-openbsd](platform-support/openbsd.md)
+    - [\*-unknown-redox](platform-support/redox.md)
     - [\*-unknown-uefi](platform-support/unknown-uefi.md)
     - [\*-uwp-windows-msvc](platform-support/uwp-windows-msvc.md)
     - [\*-wrs-vxworks](platform-support/vxworks.md)
@@ -98,13 +98,14 @@
     - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
     - [wasm32v1-none](platform-support/wasm32v1-none.md)
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
+    - [\*-win7-windows-gnu](platform-support/win7-windows-gnu.md)
     - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
     - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
     - [x86_64-pc-solaris](platform-support/solaris.md)
     - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [xtensa-\*-none-elf](platform-support/xtensa.md)
-    - [*-nuttx-\*](platform-support/nuttx.md)
+    - [\*-nuttx-\*](platform-support/nuttx.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index a68efcda1f3..deeabd810d3 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -313,6 +313,7 @@ target | std | host | notes
 [`i686-unknown-redox`](platform-support/redox.md) | ✓ |  | i686 Redox OS
 `i686-uwp-windows-gnu` | ✓ |  | [^x86_32-floats-return-ABI]
 [`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  | [^x86_32-floats-return-ABI]
+[`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |   | LoongArch64 OpenHarmony
@@ -410,6 +411,7 @@ target | std | host | notes
 [`x86_64-unknown-trusty`](platform-support/trusty.md) | ? |  |
 `x86_64-uwp-windows-gnu` | ✓ |  |
 [`x86_64-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  |
+[`x86_64-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 64-bit Windows 7 support
 [`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 64-bit Windows 7 support
 [`x86_64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 [`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell)
diff --git a/src/doc/rustc/src/platform-support/win7-windows-gnu.md b/src/doc/rustc/src/platform-support/win7-windows-gnu.md
new file mode 100644
index 00000000000..180a1dc6d26
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/win7-windows-gnu.md
@@ -0,0 +1,48 @@
+# \*-win7-windows-gnu
+
+**Tier: 3**
+
+Windows targets continuing support of Windows 7.
+
+Target triples:
+- `i686-win7-windows-gnu`
+- `x86_64-win7-windows-gnu`
+
+## Target maintainers
+
+- @tbu-
+
+## Requirements
+
+This target supports all of core, alloc, std and test. Host
+tools may also work, though those are not currently tested.
+
+Those targets follow Windows calling convention for extern "C".
+
+Like any other Windows target, the created binaries are in PE format.
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the target list in config.toml:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-win7-windows-gnu"]
+```
+
+## Building Rust programs
+
+Rust does not ship pre-compiled artifacts for this target. To compile for this
+target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy by using `build-std` or
+similar.
+
+## Testing
+
+Created binaries work fine on Windows or Wine using native hardware. Remote
+testing is possible using the `remote-test-server` described [here](https://rustc-dev-guide.rust-lang.org/tests/running.html#running-tests-on-a-remote-machine).
+
+## Cross-compilation toolchains and C code
+
+Compatible C code can be built with gcc's `{i686,x86_64}-w64-mingw32-gcc`.
diff --git a/src/doc/rustc/src/platform-support/win7-windows-msvc.md b/src/doc/rustc/src/platform-support/win7-windows-msvc.md
index 45b00a2be82..77b7d68212b 100644
--- a/src/doc/rustc/src/platform-support/win7-windows-msvc.md
+++ b/src/doc/rustc/src/platform-support/win7-windows-msvc.md
@@ -1,8 +1,12 @@
-# *-win7-windows-msvc
+# \*-win7-windows-msvc
 
 **Tier: 3**
 
-Windows targets continuing support of windows7.
+Windows targets continuing support of Windows 7.
+
+Target triples:
+- `i686-win7-windows-msvc`
+- `x86_64-win7-windows-msvc`
 
 ## Target maintainers
 
diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs
index 2d155bf0b10..f29e1e4d27a 100644
--- a/src/etc/installer/msi/rust.wxs
+++ b/src/etc/installer/msi/rust.wxs
@@ -172,11 +172,6 @@
                     <!-- tool-rust-docs-end -->
                     <Directory Id="Cargo" Name="." />
                     <Directory Id="Std" Name="." />
-                    <Directory Id="RustFmt" Name="." />
-                    <Directory Id="RustAnalyzer" Name="." />
-                    <Directory Id="Miri" Name="." />
-                    <Directory Id="Analysis" Name="." />
-                    <Directory Id="Clippy" Name="." />
                 </Directory>
             </Directory>
 
@@ -284,41 +279,7 @@
                  <ComponentRef Id="PathEnvPerMachine" />
                  <ComponentRef Id="PathEnvPerUser" />
         </Feature>
-        <Feature Id="RustFmt"
-                 Title="Formatter for rust"
-                 Display="7"
-                 Level="1"
-                 AllowAdvertise="no">
-                 <ComponentGroupRef Id="RustFmtGroup" />
-        </Feature>
-        <Feature Id="Clippy"
-                 Title="Formatter and checker for rust"
-                 Display="8"
-                 Level="1"
-                 AllowAdvertise="no">
-                 <ComponentGroupRef Id="ClippyGroup" />
-        </Feature>
-        <Feature Id="Miri"
-                 Title="Soundness checker for rust"
-                 Display="9"
-                 Level="1"
-                 AllowAdvertise="no">
-                 <ComponentGroupRef Id="MiriGroup" />
-        </Feature>
-        <Feature Id="RustAnalyzer"
-                 Title="Analyzer for rust"
-                 Display="10"
-                 Level="1"
-                 AllowAdvertise="no">
-                 <ComponentGroupRef Id="RustAnalyzerGroup" />
-        </Feature>
-        <Feature Id="Analysis"
-                 Title="Analysis for rust"
-                 Display="11"
-                 Level="1"
-                 AllowAdvertise="no">
-                 <ComponentGroupRef Id="AnalysisGroup" />
-        </Feature>
+
         <UIRef Id="RustUI" />
     </Product>
 </Wix>
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 1fb35750c15..99e88f878fb 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -314,9 +314,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         PatKind::Box(p) => return name_from_pat(p),
         PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)),
         PatKind::Ref(p, _) => return name_from_pat(p),
-        PatKind::Lit(..) => {
+        PatKind::Expr(..) => {
             warn!(
-                "tried to get argument name from PatKind::Lit, which is silly in function arguments"
+                "tried to get argument name from PatKind::Expr, which is silly in function arguments"
             );
             return Symbol::intern("()");
         }
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 3b3a78cb115..c04a73c890f 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -3,8 +3,11 @@ use clippy_utils::numeric_literal;
 use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
-use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat, walk_stmt};
+use rustc_hir::{
+    Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Pat, PatExpr, PatExprKind, PatKind, Stmt, StmtKind,
+    StructTailExpr,
+};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -219,6 +222,22 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
         walk_expr(self, expr);
     }
 
+    fn visit_pat(&mut self, pat: &'tcx Pat<'_>) {
+        match pat.kind {
+            PatKind::Expr(&PatExpr {
+                hir_id,
+                kind: PatExprKind::Lit { lit, .. },
+                ..
+            }) => {
+                let ty = self.cx.typeck_results().node_type(hir_id);
+                self.check_lit(lit, ty, hir_id);
+                return;
+            },
+            _ => {},
+        }
+        walk_pat(self, pat)
+    }
+
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         match stmt.kind {
             // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
index 9c8edfd6113..8a5cf7f56d5 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -56,7 +56,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
         PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
         PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
         PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x),
-        PatKind::Path(_) | PatKind::Lit(_) => true,
+        PatKind::Path(_) | PatKind::Expr(_) => true,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 3ea758e176f..1c63ca9d974 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -8,8 +8,8 @@ use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::{
     AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
-    ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath,
-    TraitItemRef, TyKind,
+    ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatExprKind, PatKind, PathSegment, PrimTy,
+    QPath, TraitItemRef, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -163,7 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
         if let ExprKind::Let(lt) = expr.kind
             && match lt.pat.kind {
                 PatKind::Slice([], None, []) => true,
-                PatKind::Lit(lit) if is_empty_string(lit) => true,
+                PatKind::Expr(lit) => match lit.kind {
+                    PatExprKind::Lit { lit, .. } => match lit.node {
+                        LitKind::Str(lit, _) => lit.as_str().is_empty(),
+                        _ => false,
+                    },
+                    _ => false,
+                },
                 _ => false,
             }
             && !expr.span.from_expansion()
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index 3f01f3cf30a..5b9eedd9b8b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -7,7 +7,7 @@ use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operator
 use rustc_ast::LitKind::{Byte, Char};
 use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd};
+use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd, PatExpr, PatExprKind, Lit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
         {
             let arg = peel_ref_operators(cx, arg);
             let ty_sugg = get_ty_sugg(cx, arg, start);
-            let range = check_range(start, end);
+            let range = check_expr_range(start, end);
             check_is_ascii(cx, expr.span, arg, &range, ty_sugg);
         }
     }
@@ -196,19 +196,34 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
     }
 }
 
-fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
+fn check_expr_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
     if let ExprKind::Lit(start_lit) = &start.kind
         && let ExprKind::Lit(end_lit) = &end.kind
     {
-        match (&start_lit.node, &end_lit.node) {
-            (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
-            (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
-            (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
-            (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
-            (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
-            _ => CharRange::Otherwise,
-        }
+        check_lit_range(start_lit, end_lit)
+    } else {
+        CharRange::Otherwise
+    }
+}
+
+
+fn check_range(start: &PatExpr<'_>, end: &PatExpr<'_>) -> CharRange {
+    if let PatExprKind::Lit{ lit: start_lit, negated: false } = &start.kind
+        && let PatExprKind::Lit{ lit: end_lit, negated: false  } = &end.kind
+    {
+        check_lit_range(start_lit, end_lit)
     } else {
         CharRange::Otherwise
     }
 }
+
+fn check_lit_range(start_lit: &Lit, end_lit: &Lit) -> CharRange {
+    match (&start_lit.node, &end_lit.node) {
+        (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
+        (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
+        (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
+        (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
+        (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
+        _ => CharRange::Otherwise,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
index ffa3eacf354..2e5a92915d9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
+use rustc_hir::{PatExpr, PatExprKind, PatKind, RangeEnd};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
@@ -38,14 +38,13 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
 
-fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
-    if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind {
-        expr_as_i128(expr).map(|num| -num)
-    } else if let ExprKind::Lit(lit) = expr.kind
+fn expr_as_i128(expr: &PatExpr<'_>) -> Option<i128> {
+    if let PatExprKind::Lit { lit, negated } = expr.kind
         && let LitKind::Int(num, _) = lit.node
     {
         // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
-        num.get().try_into().ok()
+        let n = i128::try_from(num.get()).ok()?;
+        Some(if negated { -n } else { n })
     } else {
         None
     }
@@ -58,7 +57,7 @@ struct Num {
 }
 
 impl Num {
-    fn new(expr: &Expr<'_>) -> Option<Self> {
+    fn new(expr: &PatExpr<'_>) -> Option<Self> {
         Some(Self {
             val: expr_as_i128(expr)?,
             span: expr.span,
@@ -90,7 +89,7 @@ impl LateLintPass<'_> for ManualRangePatterns {
             let mut ranges_found = Vec::new();
 
             for pat in pats {
-                if let PatKind::Lit(lit) = pat.kind
+                if let PatKind::Expr(lit) = pat.kind
                     && let Some(num) = Num::new(lit)
                 {
                     numbers_found.insert(num.val);
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
index 69105ff0d5c..7e43d222a66 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::{expr_block, snippet};
 use clippy_utils::sugg::Sugg;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, Expr, ExprKind, PatKind};
+use rustc_hir::{Arm, Expr, PatExprKind, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
@@ -21,8 +21,8 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>]
             move |diag| {
                 if arms.len() == 2 {
                     // no guards
-                    let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
-                        if let ExprKind::Lit(lit) = arm_bool.kind {
+                    let exprs = if let PatKind::Expr(arm_bool) = arms[0].pat.kind {
+                        if let PatExprKind::Lit { lit, .. } = arm_bool.kind {
                             match lit.node {
                                 LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
                                 LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 4b731d75972..28e05c273d5 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
+use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExprKind, PatKind, RangeEnd};
 use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
@@ -311,9 +311,9 @@ impl<'a> NormalizedPat<'a> {
                 );
                 Self::Tuple(None, pats)
             },
-            PatKind::Lit(e) => match &e.kind {
+            PatKind::Expr(e) => match &e.kind {
                 // TODO: Handle negative integers. They're currently treated as a wild match.
-                ExprKind::Lit(lit) => match lit.node {
+                PatExprKind::Lit { lit, negated: false } => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
                     LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
@@ -330,7 +330,7 @@ impl<'a> NormalizedPat<'a> {
                 let start = match start {
                     None => 0,
                     Some(e) => match &e.kind {
-                        ExprKind::Lit(lit) => match lit.node {
+                        PatExprKind::Lit { lit, negated: false } => match lit.node {
                             LitKind::Int(val, _) => val.get(),
                             LitKind::Char(val) => val.into(),
                             LitKind::Byte(val) => val.into(),
@@ -342,7 +342,7 @@ impl<'a> NormalizedPat<'a> {
                 let (end, bounds) = match end {
                     None => (u128::MAX, RangeEnd::Included),
                     Some(e) => match &e.kind {
-                        ExprKind::Lit(lit) => match lit.node {
+                        PatExprKind::Lit { lit, negated: false } => match lit.node {
                             LitKind::Int(val, _) => (val.get(), bounds),
                             LitKind::Char(val) => (val.into(), bounds),
                             LitKind::Byte(val) => (val.into(), bounds),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index 1267fc9d0a5..9f5b7c855a1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{Visitor, walk_expr};
-use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
+use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, LangItem, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Span;
@@ -85,8 +85,8 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
     };
 
     for arm in arms {
-        if let PatKind::Lit(Expr {
-            kind: ExprKind::Lit(lit),
+        if let PatKind::Expr(PatExpr {
+            kind: PatExprKind::Lit { lit, negated: false },
             ..
         }) = arm.pat.kind
             && let LitKind::Str(symbol, _) = lit.node
diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
index 63bea586caf..0d5575efc22 100644
--- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
@@ -8,7 +8,7 @@ use clippy_utils::{
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath};
+use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatExprKind, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
@@ -133,7 +133,7 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>
         },
         // compare match_expr ty with RetTy in `fn foo() -> RetTy`
         Node::Item(item) => {
-            if let ItemKind::Fn{ .. } = item.kind {
+            if let ItemKind::Fn { .. } = item.kind {
                 let output = cx
                     .tcx
                     .fn_sig(item.owner_id)
@@ -189,8 +189,12 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
             });
         },
         // Example: `5 => 5`
-        (PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => {
-            if let ExprKind::Lit(pat_spanned) = &pat_lit_expr.kind {
+        (PatKind::Expr(pat_expr_expr), ExprKind::Lit(expr_spanned)) => {
+            if let PatExprKind::Lit {
+                lit: pat_spanned,
+                negated: false,
+            } = &pat_expr_expr.kind
+            {
                 return pat_spanned.node == expr_spanned.node;
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 856311899f2..4a5d3c516b8 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,13 +34,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
             if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = if let Some(lhs) = lhs {
-                        ConstEvalCtxt::new(cx).eval(lhs)?
+                        ConstEvalCtxt::new(cx).eval_pat_expr(lhs)?
                     } else {
                         let min_val_const = ty.numeric_min_val(cx.tcx)?;
                         mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
                     };
                     let rhs_const = if let Some(rhs) = rhs {
-                        ConstEvalCtxt::new(cx).eval(rhs)?
+                        ConstEvalCtxt::new(cx).eval_pat_expr(rhs)?
                     } else {
                         let max_val_const = ty.numeric_max_val(cx.tcx)?;
                         mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
@@ -57,8 +57,10 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                     });
                 }
 
-                if let PatKind::Lit(value) = pat.kind {
-                    let value = ConstEvalCtxt::new(cx).eval_full_int(value)?;
+                if let PatKind::Expr(value) = pat.kind {
+                    let value = ConstEvalCtxt::new(cx)
+                        .eval_pat_expr(value)?
+                        .int_value(cx.tcx, cx.typeck_results().node_type(pat.hir_id))?;
                     return Some(SpannedRange {
                         span: pat.span,
                         node: (value, EndBound::Included(value)),
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index 264458a86ef..7e74b36b441 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -9,7 +9,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
+use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatExprKind, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_span::{Span, Symbol, sym};
@@ -74,8 +74,8 @@ fn find_match_true<'tcx>(
     span: Span,
     message: &'static str,
 ) {
-    if let PatKind::Lit(lit) = pat.kind
-        && let ExprKind::Lit(lit) = lit.kind
+    if let PatKind::Expr(lit) = pat.kind
+        && let PatExprKind::Lit { lit, negated: false } = lit.kind
         && let LitKind::Bool(pat_is_true) = lit.node
     {
         let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 10ca6832d9c..b1d0686ffc4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{Visitor, walk_pat};
-use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef};
 use rustc_span::{Span, sym};
@@ -114,7 +114,7 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
     }
 
     let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
-    let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
+    let (msg, sugg) = if let PatKind::Path(_) | PatKind::Expr(_) = pat.kind
         && let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
         && let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
         && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
@@ -126,8 +126,8 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
         // scrutinee derives PartialEq and the pattern is a constant.
         let pat_ref_count = match pat.kind {
             // string literals are already a reference.
-            PatKind::Lit(Expr {
-                kind: ExprKind::Lit(lit),
+            PatKind::Expr(PatExpr {
+                kind: PatExprKind::Lit { lit, negated: false },
                 ..
             }) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1,
             _ => pat_ref_count,
@@ -384,7 +384,7 @@ impl<'a> PatState<'a> {
 
             PatKind::Wild
             | PatKind::Binding(_, _, _, None)
-            | PatKind::Lit(_)
+            | PatKind::Expr(_)
             | PatKind::Range(..)
             | PatKind::Path(_)
             | PatKind::Never
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index 0d85b1b858a..3834087f797 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -11,7 +11,7 @@ use clippy_utils::visitors::{Descend, for_each_expr};
 use itertools::Itertools;
 use rustc_ast::{BinOpKind, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind};
+use rustc_hir::{Expr, ExprKind, PatExprKind, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -171,7 +171,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<
                         return ControlFlow::Break(());
                     }
                     if arm.pat.walk_short(|pat| match pat.kind {
-                        PatKind::Lit(expr) if let ExprKind::Lit(lit) = expr.kind => {
+                        PatKind::Expr(expr) if let PatExprKind::Lit { lit, negated: false } = expr.kind => {
                             if let LitKind::Char(_) = lit.node {
                                 set_char_spans.push(lit.span);
                             }
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 50a97579df7..8923484bb58 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -92,7 +92,7 @@ impl EarlyLintPass for UnnestedOrPatterns {
 }
 
 fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
-    if let Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind {
+    if let Ident(.., None) | Expr(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind {
         // This is a leaf pattern, so cloning is unprofitable.
         return;
     }
@@ -228,7 +228,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
         // Therefore they are not some form of constructor `C`,
         // with which a pattern `C(p_0)` may be formed,
         // which we would want to join with other `C(p_j)`s.
-        Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_)
+        Ident(.., None) | Expr(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_)
         // Skip immutable refs, as grouping them saves few characters,
         // and almost always requires adding parens (increasing noisiness).
         // In the case of only two patterns, replacement adds net characters.
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index c2dcb5ae1f9..4dcc8ac7fb0 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
-    FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, StructTailExpr, TyKind,
+    FnRetTy, HirId, Lit, PatExprKind, PatKind, QPath, StmtKind, StructTailExpr, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -643,6 +643,27 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
         self.expr(expr);
     }
 
+    fn pat_expr(&self, lit: &Binding<&hir::PatExpr<'_>>) {
+        let kind = |kind| chain!(self, "let PatExprKind::{kind} = {lit}.kind");
+        macro_rules! kind {
+            ($($t:tt)*) => (kind(format_args!($($t)*)));
+        }
+        match lit.value.kind {
+            PatExprKind::Lit { lit, negated } => {
+                bind!(self, lit);
+                bind!(self, negated);
+                kind!("Lit{{ref {lit}, {negated} }}");
+                self.lit(lit);
+            },
+            PatExprKind::ConstBlock(_) => kind!("ConstBlock(_)"),
+            PatExprKind::Path(ref qpath) => {
+                bind!(self, qpath);
+                kind!("Path(ref {qpath})");
+                self.qpath(qpath);
+            },
+        }
+    }
+
     fn pat(&self, pat: &Binding<&hir::Pat<'_>>) {
         let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind");
         macro_rules! kind {
@@ -717,17 +738,17 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 kind!("Guard({pat}, {cond})");
                 self.pat(pat);
                 self.expr(cond);
-            }
-            PatKind::Lit(lit_expr) => {
+            },
+            PatKind::Expr(lit_expr) => {
                 bind!(self, lit_expr);
-                kind!("Lit({lit_expr})");
-                self.expr(lit_expr);
+                kind!("Expr({lit_expr})");
+                self.pat_expr(lit_expr);
             },
             PatKind::Range(start, end, end_kind) => {
                 opt_bind!(self, start, end);
                 kind!("Range({start}, {end}, RangeEnd::{end_kind:?})");
-                start.if_some(|e| self.expr(e));
-                end.if_some(|e| self.expr(e));
+                start.if_some(|e| self.pat_expr(e));
+                end.if_some(|e| self.pat_expr(e));
             },
             PatKind::Slice(start, middle, end) => {
                 bind!(self, start, end);
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 623d9c76086..2eb09bac8d8 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -36,7 +36,7 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
         (Paren(l), _) => eq_pat(l, r),
         (_, Paren(r)) => eq_pat(l, r),
         (Wild, Wild) | (Rest, Rest) => true,
-        (Lit(l), Lit(r)) => eq_expr(l, r),
+        (Expr(l), Expr(r)) => eq_expr(l, r),
         (Ident(b1, i1, s1), Ident(b2, i2, s2)) => {
             b1 == b2 && eq_id(*i1, *i2) && both(s1.as_deref(), s2.as_deref(), eq_pat)
         },
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 43ddf06730d..d46beddf731 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -4,7 +4,6 @@
 //! executable MIR bodies, so we have to do this instead.
 #![allow(clippy::float_cmp)]
 
-use crate::macros::HirNode;
 use crate::source::{SpanRangeExt, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 
@@ -13,7 +12,7 @@ use rustc_apfloat::ieee::{Half, Quad};
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp, PatExpr, PatExprKind};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir::ConstValue;
@@ -442,30 +441,48 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
         }
     }
 
+    pub fn eval_pat_expr(&self, pat_expr: &PatExpr<'_>) -> Option<Constant<'tcx>> {
+        match &pat_expr.kind {
+            PatExprKind::Lit { lit, negated } => {
+                let ty = self.typeck.node_type_opt(pat_expr.hir_id);
+                let val = lit_to_mir_constant(&lit.node, ty);
+                if *negated {
+                    self.constant_negate(&val, ty?)
+                } else {
+                    Some(val)
+                }
+            }
+            PatExprKind::ConstBlock(ConstBlock { body, ..}) => self.expr(self.tcx.hir().body(*body).value),
+            PatExprKind::Path(qpath) => self.qpath(qpath, pat_expr.hir_id),
+        }
+    }
+
+    fn qpath(&self, qpath: &QPath<'_>, hir_id: HirId) -> Option<Constant<'tcx>> {
+        let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, hir_id).opt_def_id() {
+            self.tcx.crate_name(def_id.krate) == sym::core
+        } else {
+            false
+        };
+        self.fetch_path_and_apply(qpath, hir_id, self.typeck.node_type(hir_id), |self_, result| {
+            let result = mir_to_const(self_.tcx, result)?;
+            // If source is already Constant we wouldn't want to override it with CoreConstant
+            self_.source.set(
+                if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
+                    ConstantSource::CoreConstant
+                } else {
+                    ConstantSource::Constant
+                },
+            );
+            Some(result)
+        })
+    }
+
     /// Simple constant folding: Insert an expression, get a constant or none.
     fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
             ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
             ExprKind::DropTemps(e) => self.expr(e),
-            ExprKind::Path(ref qpath) => {
-                let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() {
-                    self.tcx.crate_name(def_id.krate) == sym::core
-                } else {
-                    false
-                };
-                self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| {
-                    let result = mir_to_const(self_.tcx, result)?;
-                    // If source is already Constant we wouldn't want to override it with CoreConstant
-                    self_.source.set(
-                        if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
-                            ConstantSource::CoreConstant
-                        } else {
-                            ConstantSource::Constant
-                        },
-                    );
-                    Some(result)
-                })
-            },
+            ExprKind::Path(ref qpath) => self.qpath(qpath, e.hir_id),
             ExprKind::Block(block, _) => self.block(block),
             ExprKind::Lit(lit) => {
                 if is_direct_expn_of(e.span, "cfg").is_some() {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 7c4e834f841..d1d0abd4690 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -9,8 +9,8 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{
     AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
     ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
-    Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty,
-    TyKind,
+    Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
+    TraitBoundModifiers, Ty, TyKind,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::LateContext;
@@ -489,6 +489,24 @@ impl HirEqInterExpr<'_, '_, '_> {
         li.name == ri.name && self.eq_pat(lp, rp)
     }
 
+    fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool {
+        match (&left.kind, &right.kind) {
+            (
+                &PatExprKind::Lit {
+                    lit: left,
+                    negated: left_neg,
+                },
+                &PatExprKind::Lit {
+                    lit: right,
+                    negated: right_neg,
+                },
+            ) => left_neg == right_neg && left.node == right.node,
+            (PatExprKind::ConstBlock(left), PatExprKind::ConstBlock(right)) => self.eq_body(left.body, right.body),
+            (PatExprKind::Path(left), PatExprKind::Path(right)) => self.eq_qpath(left, right),
+            (PatExprKind::Lit { .. } | PatExprKind::ConstBlock(..) | PatExprKind::Path(..), _) => false,
+        }
+    }
+
     /// Checks whether two patterns are the same.
     fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
         match (&left.kind, &right.kind) {
@@ -507,11 +525,11 @@ impl HirEqInterExpr<'_, '_, '_> {
                 eq
             },
             (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
-            (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
+            (&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r),
             (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
             (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
-                both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_expr(a, b))
-                    && both(le.as_ref(), re.as_ref(), |a, b| self.eq_expr(a, b))
+                both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b))
+                    && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b))
                     && (li == ri)
             },
             (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
@@ -1073,6 +1091,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
     }
 
+    pub fn hash_pat_expr(&mut self, lit: &PatExpr<'_>) {
+        std::mem::discriminant(&lit.kind).hash(&mut self.s);
+        match &lit.kind {
+            PatExprKind::Lit { lit, negated } => {
+                lit.node.hash(&mut self.s);
+                negated.hash(&mut self.s);
+            },
+            PatExprKind::ConstBlock(c) => self.hash_body(c.body),
+            PatExprKind::Path(qpath) => self.hash_qpath(qpath),
+        }
+    }
+
     pub fn hash_pat(&mut self, pat: &Pat<'_>) {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
         match pat.kind {
@@ -1084,7 +1114,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
             },
             PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
-            PatKind::Lit(expr) => self.hash_expr(expr),
+            PatKind::Expr(expr) => self.hash_pat_expr(expr),
             PatKind::Or(pats) => {
                 for pat in pats {
                     self.hash_pat(pat);
@@ -1093,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             PatKind::Path(ref qpath) => self.hash_qpath(qpath),
             PatKind::Range(s, e, i) => {
                 if let Some(s) = s {
-                    self.hash_expr(s);
+                    self.hash_pat_expr(s);
                 }
                 if let Some(e) = e {
-                    self.hash_expr(e);
+                    self.hash_pat_expr(e);
                 }
                 std::mem::discriminant(&i).hash(&mut self.s);
             },
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index ba4a0f44584..d42e40acbc0 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1777,7 +1777,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
                 },
             }
         },
-        PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) | PatKind::Guard(..) => true,
+        PatKind::Expr(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) | PatKind::Guard(..) => true,
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index a85dcddd331..8ffdf886202 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui/author/if.stdout
@@ -30,8 +30,8 @@ if let StmtKind::Let(local) = stmt.kind
 }
 if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind
     && let ExprKind::Let(let_expr) = cond.kind
-    && let PatKind::Lit(lit_expr) = let_expr.pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatKind::Expr(lit_expr) = let_expr.pat.kind
+    && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Bool(true) = lit.node
     && let ExprKind::Path(ref qpath) = let_expr.init.kind
     && match_qpath(qpath, &["a"])
diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout
index 609d2491061..c94eb171f52 100644
--- a/src/tools/clippy/tests/ui/author/loop.stdout
+++ b/src/tools/clippy/tests/ui/author/loop.stdout
@@ -76,8 +76,8 @@ if let Some(higher::While { condition: condition, body: body }) = higher::While:
     // report your lint here
 }
 if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr)
-    && let PatKind::Lit(lit_expr) = let_pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatKind::Expr(lit_expr) = let_pat.kind
+    && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Bool(true) = lit.node
     && let ExprKind::Path(ref qpath) = let_expr.kind
     && match_qpath(qpath, &["a"])
diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout
index 91b3b6f6877..acb3b140dfa 100644
--- a/src/tools/clippy/tests/ui/author/matches.stdout
+++ b/src/tools/clippy/tests/ui/author/matches.stdout
@@ -4,14 +4,14 @@ if let StmtKind::Let(local) = stmt.kind
     && let ExprKind::Lit(ref lit) = scrutinee.kind
     && let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node
     && arms.len() == 3
-    && let PatKind::Lit(lit_expr) = arms[0].pat.kind
-    && let ExprKind::Lit(ref lit1) = lit_expr.kind
+    && let PatKind::Expr(lit_expr) = arms[0].pat.kind
+    && let PatExprKind::Lit{ref lit1, negated } = lit_expr.kind
     && let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node
     && arms[0].guard.is_none()
     && let ExprKind::Lit(ref lit2) = arms[0].body.kind
     && let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node
-    && let PatKind::Lit(lit_expr1) = arms[1].pat.kind
-    && let ExprKind::Lit(ref lit3) = lit_expr1.kind
+    && let PatKind::Expr(lit_expr1) = arms[1].pat.kind
+    && let PatExprKind::Lit{ref lit3, negated1 } = lit_expr1.kind
     && let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node
     && arms[1].guard.is_none()
     && let ExprKind::Block(block, None) = arms[1].body.kind
diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout
index 0b332d5e7d0..b66bbccb3cf 100644
--- a/src/tools/clippy/tests/ui/author/struct.stdout
+++ b/src/tools/clippy/tests/ui/author/struct.stdout
@@ -23,8 +23,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind
     && match_qpath(qpath, &["Test"])
     && fields.len() == 1
     && fields[0].ident.as_str() == "field"
-    && let PatKind::Lit(lit_expr) = fields[0].pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatKind::Expr(lit_expr) = fields[0].pat.kind
+    && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
     && arm.guard.is_none()
     && let ExprKind::Block(block, None) = arm.body.kind
@@ -36,8 +36,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind
 if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind
     && match_qpath(qpath, &["TestTuple"])
     && fields.len() == 1
-    && let PatKind::Lit(lit_expr) = fields[0].kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatKind::Expr(lit_expr) = fields[0].kind
+    && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
     && arm.guard.is_none()
     && let ExprKind::Block(block, None) = arm.body.kind
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 88118cab235..fb2838a4ea0 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -10,7 +10,12 @@ fn main() {
     let version_str = t!(std::fs::read_to_string(&version_path), version_path);
     let version_str = version_str.trim();
     walk::walk_many(
-        &[&root_path.join("compiler"), &root_path.join("library")],
+        &[
+            &root_path.join("compiler"),
+            &root_path.join("library"),
+            &root_path.join("src/doc/rustc"),
+            &root_path.join("src/doc/rustdoc"),
+        ],
         |path, _is_dir| walk::filter_dirs(path),
         &mut |entry, contents| {
             if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 7b4730eadc8..b55469f332a 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -42,7 +42,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
         | ast::PatKind::Never
         | ast::PatKind::Wild
         | ast::PatKind::Err(_)
-        | ast::PatKind::Lit(_) => true,
+        | ast::PatKind::Expr(_) => true,
         ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
         ast::PatKind::Struct(..)
         | ast::PatKind::MacCall(..)
@@ -293,7 +293,7 @@ impl Rewrite for Pat {
                 let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?;
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
-            PatKind::Lit(ref expr) => expr.rewrite_result(context, shape),
+            PatKind::Expr(ref expr) => expr.rewrite_result(context, shape),
             PatKind::Slice(ref slice_pat)
                 if context.config.style_edition() <= StyleEdition::Edition2021 =>
             {
@@ -530,7 +530,7 @@ pub(crate) fn can_be_overflowed_pat(
             ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => {
                 can_be_overflowed_pat(context, &TuplePatField::Pat(p), len)
             }
-            ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len),
+            ast::PatKind::Expr(ref expr) => can_be_overflowed_expr(context, expr, len),
             _ => false,
         },
         TuplePatField::Dotdot(..) => false,
diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs
index 6415aee6fae..ab74de5c8ec 100644
--- a/tests/assembly/targets/targets-pe.rs
+++ b/tests/assembly/targets/targets-pe.rs
@@ -39,6 +39,9 @@
 //@ revisions: i686_uwp_windows_gnu
 //@ [i686_uwp_windows_gnu] compile-flags: --target i686-uwp-windows-gnu
 //@ [i686_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: i686_win7_windows_gnu
+//@ [i686_win7_windows_gnu] compile-flags: --target i686-win7-windows-gnu
+//@ [i686_win7_windows_gnu] needs-llvm-components: x86
 //@ revisions: i686_unknown_uefi
 //@ [i686_unknown_uefi] compile-flags: --target i686-unknown-uefi
 //@ [i686_unknown_uefi] needs-llvm-components: x86
@@ -72,6 +75,9 @@
 //@ revisions: x86_64_uwp_windows_gnu
 //@ [x86_64_uwp_windows_gnu] compile-flags: --target x86_64-uwp-windows-gnu
 //@ [x86_64_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_win7_windows_gnu
+//@ [x86_64_win7_windows_gnu] compile-flags: --target x86_64-win7-windows-gnu
+//@ [x86_64_win7_windows_gnu] needs-llvm-components: x86
 //@ revisions: x86_64_uwp_windows_msvc
 //@ [x86_64_uwp_windows_msvc] compile-flags: --target x86_64-uwp-windows-msvc
 //@ [x86_64_uwp_windows_msvc] needs-llvm-components: x86
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
index 4097e060f4d..5ea9902b262 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
@@ -51,7 +51,6 @@
           StorageLive(_7);
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -79,6 +78,7 @@
           _11 = const {0x1 as *const [bool; 0]};
           _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
           _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
           StorageDead(_5);
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
index ff44d0df5e3..cc5a41a7f63 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -51,7 +51,6 @@
           StorageLive(_7);
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -83,6 +82,7 @@
           _11 = const {0x1 as *const [bool; 0]};
           _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
           _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
           StorageDead(_5);
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
index 3662c3b59d2..3d398fbea79 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
@@ -51,7 +51,6 @@
           StorageLive(_7);
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -79,6 +78,7 @@
           _11 = const {0x1 as *const [bool; 0]};
           _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
           _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
           StorageDead(_5);
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
index 68dee57dee9..dc99c3f7a8c 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -51,7 +51,6 @@
           StorageLive(_7);
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -83,6 +82,7 @@
           _11 = const {0x1 as *const [bool; 0]};
           _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
           _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
           StorageDead(_5);
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
index e62fcb66e3a..6a3ec543069 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
@@ -53,7 +53,6 @@
 -         _6 = copy _7 as *mut [bool; 0] (Transmute);
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -67,7 +66,7 @@
   
       bb2: {
           StorageLive(_10);
--         _10 = copy _6 as *mut () (PtrToPtr);
+-         _10 = copy _7 as *mut () (Transmute);
 -         _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
 +         _10 = const {0x1 as *mut ()};
 +         _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable];
@@ -80,11 +79,12 @@
   
       bb4: {
           StorageDead(_8);
--         _11 = copy _6 as *const [bool; 0] (PtrToPtr);
+-         _11 = copy _7 as *const [bool; 0] (Transmute);
 -         _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
 +         _11 = const {0x1 as *const [bool; 0]};
 +         _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
 -         _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
 +         _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
index 8183abd315a..9471ad47cd9 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
@@ -53,7 +53,6 @@
 -         _6 = copy _7 as *mut [bool; 0] (Transmute);
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -71,7 +70,7 @@
   
       bb3: {
           StorageLive(_10);
--         _10 = copy _6 as *mut () (PtrToPtr);
+-         _10 = copy _7 as *mut () (Transmute);
 -         _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
 +         _10 = const {0x1 as *mut ()};
 +         _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable];
@@ -84,11 +83,12 @@
   
       bb5: {
           StorageDead(_8);
--         _11 = copy _6 as *const [bool; 0] (PtrToPtr);
+-         _11 = copy _7 as *const [bool; 0] (Transmute);
 -         _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
 +         _11 = const {0x1 as *const [bool; 0]};
 +         _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
 -         _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
 +         _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
index 4fa6ef29e06..187927b8eca 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
@@ -53,7 +53,6 @@
 -         _6 = copy _7 as *mut [bool; 0] (Transmute);
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -67,7 +66,7 @@
   
       bb2: {
           StorageLive(_10);
--         _10 = copy _6 as *mut () (PtrToPtr);
+-         _10 = copy _7 as *mut () (Transmute);
 -         _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
 +         _10 = const {0x1 as *mut ()};
 +         _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable];
@@ -80,11 +79,12 @@
   
       bb4: {
           StorageDead(_8);
--         _11 = copy _6 as *const [bool; 0] (PtrToPtr);
+-         _11 = copy _7 as *const [bool; 0] (Transmute);
 -         _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
 +         _11 = const {0x1 as *const [bool; 0]};
 +         _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
 -         _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
 +         _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
index 75329204563..031c021ba5a 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
@@ -53,7 +53,6 @@
 -         _6 = copy _7 as *mut [bool; 0] (Transmute);
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
-          StorageDead(_7);
           StorageLive(_11);
           StorageLive(_8);
           _8 = UbChecks();
@@ -71,7 +70,7 @@
   
       bb3: {
           StorageLive(_10);
--         _10 = copy _6 as *mut () (PtrToPtr);
+-         _10 = copy _7 as *mut () (Transmute);
 -         _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
 +         _10 = const {0x1 as *mut ()};
 +         _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable];
@@ -84,11 +83,12 @@
   
       bb5: {
           StorageDead(_8);
--         _11 = copy _6 as *const [bool; 0] (PtrToPtr);
+-         _11 = copy _7 as *const [bool; 0] (Transmute);
 -         _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
 +         _11 = const {0x1 as *const [bool; 0]};
 +         _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
           StorageDead(_11);
+          StorageDead(_7);
           StorageDead(_6);
 -         _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
 +         _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
diff --git a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff
new file mode 100644
index 00000000000..5ae575f300a
--- /dev/null
+++ b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff
@@ -0,0 +1,340 @@
+- // MIR for `aggregate_struct_then_transmute` before GVN
++ // MIR for `aggregate_struct_then_transmute` after GVN
+  
+  fn aggregate_struct_then_transmute(_1: u16, _2: *const u8) -> () {
+      debug id => _1;
+      debug thin => _2;
+      let mut _0: ();
+      let _3: MyId;
+      let mut _4: u16;
+      let _5: ();
+      let mut _6: u16;
+      let mut _7: MyId;
+      let mut _9: u16;
+      let mut _10: std::marker::PhantomData<std::string::String>;
+      let _11: ();
+      let mut _12: u16;
+      let mut _13: TypedId<std::string::String>;
+      let mut _15: u16;
+      let _16: ();
+      let mut _17: u16;
+      let mut _18: std::result::Result<Never, u16>;
+      let mut _20: u16;
+      let _21: ();
+      let mut _22: u32;
+      let mut _23: std::option::Option<u16>;
+      let mut _25: u16;
+      let _26: ();
+      let mut _27: i16;
+      let mut _28: MyId;
+      let mut _30: u16;
+      let mut _31: u16;
+      let _32: ();
+      let mut _33: u32;
+      let mut _34: aggregate_struct_then_transmute::Pair;
+      let mut _36: u16;
+      let mut _37: u16;
+      let _38: ();
+      let mut _39: u16;
+      let mut _40: aggregate_struct_then_transmute::Pair;
+      let mut _42: u16;
+      let _43: ();
+      let mut _44: u16;
+      let mut _45: (u16,);
+      let mut _47: u16;
+      let _48: ();
+      let mut _49: u16;
+      let mut _50: [u16; 1];
+      let mut _52: *const u8;
+      let mut _53: ();
+      let _54: ();
+      let mut _55: *const u8;
+      let mut _56: *const i32;
+      scope 1 {
+          debug a => _3;
+          let _8: TypedId<std::string::String>;
+          scope 2 {
+              debug b => _8;
+              let _14: std::result::Result<Never, u16>;
+              scope 3 {
+                  debug c => _14;
+                  let _19: std::option::Option<u16>;
+                  scope 4 {
+                      debug d => _19;
+                      let _24: MyId;
+                      scope 5 {
+                          debug e => _24;
+                          let _29: aggregate_struct_then_transmute::Pair;
+                          scope 6 {
+                              debug f => _29;
+                              let _35: aggregate_struct_then_transmute::Pair;
+                              scope 7 {
+                                  debug g => _35;
+                                  let _41: (u16,);
+                                  scope 8 {
+                                      debug h => _41;
+                                      let _46: [u16; 1];
+                                      scope 9 {
+                                          debug i => _46;
+                                          let _51: *const i32;
+                                          scope 10 {
+                                              debug j => _51;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = MyId(move _4);
++         _3 = MyId(copy _1);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+-         _7 = move _3;
+-         _6 = move _7 as u16 (Transmute);
++         _7 = copy _3;
++         _6 = copy _1;
+          StorageDead(_7);
+-         _5 = opaque::<u16>(move _6) -> [return: bb1, unwind unreachable];
++         _5 = opaque::<u16>(copy _1) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          _9 = copy _1;
+          StorageLive(_10);
+-         _10 = PhantomData::<String>;
+-         _8 = TypedId::<String>(move _9, move _10);
++         _10 = const PhantomData::<String>;
++         _8 = TypedId::<String>(copy _1, const PhantomData::<String>);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          StorageLive(_13);
+-         _13 = move _8;
+-         _12 = move _13 as u16 (Transmute);
++         _13 = copy _8;
++         _12 = copy _1;
+          StorageDead(_13);
+-         _11 = opaque::<u16>(move _12) -> [return: bb2, unwind unreachable];
++         _11 = opaque::<u16>(copy _1) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          StorageDead(_12);
+          StorageDead(_11);
+-         StorageLive(_14);
++         nop;
+          StorageLive(_15);
+          _15 = copy _1;
+-         _14 = Result::<Never, u16>::Err(move _15);
++         _14 = Result::<Never, u16>::Err(copy _1);
+          StorageDead(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+-         _18 = move _14;
+-         _17 = move _18 as u16 (Transmute);
++         _18 = copy _14;
++         _17 = copy _1;
+          StorageDead(_18);
+-         _16 = opaque::<u16>(move _17) -> [return: bb3, unwind unreachable];
++         _16 = opaque::<u16>(copy _1) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          StorageDead(_17);
+          StorageDead(_16);
+-         StorageLive(_19);
++         nop;
+          StorageLive(_20);
+          _20 = copy _1;
+-         _19 = Option::<u16>::Some(move _20);
++         _19 = Option::<u16>::Some(copy _1);
+          StorageDead(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          StorageLive(_23);
+          _23 = copy _19;
+-         _22 = move _23 as u32 (Transmute);
++         _22 = copy _19 as u32 (Transmute);
+          StorageDead(_23);
+          _21 = opaque::<u32>(move _22) -> [return: bb4, unwind unreachable];
+      }
+  
+      bb4: {
+          StorageDead(_22);
+          StorageDead(_21);
+          StorageLive(_24);
+          StorageLive(_25);
+          _25 = copy _1;
+-         _24 = MyId(move _25);
++         _24 = copy _3;
+          StorageDead(_25);
+          StorageLive(_26);
+          StorageLive(_27);
+          StorageLive(_28);
+-         _28 = move _24;
+-         _27 = move _28 as i16 (Transmute);
++         _28 = copy _3;
++         _27 = copy _1 as i16 (Transmute);
+          StorageDead(_28);
+          _26 = opaque::<i16>(move _27) -> [return: bb5, unwind unreachable];
+      }
+  
+      bb5: {
+          StorageDead(_27);
+          StorageDead(_26);
+-         StorageLive(_29);
++         nop;
+          StorageLive(_30);
+          _30 = copy _1;
+          StorageLive(_31);
+          _31 = copy _1;
+-         _29 = Pair(move _30, move _31);
++         _29 = Pair(copy _1, copy _1);
+          StorageDead(_31);
+          StorageDead(_30);
+          StorageLive(_32);
+          StorageLive(_33);
+          StorageLive(_34);
+-         _34 = move _29;
+-         _33 = move _34 as u32 (Transmute);
++         _34 = copy _29;
++         _33 = copy _29 as u32 (Transmute);
+          StorageDead(_34);
+          _32 = opaque::<u32>(move _33) -> [return: bb6, unwind unreachable];
+      }
+  
+      bb6: {
+          StorageDead(_33);
+          StorageDead(_32);
+          StorageLive(_35);
+          StorageLive(_36);
+          _36 = copy _1;
+          StorageLive(_37);
+          _37 = copy _1;
+-         _35 = Pair(move _36, move _37);
++         _35 = copy _29;
+          StorageDead(_37);
+          StorageDead(_36);
+          StorageLive(_38);
+          StorageLive(_39);
+          StorageLive(_40);
+-         _40 = move _35;
+-         _39 = move _40 as u16 (Transmute);
++         _40 = copy _29;
++         _39 = copy _29 as u16 (Transmute);
+          StorageDead(_40);
+          _38 = opaque::<u16>(move _39) -> [return: bb7, unwind unreachable];
+      }
+  
+      bb7: {
+          StorageDead(_39);
+          StorageDead(_38);
+-         StorageLive(_41);
++         nop;
+          StorageLive(_42);
+          _42 = copy _1;
+-         _41 = (move _42,);
++         _41 = (copy _1,);
+          StorageDead(_42);
+          StorageLive(_43);
+          StorageLive(_44);
+          StorageLive(_45);
+          _45 = copy _41;
+-         _44 = move _45 as u16 (Transmute);
++         _44 = copy _1;
+          StorageDead(_45);
+-         _43 = opaque::<u16>(move _44) -> [return: bb8, unwind unreachable];
++         _43 = opaque::<u16>(copy _1) -> [return: bb8, unwind unreachable];
+      }
+  
+      bb8: {
+          StorageDead(_44);
+          StorageDead(_43);
+-         StorageLive(_46);
++         nop;
+          StorageLive(_47);
+          _47 = copy _1;
+-         _46 = [move _47];
++         _46 = [copy _1];
+          StorageDead(_47);
+          StorageLive(_48);
+          StorageLive(_49);
+          StorageLive(_50);
+          _50 = copy _46;
+-         _49 = move _50 as u16 (Transmute);
++         _49 = copy _1;
+          StorageDead(_50);
+-         _48 = opaque::<u16>(move _49) -> [return: bb9, unwind unreachable];
++         _48 = opaque::<u16>(copy _1) -> [return: bb9, unwind unreachable];
+      }
+  
+      bb9: {
+          StorageDead(_49);
+          StorageDead(_48);
+-         StorageLive(_51);
++         nop;
+          StorageLive(_52);
+          _52 = copy _2;
+          StorageLive(_53);
+-         _53 = ();
+-         _51 = *const i32 from (move _52, move _53);
++         _53 = const ();
++         _51 = *const i32 from (copy _2, const ());
+          StorageDead(_53);
+          StorageDead(_52);
+          StorageLive(_54);
+          StorageLive(_55);
+          StorageLive(_56);
+          _56 = copy _51;
+-         _55 = move _56 as *const u8 (Transmute);
++         _55 = copy _2;
+          StorageDead(_56);
+-         _54 = opaque::<*const u8>(move _55) -> [return: bb10, unwind unreachable];
++         _54 = opaque::<*const u8>(copy _2) -> [return: bb10, unwind unreachable];
+      }
+  
+      bb10: {
+          StorageDead(_55);
+          StorageDead(_54);
+          _0 = const ();
+-         StorageDead(_51);
+-         StorageDead(_46);
+-         StorageDead(_41);
++         nop;
++         nop;
++         nop;
+          StorageDead(_35);
+-         StorageDead(_29);
++         nop;
+          StorageDead(_24);
+-         StorageDead(_19);
+-         StorageDead(_14);
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..3119a93fb89
--- /dev/null
+++ b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff
@@ -0,0 +1,340 @@
+- // MIR for `aggregate_struct_then_transmute` before GVN
++ // MIR for `aggregate_struct_then_transmute` after GVN
+  
+  fn aggregate_struct_then_transmute(_1: u16, _2: *const u8) -> () {
+      debug id => _1;
+      debug thin => _2;
+      let mut _0: ();
+      let _3: MyId;
+      let mut _4: u16;
+      let _5: ();
+      let mut _6: u16;
+      let mut _7: MyId;
+      let mut _9: u16;
+      let mut _10: std::marker::PhantomData<std::string::String>;
+      let _11: ();
+      let mut _12: u16;
+      let mut _13: TypedId<std::string::String>;
+      let mut _15: u16;
+      let _16: ();
+      let mut _17: u16;
+      let mut _18: std::result::Result<Never, u16>;
+      let mut _20: u16;
+      let _21: ();
+      let mut _22: u32;
+      let mut _23: std::option::Option<u16>;
+      let mut _25: u16;
+      let _26: ();
+      let mut _27: i16;
+      let mut _28: MyId;
+      let mut _30: u16;
+      let mut _31: u16;
+      let _32: ();
+      let mut _33: u32;
+      let mut _34: aggregate_struct_then_transmute::Pair;
+      let mut _36: u16;
+      let mut _37: u16;
+      let _38: ();
+      let mut _39: u16;
+      let mut _40: aggregate_struct_then_transmute::Pair;
+      let mut _42: u16;
+      let _43: ();
+      let mut _44: u16;
+      let mut _45: (u16,);
+      let mut _47: u16;
+      let _48: ();
+      let mut _49: u16;
+      let mut _50: [u16; 1];
+      let mut _52: *const u8;
+      let mut _53: ();
+      let _54: ();
+      let mut _55: *const u8;
+      let mut _56: *const i32;
+      scope 1 {
+          debug a => _3;
+          let _8: TypedId<std::string::String>;
+          scope 2 {
+              debug b => _8;
+              let _14: std::result::Result<Never, u16>;
+              scope 3 {
+                  debug c => _14;
+                  let _19: std::option::Option<u16>;
+                  scope 4 {
+                      debug d => _19;
+                      let _24: MyId;
+                      scope 5 {
+                          debug e => _24;
+                          let _29: aggregate_struct_then_transmute::Pair;
+                          scope 6 {
+                              debug f => _29;
+                              let _35: aggregate_struct_then_transmute::Pair;
+                              scope 7 {
+                                  debug g => _35;
+                                  let _41: (u16,);
+                                  scope 8 {
+                                      debug h => _41;
+                                      let _46: [u16; 1];
+                                      scope 9 {
+                                          debug i => _46;
+                                          let _51: *const i32;
+                                          scope 10 {
+                                              debug j => _51;
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = MyId(move _4);
++         _3 = MyId(copy _1);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+-         _7 = move _3;
+-         _6 = move _7 as u16 (Transmute);
++         _7 = copy _3;
++         _6 = copy _1;
+          StorageDead(_7);
+-         _5 = opaque::<u16>(move _6) -> [return: bb1, unwind continue];
++         _5 = opaque::<u16>(copy _1) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          _9 = copy _1;
+          StorageLive(_10);
+-         _10 = PhantomData::<String>;
+-         _8 = TypedId::<String>(move _9, move _10);
++         _10 = const PhantomData::<String>;
++         _8 = TypedId::<String>(copy _1, const PhantomData::<String>);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          StorageLive(_13);
+-         _13 = move _8;
+-         _12 = move _13 as u16 (Transmute);
++         _13 = copy _8;
++         _12 = copy _1;
+          StorageDead(_13);
+-         _11 = opaque::<u16>(move _12) -> [return: bb2, unwind continue];
++         _11 = opaque::<u16>(copy _1) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          StorageDead(_12);
+          StorageDead(_11);
+-         StorageLive(_14);
++         nop;
+          StorageLive(_15);
+          _15 = copy _1;
+-         _14 = Result::<Never, u16>::Err(move _15);
++         _14 = Result::<Never, u16>::Err(copy _1);
+          StorageDead(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+-         _18 = move _14;
+-         _17 = move _18 as u16 (Transmute);
++         _18 = copy _14;
++         _17 = copy _1;
+          StorageDead(_18);
+-         _16 = opaque::<u16>(move _17) -> [return: bb3, unwind continue];
++         _16 = opaque::<u16>(copy _1) -> [return: bb3, unwind continue];
+      }
+  
+      bb3: {
+          StorageDead(_17);
+          StorageDead(_16);
+-         StorageLive(_19);
++         nop;
+          StorageLive(_20);
+          _20 = copy _1;
+-         _19 = Option::<u16>::Some(move _20);
++         _19 = Option::<u16>::Some(copy _1);
+          StorageDead(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          StorageLive(_23);
+          _23 = copy _19;
+-         _22 = move _23 as u32 (Transmute);
++         _22 = copy _19 as u32 (Transmute);
+          StorageDead(_23);
+          _21 = opaque::<u32>(move _22) -> [return: bb4, unwind continue];
+      }
+  
+      bb4: {
+          StorageDead(_22);
+          StorageDead(_21);
+          StorageLive(_24);
+          StorageLive(_25);
+          _25 = copy _1;
+-         _24 = MyId(move _25);
++         _24 = copy _3;
+          StorageDead(_25);
+          StorageLive(_26);
+          StorageLive(_27);
+          StorageLive(_28);
+-         _28 = move _24;
+-         _27 = move _28 as i16 (Transmute);
++         _28 = copy _3;
++         _27 = copy _1 as i16 (Transmute);
+          StorageDead(_28);
+          _26 = opaque::<i16>(move _27) -> [return: bb5, unwind continue];
+      }
+  
+      bb5: {
+          StorageDead(_27);
+          StorageDead(_26);
+-         StorageLive(_29);
++         nop;
+          StorageLive(_30);
+          _30 = copy _1;
+          StorageLive(_31);
+          _31 = copy _1;
+-         _29 = Pair(move _30, move _31);
++         _29 = Pair(copy _1, copy _1);
+          StorageDead(_31);
+          StorageDead(_30);
+          StorageLive(_32);
+          StorageLive(_33);
+          StorageLive(_34);
+-         _34 = move _29;
+-         _33 = move _34 as u32 (Transmute);
++         _34 = copy _29;
++         _33 = copy _29 as u32 (Transmute);
+          StorageDead(_34);
+          _32 = opaque::<u32>(move _33) -> [return: bb6, unwind continue];
+      }
+  
+      bb6: {
+          StorageDead(_33);
+          StorageDead(_32);
+          StorageLive(_35);
+          StorageLive(_36);
+          _36 = copy _1;
+          StorageLive(_37);
+          _37 = copy _1;
+-         _35 = Pair(move _36, move _37);
++         _35 = copy _29;
+          StorageDead(_37);
+          StorageDead(_36);
+          StorageLive(_38);
+          StorageLive(_39);
+          StorageLive(_40);
+-         _40 = move _35;
+-         _39 = move _40 as u16 (Transmute);
++         _40 = copy _29;
++         _39 = copy _29 as u16 (Transmute);
+          StorageDead(_40);
+          _38 = opaque::<u16>(move _39) -> [return: bb7, unwind continue];
+      }
+  
+      bb7: {
+          StorageDead(_39);
+          StorageDead(_38);
+-         StorageLive(_41);
++         nop;
+          StorageLive(_42);
+          _42 = copy _1;
+-         _41 = (move _42,);
++         _41 = (copy _1,);
+          StorageDead(_42);
+          StorageLive(_43);
+          StorageLive(_44);
+          StorageLive(_45);
+          _45 = copy _41;
+-         _44 = move _45 as u16 (Transmute);
++         _44 = copy _1;
+          StorageDead(_45);
+-         _43 = opaque::<u16>(move _44) -> [return: bb8, unwind continue];
++         _43 = opaque::<u16>(copy _1) -> [return: bb8, unwind continue];
+      }
+  
+      bb8: {
+          StorageDead(_44);
+          StorageDead(_43);
+-         StorageLive(_46);
++         nop;
+          StorageLive(_47);
+          _47 = copy _1;
+-         _46 = [move _47];
++         _46 = [copy _1];
+          StorageDead(_47);
+          StorageLive(_48);
+          StorageLive(_49);
+          StorageLive(_50);
+          _50 = copy _46;
+-         _49 = move _50 as u16 (Transmute);
++         _49 = copy _1;
+          StorageDead(_50);
+-         _48 = opaque::<u16>(move _49) -> [return: bb9, unwind continue];
++         _48 = opaque::<u16>(copy _1) -> [return: bb9, unwind continue];
+      }
+  
+      bb9: {
+          StorageDead(_49);
+          StorageDead(_48);
+-         StorageLive(_51);
++         nop;
+          StorageLive(_52);
+          _52 = copy _2;
+          StorageLive(_53);
+-         _53 = ();
+-         _51 = *const i32 from (move _52, move _53);
++         _53 = const ();
++         _51 = *const i32 from (copy _2, const ());
+          StorageDead(_53);
+          StorageDead(_52);
+          StorageLive(_54);
+          StorageLive(_55);
+          StorageLive(_56);
+          _56 = copy _51;
+-         _55 = move _56 as *const u8 (Transmute);
++         _55 = copy _2;
+          StorageDead(_56);
+-         _54 = opaque::<*const u8>(move _55) -> [return: bb10, unwind continue];
++         _54 = opaque::<*const u8>(copy _2) -> [return: bb10, unwind continue];
+      }
+  
+      bb10: {
+          StorageDead(_55);
+          StorageDead(_54);
+          _0 = const ();
+-         StorageDead(_51);
+-         StorageDead(_46);
+-         StorageDead(_41);
++         nop;
++         nop;
++         nop;
+          StorageDead(_35);
+-         StorageDead(_29);
++         nop;
+          StorageDead(_24);
+-         StorageDead(_19);
+-         StorageDead(_14);
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 19b58a917f8..c895a579259 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -12,7 +12,7 @@
 #![allow(unused)]
 
 use std::intrinsics::mir::*;
-use std::marker::Freeze;
+use std::marker::{Freeze, PhantomData};
 use std::mem::transmute;
 
 struct S<T>(T);
@@ -933,6 +933,69 @@ fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) {
     // CHECK: _0 = const ();
 }
 
+unsafe fn aggregate_struct_then_transmute(id: u16, thin: *const u8) {
+    // CHECK: opaque::<u16>(copy _1)
+    let a = MyId(id);
+    opaque(std::intrinsics::transmute::<_, u16>(a));
+
+    // CHECK: opaque::<u16>(copy _1)
+    let b = TypedId::<String>(id, PhantomData);
+    opaque(std::intrinsics::transmute::<_, u16>(b));
+
+    // CHECK: opaque::<u16>(copy _1)
+    let c = Err::<Never, u16>(id);
+    opaque(std::intrinsics::transmute::<_, u16>(c));
+
+    // CHECK: [[TEMP1:_[0-9]+]] = Option::<u16>::Some(copy _1);
+    // CHECK: [[TEMP2:_[0-9]+]] = copy [[TEMP1]] as u32 (Transmute);
+    // CHECK: opaque::<u32>(move [[TEMP2]])
+    let d = Some(id);
+    opaque(std::intrinsics::transmute::<_, u32>(d));
+
+    // Still need the transmute, but the aggregate can be skipped
+    // CHECK: [[TEMP:_[0-9]+]] = copy _1 as i16 (Transmute);
+    // CHECK: opaque::<i16>(move [[TEMP]])
+    let e = MyId(id);
+    opaque(std::intrinsics::transmute::<_, i16>(e));
+
+    // CHECK: [[PAIR:_[0-9]+]] = Pair(copy _1, copy _1);
+    // CHECK: [[TEMP:_[0-9]+]] = copy [[PAIR]] as u32 (Transmute);
+    // CHECK: opaque::<u32>(move [[TEMP]])
+    struct Pair(u16, u16);
+    let f = Pair(id, id);
+    opaque(std::intrinsics::transmute::<_, u32>(f));
+
+    // CHECK: [[TEMP:_[0-9]+]] = copy [[PAIR]] as u16 (Transmute);
+    // CHECK: opaque::<u16>(move [[TEMP]])
+    let g = Pair(id, id);
+    opaque(std::intrinsics::transmute_unchecked::<_, u16>(g));
+
+    // CHECK: opaque::<u16>(copy _1)
+    let h = (id,);
+    opaque(std::intrinsics::transmute::<_, u16>(h));
+
+    // CHECK: opaque::<u16>(copy _1)
+    let i = [id];
+    opaque(std::intrinsics::transmute::<_, u16>(i));
+
+    // CHECK: opaque::<*const u8>(copy _2)
+    let j: *const i32 = std::intrinsics::aggregate_raw_ptr(thin, ());
+    opaque(std::intrinsics::transmute::<_, *const u8>(j));
+}
+
+unsafe fn transmute_then_transmute_again(a: u32, c: char) {
+    // CHECK: [[TEMP1:_[0-9]+]] = copy _1 as char (Transmute);
+    // CHECK: [[TEMP2:_[0-9]+]] = copy [[TEMP1]] as i32 (Transmute);
+    // CHECK: opaque::<i32>(move [[TEMP2]])
+    let x = std::intrinsics::transmute::<u32, char>(a);
+    opaque(std::intrinsics::transmute::<char, i32>(x));
+
+    // CHECK: [[TEMP:_[0-9]+]] = copy _2 as i32 (Transmute);
+    // CHECK: opaque::<i32>(move [[TEMP]])
+    let x = std::intrinsics::transmute::<char, u32>(c);
+    opaque(std::intrinsics::transmute::<u32, i32>(x));
+}
+
 // Transmuting can skip a pointer cast so long as it wasn't a fat-to-thin cast.
 unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
     // CHECK-LABEL: fn cast_pointer_then_transmute
@@ -946,6 +1009,28 @@ unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
     let fat_addr: usize = std::intrinsics::transmute(fat as *const ());
 }
 
+unsafe fn transmute_then_cast_pointer(addr: usize, fat: *mut [u8]) {
+    // CHECK-LABEL: fn transmute_then_cast_pointer
+
+    // This is roughly what `NonNull::dangling` does
+    // CHECK: [[CPTR:_.+]] = copy _1 as *const u8 (Transmute);
+    // CHECK: takes_const_ptr::<u8>(move [[CPTR]])
+    let p: *mut u8 = std::intrinsics::transmute(addr);
+    takes_const_ptr(p);
+
+    // This cast is fat-to-thin, so can't be merged with the transmute
+    // CHECK: [[FAT:_.+]] = move {{.+}} as *const [i32] (Transmute);
+    // CHECK: [[THIN:_.+]] = copy [[FAT]] as *const i32 (PtrToPtr);
+    // CHECK: takes_const_ptr::<i32>(move [[THIN]])
+    let q = std::intrinsics::transmute::<&mut [i32], *const [i32]>(&mut [1, 2, 3]);
+    takes_const_ptr(q as *const i32);
+
+    // CHECK: [[TPTR:_.+]] = copy _2 as *const u8 (PtrToPtr);
+    // CHECK: takes_const_ptr::<u8>(move [[TPTR]])
+    let w = std::intrinsics::transmute::<*mut [u8], *const [u8]>(fat);
+    takes_const_ptr(w as *const u8);
+}
+
 #[custom_mir(dialect = "analysis")]
 fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool {
     // CHECK-LABEL: fn remove_casts_must_change_both_sides(
@@ -1002,6 +1087,18 @@ fn identity<T>(x: T) -> T {
     x
 }
 
+#[inline(never)]
+fn takes_const_ptr<T>(_: *const T) {}
+
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_end(55555)]
+struct MyId(u16);
+
+#[repr(transparent)]
+struct TypedId<T>(u16, PhantomData<T>);
+
+enum Never {}
+
 // EMIT_MIR gvn.subexpression_elimination.GVN.diff
 // EMIT_MIR gvn.wrap_unwrap.GVN.diff
 // EMIT_MIR gvn.repeated_index.GVN.diff
@@ -1034,5 +1131,8 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.dedup_multiple_bounds_checks_lengths.GVN.diff
 // EMIT_MIR gvn.generic_cast_metadata.GVN.diff
 // EMIT_MIR gvn.cast_pointer_eq.GVN.diff
+// EMIT_MIR gvn.aggregate_struct_then_transmute.GVN.diff
+// EMIT_MIR gvn.transmute_then_transmute_again.GVN.diff
 // EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
+// EMIT_MIR gvn.transmute_then_cast_pointer.GVN.diff
 // EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff
diff --git a/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-abort.diff b/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-abort.diff
new file mode 100644
index 00000000000..0bec425dd99
--- /dev/null
+++ b/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-abort.diff
@@ -0,0 +1,115 @@
+- // MIR for `transmute_then_cast_pointer` before GVN
++ // MIR for `transmute_then_cast_pointer` after GVN
+  
+  fn transmute_then_cast_pointer(_1: usize, _2: *mut [u8]) -> () {
+      debug addr => _1;
+      debug fat => _2;
+      let mut _0: ();
+      let _3: *mut u8;
+      let mut _4: usize;
+      let _5: ();
+      let mut _6: *const u8;
+      let mut _7: *mut u8;
+      let mut _9: &mut [i32];
+      let mut _10: &mut [i32; 3];
+      let mut _11: &mut [i32; 3];
+      let mut _12: [i32; 3];
+      let _13: ();
+      let mut _14: *const i32;
+      let mut _15: *const [i32];
+      let mut _17: *mut [u8];
+      let _18: ();
+      let mut _19: *const u8;
+      let mut _20: *const [u8];
+      scope 1 {
+          debug p => _3;
+          let _8: *const [i32];
+          scope 2 {
+              debug q => _8;
+              let _16: *const [u8];
+              scope 3 {
+                  debug w => _16;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = move _4 as *mut u8 (Transmute);
++         _3 = copy _1 as *mut u8 (Transmute);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _3;
+-         _6 = move _7 as *const u8 (PtrToPtr);
++         _6 = copy _1 as *const u8 (Transmute);
+          StorageDead(_7);
+          _5 = takes_const_ptr::<u8>(move _6) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = [const 1_i32, const 2_i32, const 3_i32];
+          _11 = &mut _12;
+          _10 = &mut (*_11);
+          _9 = move _10 as &mut [i32] (PointerCoercion(Unsize, Implicit));
+          StorageDead(_10);
+          _8 = move _9 as *const [i32] (Transmute);
+          StorageDead(_9);
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+          _15 = copy _8;
+-         _14 = move _15 as *const i32 (PtrToPtr);
++         _14 = copy _8 as *const i32 (PtrToPtr);
+          StorageDead(_15);
+          _13 = takes_const_ptr::<i32>(move _14) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          StorageDead(_14);
+          StorageDead(_13);
+-         StorageLive(_16);
++         nop;
+          StorageLive(_17);
+          _17 = copy _2;
+-         _16 = move _17 as *const [u8] (Transmute);
++         _16 = copy _2 as *const [u8] (PtrToPtr);
+          StorageDead(_17);
+          StorageLive(_18);
+          StorageLive(_19);
+          StorageLive(_20);
+          _20 = copy _16;
+-         _19 = move _20 as *const u8 (PtrToPtr);
++         _19 = copy _2 as *const u8 (PtrToPtr);
+          StorageDead(_20);
+          _18 = takes_const_ptr::<u8>(move _19) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          StorageDead(_19);
+          StorageDead(_18);
+          _0 = const ();
+-         StorageDead(_16);
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-unwind.diff b/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..14f2fe08a86
--- /dev/null
+++ b/tests/mir-opt/gvn.transmute_then_cast_pointer.GVN.panic-unwind.diff
@@ -0,0 +1,115 @@
+- // MIR for `transmute_then_cast_pointer` before GVN
++ // MIR for `transmute_then_cast_pointer` after GVN
+  
+  fn transmute_then_cast_pointer(_1: usize, _2: *mut [u8]) -> () {
+      debug addr => _1;
+      debug fat => _2;
+      let mut _0: ();
+      let _3: *mut u8;
+      let mut _4: usize;
+      let _5: ();
+      let mut _6: *const u8;
+      let mut _7: *mut u8;
+      let mut _9: &mut [i32];
+      let mut _10: &mut [i32; 3];
+      let mut _11: &mut [i32; 3];
+      let mut _12: [i32; 3];
+      let _13: ();
+      let mut _14: *const i32;
+      let mut _15: *const [i32];
+      let mut _17: *mut [u8];
+      let _18: ();
+      let mut _19: *const u8;
+      let mut _20: *const [u8];
+      scope 1 {
+          debug p => _3;
+          let _8: *const [i32];
+          scope 2 {
+              debug q => _8;
+              let _16: *const [u8];
+              scope 3 {
+                  debug w => _16;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = move _4 as *mut u8 (Transmute);
++         _3 = copy _1 as *mut u8 (Transmute);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _3;
+-         _6 = move _7 as *const u8 (PtrToPtr);
++         _6 = copy _1 as *const u8 (Transmute);
+          StorageDead(_7);
+          _5 = takes_const_ptr::<u8>(move _6) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = [const 1_i32, const 2_i32, const 3_i32];
+          _11 = &mut _12;
+          _10 = &mut (*_11);
+          _9 = move _10 as &mut [i32] (PointerCoercion(Unsize, Implicit));
+          StorageDead(_10);
+          _8 = move _9 as *const [i32] (Transmute);
+          StorageDead(_9);
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+          _15 = copy _8;
+-         _14 = move _15 as *const i32 (PtrToPtr);
++         _14 = copy _8 as *const i32 (PtrToPtr);
+          StorageDead(_15);
+          _13 = takes_const_ptr::<i32>(move _14) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          StorageDead(_14);
+          StorageDead(_13);
+-         StorageLive(_16);
++         nop;
+          StorageLive(_17);
+          _17 = copy _2;
+-         _16 = move _17 as *const [u8] (Transmute);
++         _16 = copy _2 as *const [u8] (PtrToPtr);
+          StorageDead(_17);
+          StorageLive(_18);
+          StorageLive(_19);
+          StorageLive(_20);
+          _20 = copy _16;
+-         _19 = move _20 as *const u8 (PtrToPtr);
++         _19 = copy _2 as *const u8 (PtrToPtr);
+          StorageDead(_20);
+          _18 = takes_const_ptr::<u8>(move _19) -> [return: bb3, unwind continue];
+      }
+  
+      bb3: {
+          StorageDead(_19);
+          StorageDead(_18);
+          _0 = const ();
+-         StorageDead(_16);
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff
new file mode 100644
index 00000000000..962fecd2586
--- /dev/null
+++ b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff
@@ -0,0 +1,74 @@
+- // MIR for `transmute_then_transmute_again` before GVN
++ // MIR for `transmute_then_transmute_again` after GVN
+  
+  fn transmute_then_transmute_again(_1: u32, _2: char) -> () {
+      debug a => _1;
+      debug c => _2;
+      let mut _0: ();
+      let _3: char;
+      let mut _4: u32;
+      let _5: ();
+      let mut _6: i32;
+      let mut _7: char;
+      let mut _9: char;
+      let _10: ();
+      let mut _11: i32;
+      let mut _12: u32;
+      scope 1 {
+          debug x => _3;
+          let _8: u32;
+          scope 2 {
+              debug x => _8;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = move _4 as char (Transmute);
++         _3 = copy _1 as char (Transmute);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _3;
+-         _6 = move _7 as i32 (Transmute);
++         _6 = copy _3 as i32 (Transmute);
+          StorageDead(_7);
+          _5 = opaque::<i32>(move _6) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          _9 = copy _2;
+-         _8 = move _9 as u32 (Transmute);
++         _8 = copy _2 as u32 (Transmute);
+          StorageDead(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _8;
+-         _11 = move _12 as i32 (Transmute);
++         _11 = copy _2 as i32 (Transmute);
+          StorageDead(_12);
+          _10 = opaque::<i32>(move _11) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..e32397c1aed
--- /dev/null
+++ b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff
@@ -0,0 +1,74 @@
+- // MIR for `transmute_then_transmute_again` before GVN
++ // MIR for `transmute_then_transmute_again` after GVN
+  
+  fn transmute_then_transmute_again(_1: u32, _2: char) -> () {
+      debug a => _1;
+      debug c => _2;
+      let mut _0: ();
+      let _3: char;
+      let mut _4: u32;
+      let _5: ();
+      let mut _6: i32;
+      let mut _7: char;
+      let mut _9: char;
+      let _10: ();
+      let mut _11: i32;
+      let mut _12: u32;
+      scope 1 {
+          debug x => _3;
+          let _8: u32;
+          scope 2 {
+              debug x => _8;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = copy _1;
+-         _3 = move _4 as char (Transmute);
++         _3 = copy _1 as char (Transmute);
+          StorageDead(_4);
+          StorageLive(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _3;
+-         _6 = move _7 as i32 (Transmute);
++         _6 = copy _3 as i32 (Transmute);
+          StorageDead(_7);
+          _5 = opaque::<i32>(move _6) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          _9 = copy _2;
+-         _8 = move _9 as u32 (Transmute);
++         _8 = copy _2 as u32 (Transmute);
+          StorageDead(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _8;
+-         _11 = move _12 as i32 (Transmute);
++         _11 = copy _2 as i32 (Transmute);
+          StorageDead(_12);
+          _10 = opaque::<i32>(move _11) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+-         StorageDead(_8);
+-         StorageDead(_3);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
index 581244074b3..4337e0da183 100644
--- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
@@ -11,10 +11,43 @@
 +     scope 1 (inlined std::ptr::drop_in_place::<Vec<A>> - shim(Some(Vec<A>))) {
 +         let mut _6: &mut std::vec::Vec<A>;
 +         let mut _7: ();
++         scope 2 (inlined <Vec<A> as Drop>::drop) {
++             let mut _8: *mut [A];
++             let mut _9: *mut A;
++             let mut _10: usize;
++             scope 3 (inlined Vec::<A>::as_mut_ptr) {
++                 scope 4 (inlined alloc::raw_vec::RawVec::<A>::ptr) {
++                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<A>) {
++                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<A>) {
++                             let mut _11: std::ptr::NonNull<u8>;
++                             scope 7 (inlined Unique::<u8>::cast::<A>) {
++                                 scope 8 (inlined NonNull::<u8>::cast::<A>) {
++                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
++                                     }
++                                 }
++                             }
++                             scope 10 (inlined Unique::<A>::as_non_null_ptr) {
++                             }
++                         }
++                         scope 11 (inlined NonNull::<A>::as_ptr) {
++                         }
++                     }
++                 }
++             }
++             scope 12 (inlined slice_from_raw_parts_mut::<A>) {
++                 scope 13 (inlined std::ptr::from_raw_parts_mut::<[A], A>) {
++                 }
++             }
++             scope 14 (inlined std::ptr::drop_in_place::<[A]> - shim(Some([A]))) {
++                 let mut _12: usize;
++                 let mut _13: *mut A;
++                 let mut _14: bool;
++             }
++         }
 +     }
-+     scope 2 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
-+         let mut _8: isize;
-+         let mut _9: isize;
++     scope 15 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
++         let mut _15: isize;
++         let mut _16: isize;
 +     }
   
       bb0: {
@@ -25,7 +58,21 @@
 +         StorageLive(_6);
 +         StorageLive(_7);
 +         _6 = &mut (*_4);
-+         _7 = <Vec<A> as Drop>::drop(move _6) -> [return: bb2, unwind unreachable];
++         StorageLive(_10);
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_11);
++         _11 = copy (((((*_6).0: alloc::raw_vec::RawVec<A>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
++         _9 = copy _11 as *mut A (Transmute);
++         StorageDead(_11);
++         _10 = copy ((*_6).1: usize);
++         _8 = *mut [A] from (copy _9, copy _10);
++         StorageDead(_9);
++         StorageLive(_12);
++         StorageLive(_13);
++         StorageLive(_14);
++         _12 = const 0_usize;
++         goto -> bb4;
       }
   
       bb1: {
@@ -36,25 +83,41 @@
           StorageLive(_5);
           _5 = copy _2;
 -         _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind unreachable];
-+         StorageLive(_8);
-+         StorageLive(_9);
-+         _8 = discriminant((*_5));
-+         switchInt(move _8) -> [0: bb3, otherwise: bb4];
++         StorageLive(_15);
++         StorageLive(_16);
++         _15 = discriminant((*_5));
++         switchInt(move _15) -> [0: bb5, otherwise: bb6];
       }
   
       bb2: {
++         StorageDead(_14);
++         StorageDead(_13);
++         StorageDead(_12);
++         StorageDead(_8);
++         StorageDead(_10);
 +         drop(((*_4).0: alloc::raw_vec::RawVec<A>)) -> [return: bb1, unwind unreachable];
 +     }
 + 
 +     bb3: {
-+         StorageDead(_9);
-+         StorageDead(_8);
++         _13 = &raw mut (*_8)[_12];
++         _12 = Add(move _12, const 1_usize);
++         drop((*_13)) -> [return: bb4, unwind unreachable];
++     }
++ 
++     bb4: {
++         _14 = Eq(copy _12, copy _10);
++         switchInt(move _14) -> [0: bb3, otherwise: bb2];
++     }
++ 
++     bb5: {
++         StorageDead(_16);
++         StorageDead(_15);
           StorageDead(_5);
           return;
 +     }
 + 
-+     bb4: {
-+         drop((((*_5) as Some).0: B)) -> [return: bb3, unwind unreachable];
++     bb6: {
++         drop((((*_5) as Some).0: B)) -> [return: bb5, unwind unreachable];
       }
   }
   
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 02aadfc1de0..103475b608c 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -20,7 +20,7 @@ fn b(_1: &mut Box<T>) -> &mut T {
         StorageLive(_5);
         StorageLive(_6);
         _5 = copy (*_4);
-        _6 = copy (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T);
+        _6 = copy ((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>) as *const T (Transmute);
         _3 = &mut (*_6);
         StorageDead(_6);
         StorageDead(_5);
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index 1ea347510fd..babb26808ce 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -18,7 +18,7 @@ fn d(_1: &Box<T>) -> &T {
         StorageLive(_4);
         StorageLive(_5);
         _4 = copy (*_3);
-        _5 = copy (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T);
+        _5 = copy ((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>) as *const T (Transmute);
         _2 = &(*_5);
         StorageDead(_5);
         StorageDead(_4);
diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
index 70671e2089a..644d6d320de 100644
--- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
+++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
@@ -12,7 +12,7 @@
           StorageLive(_2);
           StorageLive(_3);
           _3 = move _1;
-          _4 = copy (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]);
+          _4 = copy ((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (Transmute);
           _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3];
       }
   
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
deleted file mode 100644
index 9844aa2a64e..00000000000
--- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
+++ /dev/null
@@ -1,83 +0,0 @@
-- // MIR for `adt_transmutes` before InstSimplify-after-simplifycfg
-+ // MIR for `adt_transmutes` after InstSimplify-after-simplifycfg
-  
-  fn adt_transmutes() -> () {
-      let mut _0: ();
-      let _1: u8;
-      let mut _2: std::option::Option<std::num::NonZero<u8>>;
-      let mut _4: std::num::Wrapping<i16>;
-      let mut _6: std::num::Wrapping<i16>;
-      let mut _8: Union32;
-      let mut _10: Union32;
-      let mut _12: std::mem::MaybeUninit<std::string::String>;
-      scope 1 {
-          debug _a => _1;
-          let _3: i16;
-          scope 2 {
-              debug _a => _3;
-              let _5: u16;
-              scope 3 {
-                  debug _a => _5;
-                  let _7: u32;
-                  scope 4 {
-                      debug _a => _7;
-                      let _9: i32;
-                      scope 5 {
-                          debug _a => _9;
-                          let _11: std::mem::ManuallyDrop<std::string::String>;
-                          scope 6 {
-                              debug _a => _11;
-                          }
-                      }
-                  }
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);
-          StorageLive(_2);
-          _2 = Option::<NonZero<u8>>::Some(const std::num::NonZero::<u8>::MAX);
-          _1 = move _2 as u8 (Transmute);
-          StorageDead(_2);
-          StorageLive(_3);
-          StorageLive(_4);
-          _4 = Wrapping::<i16>(const 0_i16);
--         _3 = move _4 as i16 (Transmute);
-+         _3 = move (_4.0: i16);
-          StorageDead(_4);
-          StorageLive(_5);
-          StorageLive(_6);
-          _6 = Wrapping::<i16>(const 0_i16);
-          _5 = move _6 as u16 (Transmute);
-          StorageDead(_6);
-          StorageLive(_7);
-          StorageLive(_8);
-          _8 = Union32 { u32: const 0_i32 };
-          _7 = move _8 as u32 (Transmute);
-          StorageDead(_8);
-          StorageLive(_9);
-          StorageLive(_10);
-          _10 = Union32 { u32: const 0_u32 };
-          _9 = move _10 as i32 (Transmute);
-          StorageDead(_10);
-          StorageLive(_11);
-          StorageLive(_12);
-          _12 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable];
-      }
-  
-      bb1: {
--         _11 = move _12 as std::mem::ManuallyDrop<std::string::String> (Transmute);
-+         _11 = move (_12.1: std::mem::ManuallyDrop<std::string::String>);
-          StorageDead(_12);
-          _0 = const ();
-          StorageDead(_11);
-          StorageDead(_9);
-          StorageDead(_7);
-          StorageDead(_5);
-          StorageDead(_3);
-          StorageDead(_1);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.keep_transparent_transmute.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/combine_transmutes.keep_transparent_transmute.InstSimplify-after-simplifycfg.diff
new file mode 100644
index 00000000000..66a29629591
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_transmutes.keep_transparent_transmute.InstSimplify-after-simplifycfg.diff
@@ -0,0 +1,30 @@
+- // MIR for `keep_transparent_transmute` before InstSimplify-after-simplifycfg
++ // MIR for `keep_transparent_transmute` after InstSimplify-after-simplifycfg
+  
+  fn keep_transparent_transmute() -> () {
+      let mut _0: ();
+      let _1: i16;
+      let mut _3: std::num::Wrapping<i16>;
+      scope 1 {
+          debug _a => _1;
+          let _2: i16;
+          scope 2 {
+              debug _a => _2;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          _1 = const keep_transparent_transmute::{constant#0} as i16 (Transmute);
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = Wrapping::<i16>(const 0_i16);
+          _2 = move _3 as i16 (Transmute);
+          StorageDead(_3);
+          _0 = const ();
+          StorageDead(_2);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.rs b/tests/mir-opt/instsimplify/combine_transmutes.rs
index 8a670301825..c12f307ca0e 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.rs
+++ b/tests/mir-opt/instsimplify/combine_transmutes.rs
@@ -43,22 +43,19 @@ pub unsafe fn integer_transmutes() {
     }
 }
 
-// EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
-pub unsafe fn adt_transmutes() {
-    // CHECK-LABEL: fn adt_transmutes(
-    // CHECK: as u8 (Transmute);
-    // CHECK: ({{_.*}}.0: i16);
-    // CHECK: as u16 (Transmute);
-    // CHECK: as u32 (Transmute);
-    // CHECK: as i32 (Transmute);
-    // CHECK: ({{_.*}}.1: std::mem::ManuallyDrop<std::string::String>);
+// EMIT_MIR combine_transmutes.keep_transparent_transmute.InstSimplify-after-simplifycfg.diff
+pub unsafe fn keep_transparent_transmute() {
+    // CHECK-LABEL: fn keep_transparent_transmute(
+    // CHECK-NOT: .{{[0-9]+}}: i16
+    // CHECK: as i16 (Transmute);
+    // CHECK-NOT: .{{[0-9]+}}: i16
+    // CHECK: as i16 (Transmute);
+    // CHECK-NOT: .{{[0-9]+}}: i16
 
-    let _a: u8 = transmute(Some(std::num::NonZero::<u8>::MAX));
+    // Transmutes should not be converted to field accesses, because MCP#807
+    // bans projections into `[rustc_layout_scalar_valid_range_*]` types.
+    let _a: i16 = transmute(const { std::num::NonZero::new(12345_i16).unwrap() });
     let _a: i16 = transmute(std::num::Wrapping(0_i16));
-    let _a: u16 = transmute(std::num::Wrapping(0_i16));
-    let _a: u32 = transmute(Union32 { i32: 0 });
-    let _a: i32 = transmute(Union32 { u32: 0 });
-    let _a: ManuallyDrop<String> = transmute(MaybeUninit::<String>::uninit());
 }
 
 pub union Union32 {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index a3308cc5df1..a2ef53e0e13 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -4,28 +4,28 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _23: std::option::Option<(usize, &T)>;
-    let mut _26: &impl Fn(usize, &T);
-    let mut _27: (usize, &T);
-    let _28: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _21: std::option::Option<(usize, &T)>;
+    let mut _24: &impl Fn(usize, &T);
+    let mut _25: (usize, &T);
+    let _26: ();
     scope 1 {
-        debug iter => _15;
-        let _24: usize;
-        let _25: &T;
+        debug iter => _13;
+        let _22: usize;
+        let _23: &T;
         scope 2 {
-            debug i => _24;
-            debug x => _25;
+            debug i => _22;
+            debug x => _23;
         }
         scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _16: &mut std::slice::Iter<'_, T>;
-            let mut _17: std::option::Option<&T>;
-            let mut _21: (usize, bool);
-            let mut _22: (usize, &T);
+            let mut _14: &mut std::slice::Iter<'_, T>;
+            let mut _15: std::option::Option<&T>;
+            let mut _19: (usize, bool);
+            let mut _20: (usize, &T);
             scope 19 {
-                let _20: usize;
+                let _18: usize;
                 scope 24 {
                 }
             }
@@ -40,8 +40,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 }
             }
             scope 25 (inlined <Option<&T> as Try>::branch) {
-                let mut _18: isize;
-                let _19: &T;
+                let mut _16: isize;
+                let _17: &T;
                 scope 26 {
                 }
             }
@@ -50,14 +50,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -73,8 +72,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -89,82 +87,76 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_13);
+        StorageLive(_11);
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_12);
-        _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
-        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _13, count: const 0_usize };
-        StorageDead(_13);
-        StorageLive(_15);
-        _15 = copy _14;
+        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = copy _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_23);
-        StorageLive(_20);
         StorageLive(_21);
-        StorageLive(_17);
-        StorageLive(_16);
-        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
-        _17 = <std::slice::Iter<'_, T> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable];
+        StorageLive(_18);
+        StorageLive(_19);
+        StorageLive(_15);
+        StorageLive(_14);
+        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
+        _15 = <std::slice::Iter<'_, T> as Iterator>::next(move _14) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_16);
-        StorageLive(_18);
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_14);
+        StorageLive(_16);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
+        StorageDead(_16);
+        StorageDead(_15);
+        StorageDead(_19);
         StorageDead(_18);
-        StorageDead(_17);
         StorageDead(_21);
-        StorageDead(_20);
-        StorageDead(_23);
-        StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -173,35 +165,35 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _19 = move ((_17 as Some).0: &T);
-        StorageDead(_18);
-        StorageDead(_17);
-        _20 = copy (_15.1: usize);
-        _21 = AddWithOverflow(copy (_15.1: usize), const 1_usize);
-        assert(!move (_21.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_15.1: usize), const 1_usize) -> [success: bb9, unwind unreachable];
+        _17 = move ((_15 as Some).0: &T);
+        StorageDead(_16);
+        StorageDead(_15);
+        _18 = copy (_13.1: usize);
+        _19 = AddWithOverflow(copy (_13.1: usize), const 1_usize);
+        assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_13.1: usize), const 1_usize) -> [success: bb9, unwind unreachable];
     }
 
     bb9: {
-        (_15.1: usize) = move (_21.0: usize);
-        StorageLive(_22);
-        _22 = (copy _20, copy _19);
-        _23 = Option::<(usize, &T)>::Some(move _22);
-        StorageDead(_22);
-        StorageDead(_21);
+        (_13.1: usize) = move (_19.0: usize);
+        StorageLive(_20);
+        _20 = (copy _18, copy _17);
+        _21 = Option::<(usize, &T)>::Some(move _20);
         StorageDead(_20);
-        _24 = copy (((_23 as Some).0: (usize, &T)).0: usize);
-        _25 = copy (((_23 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_26);
-        _26 = &_2;
-        StorageLive(_27);
-        _27 = (copy _24, copy _25);
-        _28 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _26, move _27) -> [return: bb10, unwind unreachable];
+        StorageDead(_19);
+        StorageDead(_18);
+        _22 = copy (((_21 as Some).0: (usize, &T)).0: usize);
+        _23 = copy (((_21 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_24);
+        _24 = &_2;
+        StorageLive(_25);
+        _25 = (copy _22, copy _23);
+        _26 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _24, move _25) -> [return: bb10, unwind unreachable];
     }
 
     bb10: {
-        StorageDead(_27);
-        StorageDead(_26);
-        StorageDead(_23);
+        StorageDead(_25);
+        StorageDead(_24);
+        StorageDead(_21);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 2a837fabd4c..c1b846e662b 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -4,35 +4,34 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _17: std::option::Option<(usize, &T)>;
-    let mut _18: isize;
-    let mut _21: &impl Fn(usize, &T);
-    let mut _22: (usize, &T);
-    let _23: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _14: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _15: std::option::Option<(usize, &T)>;
+    let mut _16: isize;
+    let mut _19: &impl Fn(usize, &T);
+    let mut _20: (usize, &T);
+    let _21: ();
     scope 1 {
-        debug iter => _15;
-        let _19: usize;
-        let _20: &T;
+        debug iter => _13;
+        let _17: usize;
+        let _18: &T;
         scope 2 {
-            debug i => _19;
-            debug x => _20;
+            debug i => _17;
+            debug x => _18;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -48,8 +47,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -64,72 +62,66 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_13);
+        StorageLive(_11);
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_12);
-        _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
-        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _13, count: const 0_usize };
-        StorageDead(_13);
-        StorageLive(_15);
-        _15 = copy _14;
+        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = copy _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_17);
-        _16 = &mut _15;
-        _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind: bb11];
+        StorageLive(_15);
+        _14 = &mut _13;
+        _15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_17);
         StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -138,19 +130,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _19 = copy (((_17 as Some).0: (usize, &T)).0: usize);
-        _20 = copy (((_17 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_21);
-        _21 = &_2;
-        StorageLive(_22);
-        _22 = (copy _19, copy _20);
-        _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
+        _17 = copy (((_15 as Some).0: (usize, &T)).0: usize);
+        _18 = copy (((_15 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_19);
+        _19 = &_2;
+        StorageLive(_20);
+        _20 = (copy _17, copy _18);
+        _21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_17);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 063045caebb..8cebf2c6bac 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -4,32 +4,31 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::slice::Iter<'_, T>;
-    let mut _15: &mut std::slice::Iter<'_, T>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::slice::Iter<'_, T>;
+    let mut _13: &mut std::slice::Iter<'_, T>;
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _16;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -45,8 +44,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -58,68 +56,62 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
+        StorageDead(_3);
         StorageLive(_12);
         _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
-        StorageDead(_3);
-        StorageLive(_14);
-        _14 = copy _13;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
-        _15 = &mut _14;
-        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
+        StorageLive(_14);
+        _13 = &mut _12;
+        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
         StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -128,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = copy ((_16 as Some).0: &T);
-        StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (copy _18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
+        _16 = copy ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (copy _16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index d401ed8fcf3..e7e39240fed 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -4,32 +4,31 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::slice::Iter<'_, T>;
-    let mut _15: &mut std::slice::Iter<'_, T>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::slice::Iter<'_, T>;
+    let mut _13: &mut std::slice::Iter<'_, T>;
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _16;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -45,8 +44,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -58,68 +56,62 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
+        StorageDead(_3);
         StorageLive(_12);
         _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
-        StorageDead(_3);
-        StorageLive(_14);
-        _14 = copy _13;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
-        _15 = &mut _14;
-        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11];
+        StorageLive(_14);
+        _13 = &mut _12;
+        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
         StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -128,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = copy ((_16 as Some).0: &T);
-        StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (copy _18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
+        _16 = copy ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (copy _16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index deb12c4f1c2..58f95d0a432 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -4,35 +4,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _17: std::option::Option<&T>;
-    let mut _18: isize;
-    let mut _20: &impl Fn(&T);
-    let mut _21: (&T,);
-    let _22: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _15: std::option::Option<&T>;
+    let mut _16: isize;
+    let mut _18: &impl Fn(&T);
+    let mut _19: (&T,);
+    let _20: ();
     scope 1 {
-        debug iter => _15;
-        let _19: &T;
+        debug iter => _13;
+        let _17: &T;
         scope 2 {
-            debug x => _19;
+            debug x => _17;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _16: &mut std::slice::Iter<'_, T>;
+            let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -48,8 +47,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -64,74 +62,68 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_13);
+        StorageLive(_11);
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_12);
-        _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
-        _14 = Rev::<std::slice::Iter<'_, T>> { iter: copy _13 };
-        StorageDead(_13);
-        StorageLive(_15);
-        _15 = copy _14;
+        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = copy _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
-        _17 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind unreachable];
+        StorageLive(_15);
+        StorageLive(_14);
+        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
+        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_16);
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_17);
         StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -140,18 +132,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _19 = copy ((_17 as Some).0: &T);
-        StorageLive(_20);
-        _20 = &_2;
-        StorageLive(_21);
-        _21 = (copy _19,);
-        _22 = <impl Fn(&T) as Fn<(&T,)>>::call(move _20, move _21) -> [return: bb9, unwind unreachable];
+        _17 = copy ((_15 as Some).0: &T);
+        StorageLive(_18);
+        _18 = &_2;
+        StorageLive(_19);
+        _19 = (copy _17,);
+        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_21);
-        StorageDead(_20);
-        StorageDead(_17);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index acd5323eb7a..e7ddacf3144 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -4,35 +4,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _17: std::option::Option<&T>;
-    let mut _18: isize;
-    let mut _20: &impl Fn(&T);
-    let mut _21: (&T,);
-    let _22: ();
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _15: std::option::Option<&T>;
+    let mut _16: isize;
+    let mut _18: &impl Fn(&T);
+    let mut _19: (&T,);
+    let _20: ();
     scope 1 {
-        debug iter => _15;
-        let _19: &T;
+        debug iter => _13;
+        let _17: &T;
         scope 2 {
-            debug x => _19;
+            debug x => _17;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _16: &mut std::slice::Iter<'_, T>;
+            let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _5: std::ptr::NonNull<[T]>;
-            let mut _9: *mut T;
-            let mut _10: *mut T;
-            let mut _12: *const T;
+            let mut _7: *mut T;
+            let mut _8: *mut T;
+            let mut _10: *const T;
             scope 5 {
-                let _8: std::ptr::NonNull<T>;
+                let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _11: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -48,8 +47,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _6: *mut [T];
-                    let mut _7: *const T;
+                    let mut _5: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -64,74 +62,68 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_13);
+        StorageLive(_11);
         StorageLive(_3);
-        StorageLive(_8);
-        _3 = PtrMetadata(copy _1);
-        StorageLive(_5);
+        StorageLive(_6);
         StorageLive(_4);
+        _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
-        _5 = NonNull::<[T]> { pointer: move _4 };
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = copy _5 as *mut [T] (Transmute);
-        _7 = copy _6 as *const T (PtrToPtr);
-        _8 = NonNull::<T> { pointer: move _7 };
-        StorageDead(_7);
-        StorageDead(_6);
+        StorageLive(_5);
+        _5 = copy _4 as *const T (PtrToPtr);
+        _6 = NonNull::<T> { pointer: move _5 };
         StorageDead(_5);
-        StorageLive(_11);
+        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_9);
-        _9 = copy _8 as *mut T (Transmute);
-        _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
-        _11 = move _10 as *const T (PtrToPtr);
-        StorageDead(_10);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (PtrToPtr);
+        _8 = Offset(copy _7, copy _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PtrToPtr);
+        StorageDead(_8);
         goto -> bb3;
     }
 
     bb2: {
-        _11 = copy _3 as *const T (Transmute);
+        _9 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_12);
-        _12 = copy _11;
-        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_8);
+        StorageLive(_10);
+        _10 = copy _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_10);
+        StorageDead(_9);
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
-        _14 = Rev::<std::slice::Iter<'_, T>> { iter: copy _13 };
-        StorageDead(_13);
-        StorageLive(_15);
-        _15 = copy _14;
+        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = copy _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
-        _17 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11];
+        StorageLive(_15);
+        StorageLive(_14);
+        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
+        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_16);
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_17);
         StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -140,18 +132,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _19 = copy ((_17 as Some).0: &T);
-        StorageLive(_20);
-        _20 = &_2;
-        StorageLive(_21);
-        _21 = (copy _19,);
-        _22 = <impl Fn(&T) as Fn<(&T,)>>::call(move _20, move _21) -> [return: bb9, unwind: bb11];
+        _17 = copy ((_15 as Some).0: &T);
+        StorageLive(_18);
+        _18 = &_2;
+        StorageLive(_19);
+        _19 = (copy _17,);
+        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_21);
-        StorageDead(_20);
-        StorageDead(_17);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 3f0d60b46f4..927deabd253 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -7,20 +7,16 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _7: *const u8;
-            let mut _8: usize;
+            let mut _3: *const u8;
+            let mut _4: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    let mut _3: *mut u8;
-                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
                                     }
                                 }
@@ -34,9 +30,9 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _7;
-                debug len => _8;
-                let _9: *const [u8];
+                debug data => _3;
+                debug len => _4;
+                let _5: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -46,10 +42,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _7;
-                    debug len => _8;
+                    debug data => _3;
+                    debug len => _4;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _7;
+                        debug data_pointer => _3;
                     }
                 }
             }
@@ -57,31 +53,19 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_6);
-        StorageLive(_7);
-        StorageLive(_5);
         StorageLive(_2);
-        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+        _3 = copy _2 as *const u8 (Transmute);
         StorageLive(_4);
-        _3 = copy _2 as *mut u8 (Transmute);
-        _4 = copy _3 as *const u8 (PtrToPtr);
-        _5 = NonNull::<u8> { pointer: move _4 };
+        _4 = copy ((*_1).1: usize);
+        StorageLive(_5);
+        _5 = *const [u8] from (copy _3, copy _4);
+        _0 = &(*_5);
+        StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
         StorageDead(_2);
-        _6 = copy _5 as *mut u8 (Transmute);
-        StorageDead(_5);
-        _7 = copy _6 as *const u8 (PtrToPtr);
-        StorageLive(_8);
-        _8 = copy ((*_1).1: usize);
-        StorageLive(_9);
-        _9 = *const [u8] from (copy _7, copy _8);
-        _0 = &(*_9);
-        StorageDead(_9);
-        StorageDead(_8);
-        StorageDead(_7);
-        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 3f0d60b46f4..927deabd253 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -7,20 +7,16 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _7: *const u8;
-            let mut _8: usize;
+            let mut _3: *const u8;
+            let mut _4: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    let mut _3: *mut u8;
-                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
                                     }
                                 }
@@ -34,9 +30,9 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _7;
-                debug len => _8;
-                let _9: *const [u8];
+                debug data => _3;
+                debug len => _4;
+                let _5: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -46,10 +42,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _7;
-                    debug len => _8;
+                    debug data => _3;
+                    debug len => _4;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _7;
+                        debug data_pointer => _3;
                     }
                 }
             }
@@ -57,31 +53,19 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_6);
-        StorageLive(_7);
-        StorageLive(_5);
         StorageLive(_2);
-        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+        _3 = copy _2 as *const u8 (Transmute);
         StorageLive(_4);
-        _3 = copy _2 as *mut u8 (Transmute);
-        _4 = copy _3 as *const u8 (PtrToPtr);
-        _5 = NonNull::<u8> { pointer: move _4 };
+        _4 = copy ((*_1).1: usize);
+        StorageLive(_5);
+        _5 = *const [u8] from (copy _3, copy _4);
+        _0 = &(*_5);
+        StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
         StorageDead(_2);
-        _6 = copy _5 as *mut u8 (Transmute);
-        StorageDead(_5);
-        _7 = copy _6 as *const u8 (PtrToPtr);
-        StorageLive(_8);
-        _8 = copy ((*_1).1: usize);
-        StorageLive(_9);
-        _9 = *const [u8] from (copy _7, copy _8);
-        _0 = &(*_9);
-        StorageDead(_9);
-        StorageDead(_8);
-        StorageDead(_7);
-        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
index e9bbe30bd77..ee6e16d20fd 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
 
     bb7: {
         backward incompatible drop(_2);
+        backward incompatible drop(_4);
         backward incompatible drop(_5);
         goto -> bb21;
     }
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
index e9bbe30bd77..ee6e16d20fd 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
 
     bb7: {
         backward incompatible drop(_2);
+        backward incompatible drop(_4);
         backward incompatible drop(_5);
         goto -> bb21;
     }
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index e0dbecff8e5..d688bfbde2b 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:70:32
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:71:17
    |
-LL |         let test_one = test_fn(one);
-   |                        ------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
+LL |         assert!(test_one == (1, 1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `test_fn`
-  --> $DIR/fn_trait_refs.rs:35:24
-   |
-LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
-   |          ------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `test_fn`
-
-error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:73:36
-   |
-LL |         let test_two = test_fn_mut(two);
-   |                        ----------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
-   |
-note: required by a bound in `test_fn_mut`
-  --> $DIR/fn_trait_refs.rs:49:27
-   |
-LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
-   |          ----------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `test_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:39:19
-   |
-LL |         tester_fn(&f),
-   |         --------- ^^
-   |         |
-   |         required by a bound introduced by this call
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:74:17
    |
-note: required by a bound in `tester_fn`
-  --> $DIR/fn_trait_refs.rs:14:24
+LL |         assert!(test_two == (2, 2));
+   |                 ^^^^^^^^^^^^^^^^^^
    |
-LL | const fn tester_fn<T>(f: T) -> T::Output
-   |          --------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `tester_fn`
-
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:41:23
-   |
-LL |         tester_fn_mut(&f),
-   |         ------------- ^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
-
-error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:53:23
-   |
-LL |         tester_fn_mut(&mut f),
-   |         ------------- ^^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL |     f()
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 25 previous errors
+error: aborting due to 22 previous errors
 
-Some errors have detailed explanations: E0015, E0277, E0635.
+Some errors have detailed explanations: E0015, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr
index dd70bb601c4..40c6d083b06 100644
--- a/tests/ui/consts/promoted_const_call.stderr
+++ b/tests/ui/consts/promoted_const_call.stderr
@@ -5,6 +5,10 @@ LL |     let _: &'static _ = &id(&Panic);
    |                              ^^^^^ - value is dropped here
    |                              |
    |                              the destructor for this type cannot be evaluated in constants
+   |
+   = note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
+   = help: add `#![feature(const_destruct)]` 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[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_call.rs:16:26
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs
new file mode 100644
index 00000000000..6f64d83f8a0
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs
@@ -0,0 +1,51 @@
+// Edition 2024 lint for change in drop order at tail expression
+// This lint is to capture potential borrow-checking errors
+// due to implementation of RFC 3606 <https://github.com/rust-lang/rfcs/pull/3606>
+//@ edition: 2021
+
+#![deny(tail_expr_drop_order)] //~ NOTE: the lint level is defined here
+
+fn should_lint_with_potential_borrowck_err() {
+    let _ = { String::new().as_str() }.len();
+    //~^ ERROR: relative drop order changing
+    //~| WARN: this changes meaning in Rust 2024
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
+    //~| NOTE: for more information, see
+}
+
+fn should_lint_with_unsafe_block() {
+    fn f(_: usize) {}
+    f(unsafe { String::new().as_str() }.len());
+    //~^ ERROR: relative drop order changing
+    //~| WARN: this changes meaning in Rust 2024
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
+    //~| NOTE: for more information, see
+}
+
+#[rustfmt::skip]
+fn should_lint_with_big_block() {
+    fn f<T>(_: T) {}
+    f({
+        &mut || 0
+        //~^ ERROR: relative drop order changing
+        //~| WARN: this changes meaning in Rust 2024
+        //~| NOTE: this temporary value will be dropped at the end of the block
+        //~| borrow later used here
+        //~| NOTE: for more information, see
+    })
+}
+
+fn another_temp_that_is_copy_in_arg() {
+    fn f() {}
+    fn g(_: &()) {}
+    g({ &f() });
+    //~^ ERROR: relative drop order changing
+    //~| WARN: this changes meaning in Rust 2024
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
+    //~| NOTE: for more information, see
+}
+
+fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr
new file mode 100644
index 00000000000..a55e366dd0b
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr
@@ -0,0 +1,52 @@
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:15
+   |
+LL |     let _ = { String::new().as_str() }.len();
+   |               ^^^^^^^^^^^^^            --- borrow later used by call
+   |               |
+   |               this temporary value will be dropped at the end of the block
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: the lint level is defined here
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:6:9
+   |
+LL | #![deny(tail_expr_drop_order)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:19:16
+   |
+LL |     f(unsafe { String::new().as_str() }.len());
+   |                ^^^^^^^^^^^^^            --- borrow later used by call
+   |                |
+   |                this temporary value will be dropped at the end of the block
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:31:9
+   |
+LL |         &mut || 0
+   |         ^^^^^^^^^
+   |         |
+   |         this temporary value will be dropped at the end of the block
+   |         borrow later used here
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:43:9
+   |
+LL |     g({ &f() });
+   |     -   ^^^^ this temporary value will be dropped at the end of the block
+   |     |
+   |     borrow later used by call
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs
index b2a5db0d871..55a2d1d3b75 100644
--- a/tests/ui/drop/lint-tail-expr-drop-order.rs
+++ b/tests/ui/drop/lint-tail-expr-drop-order.rs
@@ -17,7 +17,6 @@ impl Drop for LoudDropper {
     //~| NOTE: `#1` invokes this custom destructor
     //~| NOTE: `x` invokes this custom destructor
     //~| NOTE: `#1` invokes this custom destructor
-    //~| NOTE: `future` invokes this custom destructor
     //~| NOTE: `_x` invokes this custom destructor
     //~| NOTE: `#1` invokes this custom destructor
     fn drop(&mut self) {
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr
index 92afae5af67..6ff9b7c1268 100644
--- a/tests/ui/drop/lint-tail-expr-drop-order.stderr
+++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr
@@ -1,5 +1,5 @@
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:41:15
+  --> $DIR/lint-tail-expr-drop-order.rs:40:15
    |
 LL |     let x = LoudDropper;
    |         -
@@ -40,7 +40,7 @@ LL | #![deny(tail_expr_drop_order)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:66:19
+  --> $DIR/lint-tail-expr-drop-order.rs:65:19
    |
 LL |         let x = LoudDropper;
    |             -
@@ -76,7 +76,7 @@ LL | | }
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:93:7
+  --> $DIR/lint-tail-expr-drop-order.rs:92:7
    |
 LL |     let x = LoudDropper;
    |         -
@@ -112,7 +112,7 @@ LL | | }
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:146:5
+  --> $DIR/lint-tail-expr-drop-order.rs:145:5
    |
 LL |     let future = f();
    |         ------
@@ -138,17 +138,10 @@ LL | / impl Drop for LoudDropper {
 ...  |
 LL | | }
    | |_^
-note: `future` invokes this custom destructor
-  --> $DIR/lint-tail-expr-drop-order.rs:10:1
-   |
-LL | / impl Drop for LoudDropper {
-...  |
-LL | | }
-   | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:163:14
+  --> $DIR/lint-tail-expr-drop-order.rs:162:14
    |
 LL |     let x = T::default();
    |         -
@@ -170,7 +163,7 @@ LL | }
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:177:5
+  --> $DIR/lint-tail-expr-drop-order.rs:176:5
    |
 LL |     let x: Result<LoudDropper, ()> = Ok(LoudDropper);
    |         -
@@ -206,7 +199,7 @@ LL | | }
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:221:5
+  --> $DIR/lint-tail-expr-drop-order.rs:220:5
    |
 LL |     let x = LoudDropper2;
    |         -
@@ -226,7 +219,7 @@ LL | }
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#1` invokes this custom destructor
-  --> $DIR/lint-tail-expr-drop-order.rs:194:5
+  --> $DIR/lint-tail-expr-drop-order.rs:193:5
    |
 LL | /     impl Drop for LoudDropper3 {
 LL | |
@@ -236,7 +229,7 @@ LL | |         }
 LL | |     }
    | |_____^
 note: `x` invokes this custom destructor
-  --> $DIR/lint-tail-expr-drop-order.rs:206:5
+  --> $DIR/lint-tail-expr-drop-order.rs:205:5
    |
 LL | /     impl Drop for LoudDropper2 {
 LL | |
@@ -248,7 +241,7 @@ LL | |     }
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 error: relative drop order changing in Rust 2024
-  --> $DIR/lint-tail-expr-drop-order.rs:234:13
+  --> $DIR/lint-tail-expr-drop-order.rs:233:13
    |
 LL |             LoudDropper.get()
    |             ^^^^^^^^^^^
diff --git a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr
index d98100bc1b0..b0f971dd5ce 100644
--- a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr
+++ b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr
@@ -4,10 +4,14 @@ error: relative drop order changing in Rust 2024
 LL |         match func().await {
    |               ^^^^^^^-----
    |               |      |
+   |               |      this value will be stored in a temporary; let us call it `#3`
+   |               |      up until Edition 2021 `#3` is dropped last but will be dropped earlier in Edition 2024
    |               |      this value will be stored in a temporary; let us call it `#1`
    |               |      `#1` will be dropped later as of Edition 2024
    |               this value will be stored in a temporary; let us call it `#2`
    |               up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024
+   |               `__awaitee` calls a custom destructor
+   |               `__awaitee` will be dropped later as of Edition 2024
 ...
 LL |             Err(e) => {}
    |                 -
diff --git a/tests/ui/drop/tail_expr_drop_order-on-recursive-boxed-fut.rs b/tests/ui/drop/tail_expr_drop_order-on-recursive-boxed-fut.rs
new file mode 100644
index 00000000000..4a72f224d94
--- /dev/null
+++ b/tests/ui/drop/tail_expr_drop_order-on-recursive-boxed-fut.rs
@@ -0,0 +1,13 @@
+//@ edition: 2021
+//@ check-pass
+
+// Make sure we don't cycle error when normalizing types for tail expr drop order lint.
+
+#![deny(tail_expr_drop_order)]
+
+async fn test() -> Result<(), Box<dyn std::error::Error>> {
+    Box::pin(test()).await?;
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/drop/tail_expr_drop_order-on-thread-local.rs b/tests/ui/drop/tail_expr_drop_order-on-thread-local.rs
new file mode 100644
index 00000000000..e38175fd1b6
--- /dev/null
+++ b/tests/ui/drop/tail_expr_drop_order-on-thread-local.rs
@@ -0,0 +1,56 @@
+//@ check-pass
+
+#![feature(thread_local)]
+#![deny(tail_expr_drop_order)]
+
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
+
+pub struct Global;
+
+#[thread_local]
+static REENTRANCY_STATE: State<Global> = State { marker: PhantomData, controller: Global };
+
+pub struct Token(PhantomData<*mut ()>);
+
+pub fn with_mut<T>(f: impl FnOnce(&mut Token) -> T) -> T {
+    f(&mut REENTRANCY_STATE.borrow_mut())
+}
+
+pub struct State<T: ?Sized = Global> {
+    marker: PhantomData<*mut ()>,
+    controller: T,
+}
+
+impl<T: ?Sized> State<T> {
+    pub fn borrow_mut(&self) -> TokenMut<'_, T> {
+        todo!()
+    }
+}
+
+pub struct TokenMut<'a, T: ?Sized = Global> {
+    state: &'a State<T>,
+    token: Token,
+}
+
+impl<T> Deref for TokenMut<'_, T> {
+    type Target = Token;
+
+    fn deref(&self) -> &Self::Target {
+        todo!()
+    }
+}
+
+impl<T> DerefMut for TokenMut<'_, T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        todo!()
+    }
+}
+
+impl<T: ?Sized> Drop for TokenMut<'_, T> {
+    fn drop(&mut self) {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 0f79cefeaec..f4e8a872cec 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
-  --> $DIR/normalize-tait-in-const.rs:33:19
-   |
-LL |     with_positive(foo);
-   |     ------------- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `with_positive`
-  --> $DIR/normalize-tait-in-const.rs:26:62
-   |
-LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
-   |                                                              ^^^^^^ required by this bound in `with_positive`
-
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:27:5
    |
@@ -39,7 +25,6 @@ LL |     fun(filter_positive());
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs
index 42bd72cbfbf..bc7a0bc46c3 100644
--- a/tests/ui/invalid-compile-flags/crate-type-flag.rs
+++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs
@@ -30,6 +30,7 @@
 //@[bin] check-pass
 
 //@[proc_dash_macro] ignore-wasm (proc-macro is not supported)
+//@[proc_dash_macro] needs-unwind (panic=abort causes warning to be emitted)
 //@[proc_dash_macro] compile-flags: --crate-type=proc-macro
 //@[proc_dash_macro] check-pass
 
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index a560bf4c6ef..40033f546d3 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -569,7 +569,7 @@ fn test_pat() {
     c1!(pat, [ &pat ], "&pat");
     c1!(pat, [ &mut pat ], "&mut pat");
 
-    // PatKind::Lit
+    // PatKind::Expr
     c1!(pat, [ 1_000_i8 ], "1_000_i8");
 
     // PatKind::Range
diff --git a/tests/ui/pattern/patkind-litrange-no-expr.rs b/tests/ui/pattern/patkind-litrange-no-expr.rs
index 7ef541cb585..14d7dc737d6 100644
--- a/tests/ui/pattern/patkind-litrange-no-expr.rs
+++ b/tests/ui/pattern/patkind-litrange-no-expr.rs
@@ -6,7 +6,7 @@ macro_rules! enum_number {
 
         fn foo(value: i32) -> Option<$name> {
             match value {
-                $( $value => Some($name::$variant), )* // PatKind::Lit
+                $( $value => Some($name::$variant), )* // PatKind::Expr
                 $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
                 _ => None
             }
diff --git a/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs
new file mode 100644
index 00000000000..17a5bad0e6c
--- /dev/null
+++ b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs
@@ -0,0 +1,10 @@
+// Regression test for #135209.
+// We ensure that we don't try to access fields on a non-struct pattern type.
+fn main() {
+    if let <Vec<()> as Iterator>::Item { .. } = 1 {
+        //~^ ERROR E0658
+        //~| ERROR E0071
+        //~| ERROR E0277
+        x //~ ERROR E0425
+    }
+}
diff --git a/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr
new file mode 100644
index 00000000000..793c2d1e97f
--- /dev/null
+++ b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr
@@ -0,0 +1,34 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:8:9
+   |
+LL |         x
+   |         ^ not found in this scope
+
+error[E0658]: usage of qualified paths in this context is experimental
+  --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12
+   |
+LL |     if let <Vec<()> as Iterator>::Item { .. } = 1 {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
+   = help: add `#![feature(more_qualified_paths)]` 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[E0071]: expected struct, variant or union type, found inferred type
+  --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12
+   |
+LL |     if let <Vec<()> as Iterator>::Item { .. } = 1 {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a struct
+
+error[E0277]: `Vec<()>` is not an iterator
+  --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12
+   |
+LL |     if let <Vec<()> as Iterator>::Item { .. } = 1 {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Vec<()>` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `Vec<()>`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0071, E0277, E0425, E0658.
+For more information about an error, try `rustc --explain E0071`.
diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs
index 225891e390f..39f9f5a2c02 100644
--- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs
+++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs
@@ -3,6 +3,10 @@ struct Website {
     title: Option<String>,
 }
 
+enum Foo {
+    Bar { a: i32 },
+}
+
 fn main() {
     let website = Website {
         url: "http://www.example.com".into(),
@@ -18,4 +22,9 @@ fn main() {
         println!("[{}]({})", title, url); //~ ERROR cannot find value `title` in this scope
         //~^ NOTE not found in this scope
     }
+
+    let x = Foo::Bar { a: 1 };
+    if let Foo::Bar { .. } = x { //~ NOTE this pattern
+        println!("{a}"); //~ ERROR cannot find value `a` in this scope
+    }
 }
diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr
index 80fcd714400..b985b771754 100644
--- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr
+++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr
@@ -1,5 +1,5 @@
 error: expected `,`
-  --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:12:31
+  --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:16:31
    |
 LL |     if let Website { url, Some(title) } = website {
    |            -------            ^
@@ -7,13 +7,21 @@ LL |     if let Website { url, Some(title) } = website {
    |            while parsing the fields for this pattern
 
 error[E0425]: cannot find value `title` in this scope
-  --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:18:30
+  --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:22:30
    |
 LL |     if let Website { url, .. } = website {
    |            ------------------- this pattern doesn't include `title`, which is available in `Website`
 LL |         println!("[{}]({})", title, url);
    |                              ^^^^^ not found in this scope
 
-error: aborting due to 2 previous errors
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:28:20
+   |
+LL |     if let Foo::Bar { .. } = x {
+   |            --------------- this pattern doesn't include `a`, which is available in `Bar`
+LL |         println!("{a}");
+   |                    ^ help: a local variable with a similar name exists: `x`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
new file mode 100644
index 00000000000..c76e7a1d716
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
@@ -0,0 +1,70 @@
+#[derive(Copy, Clone)]
+struct Type;
+
+struct NewType;
+
+const fn get_size() -> usize {
+    10
+}
+
+fn get_dyn_size() -> usize {
+    10
+}
+
+fn main() {
+    let a = ["a", 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    const size_b: usize = 20;
+    let b = [Type, size_b];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let size_c: usize = 13;
+    let c = [Type, size_c];
+    //~^ ERROR mismatched types
+
+    const size_d: bool = true;
+    let d = [Type, size_d];
+    //~^ ERROR mismatched types
+
+    let e = [String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP try using a conversion method
+
+    let f = ["f", get_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let m = ["m", get_dyn_size()];
+    //~^ ERROR mismatched types
+
+    // is_vec, is_clone, is_usize_like
+    let g = vec![String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let dyn_size = 10;
+    let h = vec![Type, dyn_size];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let i = vec![Type, get_dyn_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let k = vec!['c', 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let j = vec![Type, 10_u8];
+    //~^ ERROR mismatched types
+
+    let l = vec![NewType, 10];
+    //~^ ERROR mismatched types
+
+    let byte_size: u8 = 10;
+    let h = vec![Type, byte_size];
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
new file mode 100644
index 00000000000..95eddbde9e6
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
@@ -0,0 +1,124 @@
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:15:19
+   |
+LL |     let a = ["a", 10];
+   |                   ^^ expected `&str`, found integer
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let a = ["a"; 10];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:20:20
+   |
+LL |     let b = [Type, size_b];
+   |                    ^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let b = [Type; size_b];
+   |                  ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:25:20
+   |
+LL |     let c = [Type, size_c];
+   |                    ^^^^^^ expected `Type`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:29:20
+   |
+LL |     let d = [Type, size_d];
+   |                    ^^^^^^ expected `Type`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:32:29
+   |
+LL |     let e = [String::new(), 10];
+   |                             ^^- help: try using a conversion method: `.to_string()`
+   |                             |
+   |                             expected `String`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:36:19
+   |
+LL |     let f = ["f", get_size()];
+   |                   ^^^^^^^^^^ expected `&str`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let f = ["f"; get_size()];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:40:19
+   |
+LL |     let m = ["m", get_dyn_size()];
+   |                   ^^^^^^^^^^^^^^ expected `&str`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:44:33
+   |
+LL |     let g = vec![String::new(), 10];
+   |                                 ^^ expected `String`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let g = vec![String::new(); 10];
+   |                               ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:49:24
+   |
+LL |     let h = vec![Type, dyn_size];
+   |                        ^^^^^^^^ expected `Type`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let h = vec![Type; dyn_size];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:53:24
+   |
+LL |     let i = vec![Type, get_dyn_size()];
+   |                        ^^^^^^^^^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let i = vec![Type; get_dyn_size()];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:57:23
+   |
+LL |     let k = vec!['c', 10];
+   |                       ^^ expected `char`, found `u8`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let k = vec!['c'; 10];
+   |                     ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:61:24
+   |
+LL |     let j = vec![Type, 10_u8];
+   |                        ^^^^^ expected `Type`, found `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:64:27
+   |
+LL |     let l = vec![NewType, 10];
+   |                           ^^ expected `NewType`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:68:24
+   |
+LL |     let h = vec![Type, byte_size];
+   |                        ^^^^^^^^^ expected `Type`, found `u8`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs
index 398fb390640..4819da7c3a4 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.rs
+++ b/tests/ui/traits/const-traits/const-drop-bound.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(const_precise_live_drops, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
deleted file mode 100644
index 78ba0279566..00000000000
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Foo<E>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-bound.rs:23:9
-   |
-LL |     foo(res)
-   |     --- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/const-drop-bound.rs:9:61
-   |
-LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
-   |                                                             ^^^^^^ required by this bound in `foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs
index 5e05b9db474..a7f3d5654de 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.rs
+++ b/tests/ui/traits/const-traits/const-drop-fail.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -Znext-solver
-//@ revisions: stock precise
+//@[new_precise] compile-flags: -Znext-solver
+//@[new_stock] compile-flags: -Znext-solver
+//@ revisions: new_stock old_stock new_precise old_precise
 
 #![feature(const_trait_impl, const_destruct)]
-#![cfg_attr(precise, feature(const_precise_live_drops))]
+#![cfg_attr(any(new_precise, old_precise), feature(const_precise_live_drops))]
 
 use std::marker::{Destruct, PhantomData};
 
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index e052627e71c..26c253d049b 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -651,8 +651,8 @@ mod patterns {
         let &mut pat;
     }
 
-    /// PatKind::Lit
-    fn pat_lit() {
+    /// PatKind::Expr
+    fn pat_expr() {
         let 1_000_i8;
         let -"";
     }
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 132d00cd8ed..bd7aa1117cc 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -567,8 +567,8 @@ mod patterns {
     fn pat_deref() { let deref!(pat); }
     /// PatKind::Ref
     fn pat_ref() { let &pat; let &mut pat; }
-    /// PatKind::Lit
-    fn pat_lit() { let 1_000_i8; let -""; }
+    /// PatKind::Expr
+    fn pat_expr() { let 1_000_i8; let -""; }
     /// PatKind::Range
     fn pat_range() { let ..1; let 0..; let 0..1; let 0..=1; let -2..=-1; }
     /// PatKind::Slice
diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
index c424b1afa34..43aa93c83bd 100644
--- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
+++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
@@ -14,4 +14,4 @@ extern crate std;
 
 fn main() ({ } as ())
 
-fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ())
+fn foo(-128...127: i8) ({ } as ())
diff --git a/triagebot.toml b/triagebot.toml
index 7241b448c48..67412d9e60b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -420,13 +420,20 @@ trigger_files = [
 
 [autolabel."A-testsuite"]
 trigger_files = [
+    "src/bootstrap/src/core/build_steps/test.rs",
     "src/ci",
-    "src/tools/compiletest",
     "src/tools/cargotest",
-    "src/tools/tidy",
+    "src/tools/compiletest",
+    "src/tools/miropt-test-tools",
     "src/tools/remote-test-server",
     "src/tools/remote-test-client",
-    "src/tools/tier-check"
+    "src/tools/rustdoc-gui-test",
+    "src/tools/suggest-tests",
+]
+
+[autolabel."A-tidy"]
+trigger_files = [
+    "src/tools/tidy",
 ]
 
 [autolabel."A-meta"]