about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock311
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs6
-rw-r--r--compiler/rustc_ast/src/util/parser.rs4
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs20
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs20
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs27
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs4
-rw-r--r--compiler/rustc_borrowck/src/nll.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs3
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl5
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs97
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/offset_of.rs99
-rw-r--r--compiler/rustc_codegen_cranelift/example/alloc_example.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs5
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_example.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/allocator.rs34
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs48
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs19
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs62
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml1
-rw-r--r--compiler/rustc_hir/src/hir.rs7
-rw-r--r--compiler/rustc_hir/src/intravisit.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs106
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs25
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs21
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp16
-rw-r--r--compiler/rustc_metadata/messages.ftl10
-rw-r--r--compiler/rustc_metadata/src/creader.rs68
-rw-r--r--compiler/rustc_metadata/src/errors.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs13
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs4
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs85
-rw-r--r--compiler/rustc_middle/src/thir.rs7
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs11
-rw-r--r--compiler/rustc_middle/src/ty/context.rs16
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs33
-rw-r--r--compiler/rustc_middle/src/ty/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs12
-rw-r--r--compiler/rustc_middle/src/values.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/category.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs7
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs13
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs2
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs5
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs7
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs34
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs12
-rw-r--r--compiler/rustc_mir_transform/src/remove_place_mention.rs23
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs3
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs10
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs13
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs98
-rw-r--r--compiler/rustc_passes/src/dead.rs34
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs5
-rw-r--r--compiler/rustc_passes/src/liveness.rs32
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs1
-rw-r--r--compiler/rustc_session/src/config.rs6
-rw-r--r--compiler/rustc_session/src/options.rs5
-rw-r--r--compiler/rustc_span/src/span_encoding.rs24
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs15
-rw-r--r--compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs15
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs10
-rw-r--r--library/alloc/Cargo.toml3
-rw-r--r--library/alloc/src/alloc.rs94
-rw-r--r--library/alloc/src/boxed/thin.rs10
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/vec/drain.rs4
-rw-r--r--library/alloc/src/vec/drain_filter.rs6
-rw-r--r--library/core/src/macros/mod.rs10
-rw-r--r--library/core/src/mem/mod.rs42
-rw-r--r--library/core/src/prelude/v1.rs4
-rw-r--r--library/core/src/slice/iter/macros.rs2
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/mem.rs190
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/alloc.rs73
-rw-r--r--library/std/src/fs.rs40
-rw-r--r--library/std/src/io/mod.rs24
-rw-r--r--library/std/src/io/tests.rs2
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/panicking.rs43
-rw-r--r--library/std/src/prelude/v1.rs4
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs1
-rw-r--r--src/librustdoc/html/render/print_item.rs118
-rw-r--r--src/librustdoc/html/render/type_layout.rs86
-rw-r--r--src/librustdoc/html/static/js/main.js11
-rw-r--r--src/librustdoc/html/static/js/search.js4
-rw-r--r--src/librustdoc/html/static/js/source-script.js2
-rw-r--r--src/librustdoc/html/templates/type_layout.html53
-rw-r--r--src/librustdoc/html/templates/type_layout_size.html12
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs1
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr8
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs13
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs4
-rw-r--r--src/tools/rustfmt/src/expr.rs4
-rw-r--r--src/tools/rustfmt/src/utils.rs1
-rw-r--r--src/tools/tidy/src/deps.rs9
-rw-r--r--tests/codegen/debuginfo-constant-locals.rs28
-rw-r--r--tests/debuginfo/auxiliary/macro-stepping.rs2
-rw-r--r--tests/debuginfo/macro-stepping.rs20
-rw-r--r--tests/incremental/hashes/enum_constructors.rs4
-rw-r--r--tests/incremental/hashes/let_expressions.rs12
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir6
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff6
-rw-r--r--tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff43
-rw-r--r--tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff39
-rw-r--r--tests/mir-opt/const_prop/offset_of.rs49
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir13
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir13
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir13
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir13
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff129
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir120
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff129
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir120
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir35
-rw-r--r--tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir9
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt6
-rw-r--r--tests/run-make/issue-51671/Makefile1
-rw-r--r--tests/run-make/issue-51671/app.rs7
-rw-r--r--tests/run-make/issue-69368/Makefile19
-rw-r--r--tests/run-make/issue-69368/a.rs26
-rw-r--r--tests/run-make/issue-69368/b.rs8
-rw-r--r--tests/run-make/issue-69368/c.rs34
-rw-r--r--tests/run-make/wasm-symbols-not-exported/bar.rs7
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs18
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr44
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs17
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr50
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs15
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr21
-rw-r--r--tests/ui/alloc-error/default-alloc-error-hook.rs4
-rw-r--r--tests/ui/allocator/no_std-alloc-error-handler-custom.rs84
-rw-r--r--tests/ui/associated-inherent-types/bugs/ice-substitution.stderr2
-rw-r--r--tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr32
-rw-r--r--tests/ui/borrowck/let_underscore_temporary.rs30
-rw-r--r--tests/ui/borrowck/let_underscore_temporary.stderr79
-rw-r--r--tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr28
-rw-r--r--tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs1
-rw-r--r--tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs8
-rw-r--r--tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr21
-rw-r--r--tests/ui/feature-gates/feature-gate-alloc-error-handler.rs16
-rw-r--r--tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr12
-rw-r--r--tests/ui/generics/auxiliary/foreign-generic-mismatch.rs3
-rw-r--r--tests/ui/generics/foreign-generic-mismatch.rs10
-rw-r--r--tests/ui/generics/foreign-generic-mismatch.stderr35
-rw-r--r--tests/ui/lint/dead-code/offset-of-correct-param-env.rs42
-rw-r--r--tests/ui/lint/dead-code/offset-of.rs44
-rw-r--r--tests/ui/lint/dead-code/offset-of.stderr50
-rw-r--r--tests/ui/lint/lint-uppercase-variables.stderr12
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr24
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr12
-rw-r--r--tests/ui/lint/unused/lint-unused-variables.stderr12
-rw-r--r--tests/ui/liveness/liveness-consts.stderr53
-rw-r--r--tests/ui/macros/user-defined-macro-rules.rs (renamed from tests/ui/user-defined-macro-rules.rs)0
-rw-r--r--tests/ui/missing/missing-allocator.rs6
-rw-r--r--tests/ui/offset-of/auxiliary/offset-of-staged-api.rs33
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.rs9
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.stderr20
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.rs33
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr27
-rw-r--r--tests/ui/offset-of/offset-of-enum.rs13
-rw-r--r--tests/ui/offset-of/offset-of-enum.stderr19
-rw-r--r--tests/ui/offset-of/offset-of-private.rs16
-rw-r--r--tests/ui/offset-of/offset-of-private.stderr9
-rw-r--r--tests/ui/offset-of/offset-of-unstable-with-feature.rs20
-rw-r--r--tests/ui/offset-of/offset-of-unstable.rs31
-rw-r--r--tests/ui/offset-of/offset-of-unstable.stderr79
-rw-r--r--tests/ui/oom_unwind.rs2
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr16
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr144
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr84
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr82
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr88
-rw-r--r--tests/ui/privacy/privacy2.stderr8
-rw-r--r--tests/ui/privacy/privacy3.stderr8
-rw-r--r--tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr12
-rw-r--r--tests/ui/span/send-is-not-static-std-sync-2.stderr2
-rw-r--r--tests/ui/traits/new-solver/borrowck-error.rs11
-rw-r--r--tests/ui/traits/new-solver/borrowck-error.stderr12
254 files changed, 3364 insertions, 1905 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3f2dab5e635..5ef801cb623 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -79,6 +79,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
 name = "annotate-snippets"
 version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -307,6 +316,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+
+[[package]]
 name = "bytecount"
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -456,15 +471,14 @@ dependencies = [
 
 [[package]]
 name = "chrono"
-version = "0.4.19"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
- "libc",
+ "iana-time-zone",
  "num-integer",
  "num-traits",
  "serde",
- "time",
  "winapi",
 ]
 
@@ -638,6 +652,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
 name = "collect-license-metadata"
 version = "0.1.0"
 dependencies = [
@@ -717,7 +741,7 @@ dependencies = [
  "tracing-subscriber",
  "unified-diff",
  "walkdir",
- "windows",
+ "windows 0.46.0",
 ]
 
 [[package]]
@@ -773,6 +797,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
 name = "coverage_test_macros"
 version = "0.0.0"
 
@@ -888,6 +918,50 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxx"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn 2.0.8",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.8",
+]
+
+[[package]]
 name = "datafrog"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1556,6 +1630,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"
 
 [[package]]
+name = "iana-time-zone"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows 0.48.0",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
 name = "icu_list"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1779,6 +1877,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
 name = "jsondocck"
 version = "0.1.0"
 dependencies = [
@@ -1886,6 +1993,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
+[[package]]
 name = "linkchecker"
 version = "0.1.0"
 dependencies = [
@@ -3192,7 +3308,7 @@ dependencies = [
  "tempfile",
  "thin-vec",
  "tracing",
- "windows",
+ "windows 0.46.0",
 ]
 
 [[package]]
@@ -3252,7 +3368,7 @@ dependencies = [
  "rustc_ty_utils",
  "serde_json",
  "tracing",
- "windows",
+ "windows 0.46.0",
 ]
 
 [[package]]
@@ -3302,7 +3418,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "windows",
+ "windows 0.46.0",
 ]
 
 [[package]]
@@ -3348,7 +3464,6 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 2.0.8",
- "synstructure 0.13.0",
  "unic-langid",
 ]
 
@@ -3974,7 +4089,7 @@ dependencies = [
  "smallvec",
  "termize",
  "tracing",
- "windows",
+ "windows 0.46.0",
 ]
 
 [[package]]
@@ -4303,6 +4418,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
+name = "scratch"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
+
+[[package]]
 name = "self_cell"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4440,9 +4561,9 @@ dependencies = [
 
 [[package]]
 name = "spdx-rs"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3"
+checksum = "6b1ec09829bf2d82c175c121b20de11ffab2def83bd55979002099b1f9956c9b"
 dependencies = [
  "chrono",
  "log",
@@ -4807,16 +4928,6 @@ name = "tier-check"
 version = "0.1.0"
 
 [[package]]
-name = "time"
-version = "0.1.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
 name = "tinystr"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5240,9 +5351,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
 name = "uuid"
-version = "0.8.2"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
 dependencies = [
  "getrandom",
 ]
@@ -5288,6 +5399,60 @@ dependencies = [
 ]
 
 [[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5324,7 +5489,16 @@ version = "0.46.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+dependencies = [
+ "windows-targets 0.48.0",
 ]
 
 [[package]]
@@ -5333,13 +5507,13 @@ version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
 ]
 
 [[package]]
@@ -5348,7 +5522,7 @@ version = "0.45.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.42.2",
 ]
 
 [[package]]
@@ -5357,13 +5531,28 @@ version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
 ]
 
 [[package]]
@@ -5373,42 +5562,84 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
 
 [[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
 name = "writeable"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ab0409efb3b..1e4d3ba47f4 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1271,6 +1271,7 @@ impl Expr {
             ExprKind::Continue(..) => ExprPrecedence::Continue,
             ExprKind::Ret(..) => ExprPrecedence::Ret,
             ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf,
             ExprKind::MacCall(..) => ExprPrecedence::Mac,
             ExprKind::Struct(..) => ExprPrecedence::Struct,
             ExprKind::Repeat(..) => ExprPrecedence::Repeat,
@@ -1469,6 +1470,9 @@ pub enum ExprKind {
     /// Output of the `asm!()` macro.
     InlineAsm(P<InlineAsm>),
 
+    /// Output of the `offset_of!()` macro.
+    OffsetOf(P<Ty>, P<[Ident]>),
+
     /// A macro invocation; pre-expansion.
     MacCall(P<MacCall>),
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 694d31d8f1f..99f1f4bd968 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1456,6 +1456,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
         }
         ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
         ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
+        ExprKind::OffsetOf(container, fields) => {
+            vis.visit_ty(container);
+            for field in fields.iter_mut() {
+                vis.visit_ident(field);
+            }
+        }
         ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
         ExprKind::Struct(se) => {
             let StructExpr { qself, path, fields, rest } = se.deref_mut();
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 3893875e9a4..24b4bd8623f 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -269,6 +269,7 @@ pub enum ExprPrecedence {
     Index,
     Try,
     InlineAsm,
+    OffsetOf,
     Mac,
     FormatArgs,
 
@@ -335,7 +336,8 @@ impl ExprPrecedence {
             | ExprPrecedence::Try
             | ExprPrecedence::InlineAsm
             | ExprPrecedence::Mac
-            | ExprPrecedence::FormatArgs => PREC_POSTFIX,
+            | ExprPrecedence::FormatArgs
+            | ExprPrecedence::OffsetOf => PREC_POSTFIX,
 
             // Never need parens
             ExprPrecedence::Array
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ac9b321b71c..8a6b5d5c905 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -909,6 +909,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
         ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
         ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
+        ExprKind::OffsetOf(container, fields) => {
+            visitor.visit_ty(container);
+            for &field in fields {
+                visitor.visit_ident(field);
+            }
+        }
         ExprKind::Yield(optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 0d212b3e130..6863100d9ba 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -289,6 +289,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
                 }
                 ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
+                ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
+                    self.lower_ty(
+                        container,
+                        &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
+                    ),
+                    self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
+                ),
                 ExprKind::Struct(se) => {
                     let rest = match &se.rest {
                         StructRest::Base(e) => Some(self.lower_expr(e)),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index bfd9956b004..c969d709608 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -283,6 +283,7 @@ enum ImplTraitPosition {
     FieldTy,
     Cast,
     ImplSelf,
+    OffsetOf,
 }
 
 impl std::fmt::Display for ImplTraitPosition {
@@ -313,6 +314,7 @@ impl std::fmt::Display for ImplTraitPosition {
             ImplTraitPosition::FieldTy => "field types",
             ImplTraitPosition::Cast => "cast types",
             ImplTraitPosition::ImplSelf => "impl headers",
+            ImplTraitPosition::OffsetOf => "`offset_of!` params",
         };
 
         write!(f, "{name}")
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 776bf54244e..aeb0c762020 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -549,6 +549,26 @@ impl<'a> State<'a> {
                 self.end();
                 self.pclose();
             }
+            ast::ExprKind::OffsetOf(container, fields) => {
+                // FIXME: This should have its own syntax, distinct from a macro invocation.
+                self.word("offset_of!");
+                self.popen();
+                self.rbox(0, Inconsistent);
+                self.print_type(container);
+                self.word(",");
+                self.space();
+
+                if let Some((&first, rest)) = fields.split_first() {
+                    self.print_ident(first);
+
+                    for &field in rest {
+                        self.word(".");
+                        self.print_ident(field);
+                    }
+                }
+
+                self.end();
+            }
             ast::ExprKind::MacCall(m) => self.print_mac(m),
             ast::ExprKind::Paren(e) => {
                 self.popen();
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 9e9f0b4b4ad..6259722b694 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -52,12 +52,16 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
 
+        // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
+        // contain dangling references.
+        PlaceContext::NonUse(NonUseContext::PlaceMention) |
+        PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
+
         PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
-        PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
         PlaceContext::MutatingUse(MutatingUseContext::Retag) =>
             Some(DefUse::Use),
 
@@ -72,8 +76,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
             Some(DefUse::Drop),
 
-        // This statement exists to help unsafeck. It does not require the place to be live.
-        PlaceContext::NonUse(NonUseContext::PlaceMention) => None,
         // Debug info is neither def nor use.
         PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 2320901a053..8dd03aaa72d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -10,7 +10,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::tcx::PlaceTy;
@@ -643,11 +642,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
                 return false;
             };
-            // Regions are already solved, so we must use a fresh InferCtxt,
-            // but the type has region variables, so erase those.
-            tcx.infer_ctxt()
-                .build()
-                .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env)
+            self.infcx
+                .type_implements_trait(default_trait, [ty], param_env)
                 .must_apply_modulo_regions()
         };
 
@@ -740,13 +736,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
         let tcx = self.infcx.tcx;
         // Try to find predicates on *generic params* that would allow copying `ty`
-        let infcx = tcx.infer_ctxt().build();
-
         if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
-            && infcx
+            && self.infcx
                 .type_implements_trait(
                     clone_trait_def,
-                    [tcx.erase_regions(ty)],
+                    [ty],
                     self.param_env,
                 )
                 .must_apply_modulo_regions()
@@ -770,12 +764,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             .and_then(|def_id| tcx.hir().get_generics(def_id))
         else { return; };
         // Try to find predicates on *generic params* that would allow copying `ty`
-        let infcx = tcx.infer_ctxt().build();
-        let ocx = ObligationCtxt::new(&infcx);
+        let ocx = ObligationCtxt::new(&self.infcx);
         let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
         let cause = ObligationCause::misc(span, self.mir_def_id());
 
-        ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did);
+        ocx.register_bound(cause, self.param_env, ty, copy_did);
         let errors = ocx.select_all_or_error();
 
         // Only emit suggestion if all required predicates are on generic
@@ -2219,7 +2212,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let tcx = self.infcx.tcx;
 
             let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
-            let return_ty = tcx.erase_regions(return_ty);
 
             // to avoid panics
             if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 4a85df9f8c0..299d04c4fb6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::GeneratorKind;
 use rustc_index::vec::IndexSlice;
-use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
+use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
@@ -1042,15 +1042,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
                         let ty = moved_place.ty(self.body, tcx).ty;
                         let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
-                            Some(def_id) => {
-                                let infcx = self.infcx.tcx.infer_ctxt().build();
-                                type_known_to_meet_bound_modulo_regions(
-                                    &infcx,
-                                    self.param_env,
-                                    tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
-                                    def_id,
-                                )
-                            }
+                            Some(def_id) => type_known_to_meet_bound_modulo_regions(
+                                &self.infcx,
+                                self.param_env,
+                                tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty),
+                                def_id,
+                            ),
                             _ => false,
                         };
                         if suggest {
@@ -1094,20 +1091,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             is_partial,
                             is_loop_message,
                         });
-                        let infcx = tcx.infer_ctxt().build();
                         // Erase and shadow everything that could be passed to the new infcx.
-                        let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
-                        let method_substs = tcx.erase_regions(method_substs);
+                        let ty = moved_place.ty(self.body, tcx).ty;
 
                         if let ty::Adt(def, substs) = ty.kind()
                             && Some(def.did()) == tcx.lang_items().pin_type()
                             && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
-                            && let self_ty = infcx.instantiate_binder_with_fresh_vars(
+                            && let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
                                 fn_call_span,
                                 LateBoundRegionConversionTime::FnCall,
                                 tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
                             )
-                            && infcx.can_eq(self.param_env, ty, self_ty)
+                            && self.infcx.can_eq(self.param_env, ty, self_ty)
                         {
                             err.eager_subdiagnostic(
                                 &self.infcx.tcx.sess.parse_sess.span_diagnostic,
@@ -1123,7 +1118,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 self.param_env,
                                 ty::Binder::dummy(trait_ref),
                             )
-                            && infcx.predicate_must_hold_modulo_regions(&o)
+                            && self.infcx.predicate_must_hold_modulo_regions(&o)
                         {
                             err.span_suggestion_verbose(
                                 fn_call_span.shrink_to_lo(),
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 498d254da65..06986f848bf 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -79,7 +79,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             // Only relevant for mir typeck
             StatementKind::AscribeUserType(..)
-            // Only relevant for unsafeck
+            // Only relevant for liveness and unsafeck
             | StatementKind::PlaceMention(..)
             // Doesn't have any language semantics
             | StatementKind::Coverage(..)
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 6a5a7e08d38..73ecd99c04a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -124,7 +124,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
-    debug!("run query mir_borrowck: {}", tcx.def_path_str(def.to_def_id()));
+    debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
 
     if input_body.borrow().should_skip() {
         debug!("Skipping borrowck because of injected body");
@@ -665,7 +665,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             }
             // Only relevant for mir typeck
             StatementKind::AscribeUserType(..)
-            // Only relevant for unsafeck
+            // Only relevant for liveness and unsafeck
             | StatementKind::PlaceMention(..)
             // Doesn't have any language semantics
             | StatementKind::Coverage(..)
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 78bdf00a69c..5e55e1128e8 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -235,7 +235,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
     // Create the region inference context, taking ownership of the
     // region inference data that was contained in `infcx`, and the
     // base constraints generated by the type-check.
-    let var_origins = infcx.take_region_var_origins();
+    let var_origins = infcx.get_region_var_origins();
     let MirTypeckRegionConstraints {
         placeholder_indices,
         placeholder_index_to_region: _,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 06b80bd3f29..7cb0cec82c7 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2306,7 +2306,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Rvalue::AddressOf(..)
             | Rvalue::ThreadLocalRef(..)
             | Rvalue::Len(..)
-            | Rvalue::Discriminant(..) => {}
+            | Rvalue::Discriminant(..)
+            | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
         }
     }
 
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 83dc1ac50e5..ee2aca6fc93 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -4,8 +4,6 @@ builtin_macros_requires_cfg_pattern =
 
 builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
 
-builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
-
 builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
     .label = boolean expression required
 
@@ -149,3 +147,6 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
     [one] argument
     *[more] arguments
     } in format string, but {$desc}
+builtin_macros_offset_of_expected_field = expected field
+
+builtin_macros_offset_of_expected_two_args = expected 2 arguments
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
deleted file mode 100644
index 82bae9157e7..00000000000
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-use crate::errors;
-use crate::util::check_builtin_macro_attribute;
-
-use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind};
-use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe};
-use rustc_expand::base::{Annotatable, ExtCtxt};
-use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
-use thin_vec::{thin_vec, ThinVec};
-
-pub fn expand(
-    ecx: &mut ExtCtxt<'_>,
-    _span: Span,
-    meta_item: &ast::MetaItem,
-    item: Annotatable,
-) -> Vec<Annotatable> {
-    check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
-
-    let orig_item = item.clone();
-
-    // Allow using `#[alloc_error_handler]` on an item statement
-    // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, sig_span) =
-        if let Annotatable::Item(item) = &item
-            && let ItemKind::Fn(fn_kind) = &item.kind
-        {
-            (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
-        } else if let Annotatable::Stmt(stmt) = &item
-            && let StmtKind::Item(item) = &stmt.kind
-            && let ItemKind::Fn(fn_kind) = &item.kind
-        {
-            (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
-        } else {
-            ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocErrorMustBeFn {span: item.span() });
-            return vec![orig_item];
-        };
-
-    // Generate a bunch of new items using the AllocFnFactory
-    let span = ecx.with_def_site_ctxt(item.span);
-
-    // Generate item statements for the allocator methods.
-    let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
-
-    // Generate anonymous constant serving as container for the allocator methods.
-    let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
-    let const_body = ecx.expr_block(ecx.block(span, stmts));
-    let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
-    let const_item = if is_stmt {
-        Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
-    } else {
-        Annotatable::Item(const_item)
-    };
-
-    // Return the original item and the new methods.
-    vec![orig_item, const_item]
-}
-
-// #[rustc_std_internal_symbol]
-// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
-//     handler(core::alloc::Layout::from_size_align_unchecked(size, align))
-// }
-fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt {
-    let usize = cx.path_ident(span, Ident::new(sym::usize, span));
-    let ty_usize = cx.ty_path(usize);
-    let size = Ident::from_str_and_span("size", span);
-    let align = Ident::from_str_and_span("align", span);
-
-    let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]);
-    let layout_new = cx.expr_path(cx.path(span, layout_new));
-    let layout = cx.expr_call(
-        span,
-        layout_new,
-        thin_vec![cx.expr_ident(span, size), cx.expr_ident(span, align)],
-    );
-
-    let call = cx.expr_call_ident(sig_span, handler, thin_vec![layout]);
-
-    let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
-    let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
-    let decl = cx.fn_decl(params, never);
-    let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() };
-    let sig = FnSig { decl, header, span: span };
-
-    let body = Some(cx.block_expr(call));
-    let kind = ItemKind::Fn(Box::new(Fn {
-        defaultness: ast::Defaultness::Final,
-        sig,
-        generics: Generics::default(),
-        body,
-    }));
-
-    let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
-
-    let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
-    cx.stmt_item(sig_span, item)
-}
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index c9e3cd486f8..090e00616fb 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -301,6 +301,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
             | ExprKind::If(_, _, _)
             | ExprKind::IncludedBytes(..)
             | ExprKind::InlineAsm(_)
+            | ExprKind::OffsetOf(_, _)
             | ExprKind::Let(_, _, _)
             | ExprKind::Lit(_)
             | ExprKind::Loop(_, _, _)
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 630f9b87bc3..bf0ac3f0ee3 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -20,13 +20,6 @@ pub(crate) struct OneCfgPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_alloc_error_must_be_fn)]
-pub(crate) struct AllocErrorMustBeFn {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_assert_requires_boolean)]
 pub(crate) struct AssertRequiresBoolean {
     #[primary_span]
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 134d64ce9cc..b6170161d6b 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -27,7 +27,6 @@ use rustc_expand::proc_macro::BangProcMacro;
 use rustc_fluent_macro::fluent_messages;
 use rustc_span::symbol::sym;
 
-mod alloc_error_handler;
 mod assert;
 mod cfg;
 mod cfg_accessible;
@@ -45,6 +44,7 @@ mod format;
 mod format_foreign;
 mod global_allocator;
 mod log_syntax;
+mod offset_of;
 mod source_util;
 mod test;
 mod trace_macros;
@@ -92,6 +92,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         line: source_util::expand_line,
         log_syntax: log_syntax::expand_log_syntax,
         module_path: source_util::expand_mod,
+        offset_of: offset_of::expand_offset_of,
         option_env: env::expand_option_env,
         core_panic: edition_panic::expand_panic,
         std_panic: edition_panic::expand_panic,
@@ -102,7 +103,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
     }
 
     register_attr! {
-        alloc_error_handler: alloc_error_handler::expand,
         bench: test::expand_bench,
         cfg_accessible: cfg_accessible::Expander,
         cfg_eval: cfg_eval::expand,
diff --git a/compiler/rustc_builtin_macros/src/offset_of.rs b/compiler/rustc_builtin_macros/src/offset_of.rs
new file mode 100644
index 00000000000..0ef3e000e41
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/offset_of.rs
@@ -0,0 +1,99 @@
+use rustc_ast as ast;
+use rustc_ast::ptr::P;
+use rustc_ast::token;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_errors::PResult;
+use rustc_expand::base::{self, *};
+use rustc_macros::Diagnostic;
+use rustc_parse::parser::Parser;
+use rustc_span::{symbol::Ident, Span};
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_offset_of_expected_field)]
+struct ExpectedField {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_offset_of_expected_two_args)]
+struct ExpectedTwoArgs {
+    #[primary_span]
+    span: Span,
+}
+
+fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> {
+    let token = p.token.uninterpolate();
+    let field = match token.kind {
+        token::Ident(name, _) => Ident::new(name, token.span),
+        token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => {
+            Ident::new(symbol, token.span)
+        }
+        _ => return Err(cx.create_err(ExpectedField { span: p.token.span })),
+    };
+
+    p.bump();
+
+    Ok(field)
+}
+
+fn parse_args<'a>(
+    cx: &mut ExtCtxt<'a>,
+    sp: Span,
+    tts: TokenStream,
+) -> PResult<'a, (P<ast::Ty>, P<[Ident]>)> {
+    let mut p = cx.new_parser_from_tts(tts);
+
+    let container = p.parse_ty()?;
+
+    p.expect(&token::Comma)?;
+
+    if p.eat(&token::Eof) {
+        return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
+    }
+
+    let mut fields = Vec::new();
+
+    loop {
+        let field = parse_field(cx, &mut p)?;
+        fields.push(field);
+
+        if p.eat(&token::Dot) {
+            continue;
+        }
+
+        p.eat(&token::Comma);
+
+        if !p.eat(&token::Eof) {
+            return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
+        }
+
+        break;
+    }
+
+    Ok((container, fields.into()))
+}
+
+pub fn expand_offset_of<'cx>(
+    cx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> Box<dyn base::MacResult + 'cx> {
+    match parse_args(cx, sp, tts) {
+        Ok((container, fields)) => {
+            let expr = P(ast::Expr {
+                id: ast::DUMMY_NODE_ID,
+                kind: ast::ExprKind::OffsetOf(container, fields),
+                span: sp,
+                attrs: ast::AttrVec::new(),
+                tokens: None,
+            });
+
+            MacEager::expr(expr)
+        }
+        Err(mut err) => {
+            err.emit();
+            DummyResult::any(sp)
+        }
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
index 4ede2fe4efe..e39c3272958 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
@@ -1,4 +1,4 @@
-#![feature(start, core_intrinsics, alloc_error_handler)]
+#![feature(start, core_intrinsics)]
 #![no_std]
 
 extern crate alloc;
@@ -22,11 +22,6 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
     core::intrinsics::abort();
 }
 
-#[alloc_error_handler]
-fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
-    core::intrinsics::abort();
-}
-
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
     let world: Box<&str> = Box::new("Hello World!\0");
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 2c246ceb37d..9fb8079a21f 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -6,7 +6,6 @@ use crate::prelude::*;
 use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
 use rustc_codegen_ssa::base::allocator_kind_for_codegen;
 use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
 
 /// Returns whether an allocator shim was created
 pub(crate) fn codegen(
@@ -15,13 +14,7 @@ pub(crate) fn codegen(
     unwind_context: &mut UnwindContext,
 ) -> bool {
     let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
-    codegen_inner(
-        module,
-        unwind_context,
-        kind,
-        tcx.alloc_error_handler_kind(()).unwrap(),
-        tcx.sess.opts.unstable_opts.oom,
-    );
+    codegen_inner(module, unwind_context, kind, tcx.sess.opts.unstable_opts.oom);
     true
 }
 
@@ -29,7 +22,6 @@ fn codegen_inner(
     module: &mut impl Module,
     unwind_context: &mut UnwindContext,
     kind: AllocatorKind,
-    alloc_error_handler_kind: AllocatorKind,
     oom_strategy: OomStrategy,
 ) {
     let usize_ty = module.target_config().pointer_type();
@@ -71,19 +63,6 @@ fn codegen_inner(
         );
     }
 
-    let sig = Signature {
-        call_conv: module.target_config().default_call_conv,
-        params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
-        returns: vec![],
-    };
-    crate::common::create_wrapper_function(
-        module,
-        unwind_context,
-        sig,
-        "__rust_alloc_error_handler",
-        &alloc_error_handler_kind.fn_name(sym::oom),
-    );
-
     let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
     let mut data_ctx = DataContext::new();
     data_ctx.set_align(1);
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index f5301f9f7f1..f481290583e 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -781,12 +781,15 @@ fn codegen_stmt<'tcx>(
                     let operand = operand.load_scalar(fx);
                     lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
                 }
-                Rvalue::NullaryOp(null_op, ty) => {
+                Rvalue::NullaryOp(ref null_op, ty) => {
                     assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
                     let layout = fx.layout_of(fx.monomorphize(ty));
                     let val = match null_op {
                         NullOp::SizeOf => layout.size.bytes(),
                         NullOp::AlignOf => layout.align.abi.bytes(),
+                        NullOp::OffsetOf(fields) => {
+                            layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes()
+                        }
                     };
                     let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
                     lval.write_cvalue(fx, val);
diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs
index 754e7931412..faff1dca23f 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_example.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs
@@ -1,4 +1,4 @@
-#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
+#![feature(start, core_intrinsics, lang_items)]
 #![no_std]
 
 extern crate alloc;
@@ -21,11 +21,6 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
     core::intrinsics::abort();
 }
 
-#[alloc_error_handler]
-fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
-    core::intrinsics::abort();
-}
-
 #[lang = "eh_personality"]
 fn eh_personality() -> ! {
     loop {}
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index 4bad33ee879..e90db44ece1 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -5,11 +5,10 @@ use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
 
 use crate::GccContext;
 
-pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) {
+pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind) {
     let context = &mods.context;
     let usize =
         match tcx.sess.target.pointer_width {
@@ -87,37 +86,6 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
         // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
     }
 
-    let types = [usize, usize];
-    let name = "__rust_alloc_error_handler".to_string();
-    let args: Vec<_> = types.iter().enumerate()
-        .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-        .collect();
-    let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
-
-    if tcx.sess.target.default_hidden_visibility {
-        #[cfg(feature="master")]
-        func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-    }
-
-    let callee = alloc_error_handler_kind.fn_name(sym::oom);
-    let args: Vec<_> = types.iter().enumerate()
-        .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-        .collect();
-    let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
-    #[cfg(feature="master")]
-    callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-
-    let block = func.new_block("entry");
-
-    let args = args
-        .iter()
-        .enumerate()
-        .map(|(i, _)| func.get_param(i as i32).to_rvalue())
-        .collect::<Vec<_>>();
-    let _ret = context.new_call(None, callee, &args);
-    //llvm::LLVMSetTailCall(ret, True);
-    block.end_with_void_return(None);
-
     let name = OomStrategy::SYMBOL.to_string();
     let global = context.new_global(None, GlobalKind::Exported, i8, name);
     let value = tcx.sess.opts.unstable_opts.oom.should_panic();
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 1cabb05de97..1a20dbcebd4 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -163,11 +163,11 @@ impl CodegenBackend for GccCodegenBackend {
 }
 
 impl ExtraBackendMethods for GccCodegenBackend {
-    fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
+    fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind) -> Self::Module {
         let mut mods = GccContext {
             context: Context::default(),
         };
-        unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
+        unsafe { allocator::codegen(tcx, &mut mods, module_name, kind); }
         mods
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 668d9292705..fc9251dda82 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DebugInfo, OomStrategy};
-use rustc_span::symbol::sym;
 
 use crate::debuginfo;
 use crate::llvm::{self, False, True};
@@ -15,7 +14,6 @@ pub(crate) unsafe fn codegen(
     module_llvm: &mut ModuleLlvm,
     module_name: &str,
     kind: AllocatorKind,
-    alloc_error_handler_kind: AllocatorKind,
 ) {
     let llcx = &*module_llvm.llcx;
     let llmod = module_llvm.llmod();
@@ -100,52 +98,6 @@ pub(crate) unsafe fn codegen(
         llvm::LLVMDisposeBuilder(llbuilder);
     }
 
-    // rust alloc error handler
-    let args = [usize, usize]; // size, align
-
-    let ty = llvm::LLVMFunctionType(void, args.as_ptr(), args.len() as c_uint, False);
-    let name = "__rust_alloc_error_handler";
-    let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
-    // -> ! DIFlagNoReturn
-    let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
-    attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
-
-    if tcx.sess.target.default_hidden_visibility {
-        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
-    }
-    if tcx.sess.must_emit_unwind_tables() {
-        let uwtable = attributes::uwtable_attr(llcx);
-        attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
-    }
-
-    let callee = alloc_error_handler_kind.fn_name(sym::oom);
-    let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
-    // -> ! DIFlagNoReturn
-    attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
-    llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
-
-    let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
-
-    let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
-    llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
-    let args = args
-        .iter()
-        .enumerate()
-        .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
-        .collect::<Vec<_>>();
-    let ret = llvm::LLVMRustBuildCall(
-        llbuilder,
-        ty,
-        callee,
-        args.as_ptr(),
-        args.len() as c_uint,
-        [].as_ptr(),
-        0 as c_uint,
-    );
-    llvm::LLVMSetTailCall(ret, True);
-    llvm::LLVMBuildRetVoid(llbuilder);
-    llvm::LLVMDisposeBuilder(llbuilder);
-
     // __rust_alloc_error_handler_should_panic
     let name = OomStrategy::SYMBOL;
     let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 8305a0a4c28..00b2dc1287a 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -115,11 +115,10 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
         tcx: TyCtxt<'tcx>,
         module_name: &str,
         kind: AllocatorKind,
-        alloc_error_handler_kind: AllocatorKind,
     ) -> ModuleLlvm {
         let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
         unsafe {
-            allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind);
+            allocator::codegen(tcx, &mut module_llvm, module_name, kind);
         }
         module_llvm
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 8f2f829c17c..bda0cf764e5 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -219,7 +219,7 @@ fn exported_symbols_provider_local(
         for symbol_name in ALLOCATOR_METHODS
             .iter()
             .map(|method| format!("__rust_{}", method.name))
-            .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()])
+            .chain([OomStrategy::SYMBOL.to_string()])
         {
             let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index c5ca7936a2b..3e9d29df02c 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -635,16 +635,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     if let Some(kind) = allocator_kind_for_codegen(tcx) {
         let llmod_id =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
-        let module_llvm = tcx.sess.time("write_allocator_module", || {
-            backend.codegen_allocator(
-                tcx,
-                &llmod_id,
-                kind,
-                // If allocator_kind is Some then alloc_error_handler_kind must
-                // also be Some.
-                tcx.alloc_error_handler_kind(()).unwrap(),
-            )
-        });
+        let module_llvm = tcx
+            .sess
+            .time("write_allocator_module", || backend.codegen_allocator(tcx, &llmod_id, kind));
 
         ongoing_codegen.submit_pre_codegened_module_to_llvm(
             tcx,
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index d049bafb821..b67230cf498 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -494,6 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
 
                         if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
+                            self.set_debug_loc(bx, var.source_info);
                             let base = Self::spill_operand_to_stack(
                                 &operand,
                                 Some(var.name.to_string()),
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index bd11d47500a..94de19a9c29 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -666,13 +666,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
 
-            mir::Rvalue::NullaryOp(null_op, ty) => {
+            mir::Rvalue::NullaryOp(ref null_op, ty) => {
                 let ty = self.monomorphize(ty);
                 assert!(bx.cx().type_is_sized(ty));
                 let layout = bx.cx().layout_of(ty);
                 let val = match null_op {
                     mir::NullOp::SizeOf => layout.size.bytes(),
                     mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::OffsetOf(fields) => {
+                        layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes()
+                    }
                 };
                 let val = bx.cx().const_usize(val);
                 let tcx = self.cx.tcx();
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 64bebe50ddb..2e88b7ce219 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -123,7 +123,6 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
         tcx: TyCtxt<'tcx>,
         module_name: &str,
         kind: AllocatorKind,
-        alloc_error_handler_kind: AllocatorKind,
     ) -> Self::Module;
     /// This generates the codegen unit and returns it along with
     /// a `u64` giving an estimate of the unit's processing cost.
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 9a366364e76..319b80d66e1 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -113,8 +113,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
 
-            // Statements we do not track.
-            PlaceMention(..) | AscribeUserType(..) => {}
+            // Evaluate the place expression, without reading from it.
+            PlaceMention(box place) => {
+                let _ = self.eval_place(*place)?;
+            }
+
+            // This exists purely to guide borrowck lifetime inference, and does not have
+            // an operational effect.
+            AscribeUserType(..) => {}
 
             // Currently, Miri discards Coverage statements. Coverage statements are only injected
             // via an optional compile time MIR pass and have no side effects. Since Coverage
@@ -280,20 +286,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_immediate(*val, &dest)?;
             }
 
-            NullaryOp(null_op, ty) => {
+            NullaryOp(ref null_op, ty) => {
                 let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
                 let layout = self.layout_of(ty)?;
-                if layout.is_unsized() {
+                if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() {
                     // FIXME: This should be a span_bug (#80742)
                     self.tcx.sess.delay_span_bug(
                         self.frame().current_span(),
-                        &format!("Nullary MIR operator called for unsized type {}", ty),
+                        &format!("{null_op:?} MIR operator called for unsized type {ty}"),
                     );
                     throw_inval!(SizeOfUnsizedType(ty));
                 }
                 let val = match null_op {
                     mir::NullOp::SizeOf => layout.size.bytes(),
                     mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::OffsetOf(fields) => {
+                        layout.offset_of_subfield(self, fields.iter().map(|f| f.index())).bytes()
+                    }
                 };
                 self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
             }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 76522ed6e49..696c4517700 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -558,7 +558,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
             Rvalue::Cast(_, _, _) => {}
 
-            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {}
             Rvalue::ShallowInitBox(_, _) => {}
 
             Rvalue::UnaryOp(_, operand) => {
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 1e3d61a78be..e978e344283 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -514,6 +514,7 @@ impl<'tcx> Validator<'_, 'tcx> {
             Rvalue::NullaryOp(op, _) => match op {
                 NullOp::SizeOf => {}
                 NullOp::AlignOf => {}
+                NullOp::OffsetOf(_) => {}
             },
 
             Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 8aee019e994..b8809d29c77 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -8,9 +8,10 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{
     traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
-    MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
-    RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
-    TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
+    MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
+    ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
+    Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents,
+    START_BLOCK,
 };
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -711,10 +712,54 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
             }
+            Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => {
+                let fail_out_of_bounds = |this: &Self, location, field, ty| {
+                    this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
+                };
+
+                let mut current_ty = *container;
+
+                for field in fields.iter() {
+                    match current_ty.kind() {
+                        ty::Tuple(fields) => {
+                            let Some(&f_ty) = fields.get(field.as_usize()) else {
+                                fail_out_of_bounds(self, location, field, current_ty);
+                                return;
+                            };
+
+                            current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+                        }
+                        ty::Adt(adt_def, substs) => {
+                            if adt_def.is_enum() {
+                                self.fail(
+                                    location,
+                                    format!("Cannot get field offset from enum {current_ty:?}"),
+                                );
+                                return;
+                            }
+
+                            let Some(field) = adt_def.non_enum_variant().fields.get(field) else {
+                                fail_out_of_bounds(self, location, field, current_ty);
+                                return;
+                            };
+
+                            let f_ty = field.ty(self.tcx, substs);
+                            current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+                        }
+                        _ => {
+                            self.fail(
+                                location,
+                                format!("Cannot get field offset from non-adt type {current_ty:?}"),
+                            );
+                            return;
+                        }
+                    }
+                }
+            }
             Rvalue::Repeat(_, _)
             | Rvalue::ThreadLocalRef(_)
             | Rvalue::AddressOf(_, _)
-            | Rvalue::NullaryOp(_, _)
+            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
             | Rvalue::Discriminant(_) => {}
         }
         self.super_rvalue(rvalue, location);
@@ -757,14 +802,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
             }
-            StatementKind::PlaceMention(..) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
-                    self.fail(
-                        location,
-                        "`PlaceMention` should have been removed after drop lowering phase",
-                    );
-                }
-            }
             StatementKind::AscribeUserType(..) => {
                 if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
@@ -874,6 +911,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             StatementKind::StorageDead(_)
             | StatementKind::Coverage(_)
             | StatementKind::ConstEvalCounter
+            | StatementKind::PlaceMention(..)
             | StatementKind::Nop => {}
         }
 
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 48f5bd1cb50..594e6cca912 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -291,8 +291,6 @@ declare_features! (
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
     /// Allows additional const parameter types, such as `&'static str` or user defined types
     (incomplete, adt_const_params, "1.56.0", Some(95174), None),
-    /// Allows defining an `#[alloc_error_handler]`.
-    (active, alloc_error_handler, "1.29.0", Some(51540), None),
     /// Allows trait methods with arbitrary self types.
     (active, arbitrary_self_types, "1.23.0", Some(44874), None),
     /// Allows using `const` operands in inline assembly.
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 876a31abdf8..c978d6472c8 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -47,6 +47,8 @@ declare_features! (
 
     (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
      Some("merged into `#![feature(slice_patterns)]`")),
+    /// Allows defining an `#[alloc_error_handler]`.
+    (removed, alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(51540), None, Some("now handled by panic handler")),
     (removed, allocator, "1.0.0", None, None, None),
     /// Allows a test to fail without failing the whole suite.
     (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index a45559af713..f5a6585b5c6 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -10,7 +10,6 @@ proc-macro = true
 annotate-snippets = "0.9"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
-synstructure = "0.13.0"
 syn = { version = "2", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 54b328e78f8..52ed9660256 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1715,6 +1715,7 @@ impl Expr<'_> {
             ExprKind::Continue(..) => ExprPrecedence::Continue,
             ExprKind::Ret(..) => ExprPrecedence::Ret,
             ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf,
             ExprKind::Struct(..) => ExprPrecedence::Struct,
             ExprKind::Repeat(..) => ExprPrecedence::Repeat,
             ExprKind::Yield(..) => ExprPrecedence::Yield,
@@ -1774,6 +1775,7 @@ impl Expr<'_> {
             | ExprKind::Loop(..)
             | ExprKind::Assign(..)
             | ExprKind::InlineAsm(..)
+            | ExprKind::OffsetOf(..)
             | ExprKind::AssignOp(..)
             | ExprKind::Lit(_)
             | ExprKind::ConstBlock(..)
@@ -1818,7 +1820,7 @@ impl Expr<'_> {
 
     pub fn can_have_side_effects(&self) -> bool {
         match self.peel_drop_temps().kind {
-            ExprKind::Path(_) | ExprKind::Lit(_) => false,
+            ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
             ExprKind::Type(base, _)
             | ExprKind::Unary(_, base)
             | ExprKind::Field(base, _)
@@ -2022,6 +2024,9 @@ pub enum ExprKind<'hir> {
     /// Inline assembly (from `asm!`), with its outputs and inputs.
     InlineAsm(&'hir InlineAsm<'hir>),
 
+    /// Field offset (`offset_of!`)
+    OffsetOf(&'hir Ty<'hir>, &'hir [Ident]),
+
     /// A struct or struct-like variant literal expression.
     ///
     /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 234256ab553..df0047d82e1 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -786,6 +786,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
         ExprKind::InlineAsm(ref asm) => {
             visitor.visit_inline_asm(asm, expression.hir_id);
         }
+        ExprKind::OffsetOf(ref container, ref fields) => {
+            visitor.visit_ty(container);
+            walk_list!(visitor, visit_ident, fields.iter().copied());
+        }
         ExprKind::Yield(ref subexpression, _) => {
             visitor.visit_expr(subexpression);
         }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 51ec5dd7a28..ad2624a5d2d 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -494,7 +494,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
         id.owner_id,
-        tcx.def_path_str(id.owner_id.to_def_id())
+        tcx.def_path_str(id.owner_id)
     );
     let _indenter = indenter();
     match tcx.def_kind(id.owner_id) {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 53197bc8491..b2ebbf993a1 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -155,7 +155,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
 
     debug!(
         ?item.owner_id,
-        item.name = ? tcx.def_path_str(def_id.to_def_id())
+        item.name = ? tcx.def_path_str(def_id)
     );
 
     match item.kind {
@@ -251,7 +251,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
 
     debug!(
         ?item.owner_id,
-        item.name = ? tcx.def_path_str(def_id.to_def_id())
+        item.name = ? tcx.def_path_str(def_id)
     );
 
     match item.kind {
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 465e787c92a..ac393ee15a6 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -22,7 +22,7 @@ fn check_impl(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<
     debug!(
         "(checking implementation) adding impl for trait '{:?}', item '{}'",
         trait_ref,
-        tcx.def_path_str(impl_def_id.to_def_id())
+        tcx.def_path_str(impl_def_id)
     );
 
     // Skip impls where one of the self type is an error type.
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 4c28e28f964..a4b797f77f7 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -496,8 +496,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
     });
 
-    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
-
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 408bec71ee0..6f0afae1b4c 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -92,7 +92,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
     fn build_constraints_for_item(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx();
-        debug!("build_constraints_for_item({})", tcx.def_path_str(def_id.to_def_id()));
+        debug!("build_constraints_for_item({})", tcx.def_path_str(def_id));
 
         // Skip items with no generics - there's nothing to infer in them.
         if tcx.generics_of(def_id).count() == 0 {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 74f5b359021..2db4f1e50d4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1551,6 +1551,23 @@ impl<'a> State<'a> {
                 self.word("asm!");
                 self.print_inline_asm(asm);
             }
+            hir::ExprKind::OffsetOf(container, ref fields) => {
+                self.word("offset_of!(");
+                self.print_type(container);
+                self.word(",");
+                self.space();
+
+                if let Some((&first, rest)) = fields.split_first() {
+                    self.print_ident(first);
+
+                    for &field in rest {
+                        self.word(".");
+                        self.print_ident(field);
+                    }
+                }
+
+                self.word(")");
+            }
             hir::ExprKind::Yield(expr, _) => {
                 self.word_space("yield");
                 self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 0c0a7515d9c..3ffc583d43f 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -309,6 +309,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
                 self.check_expr_asm(asm)
             }
+            ExprKind::OffsetOf(container, ref fields) => {
+                self.check_offset_of(container, fields, expr)
+            }
             ExprKind::Break(destination, ref expr_opt) => {
                 self.check_expr_break(destination, expr_opt.as_deref(), expr)
             }
@@ -2450,15 +2453,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base_did: DefId,
         return_ty: Option<Ty<'tcx>>,
     ) -> ErrorGuaranteed {
-        let struct_path = self.tcx().def_path_str(base_did);
-        let kind_name = self.tcx().def_descr(base_did);
-        let mut err = struct_span_err!(
-            self.tcx().sess,
-            field.span,
-            E0616,
-            "field `{field}` of {kind_name} `{struct_path}` is private",
-        );
-        err.span_label(field.span, "private field");
+        let mut err = self.private_field_err(field, base_did);
+
         // Also check if an accessible method exists, which is often what is meant.
         if self.method_exists(field, expr_t, expr.hir_id, false, return_ty)
             && !self.expr_in_place(expr.hir_id)
@@ -2698,6 +2694,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err
     }
 
+    fn private_field_err(
+        &self,
+        field: Ident,
+        base_did: DefId,
+    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let struct_path = self.tcx().def_path_str(base_did);
+        let kind_name = self.tcx().def_descr(base_did);
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            field.span,
+            E0616,
+            "field `{field}` of {kind_name} `{struct_path}` is private",
+        );
+        err.span_label(field.span, "private field");
+
+        err
+    }
+
     pub(crate) fn get_field_candidates_considering_privacy(
         &self,
         span: Span,
@@ -3042,4 +3056,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.tcx.mk_unit()
         }
     }
+
+    fn check_offset_of(
+        &self,
+        container: &'tcx hir::Ty<'tcx>,
+        fields: &[Ident],
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Ty<'tcx> {
+        let container = self.to_ty(container).normalized;
+
+        let mut field_indices = Vec::with_capacity(fields.len());
+        let mut current_container = container;
+
+        for &field in fields {
+            let container = self.structurally_resolved_type(expr.span, current_container);
+
+            match container.kind() {
+                ty::Adt(container_def, substs) if !container_def.is_enum() => {
+                    let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+                    let (ident, def_scope) =
+                        self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
+
+                    let fields = &container_def.non_enum_variant().fields;
+                    if let Some((index, field)) = fields
+                        .iter_enumerated()
+                        .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
+                    {
+                        let field_ty = self.field_ty(expr.span, field, substs);
+
+                        // FIXME: DSTs with static alignment should be allowed
+                        self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
+
+                        if field.vis.is_accessible_from(def_scope, self.tcx) {
+                            self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
+                        } else {
+                            self.private_field_err(ident, container_def.did()).emit();
+                        }
+
+                        // Save the index of all fields regardless of their visibility in case
+                        // of error recovery.
+                        field_indices.push(index);
+                        current_container = field_ty;
+
+                        continue;
+                    }
+                }
+                ty::Tuple(tys) => {
+                    let fstr = field.as_str();
+
+                    if let Ok(index) = fstr.parse::<usize>() {
+                        if fstr == index.to_string() {
+                            if let Some(&field_ty) = tys.get(index) {
+                                field_indices.push(index.into());
+                                current_container = field_ty;
+
+                                continue;
+                            }
+                        }
+                    }
+                }
+                _ => (),
+            };
+
+            self.no_such_field_err(field, container, expr.hir_id).emit();
+
+            break;
+        }
+
+        self.typeck_results
+            .borrow_mut()
+            .offset_of_data_mut()
+            .insert(expr.hir_id, (container, field_indices));
+
+        self.tcx.types.usize
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index ee1c6fbfd65..94b6a0f8f47 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -300,6 +300,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             hir::ExprKind::Continue(..)
             | hir::ExprKind::Lit(..)
             | hir::ExprKind::ConstBlock(..)
+            | hir::ExprKind::OffsetOf(..)
             | hir::ExprKind::Err(_) => {}
 
             hir::ExprKind::Loop(blk, ..) => {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 3e9a9ce1b31..28c44aa5703 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -215,6 +215,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
             | ExprKind::Continue(..)
             | ExprKind::Ret(..)
             | ExprKind::InlineAsm(..)
+            | ExprKind::OffsetOf(..)
             | ExprKind::Struct(..)
             | ExprKind::Repeat(..)
             | ExprKind::Yield(..)
@@ -485,6 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
             | ExprKind::Field(..)
             | ExprKind::Index(..)
             | ExprKind::InlineAsm(..)
+            | ExprKind::OffsetOf(..)
             | ExprKind::Let(..)
             | ExprKind::Lit(..)
             | ExprKind::Path(..)
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 08d3593f91f..5ccac9a6925 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -152,10 +152,6 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
     &*tcx.typeck(def_id).used_trait_imports
 }
 
-fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
-    tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
-}
-
 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
     let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
     typeck_with_fallback(tcx, def_id, fallback)
@@ -479,7 +475,6 @@ fn has_expected_num_generic_args(
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
     *providers = Providers {
-        typeck_item_bodies,
         typeck,
         diagnostic_only_typeck,
         has_typeck_results,
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 6c861b5930a..f5fca14eca8 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -381,6 +381,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Repeat(..)
             | hir::ExprKind::InlineAsm(..)
+            | hir::ExprKind::OffsetOf(..)
             | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index e876fa27593..9432a5840b2 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -70,6 +70,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
         wbcx.visit_generator_interior_types();
+        wbcx.visit_offset_of_container_types();
 
         wbcx.typeck_results.rvalue_scopes =
             mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
@@ -295,7 +296,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
                     self.visit_field_id(field.hir_id);
                 }
             }
-            hir::ExprKind::Field(..) => {
+            hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
                 self.visit_field_id(e.hir_id);
             }
             hir::ExprKind::ConstBlock(anon_const) => {
@@ -682,6 +683,28 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    fn visit_offset_of_container_types(&mut self) {
+        let fcx_typeck_results = self.fcx.typeck_results.borrow();
+        assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
+        let common_hir_owner = fcx_typeck_results.hir_owner;
+
+        for (local_id, &(container, ref indices)) in
+            fcx_typeck_results.offset_of_data().items_in_stable_order()
+        {
+            let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+
+            if cfg!(debug_assertions) && container.needs_infer() {
+                span_bug!(
+                    hir_id.to_span(self.fcx.tcx),
+                    "writeback: `{:?}` has inference variables",
+                    container
+                );
+            };
+
+            self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
+        }
+    }
+
     fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 3e80bb906e4..1cd09cde0fc 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1228,11 +1228,11 @@ impl<'tcx> InferCtxt<'tcx> {
     /// hence that `resolve_regions_and_report_errors` can never be
     /// called. This is used only during NLL processing to "hand off" ownership
     /// of the set of region variables into the NLL region context.
-    pub fn take_region_var_origins(&self) -> VarInfos {
+    pub fn get_region_var_origins(&self) -> VarInfos {
         let mut inner = self.inner.borrow_mut();
         let (var_infos, data) = inner
             .region_constraint_storage
-            .take()
+            .clone()
             .expect("regions already resolved")
             .with_log(&mut inner.undo_log)
             .into_infos_and_data();
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index de78f26eec6..61923db9623 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -761,27 +761,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
     // passes are timed inside typeck
     rustc_hir_analysis::check_crate(tcx)?;
 
-    sess.time("misc_checking_2", || {
-        parallel!(
-            {
-                sess.time("match_checking", || {
-                    tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id))
-                });
-            },
-            {
-                sess.time("liveness_checking", || {
-                    tcx.hir().par_body_owners(|def_id| {
-                        // this must run before MIR dump, because
-                        // "not all control paths return a value" is reported here.
-                        //
-                        // maybe move the check to a MIR pass?
-                        tcx.ensure().check_liveness(def_id.to_def_id());
-                    });
-                });
-            }
-        );
-    });
-
     sess.time("MIR_borrow_checking", || {
         tcx.hir().par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id));
     });
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index f5d44d239e0..ce0f90bc1cc 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -768,6 +768,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
     tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
+    tracked!(mir_keep_place_mention, true);
     tracked!(mir_opt_level, Some(4));
     tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, false);
@@ -776,7 +777,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(no_link, true);
     tracked!(no_profiler_runtime, true);
     tracked!(no_unique_section_names, true);
-    tracked!(oom, OomStrategy::Panic);
+    tracked!(oom, OomStrategy::Unwind);
     tracked!(osx_rpath_install_name, true);
     tracked!(packed_bundled_libs, true);
     tracked!(panic_abort_tests, true);
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index c9acbab253e..abbe8e59770 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -523,14 +523,14 @@ extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmS
 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
 
 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
-  if (any_isa<const Module *>(WrappedIr))
-    return any_cast<const Module *>(WrappedIr)->getName().str();
-  if (any_isa<const Function *>(WrappedIr))
-    return any_cast<const Function *>(WrappedIr)->getName().str();
-  if (any_isa<const Loop *>(WrappedIr))
-    return any_cast<const Loop *>(WrappedIr)->getName().str();
-  if (any_isa<const LazyCallGraph::SCC *>(WrappedIr))
-    return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName();
+  if (const auto *Cast = any_cast<const Module *>(&WrappedIr))
+    return (*Cast)->getName().str();
+  if (const auto *Cast = any_cast<const Function *>(&WrappedIr))
+    return (*Cast)->getName().str();
+  if (const auto *Cast = any_cast<const Loop *>(&WrappedIr))
+    return (*Cast)->getName().str();
+  if (const auto *Cast = any_cast<const LazyCallGraph::SCC *>(&WrappedIr))
+    return (*Cast)->getName();
   return "<UNKNOWN>";
 }
 
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 79b8b417257..f0158aeae85 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -155,19 +155,9 @@ metadata_no_multiple_global_alloc =
 metadata_prev_global_alloc =
     previous global allocator defined here
 
-metadata_no_multiple_alloc_error_handler =
-    cannot define multiple allocation error handlers
-    .label = cannot define a new allocation error handler
-
-metadata_prev_alloc_error_handler =
-    previous allocation error handler defined here
-
 metadata_conflicting_global_alloc =
     the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
 
-metadata_conflicting_alloc_error_handler =
-    the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
-
 metadata_global_alloc_required =
     no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 23aceca0622..89751b0b721 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -38,13 +38,8 @@ pub struct CStore {
     /// This crate needs an allocator and either provides it itself, or finds it in a dependency.
     /// If the above is true, then this field denotes the kind of the found allocator.
     allocator_kind: Option<AllocatorKind>,
-    /// This crate needs an allocation error handler and either provides it itself, or finds it in a dependency.
-    /// If the above is true, then this field denotes the kind of the found allocator.
-    alloc_error_handler_kind: Option<AllocatorKind>,
     /// This crate has a `#[global_allocator]` item.
     has_global_allocator: bool,
-    /// This crate has a `#[alloc_error_handler]` item.
-    has_alloc_error_handler: bool,
 
     /// The interned [StableCrateId]s.
     pub(crate) stable_crate_ids: StableCrateIdMap,
@@ -221,18 +216,10 @@ impl CStore {
         self.allocator_kind
     }
 
-    pub(crate) fn alloc_error_handler_kind(&self) -> Option<AllocatorKind> {
-        self.alloc_error_handler_kind
-    }
-
     pub(crate) fn has_global_allocator(&self) -> bool {
         self.has_global_allocator
     }
 
-    pub(crate) fn has_alloc_error_handler(&self) -> bool {
-        self.has_alloc_error_handler
-    }
-
     pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
         let json_unused_externs = tcx.sess.opts.json_unused_externs;
 
@@ -268,9 +255,7 @@ impl CStore {
             metas: IndexVec::from_iter(iter::once(None)),
             injected_panic_runtime: None,
             allocator_kind: None,
-            alloc_error_handler_kind: None,
             has_global_allocator: false,
-            has_alloc_error_handler: false,
             stable_crate_ids,
             unused_externs: Vec::new(),
         }
@@ -776,14 +761,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
             }
             spans => !spans.is_empty(),
         };
-        self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
-            [span1, span2, ..] => {
-                self.sess
-                    .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
-                true
-            }
-            spans => !spans.is_empty(),
-        };
 
         // Check to see if we actually need an allocator. This desire comes
         // about through the `#![needs_allocator]` attribute and is typically
@@ -824,21 +801,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 }
             }
         }
-        let mut alloc_error_handler =
-            self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate"));
-        for (_, data) in self.cstore.iter_crate_data() {
-            if data.has_alloc_error_handler() {
-                match alloc_error_handler {
-                    Some(other_crate) => {
-                        self.sess.emit_err(errors::ConflictingAllocErrorHandler {
-                            crate_name: data.name(),
-                            other_crate_name: other_crate,
-                        });
-                    }
-                    None => alloc_error_handler = Some(data.name()),
-                }
-            }
-        }
 
         if global_allocator.is_some() {
             self.cstore.allocator_kind = Some(AllocatorKind::Global);
@@ -854,14 +816,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
             }
             self.cstore.allocator_kind = Some(AllocatorKind::Default);
         }
-
-        if alloc_error_handler.is_some() {
-            self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global);
-        } else {
-            // The alloc crate provides a default allocation error handler if
-            // one isn't specified.
-            self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
-        }
     }
 
     fn inject_dependency_if(
@@ -1037,28 +991,6 @@ fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
     f.spans
 }
 
-fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
-    struct Finder {
-        name: Symbol,
-        spans: Vec<Span>,
-    }
-    impl<'ast> visit::Visitor<'ast> for Finder {
-        fn visit_item(&mut self, item: &'ast ast::Item) {
-            if item.ident.name == self.name
-                && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
-            {
-                self.spans.push(item.span);
-            }
-            visit::walk_item(self, item)
-        }
-    }
-
-    let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom));
-    let mut f = Finder { name, spans: Vec::new() };
-    visit::walk_crate(&mut f, krate);
-    f.spans
-}
-
 // On Windows the compiler would sometimes intermittently fail to open the
 // proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
 // system still holds a lock on the file, so we retry a few times before calling it
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 51b41b5f6a2..7ecb551a3e5 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -353,16 +353,6 @@ pub struct NoMultipleGlobalAlloc {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_no_multiple_alloc_error_handler)]
-pub struct NoMultipleAllocErrorHandler {
-    #[primary_span]
-    #[label]
-    pub span2: Span,
-    #[label(metadata_prev_alloc_error_handler)]
-    pub span1: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(metadata_conflicting_global_alloc)]
 pub struct ConflictingGlobalAlloc {
     pub crate_name: Symbol,
@@ -370,13 +360,6 @@ pub struct ConflictingGlobalAlloc {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_conflicting_alloc_error_handler)]
-pub struct ConflictingAllocErrorHandler {
-    pub crate_name: Symbol,
-    pub other_crate_name: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(metadata_global_alloc_required)]
 pub struct GlobalAllocRequired;
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 601281fddba..c9ab07f5f27 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1683,10 +1683,6 @@ impl CrateMetadata {
         self.root.has_global_allocator
     }
 
-    pub(crate) fn has_alloc_error_handler(&self) -> bool {
-        self.root.has_alloc_error_handler
-    }
-
     pub(crate) fn has_default_lib_allocator(&self) -> bool {
         self.root.has_default_lib_allocator
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 141980912b1..4aa3768fc3b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -290,7 +290,6 @@ provide! { tcx, def_id, other, cdata,
     is_panic_runtime => { cdata.root.panic_runtime }
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
-    has_alloc_error_handler => { cdata.root.has_alloc_error_handler }
     has_panic_handler => { cdata.root.has_panic_handler }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     required_panic_strategy => { cdata.root.required_panic_strategy }
@@ -379,7 +378,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
     // resolve! Does this work? Unsure! That's what the issue is about
     *providers = Providers {
         allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
-        alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(),
         is_private_dep: |_tcx, LocalCrate| false,
         native_library: |tcx, id| {
             tcx.native_libraries(id.krate)
@@ -496,7 +494,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
 
         dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)),
         has_global_allocator: |tcx, LocalCrate| CStore::from_tcx(tcx).has_global_allocator(),
-        has_alloc_error_handler: |tcx, LocalCrate| CStore::from_tcx(tcx).has_alloc_error_handler(),
         postorder_cnums: |tcx, ()| {
             tcx.arena
                 .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 14c1b9d5589..fd8e49efea0 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -676,7 +676,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
                 edition: tcx.sess.edition(),
                 has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
-                has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE),
                 has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
                 has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator),
                 proc_macro_data,
@@ -824,6 +823,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::AssocTy
         | DefKind::TyParam
         | DefKind::ConstParam
+        | DefKind::LifetimeParam
         | DefKind::Fn
         | DefKind::Const
         | DefKind::Static(_)
@@ -840,10 +840,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::Impl { .. }
         | DefKind::Closure
         | DefKind::Generator => true,
-        DefKind::ForeignMod
-        | DefKind::ImplTraitPlaceholder
-        | DefKind::LifetimeParam
-        | DefKind::GlobalAsm => false,
+        DefKind::ForeignMod | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm => false,
     }
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index f2302c0ad43..ee1c495ed1e 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -225,7 +225,6 @@ pub(crate) struct CrateRoot {
     panic_in_drop_strategy: PanicStrategy,
     edition: Edition,
     has_global_allocator: bool,
-    has_alloc_error_handler: bool,
     has_panic_handler: bool,
     has_default_lib_allocator: bool,
 
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 82e396a9dd3..2dc5b896993 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -364,7 +364,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
     #[inline(always)]
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         let HirId { owner, local_id } = *self;
-        format!("{}.{}", tcx.def_path_str(owner.to_def_id()), local_id.as_u32())
+        format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32())
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 64aff27744f..5c01a661326 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1217,7 +1217,7 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
 }
 
 fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
-    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
+    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id);
 
     let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
     let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 9becc04e5d1..6b6a2e561f5 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2041,7 +2041,11 @@ impl<'tcx> Debug for Rvalue<'tcx> {
             }
             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
             Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
-            NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
+            NullaryOp(ref op, ref t) => match op {
+                NullOp::SizeOf => write!(fmt, "SizeOf({:?})", t),
+                NullOp::AlignOf => write!(fmt, "AlignOf({:?})", t),
+                NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({:?}, {:?})", t, fields),
+            },
             ThreadLocalRef(did) => ty::tls::with(|tcx| {
                 let muta = tcx.static_mutability(did).unwrap().prefix_str();
                 write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c38a347809f..69ce6835ba6 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -331,9 +331,8 @@ pub enum StatementKind<'tcx> {
     /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single
     /// `PlaceMention(PLACE)`.
     ///
-    /// When executed at runtime this is a nop.
-    ///
-    /// Disallowed after drop elaboration.
+    /// When executed at runtime, this computes the given place, but then discards
+    /// it without doing a load. It is UB if the place is not pointing to live memory.
     PlaceMention(Box<Place<'tcx>>),
 
     /// Encodes a user's type ascription. These need to be preserved
@@ -1115,7 +1114,7 @@ pub enum Rvalue<'tcx> {
     CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
 
     /// Computes a value as described by the operation.
-    NullaryOp(NullOp, Ty<'tcx>),
+    NullaryOp(NullOp<'tcx>, Ty<'tcx>),
 
     /// Exactly like `BinaryOp`, but less operands.
     ///
@@ -1211,12 +1210,14 @@ pub enum AggregateKind<'tcx> {
     Generator(DefId, SubstsRef<'tcx>, hir::Movability),
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
-pub enum NullOp {
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
+pub enum NullOp<'tcx> {
     /// Returns the size of a value of that type
     SizeOf,
     /// Returns the minimum alignment of a type
     AlignOf,
+    /// Returns the offset of a field
+    OffsetOf(&'tcx List<FieldIdx>),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 4f00abf7fab..5ca82413448 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -188,7 +188,9 @@ impl<'tcx> Rvalue<'tcx> {
             }
             Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
             Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
-            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
+                tcx.types.usize
+            }
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => {
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index ace856b9f95..06874741bb0 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -16,7 +16,6 @@ TrivialTypeTraversalAndLiftImpls! {
     UserTypeAnnotationIndex,
     BorrowKind,
     CastKind,
-    NullOp,
     hir::Movability,
     BasicBlock,
     SwitchTargets,
@@ -26,6 +25,7 @@ TrivialTypeTraversalAndLiftImpls! {
 
 TrivialTypeTraversalImpls! {
     ConstValue<'tcx>,
+    NullOp<'tcx>,
 }
 
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1c370b29961..4b7bc60926e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -83,7 +83,7 @@ rustc_queries! {
     /// Avoid calling this query directly.
     query hir_module_items(key: LocalDefId) -> &'tcx rustc_middle::hir::ModuleItems {
         arena_cache
-        desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
@@ -92,14 +92,14 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_owner(key: hir::OwnerId) -> Option<crate::hir::Owner<'tcx>> {
-        desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key) }
     }
 
     /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
     ///
     /// Definitions that were generated with no HIR, would be fed to return `None`.
     query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
-        desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key) }
         feedable
     }
 
@@ -108,7 +108,7 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
-        desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) }
     }
 
     /// Gives access to the HIR nodes and bodies inside the HIR owner `key`.
@@ -116,7 +116,7 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> {
-        desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) }
     }
 
     /// Gives access to the HIR attributes inside the HIR owner `key`.
@@ -124,7 +124,7 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
-        desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) }
     }
 
     /// Given the def_id of a const-generic parameter, computes the associated default const
@@ -295,7 +295,7 @@ rustc_queries! {
     query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap {
         eval_always // fetches `resolutions`
         arena_cache
-        desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) }
     }
 
     query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> {
@@ -305,7 +305,7 @@ rustc_queries! {
 
     query parent_module_from_def_id(key: LocalDefId) -> LocalDefId {
         eval_always
-        desc { |tcx| "getting the parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "getting the parent module of `{}`", tcx.def_path_str(key) }
     }
 
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
@@ -321,7 +321,7 @@ rustc_queries! {
 
     /// Checks whether a type is representable or infinitely sized
     query representability(_: LocalDefId) -> rustc_middle::ty::Representability {
-        desc { "checking if `{}` is representable", tcx.def_path_str(key.to_def_id()) }
+        desc { "checking if `{}` is representable", tcx.def_path_str(key) }
         // infinitely sized types will cause a cycle
         cycle_delay_bug
         // we don't want recursive representability calls to be forced with
@@ -349,21 +349,21 @@ rustc_queries! {
     query thir_body(key: LocalDefId) -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed> {
         // Perf tests revealed that hashing THIR is inefficient (see #85729).
         no_hash
-        desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) }
     }
 
     /// Create a THIR tree for debugging.
     query thir_tree(key: LocalDefId) -> &'tcx String {
         no_hash
         arena_cache
-        desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key) }
     }
 
     /// Create a list-like THIR representation for debugging.
     query thir_flat(key: LocalDefId) -> &'tcx String {
         no_hash
         arena_cache
-        desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key) }
     }
 
     /// Set of all the `DefId`s in this crate that have MIR associated with
@@ -386,7 +386,7 @@ rustc_queries! {
     /// Fetch the MIR for a given `DefId` right after it's built - this includes
     /// unreachable code.
     query mir_built(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
-        desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) }
     }
 
     /// Fetch the MIR for a given `DefId` up till the point where it is
@@ -394,7 +394,7 @@ rustc_queries! {
     ///
     /// See the README for the `mir` module for details.
     query mir_const(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
-        desc { |tcx| "preparing `{}` for borrow checking", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "preparing `{}` for borrow checking", tcx.def_path_str(key) }
         no_hash
     }
 
@@ -410,7 +410,7 @@ rustc_queries! {
 
     query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
         no_hash
-        desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) }
     }
 
     query mir_for_ctfe(
@@ -426,13 +426,13 @@ rustc_queries! {
         &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
     ) {
         no_hash
-        desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) }
     }
 
     query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
         desc {
             |tcx| "finding symbols for captures of closure `{}`",
-            tcx.def_path_str(key.to_def_id())
+            tcx.def_path_str(key)
         }
     }
 
@@ -444,7 +444,7 @@ rustc_queries! {
     }
 
     query check_generator_obligations(key: LocalDefId) {
-        desc { |tcx| "verify auto trait bounds for generator interior type `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "verify auto trait bounds for generator interior type `{}`", tcx.def_path_str(key) }
     }
 
     /// MIR after our optimization passes have run. This is MIR that is ready
@@ -526,7 +526,7 @@ rustc_queries! {
     /// `explicit_predicates_of` and `explicit_item_bounds` will then take
     /// the appropriate subsets of the predicates here.
     query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> {
-        desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) }
     }
 
     /// Returns the predicates written explicitly by the user.
@@ -769,14 +769,14 @@ rustc_queries! {
 
     /// The result of unsafety-checking this `LocalDefId`.
     query unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult {
-        desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
     /// Unsafety-check this `LocalDefId` with THIR unsafeck. This should be
     /// used with `-Zthir-unsafeck`.
     query thir_check_unsafety(key: LocalDefId) {
-        desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
@@ -833,7 +833,7 @@ rustc_queries! {
         desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
     }
 
-    query check_liveness(key: DefId) {
+    query check_liveness(key: LocalDefId) {
         desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key) }
     }
 
@@ -872,21 +872,17 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query typeck_item_bodies(_: ()) -> () {
-        desc { "type-checking all item bodies" }
-    }
-
     query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
-        desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
     query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
-        desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
     query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> {
-        desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
@@ -901,7 +897,7 @@ rustc_queries! {
     /// Borrow-checks the function body. If this is a closure, returns
     /// additional requirements that the closure's creator must verify.
     query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
-        desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
     }
 
@@ -923,7 +919,7 @@ rustc_queries! {
     query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx|
             "checking whether impl `{}` follows the orphan rules",
-            tcx.def_path_str(key.to_def_id()),
+            tcx.def_path_str(key),
         }
     }
 
@@ -935,7 +931,7 @@ rustc_queries! {
         desc { |tcx|
             "computing if `{}` (transitively) calls `{}`",
             key.0,
-            tcx.def_path_str(key.1.to_def_id()),
+            tcx.def_path_str(key.1),
         }
     }
 
@@ -1026,7 +1022,7 @@ rustc_queries! {
     }
 
     query check_match(key: LocalDefId) {
-        desc { |tcx| "match-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
 
@@ -1355,13 +1351,6 @@ rustc_queries! {
         desc { "checking if the crate has_global_allocator" }
         separate_provide_extern
     }
-    query has_alloc_error_handler(_: CrateNum) -> bool {
-        // This query depends on untracked global state in CStore
-        eval_always
-        fatal_cycle
-        desc { "checking if the crate has_alloc_error_handler" }
-        separate_provide_extern
-    }
     query has_panic_handler(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate has_panic_handler" }
@@ -1373,7 +1362,7 @@ rustc_queries! {
         separate_provide_extern
     }
     query has_ffi_unwind_calls(key: LocalDefId) -> bool {
-        desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) }
         cache_on_disk_if { true }
     }
     query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> {
@@ -1419,7 +1408,7 @@ rustc_queries! {
     }
 
     query check_well_formed(key: hir::OwnerId) -> () {
-        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
+        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) }
     }
 
     // The `DefId`s of all non-generic functions and statics in the given crate
@@ -1448,7 +1437,7 @@ rustc_queries! {
     query is_unreachable_local_definition(def_id: LocalDefId) -> bool {
         desc { |tcx|
             "checking whether `{}` is reachable from outside the crate",
-            tcx.def_path_str(def_id.to_def_id()),
+            tcx.def_path_str(def_id),
         }
     }
 
@@ -1642,7 +1631,7 @@ rustc_queries! {
         separate_provide_extern
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
-        desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
+        desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
     }
 
     query lib_features(_: ()) -> &'tcx LibFeatures {
@@ -1734,10 +1723,6 @@ rustc_queries! {
         eval_always
         desc { "getting the allocator kind for the current crate" }
     }
-    query alloc_error_handler_kind(_: ()) -> Option<AllocatorKind> {
-        eval_always
-        desc { "alloc error handler kind for the current crate" }
-    }
 
     query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
         desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
@@ -1746,7 +1731,7 @@ rustc_queries! {
         desc { "fetching potentially unused trait imports" }
     }
     query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx UnordSet<Symbol> {
-        desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
+        desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id) }
     }
 
     query stability_index(_: ()) -> &'tcx stability::Index {
@@ -2069,7 +2054,7 @@ rustc_queries! {
     query compare_impl_const(
         key: (LocalDefId, DefId)
     ) -> Result<(), ErrorGuaranteed> {
-        desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
+        desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) }
     }
 
     query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index b49125f4e5f..8700a98b365 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts};
 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -481,6 +481,11 @@ pub enum ExprKind<'tcx> {
     },
     /// Inline assembly, i.e. `asm!()`.
     InlineAsm(Box<InlineAsmExpr<'tcx>>),
+    /// Field offset (`offset_of!`)
+    OffsetOf {
+        container: Ty<'tcx>,
+        fields: &'tcx List<FieldIdx>,
+    },
     /// An expression taking a reference to a thread local.
     ThreadLocalRef(DefId),
     /// A `yield` expression.
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 5614528c4cb..5c7ec31cf93 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -160,6 +160,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                 }
             }
         }
+        OffsetOf { container: _, fields: _ } => {}
         ThreadLocalRef(_) => {}
         Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
     }
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8ef4a46a733..5454d406dd1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
 pub use rustc_type_ir::{TyDecoder, TyEncoder};
 use std::hash::Hash;
 use std::intrinsics;
@@ -401,6 +402,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
     }
 }
 
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<FieldIdx> {
+    fn decode(decoder: &mut D) -> &'tcx Self {
+        let len = decoder.read_usize();
+        decoder
+            .interner()
+            .mk_fields_from_iter((0..len).map::<FieldIdx, _>(|_| Decodable::decode(decoder)))
+    }
+}
+
 impl_decodable_via_ref! {
     &'tcx ty::TypeckResults<'tcx>,
     &'tcx ty::List<Ty<'tcx>>,
@@ -412,6 +422,7 @@ impl_decodable_via_ref! {
     &'tcx mir::coverage::CodeRegion,
     &'tcx ty::List<ty::BoundVariableKind>,
     &'tcx ty::List<ty::Predicate<'tcx>>,
+    &'tcx ty::List<FieldIdx>,
 }
 
 #[macro_export]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index af3a54148e1..80d28b2e188 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -80,6 +80,8 @@ use std::iter;
 use std::mem;
 use std::ops::{Bound, Deref};
 
+use super::query::IntoQueryParam;
+
 const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
 
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
@@ -155,6 +157,7 @@ pub struct CtxtInterners<'tcx> {
     layout: InternedSet<'tcx, LayoutS>,
     adt_def: InternedSet<'tcx, AdtDefData>,
     external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
+    fields: InternedSet<'tcx, List<FieldIdx>>,
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
@@ -178,6 +181,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             layout: Default::default(),
             adt_def: Default::default(),
             external_constraints: Default::default(),
+            fields: Default::default(),
         }
     }
 
@@ -822,7 +826,8 @@ impl<'tcx> TyCtxt<'tcx> {
         self.features_query(())
     }
 
-    pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
+    pub fn def_key(self, id: impl IntoQueryParam<DefId>) -> rustc_hir::definitions::DefKey {
+        let id = id.into_query_param();
         // Accessing the DefKey is ok, since it is part of DefPathHash.
         if let Some(id) = id.as_local() {
             self.definitions_untracked().def_key(id)
@@ -1571,6 +1576,7 @@ slice_interners!(
     projs: pub mk_projs(ProjectionKind),
     place_elems: pub mk_place_elems(PlaceElem<'tcx>),
     bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
+    fields: pub mk_fields(FieldIdx),
 );
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -2239,6 +2245,14 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
     }
 
+    pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
+    {
+        T::collect_and_apply(iter, |xs| self.mk_fields(xs))
+    }
+
     pub fn mk_substs_trait(
         self,
         self_ty: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 4c7822acdf7..02baa395c3c 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -73,34 +73,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'t
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        match self {
-            // WARNING: We dedup cache the `HashStable` results for `List`
-            // while ignoring types and freely transmute
-            // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
-            // See `fn mk_type_list` for more details.
-            //
-            // We therefore hash types without adding a hash for their discriminant.
-            //
-            // In order to make it very unlikely for the sequence of bytes being hashed for
-            // a `GenericArgKind::Type` to be the same as the sequence of bytes being
-            // hashed for one of the other variants, we hash some very high number instead
-            // of their actual discriminant since `TyKind` should never start with anything
-            // that high.
-            ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
-            ty::subst::GenericArgKind::Const(ct) => {
-                0xF3u8.hash_stable(hcx, hasher);
-                ct.hash_stable(hcx, hasher);
-            }
-            ty::subst::GenericArgKind::Lifetime(lt) => {
-                0xF5u8.hash_stable(hcx, hasher);
-                lt.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
 // AllocIds get resolved to whatever they point to (to be stable)
 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index d947d96041e..5ce32c7aaaa 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -327,6 +327,6 @@ pub fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
     if def_id.is_top_level_module() {
         "top-level module".to_string()
     } else {
-        format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
+        format!("module `{}`", tcx.def_path_str(def_id))
     }
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5315aa155a8..4c95d0f8415 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,4 +1,5 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::ty::query::IntoQueryParam;
 use crate::ty::{
     self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -738,7 +739,9 @@ pub trait PrettyPrinter<'tcx>:
                 }
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
-                ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
+                ty::BoundTyKind::Anon => {
+                    self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
+                }
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -1172,6 +1175,18 @@ pub trait PrettyPrinter<'tcx>:
         }
     }
 
+    fn pretty_print_placeholder_var(
+        &mut self,
+        ui: ty::UniverseIndex,
+        var: ty::BoundVar,
+    ) -> Result<(), Self::Error> {
+        if ui == ty::UniverseIndex::ROOT {
+            write!(self, "!{}", var.index())
+        } else {
+            write!(self, "!{}_{}", ui.index(), var.index())
+        }
+    }
+
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
         None
     }
@@ -1787,17 +1802,27 @@ fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
 impl<'t> TyCtxt<'t> {
     /// Returns a string identifying this `DefId`. This string is
     /// suitable for user output.
-    pub fn def_path_str(self, def_id: DefId) -> String {
+    pub fn def_path_str(self, def_id: impl IntoQueryParam<DefId>) -> String {
         self.def_path_str_with_substs(def_id, &[])
     }
 
-    pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
+    pub fn def_path_str_with_substs(
+        self,
+        def_id: impl IntoQueryParam<DefId>,
+        substs: &'t [GenericArg<'t>],
+    ) -> String {
+        let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
         FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
     }
 
-    pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
+    pub fn value_path_str_with_substs(
+        self,
+        def_id: impl IntoQueryParam<DefId>,
+        substs: &'t [GenericArg<'t>],
+    ) -> String {
+        let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
         FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer()
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index e46cfb8dd16..bd8a22473fb 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -587,7 +587,7 @@ mod sealed {
     }
 }
 
-use sealed::IntoQueryParam;
+pub use sealed::IntoQueryParam;
 
 impl<'tcx> TyCtxt<'tcx> {
     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 73c9c86f76a..a439211ca33 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -47,7 +47,7 @@ const TYPE_TAG: usize = 0b00;
 const REGION_TAG: usize = 0b01;
 const CONST_TAG: usize = 0b10;
 
-#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
 pub enum GenericArgKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 47943b94c3b..ef8955b1d3a 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -208,6 +208,9 @@ pub struct TypeckResults<'tcx> {
     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
     /// on closure size.
     pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+
+    /// Container types and field indices of `offset_of!` expressions
+    offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
 }
 
 /// Whenever a value may be live across a generator yield, the type of that value winds up in the
@@ -280,6 +283,7 @@ impl<'tcx> TypeckResults<'tcx> {
             generator_interior_predicates: Default::default(),
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
+            offset_of_data: Default::default(),
         }
     }
 
@@ -530,6 +534,14 @@ impl<'tcx> TypeckResults<'tcx> {
     pub fn coercion_casts(&self) -> &ItemLocalSet {
         &self.coercion_casts
     }
+
+    pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
+    }
+
+    pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
+    }
 }
 
 /// Validate that the given HirId (respectively its `local_id` part) can be
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 55aa4fcff2c..5c38c0acc7f 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -158,8 +158,8 @@ pub fn recursive_type_error(
     }
     let items_list = {
         let mut s = String::new();
-        for (i, (item_id, _)) in item_and_field_ids.iter().enumerate() {
-            let path = tcx.def_path_str(item_id.to_def_id());
+        for (i, &(item_id, _)) in item_and_field_ids.iter().enumerate() {
+            let path = tcx.def_path_str(item_id);
             write!(&mut s, "`{path}`").unwrap();
             if i == (ITEM_LIMIT - 1) && cycle_len > ITEM_LIMIT {
                 write!(&mut s, " and {} more", cycle_len - 5).unwrap();
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index fb775766c65..7ec57add66b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -557,6 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::ConstBlock { .. }
             | ExprKind::StaticRef { .. }
             | ExprKind::InlineAsm { .. }
+            | ExprKind::OffsetOf { .. }
             | ExprKind::Yield { .. }
             | ExprKind::ThreadLocalRef(_)
             | ExprKind::Call { .. } => {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 8631749a524..fbde0b28f54 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -481,6 +481,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }))))
             }
 
+            ExprKind::OffsetOf { container, fields } => {
+                block.and(Rvalue::NullaryOp(NullOp::OffsetOf(fields), container))
+            }
+
             ExprKind::Literal { .. }
             | ExprKind::NamedConst { .. }
             | ExprKind::NonHirLiteral { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs
index d33401f0764..d9aa461c19d 100644
--- a/compiler/rustc_mir_build/src/build/expr/category.rs
+++ b/compiler/rustc_mir_build/src/build/expr/category.rs
@@ -67,7 +67,8 @@ impl Category {
             | ExprKind::Repeat { .. }
             | ExprKind::Assign { .. }
             | ExprKind::AssignOp { .. }
-            | ExprKind::ThreadLocalRef(_) => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
+            | ExprKind::ThreadLocalRef(_)
+            | ExprKind::OffsetOf { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
 
             ExprKind::ConstBlock { .. }
             | ExprKind::Literal { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 9b38ac1cc4c..29ff916d2cc 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -561,7 +561,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::ZstLiteral { .. }
             | ExprKind::ConstParam { .. }
             | ExprKind::ThreadLocalRef(_)
-            | ExprKind::StaticRef { .. } => {
+            | ExprKind::StaticRef { .. }
+            | ExprKind::OffsetOf { .. } => {
                 debug_assert!(match Category::of(&expr.kind).unwrap() {
                     // should be handled above
                     Category::Rvalue(RvalueFunc::Into) => false,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b05c3056cba..82274318dcf 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -51,6 +51,13 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
             // of `mir_build`, so now we can steal it
             let thir = thir.steal();
 
+            tcx.ensure().check_match(def);
+            // this must run before MIR dump, because
+            // "not all control paths return a value" is reported here.
+            //
+            // maybe move the check to a MIR pass?
+            tcx.ensure().check_liveness(def);
+
             match thir.body_type {
                 thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
                 thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index bc1a0fac129..0506f2bf238 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -323,6 +323,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             | ExprKind::Box { .. }
             | ExprKind::If { .. }
             | ExprKind::InlineAsm { .. }
+            | ExprKind::OffsetOf { .. }
             | ExprKind::LogicalOp { .. }
             | ExprKind::Use { .. } => {
                 // We don't need to save the old value and restore it
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 8e2e92e6f6a..ce13d522aae 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -664,6 +664,14 @@ impl<'tcx> Cx<'tcx> {
                 line_spans: asm.line_spans,
             })),
 
+            hir::ExprKind::OffsetOf(_, _) => {
+                let data = self.typeck_results.offset_of_data();
+                let &(container, ref indices) = data.get(expr.hir_id).unwrap();
+                let fields = tcx.mk_fields_from_iter(indices.iter().copied());
+
+                ExprKind::OffsetOf { container, fields }
+            }
+
             hir::ExprKind::ConstBlock(ref anon_const) => {
                 let ty = self.typeck_results().node_type(anon_const.hir_id);
                 let did = anon_const.def_id.to_def_id();
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 0e4eca6844f..b2f2a64e29c 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -519,6 +519,19 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_inline_asm_expr(&**expr, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
             }
+            OffsetOf { container, fields } => {
+                print_indented!(self, "OffsetOf {", depth_lvl);
+                print_indented!(self, format!("container: {:?}", container), depth_lvl + 1);
+                print_indented!(self, "fields: [", depth_lvl + 1);
+
+                for field in fields.iter() {
+                    print_indented!(self, format!("{:?}", field), depth_lvl + 2);
+                    print_indented!(self, ",", depth_lvl + 1);
+                }
+
+                print_indented!(self, "]", depth_lvl + 1);
+                print_indented!(self, "}", depth_lvl);
+            }
             ThreadLocalRef(def_id) => {
                 print_indented!(self, "ThreadLocalRef {", depth_lvl);
                 print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 64ed7a29f6f..736ca62cacc 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -360,7 +360,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             | Rvalue::AddressOf(..)
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
-            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
+            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {}
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 0923824db48..d435d3ee69b 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -24,7 +24,6 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
             for statement in basic_block.statements.iter_mut() {
                 match statement.kind {
                     StatementKind::AscribeUserType(..)
-                    | StatementKind::PlaceMention(..)
                     | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _)))
                     | StatementKind::FakeRead(..) => statement.make_nop(),
                     _ => (),
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 692b3182f7d..b9bfbefcad9 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -16,7 +16,7 @@ pub struct ConstDebugInfo;
 
 impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() > 0
+        sess.mir_opt_level() > 0
     }
 
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 18c407b42d3..7bc5183a00a 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -54,11 +54,10 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
                 | StatementKind::Coverage(_)
                 | StatementKind::Intrinsic(_)
                 | StatementKind::ConstEvalCounter
+                | StatementKind::PlaceMention(_)
                 | StatementKind::Nop => (),
 
-                StatementKind::FakeRead(_)
-                | StatementKind::PlaceMention(_)
-                | StatementKind::AscribeUserType(_, _) => {
+                StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
                     bug!("{:?} not found in this MIR phase!", &statement.kind)
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 5a842714e5d..78758e2db28 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -582,10 +582,9 @@ impl WriteInfo {
             | StatementKind::Nop
             | StatementKind::Coverage(_)
             | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_) => (),
-            StatementKind::FakeRead(_)
-            | StatementKind::AscribeUserType(_, _)
-            | StatementKind::PlaceMention(_) => {
+            | StatementKind::StorageDead(_)
+            | StatementKind::PlaceMention(_) => (),
+            StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
                 bug!("{:?} not found in this MIR phase", statement)
             }
         }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 1525933aee3..552bf43329c 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -26,8 +26,6 @@ const CALL_PENALTY: usize = 25;
 const LANDINGPAD_PENALTY: usize = 50;
 const RESUME_PENALTY: usize = 45;
 
-const UNKNOWN_SIZE_COST: usize = 10;
-
 const TOP_DOWN_DEPTH_LIMIT: usize = 5;
 
 pub struct Inline;
@@ -464,12 +462,6 @@ impl<'tcx> Inliner<'tcx> {
             }
         }
 
-        // Count up the cost of local variables and temps, if we know the size
-        // use that, otherwise we use a moderately-large dummy cost.
-        for v in callee_body.vars_and_temps_iter() {
-            checker.visit_local_decl(v, &callee_body.local_decls[v]);
-        }
-
         // Abort if type validation found anything fishy.
         checker.validation?;
 
@@ -764,14 +756,6 @@ impl<'tcx> Inliner<'tcx> {
     }
 }
 
-fn type_size_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<u64> {
-    tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
-}
-
 /// Verify that the callee body is compatible with the caller.
 ///
 /// This visitor mostly computes the inlining cost,
@@ -845,24 +829,6 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
         self.super_terminator(terminator, location);
     }
 
-    /// Count up the cost of local variables and temps, if we know the size
-    /// use that, otherwise we use a moderately-large dummy cost.
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        let tcx = self.tcx;
-        let ptr_size = tcx.data_layout.pointer_size.bytes();
-
-        let ty = self.instance.subst_mir(tcx, &local_decl.ty);
-        // Cost of the var is the size in machine-words, if we know
-        // it.
-        if let Some(size) = type_size_of(tcx, self.param_env, ty) {
-            self.cost += ((size + ptr_size - 1) / ptr_size) as usize;
-        } else {
-            self.cost += UNKNOWN_SIZE_COST;
-        }
-
-        self.super_local_decl(local, local_decl)
-    }
-
     /// This method duplicates code from MIR validation in an attempt to detect type mismatches due
     /// to normalization failure.
     fn visit_projection_elem(
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 8b811d7e870..098ce0391fc 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -13,7 +13,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
     tcx: TyCtxt<'tcx>,
     (root, target): (ty::Instance<'tcx>, LocalDefId),
 ) -> bool {
-    trace!(%root, target = %tcx.def_path_str(target.to_def_id()));
+    trace!(%root, target = %tcx.def_path_str(target));
     let param_env = tcx.param_env_reveal_all_normalized(target);
     assert_ne!(
         root.def_id().expect_local(),
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 7a2420a6d94..6d8b4dc91f4 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -48,6 +48,7 @@ mod add_retag;
 mod check_const_item_mutation;
 mod check_packed_ref;
 pub mod check_unsafety;
+mod remove_place_mention;
 // This pass is public to allow external drivers to perform MIR cleanup
 pub mod cleanup_post_borrowck;
 mod const_debuginfo;
@@ -460,8 +461,11 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
 /// Returns the sequence of passes that do the initial cleanup of runtime MIR.
 fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let passes: &[&dyn MirPass<'tcx>] =
-        &[&lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::ElaborateDrops];
+    let passes: &[&dyn MirPass<'tcx>] = &[
+        &lower_intrinsics::LowerIntrinsics,
+        &remove_place_mention::RemovePlaceMention,
+        &simplify::SimplifyCfg::ElaborateDrops,
+    ];
 
     pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
 
@@ -507,12 +511,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             //
             // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
             &const_debuginfo::ConstDebugInfo,
-            &o1(simplify_branches::SimplifyConstConditionPassName::AfterConstProp),
+            &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
             &early_otherwise_branch::EarlyOtherwiseBranch,
             &simplify_comparison_integral::SimplifyComparisonIntegral,
             &dead_store_elimination::DeadStoreElimination,
             &dest_prop::DestinationPropagation,
-            &o1(simplify_branches::SimplifyConstConditionPassName::Final),
+            &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
             &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
new file mode 100644
index 00000000000..8be1c37572d
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -0,0 +1,23 @@
+//! This pass removes `PlaceMention` statement, which has no effect at codegen.
+
+use crate::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct RemovePlaceMention;
+
+impl<'tcx> MirPass<'tcx> for RemovePlaceMention {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        !sess.opts.unstable_opts.mir_keep_place_mention
+    }
+
+    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        trace!("Running RemovePlaceMention on {:?}", body.source);
+        for data in body.basic_blocks.as_mut_preserves_cfg() {
+            data.statements.retain(|statement| match statement.kind {
+                StatementKind::PlaceMention(..) | StatementKind::Nop => false,
+                _ => true,
+            })
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index ef367faf6a7..2479856b727 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -303,8 +303,7 @@ fn find_determining_place<'tcx>(
                     | Rvalue::NullaryOp(_, _)
                     | Rvalue::ShallowInitBox(_, _)
                     | Rvalue::UnaryOp(_, Operand::Constant(_))
-                    | Rvalue::Cast(_, Operand::Constant(_), _)
-                    => return None,
+                    | Rvalue::Cast(_, Operand::Constant(_), _) => return None,
                 }
             }
 
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index ddaf86a9e73..c65a7ec6783 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,18 +2,16 @@ use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-pub enum SimplifyConstConditionPassName {
+pub enum SimplifyConstCondition {
     AfterConstProp,
     Final,
 }
 /// A pass that replaces a branch with a goto when its condition is known.
-impl<'tcx> MirPass<'tcx> for SimplifyConstConditionPassName {
+impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
     fn name(&self) -> &'static str {
         match self {
-            SimplifyConstConditionPassName::AfterConstProp => {
-                "SimplifyConstCondition-after-const-prop"
-            }
-            SimplifyConstConditionPassName::Final => "SimplifyConstCondition-final",
+            SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
+            SimplifyConstCondition::Final => "SimplifyConstCondition-final",
         }
     }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 2ed628871d2..5ac9c8e2073 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1230,7 +1230,7 @@ impl<'v> RootCollector<'_, 'v> {
             DefKind::GlobalAsm => {
                 debug!(
                     "RootCollector: ItemKind::GlobalAsm({})",
-                    self.tcx.def_path_str(id.owner_id.to_def_id())
+                    self.tcx.def_path_str(id.owner_id)
                 );
                 self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
             }
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 43a485c977d..bd24deb590a 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -16,17 +16,20 @@ use super::PartitioningCx;
 use crate::collector::InliningMap;
 use crate::partitioning::merging;
 use crate::partitioning::{
-    MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning,
+    MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
 };
 
 pub struct DefaultPartitioning;
 
-impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
-    fn place_root_mono_items(
+impl<'tcx> Partition<'tcx> for DefaultPartitioning {
+    fn place_root_mono_items<I>(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
-    ) -> PreInliningPartitioning<'tcx> {
+        mono_items: &mut I,
+    ) -> PreInliningPartitioning<'tcx>
+    where
+        I: Iterator<Item = MonoItem<'tcx>>,
+    {
         let mut roots = FxHashSet::default();
         let mut codegen_units = FxHashMap::default();
         let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 18aa0742c09..993e35c7fd2 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -118,18 +118,81 @@ use crate::errors::{
     CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
 };
 
+enum Partitioner {
+    Default(default::DefaultPartitioning),
+    // Other partitioning strategies can go here.
+    Unknown,
+}
+
+impl<'tcx> Partition<'tcx> for Partitioner {
+    fn place_root_mono_items<I>(
+        &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
+        mono_items: &mut I,
+    ) -> PreInliningPartitioning<'tcx>
+    where
+        I: Iterator<Item = MonoItem<'tcx>>,
+    {
+        match self {
+            Partitioner::Default(partitioner) => partitioner.place_root_mono_items(cx, mono_items),
+            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+        }
+    }
+
+    fn merge_codegen_units(
+        &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
+        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+    ) {
+        match self {
+            Partitioner::Default(partitioner) => {
+                partitioner.merge_codegen_units(cx, initial_partitioning)
+            }
+            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+        }
+    }
+
+    fn place_inlined_mono_items(
+        &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
+        initial_partitioning: PreInliningPartitioning<'tcx>,
+    ) -> PostInliningPartitioning<'tcx> {
+        match self {
+            Partitioner::Default(partitioner) => {
+                partitioner.place_inlined_mono_items(cx, initial_partitioning)
+            }
+            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+        }
+    }
+
+    fn internalize_symbols(
+        &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
+        post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
+    ) {
+        match self {
+            Partitioner::Default(partitioner) => {
+                partitioner.internalize_symbols(cx, post_inlining_partitioning)
+            }
+            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+        }
+    }
+}
+
 pub struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     target_cgu_count: usize,
     inlining_map: &'a InliningMap<'tcx>,
 }
 
-trait Partitioner<'tcx> {
-    fn place_root_mono_items(
+trait Partition<'tcx> {
+    fn place_root_mono_items<I>(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
-    ) -> PreInliningPartitioning<'tcx>;
+        mono_items: &mut I,
+    ) -> PreInliningPartitioning<'tcx>
+    where
+        I: Iterator<Item = MonoItem<'tcx>>;
 
     fn merge_codegen_units(
         &mut self,
@@ -150,26 +213,27 @@ trait Partitioner<'tcx> {
     );
 }
 
-fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
+fn get_partitioner(tcx: TyCtxt<'_>) -> Partitioner {
     let strategy = match &tcx.sess.opts.unstable_opts.cgu_partitioning_strategy {
         None => "default",
         Some(s) => &s[..],
     };
 
     match strategy {
-        "default" => Box::new(default::DefaultPartitioning),
-        _ => {
-            tcx.sess.emit_fatal(UnknownPartitionStrategy);
-        }
+        "default" => Partitioner::Default(default::DefaultPartitioning),
+        _ => Partitioner::Unknown,
     }
 }
 
-pub fn partition<'tcx>(
+pub fn partition<'tcx, I>(
     tcx: TyCtxt<'tcx>,
-    mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+    mono_items: &mut I,
     max_cgu_count: usize,
     inlining_map: &InliningMap<'tcx>,
-) -> Vec<CodegenUnit<'tcx>> {
+) -> Vec<CodegenUnit<'tcx>>
+where
+    I: Iterator<Item = MonoItem<'tcx>>,
+{
     let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
 
     let mut partitioner = get_partitioner(tcx);
@@ -182,7 +246,9 @@ pub fn partition<'tcx>(
         partitioner.place_root_mono_items(cx, mono_items)
     };
 
-    initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+    for cgu in &mut initial_partitioning.codegen_units {
+        cgu.create_size_estimate(tcx);
+    }
 
     debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
 
@@ -202,7 +268,9 @@ pub fn partition<'tcx>(
         partitioner.place_inlined_mono_items(cx, initial_partitioning)
     };
 
-    post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+    for cgu in &mut post_inlining.codegen_units {
+        cgu.create_size_estimate(tcx);
+    }
 
     debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
 
@@ -380,7 +448,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
             || {
                 let mut codegen_units = partition(
                     tcx,
-                    &mut items.iter().cloned(),
+                    &mut items.iter().copied(),
                     tcx.sess.codegen_units(),
                     &inlining_map,
                 );
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 5cfe691df17..3ae5b45d330 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -237,6 +237,37 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
+    fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+        let data = self.typeck_results().offset_of_data();
+        let &(container, ref indices) =
+            data.get(expr.hir_id).expect("no offset_of_data for offset_of");
+
+        let body_did = self.typeck_results().hir_owner.to_def_id();
+        let param_env = self.tcx.param_env(body_did);
+
+        let mut current_ty = container;
+
+        for &index in indices {
+            match current_ty.kind() {
+                ty::Adt(def, subst) => {
+                    let field = &def.non_enum_variant().fields[index];
+
+                    self.insert_def_id(field.did);
+                    let field_ty = field.ty(self.tcx, subst);
+
+                    current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
+                }
+                // we don't need to mark tuple fields as live,
+                // but we may need to mark subfields
+                ty::Tuple(tys) => {
+                    current_ty =
+                        self.tcx.normalize_erasing_regions(param_env, tys[index.as_usize()]);
+                }
+                _ => span_bug!(expr.span, "named field access on non-ADT"),
+            }
+        }
+    }
+
     fn mark_live_symbols(&mut self) {
         let mut scanned = LocalDefIdSet::default();
         while let Some(id) = self.worklist.pop() {
@@ -405,6 +436,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
             hir::ExprKind::Closure(cls) => {
                 self.insert_def_id(cls.def_id.to_def_id());
             }
+            hir::ExprKind::OffsetOf(..) => {
+                self.handle_offset_of(expr);
+            }
             _ => (),
         }
 
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 47e032758f2..dc5e454074d 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -302,7 +302,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
             [
                 ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
                 DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
-                Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
+                Path, AddrOf, Break, Continue, Ret, InlineAsm, OffsetOf, Struct, Repeat, Yield,
+                Err
             ]
         );
         hir_visit::walk_expr(self, e)
@@ -568,7 +569,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
                 Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
                 If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
                 AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
-                InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
+                InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
             ]
         );
         ast_visit::walk_expr(self, e)
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index a8471ce3b6f..31cfbfa9720 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -90,7 +90,7 @@ use rustc_errors::Applicability;
 use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def::*;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::vec::IndexVec;
@@ -98,6 +98,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::DUMMY_SP;
 use rustc_span::{BytePos, Span};
 
 use std::collections::VecDeque;
@@ -137,14 +138,9 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
     }
 }
 
-fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
-    let local_def_id = match def_id.as_local() {
-        None => return,
-        Some(def_id) => def_id,
-    };
-
+fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     // Don't run unused pass for #[derive()]
-    let parent = tcx.local_parent(local_def_id);
+    let parent = tcx.local_parent(def_id);
     if let DefKind::Impl { .. } = tcx.def_kind(parent)
         && tcx.has_attr(parent, sym::automatically_derived)
     {
@@ -152,12 +148,12 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
     }
 
     // Don't run unused pass for #[naked]
-    if tcx.has_attr(def_id, sym::naked) {
+    if tcx.has_attr(def_id.to_def_id(), sym::naked) {
         return;
     }
 
     let mut maps = IrMaps::new(tcx);
-    let body_id = tcx.hir().body_owned_by(local_def_id);
+    let body_id = tcx.hir().body_owned_by(def_id);
     let hir_id = tcx.hir().body_owner(body_id);
     let body = tcx.hir().body(body_id);
 
@@ -173,7 +169,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
     maps.visit_body(body);
 
     // compute liveness
-    let mut lsets = Liveness::new(&mut maps, local_def_id);
+    let mut lsets = Liveness::new(&mut maps, def_id);
     let entry_ln = lsets.compute(&body, hir_id);
     lsets.log_liveness(entry_ln, body_id.hir_id);
 
@@ -473,6 +469,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Repeat(..)
             | hir::ExprKind::InlineAsm(..)
+            | hir::ExprKind::OffsetOf(..)
             | hir::ExprKind::Type(..)
             | hir::ExprKind::Err(_)
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
@@ -591,8 +588,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> bool {
-        let successor = self.successors[ln].unwrap();
-        self.assigned_on_entry(successor, var)
+        match self.successors[ln] {
+            Some(successor) => self.assigned_on_entry(successor, var),
+            None => {
+                self.ir.tcx.sess.delay_span_bug(DUMMY_SP, "no successor");
+                true
+            }
+        }
     }
 
     fn write_vars<F>(&self, wr: &mut dyn Write, mut test: F) -> io::Result<()>
@@ -1129,7 +1131,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             | hir::ExprKind::ConstBlock(..)
             | hir::ExprKind::Err(_)
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
-            | hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
+            | hir::ExprKind::Path(hir::QPath::LangItem(..))
+            | hir::ExprKind::OffsetOf(..) => succ,
 
             // Note that labels have been resolved, so we don't need to look
             // at the label ident
@@ -1418,6 +1421,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         | hir::ExprKind::ConstBlock(..)
         | hir::ExprKind::Block(..)
         | hir::ExprKind::AddrOf(..)
+        | hir::ExprKind::OffsetOf(..)
         | hir::ExprKind::Struct(..)
         | hir::ExprKind::Repeat(..)
         | hir::ExprKind::Closure { .. }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index c398467f03e..cf8d9300a11 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -203,6 +203,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
             | ExprKind::Break(..)
             | ExprKind::Continue(..)
             | ExprKind::Ret(..)
+            | ExprKind::OffsetOf(..)
             | ExprKind::Struct(..)
             | ExprKind::Repeat(..)
             | ExprKind::Yield(..) => {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 79eb31bb105..419b6afe7c6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -3048,9 +3048,9 @@ pub(crate) mod dep_tracking {
 #[derive(Clone, Copy, PartialEq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum OomStrategy {
     /// Generate a panic that can be caught by `catch_unwind`.
-    Panic,
+    Unwind,
 
-    /// Abort the process immediately.
+    /// Calls the panic hook as normal but aborts instead of unwinding.
     Abort,
 }
 
@@ -3059,7 +3059,7 @@ impl OomStrategy {
 
     pub fn should_panic(self) -> u8 {
         match self {
-            OomStrategy::Panic => 1,
+            OomStrategy::Unwind => 1,
             OomStrategy::Abort => 0,
         }
     }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 8e8ad72ec8a..98bcacbe7ff 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -662,7 +662,7 @@ mod parse {
 
     pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
         match v {
-            Some("panic") => *slot = OomStrategy::Panic,
+            Some("unwind") => *slot = OomStrategy::Unwind,
             Some("abort") => *slot = OomStrategy::Abort,
             _ => return false,
         }
@@ -1558,6 +1558,9 @@ options! {
         "use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \
         enabled, overriding all other checks. Passes that are not specified are enabled or \
         disabled by other flags as usual."),
+    mir_keep_place_mention: bool = (false, parse_bool, [TRACKED],
+        "keep place mention MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
+        (default: no)"),
     #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index c600298c51a..1eea0f63ca0 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -181,19 +181,23 @@ impl Span {
     #[inline]
     pub fn ctxt(self) -> SyntaxContext {
         let ctxt_or_tag = self.ctxt_or_tag as u32;
-        if ctxt_or_tag <= MAX_CTXT {
-            if self.len_or_tag == LEN_TAG || self.len_or_tag & PARENT_MASK == 0 {
-                // Inline format or interned format with inline ctxt.
-                SyntaxContext::from_u32(ctxt_or_tag)
+        // Check for interned format.
+        if self.len_or_tag == LEN_TAG {
+            if ctxt_or_tag == CTXT_TAG {
+                // Fully interned format.
+                let index = self.base_or_index;
+                with_span_interner(|interner| interner.spans[index as usize].ctxt)
             } else {
-                // Inline format or interned format with inline parent.
-                // We know that the SyntaxContext is root.
-                SyntaxContext::root()
+                // Interned format with inline ctxt.
+                SyntaxContext::from_u32(ctxt_or_tag)
             }
+        } else if self.len_or_tag & PARENT_MASK == 0 {
+            // Inline format with inline ctxt.
+            SyntaxContext::from_u32(ctxt_or_tag)
         } else {
-            // Interned format.
-            let index = self.base_or_index;
-            with_span_interner(|interner| interner.spans[index as usize].ctxt)
+            // Inline format with inline parent.
+            // We know that the SyntaxContext is root.
+            SyntaxContext::root()
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d6ee7ac34aa..9891915d076 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1037,6 +1037,7 @@ symbols! {
         object_safe_for_dispatch,
         of,
         offset,
+        offset_of,
         omit_gdb_pretty_printer_section,
         on,
         on_unimplemented,
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index b4d5b7f3621..985b2210745 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -83,7 +83,7 @@ impl SymbolNamesTest<'_> {
             tcx.sess.emit_err(TestOutput {
                 span: attr.span,
                 kind: Kind::DefPath,
-                content: with_no_trimmed_paths!(tcx.def_path_str(def_id.to_def_id())),
+                content: with_no_trimmed_paths!(tcx.def_path_str(def_id)),
             });
         }
     }
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 8d2e92cc76c..589cd3cf96b 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -124,6 +124,21 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
     {
         Ty::is_unit(self)
     }
+
+    pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
+    where
+        Ty: TyAbiInterface<'a, C>,
+    {
+        let mut layout = self;
+        let mut offset = Size::ZERO;
+
+        for index in indices {
+            offset += layout.fields.offset(index);
+            layout = layout.field(cx, index);
+        }
+
+        offset
+    }
 }
 
 impl<'a, Ty> TyAndLayout<'a, Ty> {
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
index ebd74012dcd..9bcd56bed00 100644
--- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
+    base.cpu = "M68020".into();
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 3a2acbeb32e..f0840e0443c 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -73,7 +73,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                     goal.predicate.projection_ty,
                     assumption_projection_pred.projection_ty,
                 )?;
-                ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)?;
+                ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
+                    .expect("expected goal term to be fully unconstrained");
                 ecx.add_goals(requirements);
                 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             })
@@ -114,7 +115,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                     .into_iter()
                     .map(|pred| goal.with(tcx, pred)),
                 );
-                ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)?;
+                ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
+                    .expect("expected goal term to be fully unconstrained");
                 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             })
         } else {
@@ -206,7 +208,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 ty.map_bound(|ty| ty.into())
             };
 
-            ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))?;
+            ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
+                .expect("expected goal term to be fully unconstrained");
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
@@ -375,7 +378,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 ),
             };
 
-            ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into())?;
+            ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into())
+                .expect("expected goal term to be fully unconstrained");
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
@@ -513,7 +517,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         };
 
         ecx.probe(|ecx| {
-            ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())?;
+            ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())
+                .expect("expected goal term to be fully unconstrained");
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index e650792f4d5..b08a92570ed 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -256,6 +256,7 @@ fn recurse_build<'tcx>(
         ExprKind::VarRef { .. }
         | ExprKind::UpvarRef { .. }
         | ExprKind::StaticRef { .. }
+        | ExprKind::OffsetOf { .. }
         | ExprKind::ThreadLocalRef(_) => {
             error(GenericConstantTooComplexSub::OperationNotSupported(node.span))?
         }
@@ -347,6 +348,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
             | thir::ExprKind::ZstLiteral { .. }
             | thir::ExprKind::StaticRef { .. }
             | thir::ExprKind::InlineAsm(_)
+            | thir::ExprKind::OffsetOf { .. }
             | thir::ExprKind::ThreadLocalRef(_)
             | thir::ExprKind::Yield { .. } => false,
         }
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 62e699eefd7..4c1f2dd0e53 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -203,6 +203,10 @@ pub enum TyKind<I: Interner> {
     /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
     /// back to inference variables in a new inference context when inside of the query.
     ///
+    /// It is conventional to render anonymous bound types like `^N` or `^D_N`,
+    /// where `N` is the bound variable's anonymous index into the binder, and
+    /// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
+    ///
     /// See the `rustc-dev-guide` for more details about
     /// [higher-ranked trait bounds][1] and [canonical queries][2].
     ///
@@ -212,6 +216,12 @@ pub enum TyKind<I: Interner> {
 
     /// A placeholder type, used during higher ranked subtyping to instantiate
     /// bound variables.
+    ///
+    /// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
+    /// where `N` is the placeholder variable's anonymous index (which corresponds
+    /// to the bound variable's index from the binder from which it was instantiated),
+    /// and `U` is the universe index in which it is instantiated, or totally omitted
+    /// if the universe index is zero.
     Placeholder(I::PlaceholderType),
 
     /// A type variable used during type checking.
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 95c07abf731..8975ba3f06b 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -35,3 +35,6 @@ compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
 compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
 compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
+
+# Make panics and failed asserts immediately abort without formatting any message
+panic_immediate_abort = ["core/panic_immediate_abort"]
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 6f2ba957bcd..0db23e55a86 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -14,6 +14,11 @@ use core::ptr::{self, NonNull};
 #[doc(inline)]
 pub use core::alloc::*;
 
+#[cfg(not(no_global_oom_handling))]
+use core::any::Any;
+#[cfg(not(no_global_oom_handling))]
+use core::panic::BoxMeUp;
+
 #[cfg(test)]
 mod tests;
 
@@ -343,14 +348,77 @@ pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A)
     }
 }
 
-// # Allocation error handler
+/// Payload passed to the panic handler when `handle_alloc_error` is called.
+#[unstable(feature = "panic_oom_payload", issue = "none")]
+#[derive(Debug)]
+pub struct AllocErrorPanicPayload {
+    layout: Layout,
+}
+
+impl AllocErrorPanicPayload {
+    /// Internal function for the standard library to clone a payload.
+    #[unstable(feature = "std_internals", issue = "none")]
+    #[doc(hidden)]
+    pub fn internal_clone(&self) -> Self {
+        AllocErrorPanicPayload { layout: self.layout }
+    }
 
+    /// Returns the [`Layout`] of the allocation attempt that caused the error.
+    #[unstable(feature = "panic_oom_payload", issue = "none")]
+    pub fn layout(&self) -> Layout {
+        self.layout
+    }
+}
+
+#[unstable(feature = "std_internals", issue = "none")]
 #[cfg(not(no_global_oom_handling))]
-extern "Rust" {
-    // This is the magic symbol to call the global alloc error handler. rustc generates
-    // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
-    // default implementations below (`__rdl_oom`) otherwise.
-    fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
+unsafe impl BoxMeUp for AllocErrorPanicPayload {
+    fn take_box(&mut self) -> *mut (dyn Any + Send) {
+        use crate::boxed::Box;
+        Box::into_raw(Box::new(self.internal_clone()))
+    }
+
+    fn get(&mut self) -> &(dyn Any + Send) {
+        self
+    }
+}
+
+// # Allocation error handler
+
+#[cfg(all(not(no_global_oom_handling), not(test)))]
+fn rust_oom(layout: Layout) -> ! {
+    if cfg!(feature = "panic_immediate_abort") {
+        core::intrinsics::abort()
+    }
+
+    extern "Rust" {
+        // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
+        // that gets resolved to the `#[panic_handler]` function.
+        #[lang = "panic_impl"]
+        fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !;
+
+        // This symbol is emitted by rustc .
+        // Its value depends on the -Zoom={unwind,abort} compiler option.
+        static __rust_alloc_error_handler_should_panic: u8;
+    }
+
+    // Hack to work around issues with the lifetime of Arguments.
+    match format_args!("memory allocation of {} bytes failed", layout.size()) {
+        fmt => {
+            // Create a PanicInfo with a custom payload for the panic handler.
+            let can_unwind = unsafe { __rust_alloc_error_handler_should_panic != 0 };
+            let mut pi = core::panic::PanicInfo::internal_constructor(
+                Some(&fmt),
+                core::panic::Location::caller(),
+                can_unwind,
+            );
+            let payload = AllocErrorPanicPayload { layout };
+            pi.set_payload(&payload);
+
+            // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
+            unsafe { panic_impl(&pi) }
+        }
+    }
 }
 
 /// Abort on memory allocation error or failure.
@@ -358,13 +426,6 @@ extern "Rust" {
 /// Callers of memory allocation APIs wishing to abort computation
 /// in response to an allocation error are encouraged to call this function,
 /// rather than directly invoking `panic!` or similar.
-///
-/// The default behavior of this function is to print a message to standard error
-/// and abort the process.
-/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
-///
-/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
-/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
 #[cfg(all(not(no_global_oom_handling), not(test)))]
@@ -375,9 +436,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
     }
 
     fn rt_error(layout: Layout) -> ! {
-        unsafe {
-            __rust_alloc_error_handler(layout.size(), layout.align());
-        }
+        rust_oom(layout);
     }
 
     unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) }
@@ -387,6 +446,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
 #[cfg(all(not(no_global_oom_handling), test))]
 pub use std::alloc::handle_alloc_error;
 
+#[cfg(bootstrap)]
 #[cfg(all(not(no_global_oom_handling), not(test)))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
@@ -398,7 +458,7 @@ pub mod __alloc_error_handler {
     pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
         extern "Rust" {
             // This symbol is emitted by rustc next to __rust_alloc_error_handler.
-            // Its value depends on the -Zoom={panic,abort} compiler option.
+            // Its value depends on the -Zoom={unwind,abort} compiler option.
             static __rust_alloc_error_handler_should_panic: u8;
         }
 
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index ad48315fd70..f83c8f83cc9 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -7,7 +7,7 @@ use core::fmt::{self, Debug, Display, Formatter};
 use core::marker::PhantomData;
 #[cfg(not(no_global_oom_handling))]
 use core::marker::Unsize;
-use core::mem;
+use core::mem::{self, SizedTypeProperties};
 use core::ops::{Deref, DerefMut};
 use core::ptr::Pointee;
 use core::ptr::{self, NonNull};
@@ -202,9 +202,7 @@ impl<H> WithHeader<H> {
             let ptr = if layout.size() == 0 {
                 // Some paranoia checking, mostly so that the ThinBox tests are
                 // more able to catch issues.
-                debug_assert!(
-                    value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
-                );
+                debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);
                 layout.dangling()
             } else {
                 let ptr = alloc::alloc(layout);
@@ -249,9 +247,7 @@ impl<H> WithHeader<H> {
                         alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
                     } else {
                         debug_assert!(
-                            value_offset == 0
-                                && mem::size_of::<H>() == 0
-                                && self.value_layout.size() == 0
+                            value_offset == 0 && H::IS_ZST && self.value_layout.size() == 0
                         );
                     }
                 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index a002421aeef..2c6a266e2a1 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -135,6 +135,7 @@
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_uninit_array_transpose)]
+#![feature(panic_internals)]
 #![feature(pattern)]
 #![feature(pointer_byte_offsets)]
 #![feature(provide_any)]
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index e3ca6eb7833..3091efabd68 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -112,9 +112,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
             let unyielded_ptr = this.iter.as_slice().as_ptr();
 
             // ZSTs have no identity, so we don't need to move them around.
-            let needs_move = mem::size_of::<T>() != 0;
-
-            if needs_move {
+            if !T::IS_ZST {
                 let start_ptr = source_vec.as_mut_ptr().add(start);
 
                 // memmove back unyielded elements
diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs
index 8c03f1692d9..650f9213890 100644
--- a/library/alloc/src/vec/drain_filter.rs
+++ b/library/alloc/src/vec/drain_filter.rs
@@ -1,5 +1,5 @@
 use crate::alloc::{Allocator, Global};
-use core::mem::{self, ManuallyDrop};
+use core::mem::{ManuallyDrop, SizedTypeProperties};
 use core::ptr;
 use core::slice;
 
@@ -96,9 +96,7 @@ where
 
         unsafe {
             // ZSTs have no identity, so we don't need to move them around.
-            let needs_move = mem::size_of::<T>() != 0;
-
-            if needs_move && this.idx < this.old_len && this.del > 0 {
+            if !T::IS_ZST && this.idx < this.old_len && this.del > 0 {
                 let ptr = this.vec.as_mut_ptr();
                 let src = ptr.add(this.idx);
                 let dst = src.sub(this.del);
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 7c93c93b4a0..cc3179ee780 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1531,16 +1531,6 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
-    /// Attribute macro applied to a function to register it as a handler for allocation failure.
-    ///
-    /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html).
-    #[unstable(feature = "alloc_error_handler", issue = "51540")]
-    #[allow_internal_unstable(rustc_attrs)]
-    #[rustc_builtin_macro]
-    pub macro alloc_error_handler($item:item) {
-        /* compiler built-in */
-    }
-
     /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise.
     #[unstable(
         feature = "cfg_accessible",
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 30ec73cabf8..7d2f2971523 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1279,3 +1279,45 @@ pub trait SizedTypeProperties: Sized {
 #[doc(hidden)]
 #[unstable(feature = "sized_type_properties", issue = "none")]
 impl<T> SizedTypeProperties for T {}
+
+/// Expands to the offset in bytes of a field from the beginning of the given type.
+///
+/// Only structs, unions and tuples are supported.
+///
+/// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`.
+///
+/// Note that the output of this macro is not stable, except for `#[repr(C)]` types.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(offset_of)]
+///
+/// use std::mem;
+/// #[repr(C)]
+/// struct FieldStruct {
+///     first: u8,
+///     second: u16,
+///     third: u8
+/// }
+///
+/// assert_eq!(mem::offset_of!(FieldStruct, first), 0);
+/// assert_eq!(mem::offset_of!(FieldStruct, second), 2);
+/// assert_eq!(mem::offset_of!(FieldStruct, third), 4);
+///
+/// #[repr(C)]
+/// struct NestedA {
+///     b: NestedB
+/// }
+///
+/// #[repr(C)]
+/// struct NestedB(u8);
+///
+/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
+/// ```
+#[unstable(feature = "offset_of", issue = "106655")]
+#[rustc_builtin_macro]
+#[cfg(not(bootstrap))]
+pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
+    /* compiler built-in */
+}
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 10525a16f3a..9c4c0f6ab7a 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -76,9 +76,7 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable};
 // Do not `doc(no_inline)` so that they become doc items on their own
 // (no public module for them to be re-exported from).
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-pub use crate::macros::builtin::{
-    alloc_error_handler, bench, derive, global_allocator, test, test_case,
-};
+pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
 
 #[unstable(feature = "derive_const", issue = "none")]
 pub use crate::macros::builtin::derive_const;
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index b73e35f1e91..b1ca872b845 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -73,7 +73,7 @@ macro_rules! iterator {
             // Unsafe because the offset must not exceed `self.len()`.
             #[inline(always)]
             unsafe fn post_inc_start(&mut self, offset: usize) -> * $raw_mut T {
-                if mem::size_of::<T>() == 0 {
+                if T::IS_ZST {
                     zst_shrink!(self, offset);
                     self.ptr.as_ptr()
                 } else {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index f460da35dd3..84859a54c26 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -109,6 +109,7 @@
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
+#![cfg_attr(not(bootstrap), feature(offset_of))]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![deny(fuzzy_provenance_casts)]
 
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index f7740a114e7..7f033816901 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -364,3 +364,193 @@ fn const_maybe_uninit() {
 
     assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
 }
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of() {
+    #[repr(C)]
+    struct Foo {
+        x: u8,
+        y: u16,
+        z: Bar,
+    }
+
+    #[repr(C)]
+    struct Bar(u8, u8);
+
+    assert_eq!(offset_of!(Foo, x), 0);
+    assert_eq!(offset_of!(Foo, y), 2);
+    assert_eq!(offset_of!(Foo, z.0), 4);
+    assert_eq!(offset_of!(Foo, z.1), 5);
+
+    // Layout of tuples is unstable
+    assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
+    assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_union() {
+    #[repr(C)]
+    union Foo {
+        x: u8,
+        y: u16,
+        z: Bar,
+    }
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    struct Bar(u8, u8);
+
+    assert_eq!(offset_of!(Foo, x), 0);
+    assert_eq!(offset_of!(Foo, y), 0);
+    assert_eq!(offset_of!(Foo, z.0), 0);
+    assert_eq!(offset_of!(Foo, z.1), 1);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_dst() {
+    #[repr(C)]
+    struct Alpha {
+        x: u8,
+        y: u16,
+        z: [u8],
+    }
+
+    trait Trait {}
+
+    #[repr(C)]
+    struct Beta {
+        x: u8,
+        y: u16,
+        z: dyn Trait,
+    }
+
+    extern "C" {
+        type Extern;
+    }
+
+    #[repr(C)]
+    struct Gamma {
+        x: u8,
+        y: u16,
+        z: Extern,
+    }
+
+    assert_eq!(offset_of!(Alpha, x), 0);
+    assert_eq!(offset_of!(Alpha, y), 2);
+
+    assert_eq!(offset_of!(Beta, x), 0);
+    assert_eq!(offset_of!(Beta, y), 2);
+
+    assert_eq!(offset_of!(Gamma, x), 0);
+    assert_eq!(offset_of!(Gamma, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_packed() {
+    #[repr(C, packed)]
+    struct Foo {
+        x: u8,
+        y: u16,
+    }
+
+    assert_eq!(offset_of!(Foo, x), 0);
+    assert_eq!(offset_of!(Foo, y), 1);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_projection() {
+    #[repr(C)]
+    struct Foo {
+        x: u8,
+        y: u16,
+    }
+
+    trait Projector {
+        type Type;
+    }
+
+    impl Projector for () {
+        type Type = Foo;
+    }
+
+    assert_eq!(offset_of!(<() as Projector>::Type, x), 0);
+    assert_eq!(offset_of!(<() as Projector>::Type, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_alias() {
+    #[repr(C)]
+    struct Foo {
+        x: u8,
+        y: u16,
+    }
+
+    type Bar = Foo;
+
+    assert_eq!(offset_of!(Bar, x), 0);
+    assert_eq!(offset_of!(Bar, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn const_offset_of() {
+    #[repr(C)]
+    struct Foo {
+        x: u8,
+        y: u16,
+    }
+
+    const X_OFFSET: usize = offset_of!(Foo, x);
+    const Y_OFFSET: usize = offset_of!(Foo, y);
+
+    assert_eq!(X_OFFSET, 0);
+    assert_eq!(Y_OFFSET, 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_without_const_promotion() {
+    #[repr(C)]
+    struct Foo<SuppressConstPromotion> {
+        x: u8,
+        y: u16,
+        _scp: SuppressConstPromotion,
+    }
+
+    // Normally, offset_of is always const promoted.
+    // The generic parameter prevents this from happening.
+    // This is needed to test the codegen impl of offset_of
+    fn inner<SuppressConstPromotion>() {
+        assert_eq!(offset_of!(Foo<SuppressConstPromotion>, x), 0);
+        assert_eq!(offset_of!(Foo<SuppressConstPromotion>, y), 2);
+    }
+
+    inner::<()>();
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_addr() {
+    #[repr(C)]
+    struct Foo {
+        x: u8,
+        y: u16,
+        z: Bar,
+    }
+
+    #[repr(C)]
+    struct Bar(u8, u8);
+
+    let base = Foo { x: 0, y: 0, z: Bar(0, 0) };
+
+    assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, x), ptr::addr_of!(base.x).addr());
+    assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
+    assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
+    assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
+}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index f2fda64a1ee..109387b09d0 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -67,7 +67,7 @@ llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
 
 # Make panics and failed asserts immediately abort without formatting any message
-panic_immediate_abort = ["core/panic_immediate_abort"]
+panic_immediate_abort = ["alloc/panic_immediate_abort"]
 
 # Enable std_detect default features for stdarch/crates/std_detect:
 # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index c5a5991cc81..448a8edc291 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -57,9 +57,8 @@
 #![stable(feature = "alloc_module", since = "1.28.0")]
 
 use core::intrinsics;
+use core::ptr;
 use core::ptr::NonNull;
-use core::sync::atomic::{AtomicPtr, Ordering};
-use core::{mem, ptr};
 
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
@@ -286,76 +285,6 @@ unsafe impl Allocator for System {
     }
 }
 
-static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
-
-/// Registers a custom allocation error hook, replacing any that was previously registered.
-///
-/// The allocation error hook is invoked when an infallible memory allocation fails, before
-/// the runtime aborts. The default hook prints a message to standard error,
-/// but this behavior can be customized with the [`set_alloc_error_hook`] and
-/// [`take_alloc_error_hook`] functions.
-///
-/// The hook is provided with a `Layout` struct which contains information
-/// about the allocation that failed.
-///
-/// The allocation error hook is a global resource.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(alloc_error_hook)]
-///
-/// use std::alloc::{Layout, set_alloc_error_hook};
-///
-/// fn custom_alloc_error_hook(layout: Layout) {
-///    panic!("memory allocation of {} bytes failed", layout.size());
-/// }
-///
-/// set_alloc_error_hook(custom_alloc_error_hook);
-/// ```
-#[unstable(feature = "alloc_error_hook", issue = "51245")]
-pub fn set_alloc_error_hook(hook: fn(Layout)) {
-    HOOK.store(hook as *mut (), Ordering::SeqCst);
-}
-
-/// Unregisters the current allocation error hook, returning it.
-///
-/// *See also the function [`set_alloc_error_hook`].*
-///
-/// If no custom hook is registered, the default hook will be returned.
-#[unstable(feature = "alloc_error_hook", issue = "51245")]
-pub fn take_alloc_error_hook() -> fn(Layout) {
-    let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
-    if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }
-}
-
-fn default_alloc_error_hook(layout: Layout) {
-    extern "Rust" {
-        // This symbol is emitted by rustc next to __rust_alloc_error_handler.
-        // Its value depends on the -Zoom={panic,abort} compiler option.
-        static __rust_alloc_error_handler_should_panic: u8;
-    }
-
-    #[allow(unused_unsafe)]
-    if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
-        panic!("memory allocation of {} bytes failed", layout.size());
-    } else {
-        rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
-    }
-}
-
-#[cfg(not(test))]
-#[doc(hidden)]
-#[alloc_error_handler]
-#[unstable(feature = "alloc_internals", issue = "none")]
-pub fn rust_oom(layout: Layout) -> ! {
-    let hook = HOOK.load(Ordering::SeqCst);
-    let hook: fn(Layout) =
-        if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } };
-    hook(layout);
-    crate::process::abort()
-}
-
 #[cfg(not(test))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index c550378e7d6..55580b23a62 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -249,9 +249,9 @@ pub struct DirBuilder {
 pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
     fn inner(path: &Path) -> io::Result<Vec<u8>> {
         let mut file = File::open(path)?;
-        let size = file.metadata().map(|m| m.len()).unwrap_or(0);
-        let mut bytes = Vec::with_capacity(size as usize);
-        io::default_read_to_end(&mut file, &mut bytes)?;
+        let size = file.metadata().map(|m| m.len() as usize).ok();
+        let mut bytes = Vec::with_capacity(size.unwrap_or(0));
+        io::default_read_to_end(&mut file, &mut bytes, size)?;
         Ok(bytes)
     }
     inner(path.as_ref())
@@ -289,9 +289,9 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
 pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
     fn inner(path: &Path) -> io::Result<String> {
         let mut file = File::open(path)?;
-        let size = file.metadata().map(|m| m.len()).unwrap_or(0);
-        let mut string = String::with_capacity(size as usize);
-        io::default_read_to_string(&mut file, &mut string)?;
+        let size = file.metadata().map(|m| m.len() as usize).ok();
+        let mut string = String::with_capacity(size.unwrap_or(0));
+        io::default_read_to_string(&mut file, &mut string, size)?;
         Ok(string)
     }
     inner(path.as_ref())
@@ -732,12 +732,12 @@ impl fmt::Debug for File {
 }
 
 /// Indicates how much extra capacity is needed to read the rest of the file.
-fn buffer_capacity_required(mut file: &File) -> usize {
-    let size = file.metadata().map(|m| m.len()).unwrap_or(0);
-    let pos = file.stream_position().unwrap_or(0);
+fn buffer_capacity_required(mut file: &File) -> Option<usize> {
+    let size = file.metadata().map(|m| m.len()).ok()?;
+    let pos = file.stream_position().ok()?;
     // Don't worry about `usize` overflow because reading will fail regardless
     // in that case.
-    size.saturating_sub(pos) as usize
+    Some(size.saturating_sub(pos) as usize)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -761,14 +761,16 @@ impl Read for File {
 
     // Reserves space in the buffer based on the file size when available.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        buf.reserve(buffer_capacity_required(self));
-        io::default_read_to_end(self, buf)
+        let size = buffer_capacity_required(self);
+        buf.reserve(size.unwrap_or(0));
+        io::default_read_to_end(self, buf, size)
     }
 
     // Reserves space in the buffer based on the file size when available.
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        buf.reserve(buffer_capacity_required(self));
-        io::default_read_to_string(self, buf)
+        let size = buffer_capacity_required(self);
+        buf.reserve(size.unwrap_or(0));
+        io::default_read_to_string(self, buf, size)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -817,14 +819,16 @@ impl Read for &File {
 
     // Reserves space in the buffer based on the file size when available.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        buf.reserve(buffer_capacity_required(self));
-        io::default_read_to_end(self, buf)
+        let size = buffer_capacity_required(self);
+        buf.reserve(size.unwrap_or(0));
+        io::default_read_to_end(self, buf, size)
     }
 
     // Reserves space in the buffer based on the file size when available.
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        buf.reserve(buffer_capacity_required(self));
-        io::default_read_to_string(self, buf)
+        let size = buffer_capacity_required(self);
+        buf.reserve(size.unwrap_or(0));
+        io::default_read_to_string(self, buf, size)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 8c1c8cac0ef..4cd7885bd4a 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -357,9 +357,17 @@ where
 // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
 // time is 4,500 times (!) slower than a default reservation size of 32 if the
 // reader has a very small amount of data to return.
-pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
+pub(crate) fn default_read_to_end<R: Read + ?Sized>(
+    r: &mut R,
+    buf: &mut Vec<u8>,
+    size_hint: Option<usize>,
+) -> Result<usize> {
     let start_len = buf.len();
     let start_cap = buf.capacity();
+    // Optionally limit the maximum bytes read on each iteration.
+    // This adds an arbitrary fiddle factor to allow for more data than we expect.
+    let max_read_size =
+        size_hint.and_then(|s| s.checked_add(1024)?.checked_next_multiple_of(DEFAULT_BUF_SIZE));
 
     let mut initialized = 0; // Extra initialized bytes from previous loop iteration
     loop {
@@ -367,7 +375,12 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
             buf.reserve(32); // buf is full, need more space
         }
 
-        let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into();
+        let mut spare = buf.spare_capacity_mut();
+        if let Some(size) = max_read_size {
+            let len = cmp::min(spare.len(), size);
+            spare = &mut spare[..len]
+        }
+        let mut read_buf: BorrowedBuf<'_> = spare.into();
 
         // SAFETY: These bytes were initialized but not filled in the previous loop
         unsafe {
@@ -419,6 +432,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
 pub(crate) fn default_read_to_string<R: Read + ?Sized>(
     r: &mut R,
     buf: &mut String,
+    size_hint: Option<usize>,
 ) -> Result<usize> {
     // Note that we do *not* call `r.read_to_end()` here. We are passing
     // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
@@ -429,7 +443,7 @@ pub(crate) fn default_read_to_string<R: Read + ?Sized>(
     // To prevent extraneously checking the UTF-8-ness of the entire buffer
     // we pass it to our hardcoded `default_read_to_end` implementation which
     // we know is guaranteed to only read data into the end of the buffer.
-    unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) }
+    unsafe { append_to_string(buf, |b| default_read_to_end(r, b, size_hint)) }
 }
 
 pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
@@ -709,7 +723,7 @@ pub trait Read {
     /// [`std::fs::read`]: crate::fs::read
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
-        default_read_to_end(self, buf)
+        default_read_to_end(self, buf, None)
     }
 
     /// Read all bytes until EOF in this source, appending them to `buf`.
@@ -752,7 +766,7 @@ pub trait Read {
     /// [`std::fs::read_to_string`]: crate::fs::read_to_string
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
-        default_read_to_string(self, buf)
+        default_read_to_string(self, buf, None)
     }
 
     /// Read the exact number of bytes required to fill `buf`.
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index f4a886d889a..6d30f5e6c6c 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -314,7 +314,7 @@ fn bench_read_to_end(b: &mut test::Bencher) {
     b.iter(|| {
         let mut lr = repeat(1).take(10000000);
         let mut vec = Vec::with_capacity(1024);
-        super::default_read_to_end(&mut lr, &mut vec)
+        super::default_read_to_end(&mut lr, &mut vec, None)
     });
 }
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 98fcc76aa98..933f75d638b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -236,7 +236,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![feature(alloc_error_handler)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
@@ -289,6 +288,7 @@
 #![feature(float_next_up_down)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
+#![feature(int_roundings)]
 #![feature(ip)]
 #![feature(ip_in_core)]
 #![feature(maybe_uninit_slice)]
@@ -319,6 +319,7 @@
 #![feature(get_mut_unchecked)]
 #![feature(map_try_insert)]
 #![feature(new_uninit)]
+#![feature(panic_oom_payload)]
 #![feature(slice_concat_trait)]
 #![feature(thin_box)]
 #![feature(try_reserve_kind)]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index a46a29cbad6..ca4cf68ad54 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -245,19 +245,24 @@ fn default_hook(info: &PanicInfo<'_>) {
 
     // The current implementation always returns `Some`.
     let location = info.location().unwrap();
-
-    let msg = match info.payload().downcast_ref::<&'static str>() {
-        Some(s) => *s,
-        None => match info.payload().downcast_ref::<String>() {
-            Some(s) => &s[..],
-            None => "Box<dyn Any>",
-        },
-    };
     let thread = thread_info::current_thread();
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
     let write = |err: &mut dyn crate::io::Write| {
-        let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
+        // Use the panic message directly if available, otherwise take it from
+        // the payload.
+        if let Some(msg) = info.message() {
+            let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
+        } else {
+            let msg = if let Some(s) = info.payload().downcast_ref::<&'static str>() {
+                *s
+            } else if let Some(s) = info.payload().downcast_ref::<String>() {
+                &s[..]
+            } else {
+                "Box<dyn Any>"
+            };
+            let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
+        }
 
         static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
@@ -524,6 +529,8 @@ pub fn panicking() -> bool {
 #[cfg(not(test))]
 #[panic_handler]
 pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
+    use alloc::alloc::AllocErrorPanicPayload;
+
     struct PanicPayload<'a> {
         inner: &'a fmt::Arguments<'a>,
         string: Option<String>,
@@ -550,8 +557,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
     unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
         fn take_box(&mut self) -> *mut (dyn Any + Send) {
             // We do two allocations here, unfortunately. But (a) they're required with the current
-            // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
-            // begin_panic below).
+            // scheme, and (b) OOM uses its own separate payload type which doesn't allocate.
             let contents = mem::take(self.fill());
             Box::into_raw(Box::new(contents))
         }
@@ -576,7 +582,14 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
     let loc = info.location().unwrap(); // The current implementation always returns Some
     let msg = info.message().unwrap(); // The current implementation always returns Some
     crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
-        if let Some(msg) = msg.as_str() {
+        if let Some(payload) = info.payload().downcast_ref::<AllocErrorPanicPayload>() {
+            rust_panic_with_hook(
+                &mut payload.internal_clone(),
+                info.message(),
+                loc,
+                info.can_unwind(),
+            );
+        } else if let Some(msg) = msg.as_str() {
             rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind());
         } else {
             rust_panic_with_hook(
@@ -623,11 +636,7 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
 
     unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
         fn take_box(&mut self) -> *mut (dyn Any + Send) {
-            // Note that this should be the only allocation performed in this code path. Currently
-            // this means that panic!() on OOM will invoke this code path, but then again we're not
-            // really ready for panic on OOM anyway. If we do start doing this, then we should
-            // propagate this allocation to be performed in the parent of this thread instead of the
-            // thread that's panicking.
+            // Note that this should be the only allocation performed in this code path.
             let data = match self.inner.take() {
                 Some(a) => Box::new(a) as Box<dyn Any + Send>,
                 None => process::abort(),
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 2aefd7c513d..4f325a70b18 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -60,9 +60,7 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable};
 // Do not `doc(no_inline)` so that they become doc items on their own
 // (no public module for them to be re-exported from).
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-pub use core::prelude::v1::{
-    alloc_error_handler, bench, derive, global_allocator, test, test_case,
-};
+pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
 
 #[unstable(feature = "derive_const", issue = "none")]
 pub use core::prelude::v1::derive_const;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b392ba05836..46834a1d7f4 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -258,8 +258,6 @@ pub(crate) fn create_config(
         override_queries: Some(|_sess, providers, _external_providers| {
             // Most lints will require typechecking, so just don't run them.
             providers.lint_mod = |_, _| {};
-            // Prevent `rustc_hir_analysis::check_crate` from calling `typeck` on all bodies.
-            providers.typeck_item_bodies = |_, _| {};
             // hack so that `used_trait_imports` won't try to call typeck
             providers.used_trait_imports = |_, _| {
                 static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 463184acaa1..a5f08fdac11 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -32,6 +32,7 @@ mod context;
 mod print_item;
 mod sidebar;
 mod span_map;
+mod type_layout;
 mod write_shared;
 
 pub(crate) use self::context::*;
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 9a968e48b27..3e71d41ec96 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -6,16 +6,14 @@ use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::stability;
-use rustc_middle::span_bug;
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, Adt, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
 
+use super::type_layout::document_type_layout;
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
     item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
@@ -1933,118 +1931,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a
     })
 }
 
-fn document_type_layout<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    ty_def_id: DefId,
-) -> impl fmt::Display + 'a + Captures<'cx> {
-    fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
-        if layout.abi.is_unsized() {
-            write!(w, "(unsized)").unwrap();
-        } else {
-            let size = layout.size.bytes() - tag_size;
-            write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
-            if layout.abi.is_uninhabited() {
-                write!(
-                    w,
-                    " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
-                ).unwrap();
-            }
-        }
-    }
-
-    display_fn(move |mut f| {
-        if !cx.shared.show_type_layout {
-            return Ok(());
-        }
-
-        writeln!(
-            f,
-            "<h2 id=\"layout\" class=\"small-section-header\"> \
-            Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
-        )?;
-        writeln!(f, "<div class=\"docblock\">")?;
-
-        let tcx = cx.tcx();
-        let param_env = tcx.param_env(ty_def_id);
-        let ty = tcx.type_of(ty_def_id).subst_identity();
-        match tcx.layout_of(param_env.and(ty)) {
-            Ok(ty_layout) => {
-                writeln!(
-                    f,
-                    "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
-                    <strong>completely unstable</strong> and may even differ between compilations. \
-                    The only exception is types with certain <code>repr(...)</code> attributes. \
-                    Please see the Rust Reference’s \
-                    <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
-                    chapter for details on type layout guarantees.</p></div>"
-                )?;
-                f.write_str("<p><strong>Size:</strong> ")?;
-                write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
-                writeln!(f, "</p>")?;
-                if let Variants::Multiple { variants, tag, tag_encoding, .. } =
-                    &ty_layout.layout.variants()
-                {
-                    if !variants.is_empty() {
-                        f.write_str(
-                            "<p><strong>Size for each variant:</strong></p>\
-                                <ul>",
-                        )?;
-
-                        let Adt(adt, _) = ty_layout.ty.kind() else {
-                            span_bug!(tcx.def_span(ty_def_id), "not an adt")
-                        };
-
-                        let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
-                            0
-                        } else if let Primitive::Int(i, _) = tag.primitive() {
-                            i.size().bytes()
-                        } else {
-                            span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
-                        };
-
-                        for (index, layout) in variants.iter_enumerated() {
-                            let name = adt.variant(index).name;
-                            write!(&mut f, "<li><code>{name}</code>: ")?;
-                            write_size_of_layout(&mut f, layout, tag_size);
-                            writeln!(&mut f, "</li>")?;
-                        }
-                        f.write_str("</ul>")?;
-                    }
-                }
-            }
-            // This kind of layout error can occur with valid code, e.g. if you try to
-            // get the layout of a generic type such as `Vec<T>`.
-            Err(LayoutError::Unknown(_)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Unable to compute type layout, \
-                    possibly due to this type having generic parameters. \
-                    Layout can only be computed for concrete, fully-instantiated types.</p>"
-                )?;
-            }
-            // This kind of error probably can't happen with valid code, but we don't
-            // want to panic and prevent the docs from building, so we just let the
-            // user know that we couldn't compute the layout.
-            Err(LayoutError::SizeOverflow(_)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Encountered an error during type layout; \
-                    the type was too big.</p>"
-                )?;
-            }
-            Err(LayoutError::NormalizationFailure(_, _)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Encountered an error during type layout; \
-                    the type failed to be normalized.</p>"
-                )?;
-            }
-        }
-
-        writeln!(f, "</div>")
-    })
-}
-
 fn pluralize(count: usize) -> &'static str {
     if count > 1 { "s" } else { "" }
 }
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
new file mode 100644
index 00000000000..22aec623335
--- /dev/null
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -0,0 +1,86 @@
+use askama::Template;
+
+use rustc_data_structures::captures::Captures;
+use rustc_hir::def_id::DefId;
+use rustc_middle::span_bug;
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::Adt;
+use rustc_span::symbol::Symbol;
+use rustc_target::abi::{Primitive, TagEncoding, Variants};
+
+use std::fmt;
+
+use crate::html::format::display_fn;
+use crate::html::render::Context;
+
+#[derive(Template)]
+#[template(path = "type_layout.html")]
+struct TypeLayout<'cx> {
+    variants: Vec<(Symbol, TypeLayoutSize)>,
+    type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
+}
+
+#[derive(Template)]
+#[template(path = "type_layout_size.html")]
+struct TypeLayoutSize {
+    is_unsized: bool,
+    is_uninhabited: bool,
+    size: u64,
+}
+
+pub(crate) fn document_type_layout<'a, 'cx: 'a>(
+    cx: &'a Context<'cx>,
+    ty_def_id: DefId,
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |f| {
+        if !cx.shared.show_type_layout {
+            return Ok(());
+        }
+
+        let tcx = cx.tcx();
+        let param_env = tcx.param_env(ty_def_id);
+        let ty = tcx.type_of(ty_def_id).subst_identity();
+        let type_layout = tcx.layout_of(param_env.and(ty));
+
+        let variants =
+            if let Ok(type_layout) = type_layout &&
+                let Variants::Multiple { variants, tag, tag_encoding, .. } =
+                    type_layout.layout.variants() &&
+                !variants.is_empty()
+            {
+                let tag_size =
+                    if let TagEncoding::Niche { .. } = tag_encoding {
+                        0
+                    } else if let Primitive::Int(i, _) = tag.primitive() {
+                        i.size().bytes()
+                    } else {
+                        span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int")
+                    };
+                variants
+                    .iter_enumerated()
+                    .map(|(variant_idx, variant_layout)| {
+                        let Adt(adt, _) = type_layout.ty.kind() else {
+                            span_bug!(cx.tcx().def_span(ty_def_id), "not an adt")
+                        };
+                        let name = adt.variant(variant_idx).name;
+                        let is_unsized = variant_layout.abi.is_unsized();
+                        let is_uninhabited = variant_layout.abi.is_uninhabited();
+                        let size = variant_layout.size.bytes() - tag_size;
+                        let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
+                        (name, type_layout_size)
+                    })
+                    .collect()
+            } else {
+                Vec::new()
+            };
+
+        let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
+            let is_unsized = layout.abi.is_unsized();
+            let is_uninhabited = layout.abi.is_uninhabited();
+            let size = layout.size.bytes();
+            TypeLayoutSize { is_unsized, is_uninhabited, size }
+        });
+
+        Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap())
+    })
+}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 93d657fd605..bccf675c14b 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -375,10 +375,7 @@ function preLoadCss(cssUrl) {
 
     function handleEscape(ev) {
         searchState.clearInputTimeout();
-        switchDisplayedElement(null);
-        if (browserSupportsHistoryApi()) {
-            history.replaceState(null, "", getNakedUrl() + window.location.hash);
-        }
+        searchState.hideResults();
         ev.preventDefault();
         searchState.defocus();
         window.hideAllModals(true); // true = reset focus for tooltips
@@ -533,9 +530,11 @@ function preLoadCss(cssUrl) {
         // ignored are included in the attribute `data-ignore-extern-crates`.
         const script = document
             .querySelector("script[data-ignore-extern-crates]");
-        const ignoreExternCrates = script ? script.getAttribute("data-ignore-extern-crates") : "";
+        const ignoreExternCrates = new Set(
+            (script ? script.getAttribute("data-ignore-extern-crates") : "").split(",")
+        );
         for (const lib of libs) {
-            if (lib === window.currentCrate || ignoreExternCrates.indexOf(lib) !== -1) {
+            if (lib === window.currentCrate || ignoreExternCrates.has(lib)) {
                 continue;
             }
             const structs = imp[lib];
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 929dae81c8d..3dc4f2149b8 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2412,10 +2412,6 @@ function initSearch(rawSearchIndex) {
         const searchAfter500ms = () => {
             searchState.clearInputTimeout();
             if (searchState.input.value.length === 0) {
-                if (browserSupportsHistoryApi()) {
-                    history.replaceState(null, window.currentCrate + " - Rust",
-                        getNakedUrl() + window.location.hash);
-                }
                 searchState.hideResults();
             } else {
                 searchState.timeout = setTimeout(search, 500);
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 9aa75517330..d999f3b36fd 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -52,12 +52,12 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
     const files = document.createElement("div");
     files.className = "files";
     if (elem[FILES_OFFSET]) {
+        const w = window.location.href.split("#")[0];
         for (const file_text of elem[FILES_OFFSET]) {
             const file = document.createElement("a");
             file.innerText = file_text;
             file.href = rootPath + "src/" + fullPath + file_text + ".html";
             file.addEventListener("click", closeSidebarIfMobile);
-            const w = window.location.href.split("#")[0];
             if (!hasFoundFile && w === file.href) {
                 file.className = "selected";
                 dirEntry.open = true;
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
new file mode 100644
index 00000000000..58b220c7428
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -0,0 +1,53 @@
+<h2 id="layout" class="small-section-header">  {# #}
+    Layout<a href="#layout" class="anchor">§</a> {# #}
+</h2> {# #}
+<div class="docblock"> {# #}
+    {% match type_layout_size %}
+        {% when Ok(type_layout_size) %}
+            <div class="warning"> {# #}
+                <p> {# #}
+                    <strong>Note:</strong> Most layout information is <strong>completely {#+ #}
+                    unstable</strong> and may even differ between compilations. {#+ #}
+                    The only exception is types with certain <code>repr(...)</code> {#+ #}
+                    attributes. Please see the Rust Reference’s {#+ #}
+                    <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
+                    chapter for details on type layout guarantees. {# #}
+                </p> {# #}
+            </div> {# #}
+            <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
+            {% if !variants.is_empty() %}
+                <p> {# #}
+                    <strong>Size for each variant:</strong> {# #}
+                </p> {# #}
+                <ul> {# #}
+                    {% for (name, layout_size) in variants %}
+                        <li> {# #}
+                            <code>{{ name }}</code>: {#+ #}
+                            {{ layout_size|safe }}
+                        </li> {# #}
+                    {% endfor %}
+                </ul> {# #}
+            {% endif %}
+        {# This kind of layout error can occur with valid code, e.g. if you try to
+           get the layout of a generic type such as `Vec<T>`. #}
+        {% when Err(LayoutError::Unknown(_)) %}
+            <p> {# #}
+                <strong>Note:</strong> Unable to compute type layout, {#+ #}
+                possibly due to this type having generic parameters. {#+ #}
+                Layout can only be computed for concrete, fully-instantiated types. {# #}
+            </p> {# #}
+        {# This kind of error probably can't happen with valid code, but we don't
+           want to panic and prevent the docs from building, so we just let the
+           user know that we couldn't compute the layout. #}
+        {% when Err(LayoutError::SizeOverflow(_)) %}
+            <p> {# #}
+                <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+                the type was too big. {# #}
+            </p> {# #}
+        {% when Err(LayoutError::NormalizationFailure(_, _)) %}
+            <p> {# #}
+                <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+                the type failed to be normalized. {# #}
+            </p> {# #}
+    {% endmatch %}
+</div> {# #}
diff --git a/src/librustdoc/html/templates/type_layout_size.html b/src/librustdoc/html/templates/type_layout_size.html
new file mode 100644
index 00000000000..9c2b39edc9f
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout_size.html
@@ -0,0 +1,12 @@
+{% if is_unsized %}
+  (unsized)
+{% else %}
+  {% if size == 1 %}
+    1 byte
+  {% else %}
+    {{ size +}} bytes
+  {% endif %}
+  {% if is_uninhabited %}
+    {# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)
+  {% endif %}
+{% endif %}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject d0a4cbcee614fdb7ba66e860e603a00a644d71f
+Subproject de80432f04da61d98dcbbc1572598071718ccfd
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index dec357ab75c..03b5a2d6d08 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
                 None,
                 &format!(
                     "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
-                    cx.tcx.def_path_str(item.owner_id.to_def_id())
+                    cx.tcx.def_path_str(item.owner_id)
                 ),
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index f0a1b1dfe56..5f1fdf00be8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -226,7 +226,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
                 | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
             })
             .fold(NeverLoopResult::Otherwise, combine_seq),
-        ExprKind::Yield(_, _)
+        ExprKind::OffsetOf(_, _)
+        | ExprKind::Yield(_, _)
         | ExprKind::Closure { .. }
         | ExprKind::Path(_)
         | ExprKind::ConstBlock(_)
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 04225beeb70..7945275393c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -342,6 +342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
             ExprKind::DropTemps(_) |
             ExprKind::Err(_) |
             ExprKind::InlineAsm(_) |
+            ExprKind::OffsetOf(_, _) |
             ExprKind::Let(_) |
             ExprKind::Lit(_) |
             ExprKind::Loop(_, _, _, _) |
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 1382c1a40da..98f5b47f7a0 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
                 None,
                 &format!(
                     "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute",
-                    cx.tcx.def_path_str(item.owner_id.to_def_id())
+                    cx.tcx.def_path_str(item.owner_id)
                 ),
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 2dac807c420..01927b6b5f1 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -558,6 +558,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 kind!("InlineAsm(_)");
                 out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment");
             },
+            ExprKind::OffsetOf(container, ref fields) => {
+                bind!(self, container, fields);
+                kind!("OffsetOf({container}, {fields})");
+            }
             ExprKind::Struct(qpath, fields, base) => {
                 bind!(self, qpath, fields);
                 opt_bind!(self, base);
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 28c85717061..3df40942e7b 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -218,7 +218,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::AddrOf(..)
                 | ExprKind::Struct(..)
                 | ExprKind::Repeat(..)
-                | ExprKind::Block(Block { stmts: [], .. }, _) => (),
+                | ExprKind::Block(Block { stmts: [], .. }, _)
+                | ExprKind::OffsetOf(..) => (),
 
                 // Assignment might be to a local defined earlier, so don't eagerly evaluate.
                 // Blocks with multiple statements might be expensive, so don't eagerly evaluate.
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 3ee7147828b..d972ed82c25 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -301,6 +301,9 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
             (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
             (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
+            (&ExprKind::OffsetOf(l_container, ref l_fields), &ExprKind::OffsetOf(r_container, ref r_fields)) => {
+                self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
+            },
             _ => false,
         };
         (is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
@@ -701,6 +704,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     }
                 }
             },
+            ExprKind::OffsetOf(container, fields) => {
+                self.hash_ty(container);
+                for field in fields {
+                    self.hash_name(field.name);
+                }
+            },
             ExprKind::Let(Let { pat, init, ty, .. }) => {
                 self.hash_expr(init);
                 if let Some(ty) = ty {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 354b6d71aa4..ecd712f32dc 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -194,7 +194,7 @@ fn check_rvalue<'tcx>(
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
+        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index a5a4a921d94..e81eadceec0 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -139,6 +139,7 @@ impl<'a> Sugg<'a> {
             | hir::ExprKind::Field(..)
             | hir::ExprKind::Index(..)
             | hir::ExprKind::InlineAsm(..)
+            | hir::ExprKind::OffsetOf(..)
             | hir::ExprKind::ConstBlock(..)
             | hir::ExprKind::Lit(..)
             | hir::ExprKind::Loop(..)
@@ -197,6 +198,7 @@ impl<'a> Sugg<'a> {
             | ast::ExprKind::ForLoop(..)
             | ast::ExprKind::Index(..)
             | ast::ExprKind::InlineAsm(..)
+            | ast::ExprKind::OffsetOf(..)
             | ast::ExprKind::ConstBlock(..)
             | ast::ExprKind::Lit(..)
             | ast::ExprKind::IncludedBytes(..)
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 1dc19bac984..5dcd71cef12 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -662,6 +662,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
             | ExprKind::Path(_)
             | ExprKind::Continue(_)
             | ExprKind::InlineAsm(_)
+            | ExprKind::OffsetOf(..)
             | ExprKind::Err(_) => (),
         }
         ControlFlow::Continue(())
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 0456005dce4..35ce89c7986 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -25,7 +25,7 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> {
 fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
     let _ = string.map_or(0, |s| s.len());
     let _ = num.as_ref().map_or(&0, |s| s);
-    let _ = num.as_mut().map_or(&mut 0, |s| {
+    let _ = num.as_mut().map_or(&0, |s| {
         *s += 1;
         s
     });
@@ -34,7 +34,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         s += 1;
         s
     });
-    let _ = num.as_mut().map_or(&mut 0, |s| {
+    let _ = num.as_mut().map_or(&0, |s| {
         *s += 1;
         s
     });
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 23b148752cb..c8683e5aae2 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -33,7 +33,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         *s += 1;
         s
     } else {
-        &mut 0
+        &0
     };
     let _ = if let Some(ref s) = num { s } else { &0 };
     let _ = if let Some(mut s) = num {
@@ -46,7 +46,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         *s += 1;
         s
     } else {
-        &mut 0
+        &0
     };
 }
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index a5dbf6e1f22..f5e4affb672 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -30,13 +30,13 @@ LL |       let _ = if let Some(s) = &mut num {
 LL | |         *s += 1;
 LL | |         s
 LL | |     } else {
-LL | |         &mut 0
+LL | |         &0
 LL | |     };
    | |_____^
    |
 help: try
    |
-LL ~     let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~     let _ = num.as_mut().map_or(&0, |s| {
 LL +         *s += 1;
 LL +         s
 LL ~     });
@@ -76,13 +76,13 @@ LL |       let _ = if let Some(ref mut s) = num {
 LL | |         *s += 1;
 LL | |         s
 LL | |     } else {
-LL | |         &mut 0
+LL | |         &0
 LL | |     };
    | |_____^
    |
 help: try
    |
-LL ~     let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~     let _ = num.as_mut().map_or(&0, |s| {
 LL +         *s += 1;
 LL +         s
 LL ~     });
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f67a718ba73..fc938080a0e 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -130,6 +130,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
     "-Zalways-encode-mir",
     "-Zextra-const-ub-checks",
     "-Zmir-emit-retag",
+    "-Zmir-keep-place-mention",
     "-Zmir-opt-level=0",
     "-Zmir-enable-passes=-CheckAlignment",
 ];
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs
new file mode 100644
index 00000000000..7c5f440b774
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs
@@ -0,0 +1,13 @@
+// Make sure we find these even with many checks disabled.
+//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
+
+fn main() {
+    let p = {
+        let b = Box::new(42);
+        &*b as *const i32
+    };
+    unsafe {
+        let _ = *p; //~ ERROR: dereferenced after this allocation got freed
+    }
+    panic!("this should never print");
+}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr
new file mode 100644
index 00000000000..7b76389c753
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed
+  --> $DIR/dangling_pointer_deref_underscore.rs:LL:CC
+   |
+LL |         let _ = *p;
+   |                 ^^ pointer to ALLOC was dereferenced after this allocation got freed
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/dangling_pointer_deref_underscore.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
index f7c1e683d0d..e3e5fac98c0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
@@ -382,10 +382,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
     rustc_attr!(rustc_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
     gated!(
-        alloc_error_handler, Normal, template!(Word), WarnFollowing,
-        experimental!(alloc_error_handler)
-    ),
-    gated!(
         default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
         experimental!(default_lib_allocator),
     ),
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index ac96bedf2fe..824e4219136 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -399,7 +399,9 @@ pub(crate) fn format_expr(
             }
         }
         ast::ExprKind::Underscore => Some("_".to_owned()),
-        ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => {
+        ast::ExprKind::FormatArgs(..)
+        | ast::ExprKind::IncludedBytes(..)
+        | ast::ExprKind::OffsetOf(..) => {
             // These do not occur in the AST because macros aren't expanded.
             unreachable!()
         }
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index a26375ee643..ca171657407 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -499,6 +499,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
         | ast::ExprKind::Field(..)
         | ast::ExprKind::IncludedBytes(..)
         | ast::ExprKind::InlineAsm(..)
+        | ast::ExprKind::OffsetOf(..)
         | ast::ExprKind::Let(..)
         | ast::ExprKind::Path(..)
         | ast::ExprKind::Range(..)
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 0e0a517ae49..411cbc760e0 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -36,10 +36,11 @@ const EXCEPTIONS: &[(&str, &str)] = &[
     ("mdbook", "MPL-2.0"),                                   // mdbook
     ("colored", "MPL-2.0"),                                  // rustfmt
     ("ryu", "Apache-2.0 OR BSL-1.0"),                        // cargo/... (because of serde)
-    ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
-    ("snap", "BSD-3-Clause"),    // rustc
-    ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
-    ("self_cell", "Apache-2.0"), // rustc (fluent translations)
+    ("codespan-reporting", "Apache-2.0"), // cxx via iana-time-zone-haiku via time, only on haiku
+    ("instant", "BSD-3-Clause"),          // rustc_driver/tracing-subscriber/parking_lot
+    ("snap", "BSD-3-Clause"),             // rustc
+    ("fluent-langneg", "Apache-2.0"),     // rustc (fluent translations)
+    ("self_cell", "Apache-2.0"),          // rustc (fluent translations)
     // FIXME: this dependency violates the documentation comment above:
     ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
     ("dissimilar", "Apache-2.0"),    // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
diff --git a/tests/codegen/debuginfo-constant-locals.rs b/tests/codegen/debuginfo-constant-locals.rs
new file mode 100644
index 00000000000..95a1b8c9d21
--- /dev/null
+++ b/tests/codegen/debuginfo-constant-locals.rs
@@ -0,0 +1,28 @@
+// compile-flags: -g -O
+
+// Check that simple constant values are preserved in debuginfo across both MIR opts and LLVM opts
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn check_it() {
+    let a = 1;
+    let b = 42;
+
+    foo(a + b);
+}
+
+#[inline(never)]
+fn foo(x: i32) {
+    std::process::exit(x);
+}
+
+// CHECK-LABEL: @check_it
+// CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[a_metadata:[0-9]+]], metadata !DIExpression())
+// CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[b_metadata:[0-9]+]], metadata !DIExpression())
+
+// CHECK: ![[a_metadata]] = !DILocalVariable(name: "a"
+// CHECK-SAME: line: 9
+
+// CHECK: ![[b_metadata]] = !DILocalVariable(name: "b"
+// CHECK-SAME: line: 10
diff --git a/tests/debuginfo/auxiliary/macro-stepping.rs b/tests/debuginfo/auxiliary/macro-stepping.rs
index 4447dd22ddb..ae50e11440b 100644
--- a/tests/debuginfo/auxiliary/macro-stepping.rs
+++ b/tests/debuginfo/auxiliary/macro-stepping.rs
@@ -5,6 +5,6 @@
 #[macro_export]
 macro_rules! new_scope {
     () => {
-        let x = 1;
+        let x = 1; opaque(x);
     }
 }
diff --git a/tests/debuginfo/macro-stepping.rs b/tests/debuginfo/macro-stepping.rs
index e4b2b7b79bc..a7287cffd02 100644
--- a/tests/debuginfo/macro-stepping.rs
+++ b/tests/debuginfo/macro-stepping.rs
@@ -79,22 +79,28 @@ extern crate macro_stepping; // exports new_scope!()
 // lldb-check:[...]#inc-loc2[...]
 // lldb-command:next
 // lldb-command:frame select
+// lldb-check:[...]#inc-loc1[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc2[...]
+// lldb-command:next
+// lldb-command:frame select
 // lldb-check:[...]#inc-loc3[...]
 
 macro_rules! foo {
     () => {
-        let a = 1;
-        let b = 2;
-        let c = 3;
-    }
+        let a = 1; opaque(a);
+        let b = 2; opaque(b);
+        let c = 3; opaque(c);
+    };
 }
 
 macro_rules! foo2 {
     () => {
         foo!();
-        let x = 1;
+        let x = 1; opaque(x);
         foo!();
-    }
+    };
 }
 
 fn main() {
@@ -118,4 +124,6 @@ fn main() {
 
 fn zzz() {()}
 
+fn opaque(_: u32) {}
+
 include!("macro-stepping.inc");
diff --git a/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs
index db367d07094..f685fe46d70 100644
--- a/tests/incremental/hashes/enum_constructors.rs
+++ b/tests/incremental/hashes/enum_constructors.rs
@@ -334,9 +334,9 @@ pub fn change_constructor_variant_c_like() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::C;
diff --git a/tests/incremental/hashes/let_expressions.rs b/tests/incremental/hashes/let_expressions.rs
index 7aca4324233..a835b8eef8c 100644
--- a/tests/incremental/hashes/let_expressions.rs
+++ b/tests/incremental/hashes/let_expressions.rs
@@ -91,7 +91,7 @@ pub fn change_mutability_of_slot() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
@@ -176,7 +176,7 @@ pub fn change_mutability_of_binding_in_pattern() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
@@ -193,9 +193,9 @@ pub fn add_initializer() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
@@ -210,9 +210,9 @@ pub fn change_initializer() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_initializer() {
     let _x = 5u16;
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
index 19daae86589..41657b53fc1 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
@@ -7,10 +7,10 @@ promoted[0] in FOO: &[&i32; 1] = {
     let mut _3: *const i32;              // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
 
     bb0: {
-        _3 = const {alloc2: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
+        _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
                                          // mir::Constant
                                          // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43
-                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
+                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
         _2 = &(*_3);                     // scope 0 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43
         _1 = [move _2];                  // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
         _0 = &_1;                        // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
@@ -18,4 +18,4 @@ promoted[0] in FOO: &[&i32; 1] = {
     }
 }
 
-alloc2 (extern static: X)
+alloc3 (extern static: X)
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 5b13d60052f..25ba0face6b 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -18,11 +18,11 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
 -         StorageLive(_4);                 // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45
 -         StorageLive(_5);                 // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
--         _5 = const {alloc2: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
+-         _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
 +         _6 = const _;                    // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
                                            // mir::Constant
 -                                          // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43
--                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
+-                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
 -         _4 = &(*_5);                     // scope 1 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43
 -         _3 = [move _4];                  // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
 -         _2 = &_3;                        // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
@@ -50,5 +50,5 @@
       }
   }
 - 
-- alloc2 (extern static: X)
+- alloc3 (extern static: X)
   
diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff
new file mode 100644
index 00000000000..4e2f1b39d2b
--- /dev/null
+++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff
@@ -0,0 +1,43 @@
+- // MIR for `concrete` before ConstProp
++ // MIR for `concrete` after ConstProp
+  
+  fn concrete() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/offset_of.rs:+0:15: +0:15
+      let _1: usize;                       // in scope 0 at $DIR/offset_of.rs:+1:9: +1:10
+      scope 1 {
+          debug x => _1;                   // in scope 1 at $DIR/offset_of.rs:+1:9: +1:10
+          let _2: usize;                   // in scope 1 at $DIR/offset_of.rs:+2:9: +2:10
+          scope 2 {
+              debug y => _2;               // in scope 2 at $DIR/offset_of.rs:+2:9: +2:10
+              let _3: usize;               // in scope 2 at $DIR/offset_of.rs:+3:9: +3:11
+              scope 3 {
+                  debug z0 => _3;          // in scope 3 at $DIR/offset_of.rs:+3:9: +3:11
+                  let _4: usize;           // in scope 3 at $DIR/offset_of.rs:+4:9: +4:11
+                  scope 4 {
+                      debug z1 => _4;      // in scope 4 at $DIR/offset_of.rs:+4:9: +4:11
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/offset_of.rs:+1:9: +1:10
+-         _1 = OffsetOf(Alpha, [0]);       // scope 0 at $DIR/offset_of.rs:+1:13: +1:33
++         _1 = const 4_usize;              // scope 0 at $DIR/offset_of.rs:+1:13: +1:33
+          StorageLive(_2);                 // scope 1 at $DIR/offset_of.rs:+2:9: +2:10
+-         _2 = OffsetOf(Alpha, [1]);       // scope 1 at $DIR/offset_of.rs:+2:13: +2:33
++         _2 = const 0_usize;              // scope 1 at $DIR/offset_of.rs:+2:13: +2:33
+          StorageLive(_3);                 // scope 2 at $DIR/offset_of.rs:+3:9: +3:11
+-         _3 = OffsetOf(Alpha, [2, 0]);    // scope 2 at $DIR/offset_of.rs:+3:14: +3:36
++         _3 = const 2_usize;              // scope 2 at $DIR/offset_of.rs:+3:14: +3:36
+          StorageLive(_4);                 // scope 3 at $DIR/offset_of.rs:+4:9: +4:11
+-         _4 = OffsetOf(Alpha, [2, 1]);    // scope 3 at $DIR/offset_of.rs:+4:14: +4:36
++         _4 = const 3_usize;              // scope 3 at $DIR/offset_of.rs:+4:14: +4:36
+          StorageDead(_4);                 // scope 3 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_3);                 // scope 2 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_2);                 // scope 1 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_1);                 // scope 0 at $DIR/offset_of.rs:+5:1: +5:2
+          return;                          // scope 0 at $DIR/offset_of.rs:+5:2: +5:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff
new file mode 100644
index 00000000000..5c6cb47089e
--- /dev/null
+++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff
@@ -0,0 +1,39 @@
+- // MIR for `generic` before ConstProp
++ // MIR for `generic` after ConstProp
+  
+  fn generic() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/offset_of.rs:+0:17: +0:17
+      let _1: usize;                       // in scope 0 at $DIR/offset_of.rs:+1:9: +1:11
+      scope 1 {
+          debug gx => _1;                  // in scope 1 at $DIR/offset_of.rs:+1:9: +1:11
+          let _2: usize;                   // in scope 1 at $DIR/offset_of.rs:+2:9: +2:11
+          scope 2 {
+              debug gy => _2;              // in scope 2 at $DIR/offset_of.rs:+2:9: +2:11
+              let _3: usize;               // in scope 2 at $DIR/offset_of.rs:+3:9: +3:11
+              scope 3 {
+                  debug dx => _3;          // in scope 3 at $DIR/offset_of.rs:+3:9: +3:11
+                  let _4: usize;           // in scope 3 at $DIR/offset_of.rs:+4:9: +4:11
+                  scope 4 {
+                      debug dy => _4;      // in scope 4 at $DIR/offset_of.rs:+4:9: +4:11
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/offset_of.rs:+1:9: +1:11
+          _1 = OffsetOf(Gamma<T>, [0]);    // scope 0 at $DIR/offset_of.rs:+1:14: +1:37
+          StorageLive(_2);                 // scope 1 at $DIR/offset_of.rs:+2:9: +2:11
+          _2 = OffsetOf(Gamma<T>, [1]);    // scope 1 at $DIR/offset_of.rs:+2:14: +2:37
+          StorageLive(_3);                 // scope 2 at $DIR/offset_of.rs:+3:9: +3:11
+          _3 = OffsetOf(Delta<T>, [1]);    // scope 2 at $DIR/offset_of.rs:+3:14: +3:37
+          StorageLive(_4);                 // scope 3 at $DIR/offset_of.rs:+4:9: +4:11
+          _4 = OffsetOf(Delta<T>, [2]);    // scope 3 at $DIR/offset_of.rs:+4:14: +4:37
+          StorageDead(_4);                 // scope 3 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_3);                 // scope 2 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_2);                 // scope 1 at $DIR/offset_of.rs:+5:1: +5:2
+          StorageDead(_1);                 // scope 0 at $DIR/offset_of.rs:+5:1: +5:2
+          return;                          // scope 0 at $DIR/offset_of.rs:+5:2: +5:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs
new file mode 100644
index 00000000000..eabdf848079
--- /dev/null
+++ b/tests/mir-opt/const_prop/offset_of.rs
@@ -0,0 +1,49 @@
+// unit-test
+// compile-flags: -O
+
+#![feature(offset_of)]
+
+use std::marker::PhantomData;
+use std::mem::offset_of;
+
+struct Alpha {
+    x: u8,
+    y: u16,
+    z: Beta,
+}
+
+struct Beta(u8, u8);
+
+struct Gamma<T> {
+    x: u8,
+    y: u16,
+    _t: T,
+}
+
+#[repr(C)]
+struct Delta<T> {
+    _phantom: PhantomData<T>,
+    x: u8,
+    y: u16,
+}
+
+// EMIT_MIR offset_of.concrete.ConstProp.diff
+fn concrete() {
+    let x = offset_of!(Alpha, x);
+    let y = offset_of!(Alpha, y);
+    let z0 = offset_of!(Alpha, z.0);
+    let z1 = offset_of!(Alpha, z.1);
+}
+
+// EMIT_MIR offset_of.generic.ConstProp.diff
+fn generic<T>() {
+    let gx = offset_of!(Gamma<T>, x);
+    let gy = offset_of!(Gamma<T>, y);
+    let dx = offset_of!(Delta<T>, x);
+    let dy = offset_of!(Delta<T>, y);
+}
+
+fn main() {
+    concrete();
+    generic::<()>();
+}
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
index 81cfd22db6c..7886bf19e0c 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
@@ -2,24 +2,17 @@
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
-    let _1: i32;                         // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-    let mut _3: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
     scope 1 {
-        debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        let _2: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+        debug x => const 4_i32;          // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
         scope 2 {
-            debug y => _2;               // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+            debug y => const 3_i32;      // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
             scope 3 {
-                debug z => _3;           // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+                debug z => const 42_u32; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
             }
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        StorageLive(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
-        StorageDead(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
-        StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
index 81cfd22db6c..7886bf19e0c 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
@@ -2,24 +2,17 @@
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
-    let _1: i32;                         // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-    let mut _3: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
     scope 1 {
-        debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        let _2: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+        debug x => const 4_i32;          // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
         scope 2 {
-            debug y => _2;               // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+            debug y => const 3_i32;      // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
             scope 3 {
-                debug z => _3;           // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+                debug z => const 42_u32; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
             }
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        StorageLive(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
-        StorageDead(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
-        StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
index 002e914e8fa..5bea94c7fe8 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
@@ -2,24 +2,17 @@
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
-    let _1: i32;                         // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-    let mut _3: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
     scope 1 {
-        debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        let _2: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+        debug x => const 4_i32;          // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
         scope 2 {
-            debug y => _2;               // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+            debug y => const 3_i32;      // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
             scope 3 {
-                debug z => _3;           // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+                debug z => const 42_u32; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
             }
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        StorageLive(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
-        StorageDead(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
-        StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
index 002e914e8fa..5bea94c7fe8 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
@@ -2,24 +2,17 @@
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
-    let _1: i32;                         // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-    let mut _3: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
     scope 1 {
-        debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        let _2: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+        debug x => const 4_i32;          // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
         scope 2 {
-            debug y => _2;               // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
+            debug y => const 3_i32;      // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
             scope 3 {
-                debug z => _3;           // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+                debug z => const 42_u32; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
             }
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
-        StorageLive(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
-        StorageDead(_2);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
-        StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
index 18df6f9af5f..3aebfb69e0a 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
@@ -8,7 +8,7 @@
 +         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
 +         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25
 +         scope 2 {
-+             debug buffer => _3;          // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15
++             debug buffer => const _;     // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15
 +             scope 3 {
 +                 debug index => _0;       // in scope 3 at $DIR/issue_106141.rs:13:9: 13:14
 +             }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index 473e02f1cb1..d76cd0e2bb8 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _5: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
+-                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl u16>::unchecked_shl::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
--                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 65535_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<u16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<u16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 9b7b11ef659..3c175ed1504 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _3: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl u16>::unchecked_shl::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+    }
+
+    bb2: {
+        _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<u16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
     }
-
-    bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
-    }
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 9638ddda46b..f3d3e6090bb 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _5: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
+-                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl i16>::unchecked_shr::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
--                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 32767_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<i16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<i16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index afe6d08741b..724b3c56723 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _3: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl i16>::unchecked_shr::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+    }
+
+    bb2: {
+        _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<i16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
     }
-
-    bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
-    }
 }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index 42b60532690..9f955b4717b 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -4,31 +4,29 @@ fn num_to_digit(_1: char) -> u32 {
     debug num => _1;                     // in scope 0 at $DIR/issue_59352.rs:+0:21: +0:24
     let mut _0: u32;                     // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38
     let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
-    let mut _3: u32;                     // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
     scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:15:12: 15:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        debug radix => _3;               // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        let _5: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        debug radix => const 8_u32;      // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        let mut _3: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        let _4: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         scope 2 (inlined Option::<u32>::is_some) { // at $SRC_DIR/core/src/char/methods.rs:LL:COL
-            debug self => _4;            // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-            let mut _6: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+            debug self => _3;            // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+            let mut _5: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
     scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:15:42: 15:50
         debug self => _2;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        let mut _7: isize;               // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        let mut _8: !;                   // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        let mut _6: isize;               // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        let mut _7: !;                   // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 4 {
             debug val => _0;             // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
+        StorageLive(_3);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        StorageLive(_5);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        _5 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        _4 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/char/methods.rs:LL:COL
                                          // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
@@ -43,8 +41,8 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb2: {
-        _7 = discriminant(_2);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _7) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        _6 = discriminant(_2);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _6) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb3: {
@@ -57,16 +55,15 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb5: {
-        _4 = &_5;                        // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        _6 = discriminant((*_4));        // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+        _3 = &_4;                        // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        _5 = discriminant((*_3));        // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        StorageDead(_3);                 // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
-        switchInt(move _6) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
+        switchInt(move _5) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
     }
 
     bb6: {
-        _8 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/option.rs:LL:COL
                                          // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
index 4f5df133181..f1f7857a1bd 100644
--- a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
+++ b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
@@ -2,24 +2,21 @@
 
 fn f_u64() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:16: +0:16
-    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
     scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:15:5: 15:21
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        debug t => const 0_u64;          // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
+        let _1: ();                      // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
         scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
-        _2 = f_non_zst::<u64>(const 0_u64) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        _1 = f_non_zst::<u64>(const 0_u64) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
         return;                          // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2
     }
 }
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
index 4a60432c14c..9c3192c008c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -136,10 +136,10 @@
   134|       |
   135|       |impl std::fmt::Debug for Foo {
   136|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-  137|      7|        write!(f, "try and succeed")?;
+  137|      9|        write!(f, "try and succeed")?;
                                                   ^0
-  138|      7|        Ok(())
-  139|      7|    }
+  138|      9|        Ok(())
+  139|      9|    }
   140|       |}
   141|       |
   142|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
diff --git a/tests/run-make/issue-51671/Makefile b/tests/run-make/issue-51671/Makefile
index c9364536992..00cf9134662 100644
--- a/tests/run-make/issue-51671/Makefile
+++ b/tests/run-make/issue-51671/Makefile
@@ -6,4 +6,3 @@ all:
 	$(RUSTC) --emit=obj app.rs
 	nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind
 	nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality
-	nm $(TMPDIR)/app.o | $(CGREP) __rg_oom
diff --git a/tests/run-make/issue-51671/app.rs b/tests/run-make/issue-51671/app.rs
index e9dc1e9744f..a9d3457bf90 100644
--- a/tests/run-make/issue-51671/app.rs
+++ b/tests/run-make/issue-51671/app.rs
@@ -1,5 +1,5 @@
 #![crate_type = "bin"]
-#![feature(lang_items, alloc_error_handler)]
+#![feature(lang_items)]
 #![no_main]
 #![no_std]
 
@@ -13,8 +13,3 @@ fn panic(_: &PanicInfo) -> ! {
 
 #[lang = "eh_personality"]
 fn eh() {}
-
-#[alloc_error_handler]
-fn oom(_: Layout) -> ! {
-    loop {}
-}
diff --git a/tests/run-make/issue-69368/Makefile b/tests/run-make/issue-69368/Makefile
deleted file mode 100644
index b1229d1b07f..00000000000
--- a/tests/run-make/issue-69368/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Test that previously triggered a linker failure with root cause
-# similar to one found in the issue #69368.
-#
-# The crate that provides oom lang item is missing some other lang
-# items. Necessary to prevent the use of start-group / end-group.
-#
-# The weak lang items are defined in a separate compilation units,
-# so that linker could omit them if not used.
-#
-# The crates that need those weak lang items are dependencies of
-# crates that provide them.
-
-all:
-	$(RUSTC) a.rs
-	$(RUSTC) b.rs
-	$(RUSTC) c.rs
diff --git a/tests/run-make/issue-69368/a.rs b/tests/run-make/issue-69368/a.rs
deleted file mode 100644
index a54f429550e..00000000000
--- a/tests/run-make/issue-69368/a.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#![crate_type = "rlib"]
-#![feature(lang_items)]
-#![feature(panic_unwind)]
-#![no_std]
-
-extern crate panic_unwind;
-
-#[panic_handler]
-pub fn panic_handler(_: &core::panic::PanicInfo) -> ! {
-    loop {}
-}
-
-#[no_mangle]
-extern "C" fn __rust_drop_panic() -> ! {
-    loop {}
-}
-
-#[no_mangle]
-extern "C" fn __rust_foreign_exception() -> ! {
-    loop {}
-}
-
-#[lang = "eh_personality"]
-fn eh_personality() {
-    loop {}
-}
diff --git a/tests/run-make/issue-69368/b.rs b/tests/run-make/issue-69368/b.rs
deleted file mode 100644
index 4d6af026656..00000000000
--- a/tests/run-make/issue-69368/b.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![crate_type = "rlib"]
-#![feature(alloc_error_handler)]
-#![no_std]
-
-#[alloc_error_handler]
-pub fn error_handler(_: core::alloc::Layout) -> ! {
-    panic!();
-}
diff --git a/tests/run-make/issue-69368/c.rs b/tests/run-make/issue-69368/c.rs
deleted file mode 100644
index 729c4249a05..00000000000
--- a/tests/run-make/issue-69368/c.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-#![crate_type = "bin"]
-#![feature(start)]
-#![no_std]
-
-extern crate alloc;
-extern crate a;
-extern crate b;
-
-use alloc::vec::Vec;
-use core::alloc::*;
-
-struct Allocator;
-
-unsafe impl GlobalAlloc for Allocator {
-    unsafe fn alloc(&self, _: Layout) -> *mut u8 {
-        loop {}
-    }
-
-    unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
-        loop {}
-    }
-}
-
-#[global_allocator]
-static ALLOCATOR: Allocator = Allocator;
-
-#[start]
-fn main(argc: isize, _argv: *const *const u8) -> isize {
-    let mut v = Vec::new();
-    for i in 0..argc {
-        v.push(i);
-    }
-    v.iter().sum()
-}
diff --git a/tests/run-make/wasm-symbols-not-exported/bar.rs b/tests/run-make/wasm-symbols-not-exported/bar.rs
index 6ffbd3ec690..eb768446b4b 100644
--- a/tests/run-make/wasm-symbols-not-exported/bar.rs
+++ b/tests/run-make/wasm-symbols-not-exported/bar.rs
@@ -1,4 +1,4 @@
-#![feature(panic_handler, alloc_error_handler)]
+#![feature(panic_handler)]
 #![crate_type = "cdylib"]
 #![no_std]
 
@@ -24,11 +24,6 @@ pub extern fn foo(a: u32) -> u32 {
     a * 2
 }
 
-#[alloc_error_handler]
-fn a(_: core::alloc::Layout) -> ! {
-    loop {}
-}
-
 #[panic_handler]
 fn b(_: &core::panic::PanicInfo) -> ! {
     loop {}
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
deleted file mode 100644
index cd06423e3a5..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// compile-flags:-C panic=abort
-
-#![feature(alloc_error_handler)]
-#![no_std]
-#![no_main]
-
-use core::alloc::Layout;
-
-#[alloc_error_handler]
-fn oom(
-    info: &Layout, //~^ ERROR mismatched types
-) -> () //~^^ ERROR mismatched types
-{
-    loop {}
-}
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
deleted file mode 100644
index de92841d7f1..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
-   |
-LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
-LL | // fn oom(
-LL | ||     info: &Layout,
-LL | || ) -> ()
-   | ||_______- arguments to this function are incorrect
-LL | |  {
-LL | |      loop {}
-LL | |  }
-   | |__^ expected `&Layout`, found `Layout`
-   |
-note: function defined here
-  --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4
-   |
-LL | fn oom(
-   |    ^^^
-LL |     info: &Layout,
-   |     -------------
-   = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0308]: mismatched types
-  --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
-   |
-LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
-LL | // fn oom(
-LL | ||     info: &Layout,
-LL | || ) -> ()
-   | ||_______^ expected `!`, found `()`
-LL | |  {
-LL | |      loop {}
-LL | |  }
-   | |__- expected `!` because of return type
-   |
-   = note:   expected type `!`
-           found unit type `()`
-   = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
deleted file mode 100644
index 4f76257fc72..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-flags:-C panic=abort
-
-#![feature(alloc_error_handler)]
-#![no_std]
-#![no_main]
-
-struct Layout;
-
-#[alloc_error_handler]
-fn oom(
-    info: Layout, //~^ ERROR mismatched types
-) { //~^^ ERROR mismatched types
-    loop {}
-}
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
deleted file mode 100644
index 7a495380f2b..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
+++ /dev/null
@@ -1,50 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
-   |
-LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
-LL | // fn oom(
-LL | ||     info: Layout,
-LL | || ) {
-   | ||_- arguments to this function are incorrect
-LL | |      loop {}
-LL | |  }
-   | |__^ expected `Layout`, found `core::alloc::Layout`
-   |
-   = note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types
-note: `core::alloc::Layout` is defined in crate `core`
-  --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-note: `Layout` is defined in the current crate
-  --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
-   |
-LL | struct Layout;
-   | ^^^^^^^^^^^^^
-note: function defined here
-  --> $DIR/alloc-error-handler-bad-signature-2.rs:10:4
-   |
-LL | fn oom(
-   |    ^^^
-LL |     info: Layout,
-   |     ------------
-   = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0308]: mismatched types
-  --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
-   |
-LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
-LL | // fn oom(
-LL | ||     info: Layout,
-LL | || ) {
-   | ||_^ expected `!`, found `()`
-LL | |      loop {}
-LL | |  }
-   | |__- expected `!` because of return type
-   |
-   = note:   expected type `!`
-           found unit type `()`
-   = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
deleted file mode 100644
index ea9ad39a70d..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// compile-flags:-C panic=abort
-
-#![feature(alloc_error_handler)]
-#![no_std]
-#![no_main]
-
-struct Layout;
-
-#[alloc_error_handler]
-fn oom() -> ! { //~ ERROR function takes 0 arguments but 1 argument was supplied
-    loop {}
-}
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
deleted file mode 100644
index eb739b149a1..00000000000
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0061]: this function takes 0 arguments but 1 argument was supplied
-  --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1
-   |
-LL |   #[alloc_error_handler]
-   |   ---------------------- in this procedural macro expansion
-LL |   fn oom() -> ! {
-   |  _-^^^^^^^^^^^^
-LL | |     loop {}
-LL | | }
-   | |_- unexpected argument of type `core::alloc::Layout`
-   |
-note: function defined here
-  --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4
-   |
-LL | fn oom() -> ! {
-   |    ^^^
-   = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/alloc-error/default-alloc-error-hook.rs b/tests/ui/alloc-error/default-alloc-error-hook.rs
index 8be09500f4e..919d4b714a1 100644
--- a/tests/ui/alloc-error/default-alloc-error-hook.rs
+++ b/tests/ui/alloc-error/default-alloc-error-hook.rs
@@ -2,7 +2,7 @@
 // ignore-emscripten no processes
 // ignore-sgx no processes
 
-use std::alloc::{Layout, handle_alloc_error};
+use std::alloc::{handle_alloc_error, Layout};
 use std::env;
 use std::process::Command;
 use std::str;
@@ -24,5 +24,5 @@ fn main() {
         .strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n")
         .unwrap_or(stderr);
 
-    assert_eq!(stderr, "memory allocation of 42 bytes failed\n");
+    assert!(stderr.contains("memory allocation of 42 bytes failed"));
 }
diff --git a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
deleted file mode 100644
index 28926243390..00000000000
--- a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-// run-pass
-// ignore-android no libc
-// ignore-emscripten no libc
-// ignore-sgx no libc
-// ignore-wasm32 no libc
-// only-linux
-// compile-flags:-C panic=abort
-// aux-build:helper.rs
-
-#![feature(rustc_private, lang_items)]
-#![feature(alloc_error_handler)]
-#![no_std]
-#![no_main]
-
-extern crate alloc;
-extern crate libc;
-
-// ARM targets need these symbols
-#[no_mangle]
-pub fn __aeabi_unwind_cpp_pr0() {}
-
-#[no_mangle]
-pub fn __aeabi_unwind_cpp_pr1() {}
-
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use core::alloc::{GlobalAlloc, Layout};
-use core::ptr::null_mut;
-
-extern crate helper;
-
-struct MyAllocator;
-
-#[alloc_error_handler]
-fn my_oom(layout: Layout) -> ! {
-    use alloc::fmt::write;
-    unsafe {
-        let size = layout.size();
-        let mut s = alloc::string::String::new();
-        write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
-        libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
-        libc::exit(0)
-    }
-}
-
-unsafe impl GlobalAlloc for MyAllocator {
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
-    }
-    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
-}
-
-#[global_allocator]
-static A: MyAllocator = MyAllocator;
-
-#[panic_handler]
-fn panic(panic_info: &core::panic::PanicInfo) -> ! {
-    unsafe {
-        let s = panic_info.to_string();
-        const PSTR: &str = "panic occurred: ";
-        const CR: &str = "\n";
-        libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
-        libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
-        libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
-        libc::exit(1)
-    }
-}
-
-// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed.
-// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions
-// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
-// unwind. So, for this test case we will define the symbol.
-#[lang = "eh_personality"]
-extern "C" fn rust_eh_personality() {}
-
-#[derive(Default, Debug)]
-struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
-
-#[no_mangle]
-fn main(_argc: i32, _argv: *const *const u8) -> isize {
-    let zero = Box::<Page>::new(Default::default());
-    helper::work_with(&zero);
-    1
-}
diff --git a/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr b/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr
index 7b0d1c50516..1648cfb266b 100644
--- a/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr
+++ b/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr
@@ -2,5 +2,5 @@ error: the compiler unexpectedly panicked. this is a bug.
 
 query stack during panic:
 #0 [typeck] type-checking `weird`
-#1 [typeck_item_bodies] type-checking all item bodies
+#1 [used_trait_imports] finding used_trait_imports `weird`
 end of query stack
diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
index 0ca14c3f3bc..047175626e3 100644
--- a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
+++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -1,19 +1,3 @@
-error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9
-   |
-LL |         ref foo @ [.., ref mut bar] => (),
-   |         ^^^^^^^        ----------- value is mutably borrowed by `bar` here
-   |         |
-   |         value is borrowed by `foo` here
-
-error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
-   |
-LL |         ref foo @ Some(box ref mut s) => (),
-   |         ^^^^^^^            --------- value is mutably borrowed by `s` here
-   |         |
-   |         value is borrowed by `foo` here
-
 error[E0382]: borrow of moved value: `x`
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:18:5
    |
@@ -43,6 +27,14 @@ LL |     &x;
 LL |     drop(r);
    |          - mutable borrow later used here
 
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9
+   |
+LL |         ref foo @ [.., ref mut bar] => (),
+   |         ^^^^^^^        ----------- value is mutably borrowed by `bar` here
+   |         |
+   |         value is borrowed by `foo` here
+
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:50:5
    |
@@ -120,6 +112,14 @@ LL |     &mut x;
 LL |     drop(r);
    |          - immutable borrow later used here
 
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
+   |
+LL |         ref foo @ Some(box ref mut s) => (),
+   |         ^^^^^^^            --------- value is mutably borrowed by `s` here
+   |         |
+   |         value is borrowed by `foo` here
+
 error[E0382]: borrow of moved value: `x`
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:134:5
    |
diff --git a/tests/ui/borrowck/let_underscore_temporary.rs b/tests/ui/borrowck/let_underscore_temporary.rs
index 37b5c5d9d7a..835cd20798f 100644
--- a/tests/ui/borrowck/let_underscore_temporary.rs
+++ b/tests/ui/borrowck/let_underscore_temporary.rs
@@ -1,4 +1,4 @@
-// check-pass
+// check-fail
 
 fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
     let _ = if let Some(s) = *string { s.len() } else { 0 };
@@ -8,6 +8,7 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
         s
     } else {
         &mut 0
+        //~^ ERROR temporary value dropped while borrowed
     };
     let _ = if let Some(ref s) = num { s } else { &0 };
     let _ = if let Some(mut s) = num {
@@ -21,6 +22,33 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
         s
     } else {
         &mut 0
+        //~^ ERROR temporary value dropped while borrowed
+    };
+}
+
+fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
+    let _: _ = if let Some(s) = *string { s.len() } else { 0 };
+    let _: _ = if let Some(s) = &num { s } else { &0 };
+    let _: _ = if let Some(s) = &mut num {
+        *s += 1;
+        s
+    } else {
+        &mut 0
+        //~^ ERROR temporary value dropped while borrowed
+    };
+    let _: _ = if let Some(ref s) = num { s } else { &0 };
+    let _: _ = if let Some(mut s) = num {
+        s += 1;
+        s
+    } else {
+        0
+    };
+    let _: _ = if let Some(ref mut s) = num {
+        *s += 1;
+        s
+    } else {
+        &mut 0
+        //~^ ERROR temporary value dropped while borrowed
     };
 }
 
diff --git a/tests/ui/borrowck/let_underscore_temporary.stderr b/tests/ui/borrowck/let_underscore_temporary.stderr
new file mode 100644
index 00000000000..74f3598c4d0
--- /dev/null
+++ b/tests/ui/borrowck/let_underscore_temporary.stderr
@@ -0,0 +1,79 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/let_underscore_temporary.rs:10:14
+   |
+LL |       let _ = if let Some(s) = &mut num {
+   |  _____________-
+LL | |         *s += 1;
+LL | |         s
+LL | |     } else {
+LL | |         &mut 0
+   | |              ^ creates a temporary value which is freed while still in use
+LL | |
+LL | |     };
+   | |     -
+   | |     |
+   | |_____temporary value is freed at the end of this statement
+   |       borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/let_underscore_temporary.rs:24:14
+   |
+LL |       let _ = if let Some(ref mut s) = num {
+   |  _____________-
+LL | |         *s += 1;
+LL | |         s
+LL | |     } else {
+LL | |         &mut 0
+   | |              ^ creates a temporary value which is freed while still in use
+LL | |
+LL | |     };
+   | |     -
+   | |     |
+   | |_____temporary value is freed at the end of this statement
+   |       borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/let_underscore_temporary.rs:36:14
+   |
+LL |       let _: _ = if let Some(s) = &mut num {
+   |  ________________-
+LL | |         *s += 1;
+LL | |         s
+LL | |     } else {
+LL | |         &mut 0
+   | |              ^ creates a temporary value which is freed while still in use
+LL | |
+LL | |     };
+   | |     -
+   | |     |
+   | |_____temporary value is freed at the end of this statement
+   |       borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/let_underscore_temporary.rs:50:14
+   |
+LL |       let _: _ = if let Some(ref mut s) = num {
+   |  ________________-
+LL | |         *s += 1;
+LL | |         s
+LL | |     } else {
+LL | |         &mut 0
+   | |              ^ creates a temporary value which is freed while still in use
+LL | |
+LL | |     };
+   | |     -
+   | |     |
+   | |_____temporary value is freed at the end of this statement
+   |       borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
index ad061d93cb2..8a32f0d99e7 100644
--- a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
@@ -1,17 +1,3 @@
-error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/pattern-matching-should-fail.rs:67:23
-   |
-LL |     let c1 = || match x { };
-   |                       ^
-   |
-   = note: the matched value is of type `u8`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-   |
-LL ~     let c1 = || match x {
-LL +         _ => todo!(),
-LL ~     };
-   |
-
 error[E0381]: used binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:8:23
    |
@@ -69,6 +55,20 @@ LL |     let t: !;
 LL |             match t { };
    |                   ^ `t` used here but it isn't initialized
 
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/pattern-matching-should-fail.rs:67:23
+   |
+LL |     let c1 = || match x { };
+   |                       ^
+   |
+   = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let c1 = || match x {
+LL +         _ => todo!(),
+LL ~     };
+   |
+
 error[E0381]: used binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:67:23
    |
diff --git a/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs
deleted file mode 100644
index 85b0c6c9df8..00000000000
--- a/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub fn test<const N: usize, T>() {}
diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs
deleted file mode 100644
index 7590abbd827..00000000000
--- a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// aux-build: foreign-generic-mismatch-with-const-arg.rs
-
-extern crate foreign_generic_mismatch_with_const_arg;
-
-fn main() {
-    foreign_generic_mismatch_with_const_arg::test::<1>();
-    //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
-}
diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr
deleted file mode 100644
index 4cc03a20514..00000000000
--- a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
-  --> $DIR/foreign-generic-mismatch-with-const-arg.rs:6:46
-   |
-LL |     foreign_generic_mismatch_with_const_arg::test::<1>();
-   |                                              ^^^^   - supplied 1 generic argument
-   |                                              |
-   |                                              expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `N`, `T`
-  --> $DIR/auxiliary/foreign-generic-mismatch-with-const-arg.rs:1:8
-   |
-LL | pub fn test<const N: usize, T>() {}
-   |        ^^^^ --------------  -
-help: add missing generic argument
-   |
-LL |     foreign_generic_mismatch_with_const_arg::test::<1, T>();
-   |                                                      +++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs
deleted file mode 100644
index 78d189d20b6..00000000000
--- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// compile-flags:-C panic=abort
-
-#![no_std]
-#![no_main]
-
-use core::alloc::Layout;
-
-#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler'
-fn oom(info: Layout) -> ! {
-    loop {}
-}
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! {
-    loop {}
-}
diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr
deleted file mode 100644
index f414eb463df..00000000000
--- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: use of unstable library feature 'alloc_error_handler'
-  --> $DIR/feature-gate-alloc-error-handler.rs:8:3
-   |
-LL | #[alloc_error_handler]
-   |   ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51540 <https://github.com/rust-lang/rust/issues/51540> for more information
-   = help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/generics/auxiliary/foreign-generic-mismatch.rs b/tests/ui/generics/auxiliary/foreign-generic-mismatch.rs
new file mode 100644
index 00000000000..d89c1e03688
--- /dev/null
+++ b/tests/ui/generics/auxiliary/foreign-generic-mismatch.rs
@@ -0,0 +1,3 @@
+pub fn const_arg<const N: usize, T>() {}
+
+pub fn lt_arg<'a: 'a>() {}
diff --git a/tests/ui/generics/foreign-generic-mismatch.rs b/tests/ui/generics/foreign-generic-mismatch.rs
new file mode 100644
index 00000000000..403fd73d7df
--- /dev/null
+++ b/tests/ui/generics/foreign-generic-mismatch.rs
@@ -0,0 +1,10 @@
+// aux-build: foreign-generic-mismatch.rs
+
+extern crate foreign_generic_mismatch;
+
+fn main() {
+    foreign_generic_mismatch::const_arg::<()>();
+    //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
+    foreign_generic_mismatch::lt_arg::<'static, 'static>();
+    //~^ ERROR function takes 1 lifetime argument but 2 lifetime arguments were supplied
+}
diff --git a/tests/ui/generics/foreign-generic-mismatch.stderr b/tests/ui/generics/foreign-generic-mismatch.stderr
new file mode 100644
index 00000000000..5322b3f919d
--- /dev/null
+++ b/tests/ui/generics/foreign-generic-mismatch.stderr
@@ -0,0 +1,35 @@
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/foreign-generic-mismatch.rs:6:31
+   |
+LL |     foreign_generic_mismatch::const_arg::<()>();
+   |                               ^^^^^^^^^   -- supplied 1 generic argument
+   |                               |
+   |                               expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `N`, `T`
+  --> $DIR/auxiliary/foreign-generic-mismatch.rs:1:8
+   |
+LL | pub fn const_arg<const N: usize, T>() {}
+   |        ^^^^^^^^^ --------------  -
+help: add missing generic argument
+   |
+LL |     foreign_generic_mismatch::const_arg::<(), T>();
+   |                                             +++
+
+error[E0107]: function takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/foreign-generic-mismatch.rs:8:31
+   |
+LL |     foreign_generic_mismatch::lt_arg::<'static, 'static>();
+   |                               ^^^^^^            ------- help: remove this lifetime argument
+   |                               |
+   |                               expected 1 lifetime argument
+   |
+note: function defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/auxiliary/foreign-generic-mismatch.rs:3:8
+   |
+LL | pub fn lt_arg<'a: 'a>() {}
+   |        ^^^^^^ --
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
new file mode 100644
index 00000000000..2c6fcef2500
--- /dev/null
+++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
@@ -0,0 +1,42 @@
+// check-pass
+
+#![feature(offset_of)]
+#![deny(dead_code)]
+
+// This struct contains a projection that can only be normalized after getting the field type.
+struct A<T: Project> {
+    a: <T as Project>::EquateParamTo,
+}
+
+// This is the inner struct that we want to get.
+struct MyFieldIsNotDead {
+    not_dead: u8,
+}
+
+// These are some helpers.
+// Inside the param env of `test`, we want to make it so that it considers T=MyFieldIsNotDead.
+struct GenericIsEqual<T>(T);
+trait Project {
+    type EquateParamTo;
+}
+impl<T> Project for GenericIsEqual<T> {
+    type EquateParamTo = T;
+}
+
+fn test<T>() -> usize
+where
+    GenericIsEqual<T>: Project<EquateParamTo = MyFieldIsNotDead>,
+{
+    // The first field of the A that we construct here is
+    // `<GenericIsEqual<T>> as Project>::EquateParamTo`.
+    // Typeck normalizes this and figures that the not_dead field is totally fine and accessible.
+    // But importantly, the normalization ends up with T, which, as we've declared in our param
+    // env is MyFieldDead. When we're in the param env of the `a` field, the where bound above
+    // is not in scope, so we don't know what T is - it's generic.
+    // If we use the wrong param env, the lint will ICE.
+    std::mem::offset_of!(A<GenericIsEqual<T>>, a.not_dead)
+}
+
+fn main() {
+    test::<MyFieldIsNotDead>();
+}
diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs
new file mode 100644
index 00000000000..da91de3862f
--- /dev/null
+++ b/tests/ui/lint/dead-code/offset-of.rs
@@ -0,0 +1,44 @@
+#![feature(offset_of)]
+#![deny(dead_code)]
+
+use std::mem::offset_of;
+
+struct Alpha {
+    a: (),
+    b: (), //~ ERROR field `b` is never read
+    c: Beta,
+}
+
+struct Beta {
+    a: (), //~ ERROR field `a` is never read
+    b: (),
+}
+
+struct Gamma {
+    a: (), //~ ERROR field `a` is never read
+    b: (),
+}
+
+struct Delta {
+    a: (),
+    b: (), //~ ERROR field `b` is never read
+}
+
+trait Trait {
+    type Assoc;
+}
+impl Trait for () {
+    type Assoc = Delta;
+}
+
+struct Project<T: Trait> {
+    a: u8, //~ ERROR field `a` is never read
+    b: <T as Trait>::Assoc,
+}
+
+fn main() {
+    offset_of!(Alpha, a);
+    offset_of!(Alpha, c.b);
+    offset_of!((Gamma,), 0.b);
+    offset_of!(Project::<()>, b.a);
+}
diff --git a/tests/ui/lint/dead-code/offset-of.stderr b/tests/ui/lint/dead-code/offset-of.stderr
new file mode 100644
index 00000000000..ed2916461cd
--- /dev/null
+++ b/tests/ui/lint/dead-code/offset-of.stderr
@@ -0,0 +1,50 @@
+error: field `b` is never read
+  --> $DIR/offset-of.rs:8:5
+   |
+LL | struct Alpha {
+   |        ----- field in this struct
+LL |     a: (),
+LL |     b: (),
+   |     ^
+   |
+note: the lint level is defined here
+  --> $DIR/offset-of.rs:2:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field `a` is never read
+  --> $DIR/offset-of.rs:13:5
+   |
+LL | struct Beta {
+   |        ---- field in this struct
+LL |     a: (),
+   |     ^
+
+error: field `a` is never read
+  --> $DIR/offset-of.rs:18:5
+   |
+LL | struct Gamma {
+   |        ----- field in this struct
+LL |     a: (),
+   |     ^
+
+error: field `b` is never read
+  --> $DIR/offset-of.rs:24:5
+   |
+LL | struct Delta {
+   |        ----- field in this struct
+LL |     a: (),
+LL |     b: (),
+   |     ^
+
+error: field `a` is never read
+  --> $DIR/offset-of.rs:35:5
+   |
+LL | struct Project<T: Trait> {
+   |        ------- field in this struct
+LL |     a: u8,
+   |     ^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/lint/lint-uppercase-variables.stderr b/tests/ui/lint/lint-uppercase-variables.stderr
index 42ec9364bc6..9220828014f 100644
--- a/tests/ui/lint/lint-uppercase-variables.stderr
+++ b/tests/ui/lint/lint-uppercase-variables.stderr
@@ -12,12 +12,6 @@ error[E0170]: pattern binding `Foo` is named the same as one of the variants of
 LL |     let Foo = foo::Foo::Foo;
    |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
 
-error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
-  --> $DIR/lint-uppercase-variables.rs:33:17
-   |
-LL |     fn in_param(Foo: foo::Foo) {}
-   |                 ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
-
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
    |
@@ -37,6 +31,12 @@ warning: unused variable: `Foo`
 LL |     let Foo = foo::Foo::Foo;
    |         ^^^ help: if this is intentional, prefix it with an underscore: `_Foo`
 
+error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
+  --> $DIR/lint-uppercase-variables.rs:33:17
+   |
+LL |     fn in_param(Foo: foo::Foo) {}
+   |                 ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:33:17
    |
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
index 2c35647b8a3..4852c331396 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
+++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
@@ -1,15 +1,3 @@
-error: unused variable: `this_is_my_function`
-  --> $DIR/expect_nested_lint_levels.rs:48:9
-   |
-LL |     let this_is_my_function = 3;
-   |         ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function`
-   |
-note: the lint level is defined here
-  --> $DIR/expect_nested_lint_levels.rs:45:10
-   |
-LL | #[forbid(unused_variables)]
-   |          ^^^^^^^^^^^^^^^^
-
 warning: variable does not need to be mutable
   --> $DIR/expect_nested_lint_levels.rs:36:13
    |
@@ -25,6 +13,18 @@ note: the lint level is defined here
 LL |         unused_mut,
    |         ^^^^^^^^^^
 
+error: unused variable: `this_is_my_function`
+  --> $DIR/expect_nested_lint_levels.rs:48:9
+   |
+LL |     let this_is_my_function = 3;
+   |         ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function`
+   |
+note: the lint level is defined here
+  --> $DIR/expect_nested_lint_levels.rs:45:10
+   |
+LL | #[forbid(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^
+
 warning: this lint expectation is unfulfilled
   --> $DIR/expect_nested_lint_levels.rs:7:5
    |
diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
index 5942fa8aeb4..169f03aed94 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
+++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
@@ -12,12 +12,6 @@ warning: unused variable: `fox_name`
 LL |     let fox_name = "Sir Nibbles";
    |         ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_fox_name`
 
-warning: unused variable: `this_should_fulfill_the_expectation`
-  --> $DIR/force_warn_expected_lints_fulfilled.rs:43:9
-   |
-LL |     let this_should_fulfill_the_expectation = "The `#[allow]` has no power here";
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation`
-
 warning: variable does not need to be mutable
   --> $DIR/force_warn_expected_lints_fulfilled.rs:32:9
    |
@@ -28,6 +22,12 @@ LL |     let mut what_does_the_fox_say = "*ding* *deng* *dung*";
    |
    = note: requested on the command line with `--force-warn unused-mut`
 
+warning: unused variable: `this_should_fulfill_the_expectation`
+  --> $DIR/force_warn_expected_lints_fulfilled.rs:43:9
+   |
+LL |     let this_should_fulfill_the_expectation = "The `#[allow]` has no power here";
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation`
+
 warning: denote infinite loops with `loop { ... }`
   --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5
    |
diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr
index fd9a5bcbfc4..09729eeba79 100644
--- a/tests/ui/lint/unused/lint-unused-variables.stderr
+++ b/tests/ui/lint/unused/lint-unused-variables.stderr
@@ -10,12 +10,6 @@ note: the lint level is defined here
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
-error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:14:5
-   |
-LL |     b: i32,
-   |     ^ help: if this is intentional, prefix it with an underscore: `_b`
-
 error: unused variable: `a`
   --> $DIR/lint-unused-variables.rs:22:9
    |
@@ -23,6 +17,12 @@ LL |         a: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_a`
 
 error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:14:5
+   |
+LL |     b: i32,
+   |     ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
   --> $DIR/lint-unused-variables.rs:29:9
    |
 LL |         b: i32,
diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr
index 6199ea96c98..016debdd396 100644
--- a/tests/ui/liveness/liveness-consts.stderr
+++ b/tests/ui/liveness/liveness-consts.stderr
@@ -1,10 +1,9 @@
-warning: variable `a` is assigned to, but never used
-  --> $DIR/liveness-consts.rs:7:13
+warning: unused variable: `e`
+  --> $DIR/liveness-consts.rs:24:13
    |
-LL |     let mut a = 0;
-   |             ^
+LL |         let e = 1;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_e`
    |
-   = note: consider using `_a` instead
 note: the lint level is defined here
   --> $DIR/liveness-consts.rs:2:9
    |
@@ -12,21 +11,6 @@ LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
-warning: value assigned to `b` is never read
-  --> $DIR/liveness-consts.rs:17:5
-   |
-LL |     b += 1;
-   |     ^
-   |
-   = help: maybe it is overwritten before being read?
-   = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
-
-warning: unused variable: `e`
-  --> $DIR/liveness-consts.rs:24:13
-   |
-LL |         let e = 1;
-   |             ^ help: if this is intentional, prefix it with an underscore: `_e`
-
 warning: unused variable: `s`
   --> $DIR/liveness-consts.rs:33:24
    |
@@ -39,6 +23,29 @@ warning: unused variable: `z`
 LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
    |                                                       ^ help: if this is intentional, prefix it with an underscore: `_z`
 
+warning: unused variable: `z`
+  --> $DIR/liveness-consts.rs:60:13
+   |
+LL |         let z = 42;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_z`
+
+warning: variable `a` is assigned to, but never used
+  --> $DIR/liveness-consts.rs:7:13
+   |
+LL |     let mut a = 0;
+   |             ^
+   |
+   = note: consider using `_a` instead
+
+warning: value assigned to `b` is never read
+  --> $DIR/liveness-consts.rs:17:5
+   |
+LL |     b += 1;
+   |     ^
+   |
+   = help: maybe it is overwritten before being read?
+   = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+
 warning: value assigned to `t` is never read
   --> $DIR/liveness-consts.rs:42:9
    |
@@ -53,11 +60,5 @@ warning: unused variable: `w`
 LL |         let w = 10;
    |             ^ help: if this is intentional, prefix it with an underscore: `_w`
 
-warning: unused variable: `z`
-  --> $DIR/liveness-consts.rs:60:13
-   |
-LL |         let z = 42;
-   |             ^ help: if this is intentional, prefix it with an underscore: `_z`
-
 warning: 8 warnings emitted
 
diff --git a/tests/ui/user-defined-macro-rules.rs b/tests/ui/macros/user-defined-macro-rules.rs
index 09e071ec454..09e071ec454 100644
--- a/tests/ui/user-defined-macro-rules.rs
+++ b/tests/ui/macros/user-defined-macro-rules.rs
diff --git a/tests/ui/missing/missing-allocator.rs b/tests/ui/missing/missing-allocator.rs
index 2dc509f2c63..e06e603e3bf 100644
--- a/tests/ui/missing/missing-allocator.rs
+++ b/tests/ui/missing/missing-allocator.rs
@@ -3,16 +3,10 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(alloc_error_handler)]
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
 
-#[alloc_error_handler]
-fn oom(_: core::alloc::Layout) -> ! {
-    loop {}
-}
-
 extern crate alloc;
diff --git a/tests/ui/offset-of/auxiliary/offset-of-staged-api.rs b/tests/ui/offset-of/auxiliary/offset-of-staged-api.rs
new file mode 100644
index 00000000000..088086cc580
--- /dev/null
+++ b/tests/ui/offset-of/auxiliary/offset-of-staged-api.rs
@@ -0,0 +1,33 @@
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "stable_test_feature", since = "1.0")]
+
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub struct Unstable {
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    pub unstable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0")]
+pub struct Stable {
+    #[stable(feature = "stable_test_feature", since = "1.0")]
+    pub stable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0")]
+pub struct StableWithUnstableField {
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    pub unstable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0")]
+pub struct StableWithUnstableFieldType {
+    #[stable(feature = "stable_test_feature", since = "1.0")]
+    pub stable: Unstable,
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub struct UnstableWithStableFieldType {
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    pub unstable: Stable,
+}
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
new file mode 100644
index 00000000000..163b07454ec
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -0,0 +1,9 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+fn main() {
+    offset_of!(NotEnoughArguments); //~ ERROR expected one of
+    offset_of!(NotEnoughArgumentsWithAComma, ); //~ ERROR expected 2 arguments
+    offset_of!(Container, field, too many arguments); //~ ERROR expected 2 arguments
+}
diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr
new file mode 100644
index 00000000000..ebecc982c51
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-arg-count.stderr
@@ -0,0 +1,20 @@
+error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `<eof>`
+  --> $DIR/offset-of-arg-count.rs:6:16
+   |
+LL |     offset_of!(NotEnoughArguments);
+   |                ^^^^^^^^^^^^^^^^^^ expected one of `!`, `(`, `+`, `,`, `::`, or `<`
+
+error: expected 2 arguments
+  --> $DIR/offset-of-arg-count.rs:7:5
+   |
+LL |     offset_of!(NotEnoughArgumentsWithAComma, );
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected 2 arguments
+  --> $DIR/offset-of-arg-count.rs:8:5
+   |
+LL |     offset_of!(Container, field, too many arguments);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
new file mode 100644
index 00000000000..a0269ca2d12
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -0,0 +1,33 @@
+#![feature(offset_of, extern_types)]
+
+use std::mem::offset_of;
+
+struct Alpha {
+    x: u8,
+    y: u16,
+    z: [u8],
+}
+
+trait Trait {}
+
+struct Beta {
+    x: u8,
+    y: u16,
+    z: dyn Trait,
+}
+
+extern {
+    type Extern;
+}
+
+struct Gamma {
+    x: u8,
+    y: u16,
+    z: Extern,
+}
+
+fn main() {
+    offset_of!(Alpha, z); //~ ERROR the size for values of type
+    offset_of!(Beta, z); //~ ERROR the size for values of type
+    offset_of!(Gamma, z); //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
new file mode 100644
index 00000000000..8e88015b07a
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:30:5
+   |
+LL |     offset_of!(Alpha, z);
+   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:31:5
+   |
+LL |     offset_of!(Beta, z);
+   |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+
+error[E0277]: the size for values of type `Extern` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:32:5
+   |
+LL |     offset_of!(Gamma, z);
+   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `Extern`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs
new file mode 100644
index 00000000000..d73505821ff
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-enum.rs
@@ -0,0 +1,13 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+enum Alpha {
+    One(u8),
+    Two(u8),
+}
+
+fn main() {
+    offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One`
+    offset_of!(Alpha, Two.0); //~ ERROR no field `Two` on type `Alpha`
+}
diff --git a/tests/ui/offset-of/offset-of-enum.stderr b/tests/ui/offset-of/offset-of-enum.stderr
new file mode 100644
index 00000000000..6958d199fbd
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-enum.stderr
@@ -0,0 +1,19 @@
+error[E0573]: expected type, found variant `Alpha::One`
+  --> $DIR/offset-of-enum.rs:11:16
+   |
+LL |     offset_of!(Alpha::One, 0);
+   |                ^^^^^^^^^^
+   |                |
+   |                not a type
+   |                help: try using the variant's enum: `Alpha`
+
+error[E0609]: no field `Two` on type `Alpha`
+  --> $DIR/offset-of-enum.rs:12:23
+   |
+LL |     offset_of!(Alpha, Two.0);
+   |                       ^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0573, E0609.
+For more information about an error, try `rustc --explain E0573`.
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
new file mode 100644
index 00000000000..0291b7825ca
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -0,0 +1,16 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+mod m {
+    #[repr(C)]
+    pub struct Foo {
+        pub public: u8,
+        private: u8,
+    }
+}
+
+fn main() {
+    offset_of!(m::Foo, public);
+    offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
+}
diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr
new file mode 100644
index 00000000000..8a186dd5a02
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-private.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `private` of struct `Foo` is private
+  --> $DIR/offset-of-private.rs:15:24
+   |
+LL |     offset_of!(m::Foo, private);
+   |                        ^^^^^^^ private field
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
new file mode 100644
index 00000000000..7d2eb46c056
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
@@ -0,0 +1,20 @@
+// check-pass
+// aux-build:offset-of-staged-api.rs
+
+#![feature(offset_of, unstable_test_feature)]
+
+use std::mem::offset_of;
+
+extern crate offset_of_staged_api;
+
+use offset_of_staged_api::*;
+
+fn main() {
+    offset_of!(Unstable, unstable);
+    offset_of!(Stable, stable);
+    offset_of!(StableWithUnstableField, unstable);
+    offset_of!(StableWithUnstableFieldType, stable);
+    offset_of!(StableWithUnstableFieldType, stable.unstable);
+    offset_of!(UnstableWithStableFieldType, unstable);
+    offset_of!(UnstableWithStableFieldType, unstable.stable);
+}
diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs
new file mode 100644
index 00000000000..1e19f2091f2
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-unstable.rs
@@ -0,0 +1,31 @@
+// aux-build:offset-of-staged-api.rs
+
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+extern crate offset_of_staged_api;
+
+use offset_of_staged_api::*;
+
+fn main() {
+    offset_of!(
+        //~^ ERROR use of unstable library feature
+        Unstable, //~ ERROR use of unstable library feature
+        unstable
+    );
+    offset_of!(Stable, stable);
+    offset_of!(StableWithUnstableField, unstable); //~ ERROR use of unstable library feature
+    offset_of!(StableWithUnstableFieldType, stable);
+    offset_of!(StableWithUnstableFieldType, stable.unstable); //~ ERROR use of unstable library feature
+    offset_of!(
+        //~^ ERROR use of unstable library feature
+        UnstableWithStableFieldType, //~ ERROR use of unstable library feature
+        unstable
+    );
+    offset_of!(
+        //~^ ERROR use of unstable library feature
+        UnstableWithStableFieldType, //~ ERROR use of unstable library feature
+        unstable.stable
+    );
+}
diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr
new file mode 100644
index 00000000000..25811a061d7
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-unstable.stderr
@@ -0,0 +1,79 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:14:9
+   |
+LL |         Unstable,
+   |         ^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:23:9
+   |
+LL |         UnstableWithStableFieldType,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:28:9
+   |
+LL |         UnstableWithStableFieldType,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:12:5
+   |
+LL | /     offset_of!(
+LL | |
+LL | |         Unstable,
+LL | |         unstable
+LL | |     );
+   | |_____^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:18:5
+   |
+LL |     offset_of!(StableWithUnstableField, unstable);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:20:5
+   |
+LL |     offset_of!(StableWithUnstableFieldType, stable.unstable);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:21:5
+   |
+LL | /     offset_of!(
+LL | |
+LL | |         UnstableWithStableFieldType,
+LL | |         unstable
+LL | |     );
+   | |_____^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/offset-of-unstable.rs:26:5
+   |
+LL | /     offset_of!(
+LL | |
+LL | |         UnstableWithStableFieldType,
+LL | |         unstable.stable
+LL | |     );
+   | |_____^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/oom_unwind.rs b/tests/ui/oom_unwind.rs
index 21a8fb2b22b..704d6f8b810 100644
--- a/tests/ui/oom_unwind.rs
+++ b/tests/ui/oom_unwind.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z oom=panic
+// compile-flags: -Z oom=unwind
 // run-pass
 // no-prefer-dynamic
 // needs-unwind
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 9305facc406..3ce48b1a72f 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -54,14 +54,6 @@ LL |         ref mut a @ box ref b => {
    |         |
    |         value is mutably borrowed by `a` here
 
-error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:54:11
-   |
-LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
-   |           ^^^^^^^^^       ----- value is borrowed by `b` here
-   |           |
-   |           value is mutably borrowed by `a` here
-
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-at-and-box.rs:31:9
    |
@@ -120,6 +112,14 @@ LL |         ref mut a @ box ref b => {
 LL |             drop(b);
    |                  - immutable borrow later used here
 
+error: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-at-and-box.rs:54:11
+   |
+LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
+   |           ^^^^^^^^^       ----- value is borrowed by `b` here
+   |           |
+   |           value is mutably borrowed by `a` here
+
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-at-and-box.rs:54:11
    |
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
index 13989ebadcb..1ed019f0a69 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
@@ -286,78 +286,6 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |         ref mut a @ Some([ref b, ref mut c]) => {}
    |         +++
 
-error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
-   |
-LL |     fn f1(a @ ref b: U) {}
-   |           ^   ----- value borrowed here after move
-   |           |
-   |           value moved into `a` here
-   |           move occurs because `a` has type `U` which does not implement the `Copy` trait
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     fn f1(ref a @ ref b: U) {}
-   |           +++
-
-error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
-   |
-LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |           ^^^^^        -----          ----- value borrowed here after move
-   |           |            |
-   |           |            value borrowed here after move
-   |           value moved into `a` here
-   |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |           +++
-
-error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20
-   |
-LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |                    ^   ----- value borrowed here after move
-   |                    |
-   |                    value moved into `b` here
-   |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {}
-   |                    +++
-
-error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31
-   |
-LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |                               ^^^^^   ----- value borrowed here after move
-   |                               |
-   |                               value moved into `d` here
-   |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {}
-   |                               +++
-
-error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11
-   |
-LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
-   |           ^    ---------  ----- value borrowed here after move
-   |           |    |
-   |           |    value borrowed here after move
-   |           value moved into `a` here
-   |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {}
-   |           +++
-
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
    |
@@ -447,6 +375,63 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         |
    |         value moved here
 
+error: borrow of moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
+   |
+LL |     fn f1(a @ ref b: U) {}
+   |           ^   ----- value borrowed here after move
+   |           |
+   |           value moved into `a` here
+   |           move occurs because `a` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f1(ref a @ ref b: U) {}
+   |           +++
+
+error: borrow of moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
+   |
+LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
+   |           ^^^^^        -----          ----- value borrowed here after move
+   |           |            |
+   |           |            value borrowed here after move
+   |           value moved into `a` here
+   |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
+   |           +++
+
+error: borrow of moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20
+   |
+LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
+   |                    ^   ----- value borrowed here after move
+   |                    |
+   |                    value moved into `b` here
+   |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {}
+   |                    +++
+
+error: borrow of moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31
+   |
+LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
+   |                               ^^^^^   ----- value borrowed here after move
+   |                               |
+   |                               value moved into `d` here
+   |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {}
+   |                               +++
+
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
    |
@@ -457,6 +442,21 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
+error: borrow of moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11
+   |
+LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
+   |           ^    ---------  ----- value borrowed here after move
+   |           |    |
+   |           |    value borrowed here after move
+   |           value moved into `a` here
+   |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
+   |
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |     fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {}
+   |           +++
+
 error: aborting due to 33 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
index 00593b2a98f..c8c4d9b8fdb 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
@@ -166,48 +166,6 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         |                 value is moved into `b` here
    |         value is mutably borrowed by `a` here
 
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
-   |
-LL |     fn f1(ref a @ b: U) {}
-   |           ^^^^^   - value is moved into `b` here
-   |           |
-   |           value is borrowed by `a` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
-   |
-LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |           ^^^^^            -----          - value is moved into `e` here
-   |           |                |
-   |           |                value is moved into `c` here
-   |           value is borrowed by `a` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
-   |
-LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |                    ^^^^^   ----- value is moved into `c` here
-   |                    |
-   |                    value is borrowed by `b` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
-   |
-LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |                                   ^^^^^   - value is moved into `e` here
-   |                                   |
-   |                                   value is borrowed by `d` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
-   |
-LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
-   |           ^^^^^^^^^    -  ----- value is moved into `c` here
-   |           |            |
-   |           |            value is moved into `b` here
-   |           value is mutably borrowed by `a` here
-
 error[E0382]: borrow of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
    |
@@ -306,6 +264,14 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |         ref a @ Some((ref b @ mut c, ref d @ ref e)) => {}
    |                                              +++
 
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
+   |
+LL |     fn f1(ref a @ b: U) {}
+   |           ^^^^^   - value is moved into `b` here
+   |           |
+   |           value is borrowed by `a` here
+
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
    |
@@ -315,6 +281,31 @@ LL |     fn f1(ref a @ b: U) {}
    |           value borrowed here after move
    |           move occurs because value has type `U`, which does not implement the `Copy` trait
 
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
+   |
+LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
+   |           ^^^^^            -----          - value is moved into `e` here
+   |           |                |
+   |           |                value is moved into `c` here
+   |           value is borrowed by `a` here
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
+   |
+LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
+   |                    ^^^^^   ----- value is moved into `c` here
+   |                    |
+   |                    value is borrowed by `b` here
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
+   |
+LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
+   |                                   ^^^^^   - value is moved into `e` here
+   |                                   |
+   |                                   value is borrowed by `d` here
+
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
    |
@@ -335,6 +326,15 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
+   |
+LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
+   |           ^^^^^^^^^    -  ----- value is moved into `c` here
+   |           |            |
+   |           |            value is moved into `b` here
+   |           value is mutably borrowed by `a` here
+
 error[E0382]: borrow of partially moved value
   --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
    |
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index d6409d1b643..c0a6558a1bf 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -221,47 +221,6 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         |            value is borrowed by `b` here
    |         value is mutably borrowed by `a` here
 
-error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11
-   |
-LL |     fn f1(ref a @ ref mut b: U) {}
-   |           ^^^^^   --------- value is mutably borrowed by `b` here
-   |           |
-   |           value is borrowed by `a` here
-
-error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
-   |
-LL |     fn f2(ref mut a @ ref b: U) {}
-   |           ^^^^^^^^^   ----- value is borrowed by `b` here
-   |           |
-   |           value is mutably borrowed by `a` here
-
-error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
-   |
-LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
-   |           ^^^^^           ----------- value is mutably borrowed by `mid` here
-   |           |
-   |           value is borrowed by `a` here
-
-error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22
-   |
-LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
-   |                      ^^^^^   ---------   - value is moved into `c` here
-   |                      |       |
-   |                      |       value is mutably borrowed by `b` here
-   |                      value is borrowed by `a` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
-   |
-LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
-   |                              ^^^^^^^^^   - value is moved into `c` here
-   |                              |
-   |                              value is mutably borrowed by `b` here
-
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31
    |
@@ -398,6 +357,47 @@ LL |
 LL |     *b = U;
    |     ------ mutable borrow later used here
 
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11
+   |
+LL |     fn f1(ref a @ ref mut b: U) {}
+   |           ^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
+   |           value is borrowed by `a` here
+
+error: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
+   |
+LL |     fn f2(ref mut a @ ref b: U) {}
+   |           ^^^^^^^^^   ----- value is borrowed by `b` here
+   |           |
+   |           value is mutably borrowed by `a` here
+
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
+   |
+LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
+   |           ^^^^^           ----------- value is mutably borrowed by `mid` here
+   |           |
+   |           value is borrowed by `a` here
+
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22
+   |
+LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
+   |                      ^^^^^   ---------   - value is moved into `c` here
+   |                      |       |
+   |                      |       value is mutably borrowed by `b` here
+   |                      value is borrowed by `a` here
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
+   |
+LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
+   |                              ^^^^^^^^^   - value is moved into `c` here
+   |                              |
+   |                              value is mutably borrowed by `b` here
+
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
    |
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 24189d0615c..c634ea470c5 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -194,50 +194,6 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     |
    |                                     value is mutably borrowed by `a` here
 
-error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
-   |
-LL |     fn f1(ref mut a @ ref mut b: U) {}
-   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
-   |           |
-   |           value is mutably borrowed by `a` here
-
-error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
-   |
-LL |     fn f2(ref mut a @ ref mut b: U) {}
-   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
-   |           |
-   |           value is mutably borrowed by `a` here
-
-error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9
-   |
-LL |         ref mut a @ [
-   |         ^^^^^^^^^ value is mutably borrowed by `a` here
-LL |
-LL |             [ref b @ .., _],
-   |              ----- value is borrowed by `b` here
-LL |             [_, ref mut mid @ ..],
-   |                 ----------- value is mutably borrowed by `mid` here
-
-error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22
-   |
-LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
-   |                      ^^^^^^^^^   ---------   - value is moved into `c` here
-   |                      |           |
-   |                      |           value is mutably borrowed by `b` here
-   |                      value is mutably borrowed by `a` here
-
-error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
-   |
-LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
-   |                                  ^^^^^^^^^   - value is moved into `c` here
-   |                                  |
-   |                                  value is mutably borrowed by `b` here
-
 error[E0499]: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
    |
@@ -304,6 +260,50 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
 LL |             drop(a);
    |                  - first borrow later used here
 
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
+   |
+LL |     fn f1(ref mut a @ ref mut b: U) {}
+   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
+   |           value is mutably borrowed by `a` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
+   |
+LL |     fn f2(ref mut a @ ref mut b: U) {}
+   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
+   |           value is mutably borrowed by `a` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9
+   |
+LL |         ref mut a @ [
+   |         ^^^^^^^^^ value is mutably borrowed by `a` here
+LL |
+LL |             [ref b @ .., _],
+   |              ----- value is borrowed by `b` here
+LL |             [_, ref mut mid @ ..],
+   |                 ----------- value is mutably borrowed by `mid` here
+
+error: cannot borrow value as mutable more than once at a time
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22
+   |
+LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
+   |                      ^^^^^^^^^   ---------   - value is moved into `c` here
+   |                      |           |
+   |                      |           value is mutably borrowed by `b` here
+   |                      value is mutably borrowed by `a` here
+
+error: cannot move out of value because it is borrowed
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
+   |
+LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
+   |                                  ^^^^^^^^^   - value is moved into `c` here
+   |                                  |
+   |                                  value is mutably borrowed by `b` here
+
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
    |
diff --git a/tests/ui/privacy/privacy2.stderr b/tests/ui/privacy/privacy2.stderr
index 882f314655d..c2a33ce1f59 100644
--- a/tests/ui/privacy/privacy2.stderr
+++ b/tests/ui/privacy/privacy2.stderr
@@ -23,13 +23,7 @@ LL | pub fn foo() {}
 
 error: requires `sized` lang_item
 
-error: requires `sized` lang_item
-
-error: requires `sized` lang_item
-
-error: requires `sized` lang_item
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0432, E0603.
 For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/privacy/privacy3.stderr b/tests/ui/privacy/privacy3.stderr
index 42ce456d962..22c1e48b07d 100644
--- a/tests/ui/privacy/privacy3.stderr
+++ b/tests/ui/privacy/privacy3.stderr
@@ -6,12 +6,6 @@ LL |     use bar::gpriv;
 
 error: requires `sized` lang_item
 
-error: requires `sized` lang_item
-
-error: requires `sized` lang_item
-
-error: requires `sized` lang_item
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
index 6d18d295cfc..16e1af46059 100644
--- a/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
+++ b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
@@ -10,6 +10,12 @@ note: the lint level is defined here
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
+error: unused variable: `a`
+  --> $DIR/param-attrs-cfg.rs:41:27
+   |
+LL |         #[cfg(something)] a: i32,
+   |                           ^ help: if this is intentional, prefix it with an underscore: `_a`
+
 error: unused variable: `b`
   --> $DIR/param-attrs-cfg.rs:30:23
    |
@@ -22,12 +28,6 @@ error: unused variable: `c`
 LL |     #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                        ^ help: if this is intentional, prefix it with an underscore: `_c`
 
-error: unused variable: `a`
-  --> $DIR/param-attrs-cfg.rs:41:27
-   |
-LL |         #[cfg(something)] a: i32,
-   |                           ^ help: if this is intentional, prefix it with an underscore: `_a`
-
 error: unused variable: `b`
   --> $DIR/param-attrs-cfg.rs:48:27
    |
diff --git a/tests/ui/span/send-is-not-static-std-sync-2.stderr b/tests/ui/span/send-is-not-static-std-sync-2.stderr
index b0267fa6f43..c825cc8d668 100644
--- a/tests/ui/span/send-is-not-static-std-sync-2.stderr
+++ b/tests/ui/span/send-is-not-static-std-sync-2.stderr
@@ -25,8 +25,6 @@ LL |     };
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-std-sync-2.rs:31:25
    |
-LL |     let (_tx, rx) = {
-   |          --- borrow later used here
 LL |         let x = 1;
    |             - binding `x` declared here
 LL |         let (tx, rx) = mpsc::channel();
diff --git a/tests/ui/traits/new-solver/borrowck-error.rs b/tests/ui/traits/new-solver/borrowck-error.rs
new file mode 100644
index 00000000000..4787a2c7e11
--- /dev/null
+++ b/tests/ui/traits/new-solver/borrowck-error.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Ztrait-solver=next
+
+use std::collections::HashMap;
+
+fn foo() -> &'static HashMap<i32, i32>
+{
+    &HashMap::new()
+    //~^ ERROR cannot return reference to temporary value
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/borrowck-error.stderr b/tests/ui/traits/new-solver/borrowck-error.stderr
new file mode 100644
index 00000000000..a7d8201747a
--- /dev/null
+++ b/tests/ui/traits/new-solver/borrowck-error.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/borrowck-error.rs:7:5
+   |
+LL |     &HashMap::new()
+   |     ^--------------
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.