about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml8
-rw-r--r--RELEASES.md99
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs30
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs14
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs13
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs49
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs26
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs31
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs23
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs16
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs10
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs68
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs28
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs24
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs27
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs23
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs7
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs7
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs10
-rw-r--r--compiler/rustc_middle/src/mir/query.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs7
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs5
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs7
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs13
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs3
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs6
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs2
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs12
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs71
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs77
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs75
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs135
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs23
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs51
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs1
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs6
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs3
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs1
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs2
-rw-r--r--compiler/rustc_traits/src/type_op.rs55
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs1
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs2
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs2
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs1
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs12
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs1
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs1
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs12
-rw-r--r--compiler/rustc_typeck/src/collect.rs1
-rw-r--r--compiler/rustc_typeck/src/outlives/implicit_infer.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/core/src/cell.rs21
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/task/wake.rs9
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/task.rs17
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/builder/tests.rs4
-rw-r--r--src/bootstrap/dist.rs39
-rw-r--r--src/bootstrap/doc.rs212
-rw-r--r--src/bootstrap/flags.rs20
-rw-r--r--src/bootstrap/lib.rs5
-rw-r--r--src/ci/github-actions/ci.yml9
-rw-r--r--src/librustdoc/clean/blanket_impl.rs1
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/test/mir-opt/issue-101867.rs9
-rw-r--r--src/test/mir-opt/issue_101867.main.mir_map.0.mir75
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/Makefile15
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs4
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/main.rs9
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/Makefile12
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs9
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs4
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.stderr2
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs35
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr20
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs40
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr22
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs23
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr22
-rw-r--r--src/test/ui/generic-associated-types/trait-objects.extended.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr6
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr6
-rw-r--r--src/test/ui/invalid/invalid-inline.rs9
-rw-r--r--src/test/ui/invalid/invalid-inline.stderr15
-rw-r--r--src/test/ui/issues/issue-26217.stderr6
-rw-r--r--src/test/ui/let-else/const-fn.rs19
-rw-r--r--src/test/ui/lexer/lex-emoji-identifiers.rs17
-rw-r--r--src/test/ui/lexer/lex-emoji-identifiers.stderr52
-rw-r--r--src/test/ui/nll/local-outlives-static-via-hrtb.stderr12
-rw-r--r--src/test/ui/nll/type-test-universe.stderr6
-rw-r--r--src/test/ui/span/E0535.stderr2
-rw-r--r--src/test/ui/suggestions/issue-101623.rs25
-rw-r--r--src/test/ui/suggestions/issue-101623.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs92
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs2
-rw-r--r--src/tools/tidy/src/walk.rs6
181 files changed, 1689 insertions, 663 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ec1ef041b20..6693182e0c5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -25,11 +25,15 @@ name: CI
   pull_request:
     branches:
       - "**"
+permissions:
+  contents: read
 defaults:
   run:
     shell: bash
 jobs:
   pr:
+    permissions:
+      actions: write
     name: PR
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
@@ -142,6 +146,8 @@ jobs:
           AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
         if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
   auto:
+    permissions:
+      actions: write
     name: auto
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
@@ -547,6 +553,8 @@ jobs:
           AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
         if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
   try:
+    permissions:
+      actions: write
     name: try
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
diff --git a/RELEASES.md b/RELEASES.md
index 51c25030cad..694bd09658f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -3,63 +3,33 @@ Version 1.64.0 (2022-09-22)
 
 Language
 --------
-- [make `const_err` show up in future breakage reports](https://github.com/rust-lang/rust/pull/97743/)
-- [allow unions with mutable references and tuples of allowed types](https://github.com/rust-lang/rust/pull/97995/)
+- [Unions with mutable references or tuples of allowed types are now allowed](https://github.com/rust-lang/rust/pull/97995/)
 - It is now considered valid to deallocate memory pointed to by a shared reference `&T` [if every byte in `T` is inside an `UnsafeCell`](https://github.com/rust-lang/rust/pull/98017/)
 - Unused tuple struct fields are now warned against in an allow-by-default lint, [`unused_tuple_struct_fields`](https://github.com/rust-lang/rust/pull/95977/), similar to the existing warning for unused struct fields. This lint will become warn-by-default in the future.
 
 Compiler
 --------
-- The minimum required versions for all `-linux-gnu` targets are now at least kernel 3.2 and glibc 2.17, for targets that previously supported older versions: [Increase the minimum linux-gnu versions](https://github.com/rust-lang/rust/pull/95026/)
-- [Keep unstable target features for asm feature checking](https://github.com/rust-lang/rust/pull/99155/)
 - [Add Nintendo Switch as tier 3 target](https://github.com/rust-lang/rust/pull/88991/)
   - Refer to Rust's [platform support page][platform-support-doc] for more
     information on Rust's tiered platform support.
-- [Only compile #[used] as llvm.compiler.used for ELF targets](https://github.com/rust-lang/rust/pull/93718/)
-- [sess: stabilize `-Zterminal-width` as `--diagnostic-width`](https://github.com/rust-lang/rust/pull/95635/)
-- [Fix repr(align) enum handling](https://github.com/rust-lang/rust/pull/96814/)
-- [Suggest defining variable as mutable on `&mut _` type mismatch in pats](https://github.com/rust-lang/rust/pull/98431/)
-- [Emit warning when named arguments are used positionally in format](https://github.com/rust-lang/rust/pull/98580/)
-- [Add support for link-flavor rust-lld for iOS, tvOS and watchOS](https://github.com/rust-lang/rust/pull/98771/)
-- [Do not mention private types from other crates as impl candidates](https://github.com/rust-lang/rust/pull/99091/)
+- [Only compile `#[used]` as llvm.compiler.used for ELF targets](https://github.com/rust-lang/rust/pull/93718/)
+- [Add the `--diagnostic-width` compiler flag to define the terminal width.](https://github.com/rust-lang/rust/pull/95635/)
+- [Add support for link-flavor `rust-lld` for iOS, tvOS and watchOS](https://github.com/rust-lang/rust/pull/98771/)
 
 Libraries
 ---------
-- [Implement network primitives with ideal Rust layout, not C system layout](https://github.com/rust-lang/rust/pull/78802/)
 - [Remove restrictions on compare-exchange memory ordering.](https://github.com/rust-lang/rust/pull/98383/)
 - You can now `write!` or `writeln!` into an `OsString`: [Implement `fmt::Write` for `OsString`](https://github.com/rust-lang/rust/pull/97915/)
-- [Enforce that layout size fits in isize in Layout](https://github.com/rust-lang/rust/pull/95295/)
 - [Make RwLockReadGuard covariant](https://github.com/rust-lang/rust/pull/96820/)
 - [Implement `FusedIterator` for `std::net::[Into]Incoming`](https://github.com/rust-lang/rust/pull/97300/)
 - [`impl<T: AsRawFd> AsRawFd for {Arc,Box}<T>`](https://github.com/rust-lang/rust/pull/97437/)
-- [ptr::copy and ptr::swap are doing untyped copies](https://github.com/rust-lang/rust/pull/97712/)
-- [Add assertion that `transmute_copy`'s U is not larger than T](https://github.com/rust-lang/rust/pull/98839/)
-- [A soundness bug in `BTreeMap` was fixed](https://github.com/rust-lang/rust/pull/99413/) that allowed data it was borrowing to be dropped before the container.
+- [`ptr::copy` and `ptr::swap` are doing untyped copies](https://github.com/rust-lang/rust/pull/97712/)
 - [Add cgroupv1 support to `available_parallelism`](https://github.com/rust-lang/rust/pull/97925/)
-- [mem::uninitialized: mitigate many incorrect uses of this function](https://github.com/rust-lang/rust/pull/99182/)
+- [Mitigate many incorrect uses of `mem::uninitialized`](https://github.com/rust-lang/rust/pull/99182/)
 
 Stabilized APIs
 ---------------
 
-- [`ffi::CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html)
-- [`ffi::CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html)
-- [`ffi::FromBytesWithNulError`](https://doc.rust-lang.org/stable/std/ffi/struct.FromBytesWithNulError.html)
-- [`ffi::FromVecWithNulError`](https://doc.rust-lang.org/stable/std/ffi/struct.FromVecWithNulError.html)
-- [`ffi::IntoStringError`](https://doc.rust-lang.org/stable/std/ffi/struct.IntoStringError.html)
-- [`ffi::NulError`](https://doc.rust-lang.org/stable/std/ffi/struct.NulError.html)
-- [`ffi::c_char`](https://doc.rust-lang.org/stable/std/ffi/type.c_char.html)
-- [`ffi::c_double`](https://doc.rust-lang.org/stable/std/ffi/type.c_double.html)
-- [`ffi::c_float`](https://doc.rust-lang.org/stable/std/ffi/type.c_float.html)
-- [`ffi::c_int`](https://doc.rust-lang.org/stable/std/ffi/type.c_int.html)
-- [`ffi::c_long`](https://doc.rust-lang.org/stable/std/ffi/type.c_long.html)
-- [`ffi::c_longlong`](https://doc.rust-lang.org/stable/std/ffi/type.c_longlong.html)
-- [`ffi::c_schar`](https://doc.rust-lang.org/stable/std/ffi/type.c_schar.html)
-- [`ffi::c_short`](https://doc.rust-lang.org/stable/std/ffi/type.c_short.html)
-- [`ffi::c_uchar`](https://doc.rust-lang.org/stable/std/ffi/type.c_uchar.html)
-- [`ffi::c_uint`](https://doc.rust-lang.org/stable/std/ffi/type.c_uint.html)
-- [`ffi::c_ulong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulong.html)
-- [`ffi::c_ulonglong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulonglong.html)
-- [`ffi::c_ushort`](https://doc.rust-lang.org/stable/std/ffi/type.c_ushort.html)
 - [`future::IntoFuture`](https://doc.rust-lang.org/stable/std/future/trait.IntoFuture.html)
 - [`future::poll_fn`](https://doc.rust-lang.org/stable/std/future/fn.poll_fn.html)
 - [`task::ready!`](https://doc.rust-lang.org/stable/std/task/macro.ready.html)
@@ -80,46 +50,65 @@ Stabilized APIs
 - [`os::windows::fs::FileTypeExt::is_symlink_dir`](https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_dir)
 - [`os::windows::fs::FileTypeExt::is_symlink_file`](https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_file)
 
+These types were previously stable in `std::ffi`, but are now also available in `core` and `alloc`:
+
+- [`core::ffi::CStr`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html)
+- [`core::ffi::FromBytesWithNulError`](https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesWithNulError.html)
+- [`alloc::ffi::CString`](https://doc.rust-lang.org/stable/alloc/ffi/struct.CString.html)
+- [`alloc::ffi::FromVecWithNulError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.FromVecWithNulError.html)
+- [`alloc::ffi::IntoStringError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.IntoStringError.html)
+- [`alloc::ffi::NulError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.NulError.html)
+
+These types were previously stable in `std::os::raw`, but are now also available in `core::ffi` and `std::ffi`:
+
+- [`ffi::c_char`](https://doc.rust-lang.org/stable/std/ffi/type.c_char.html)
+- [`ffi::c_double`](https://doc.rust-lang.org/stable/std/ffi/type.c_double.html)
+- [`ffi::c_float`](https://doc.rust-lang.org/stable/std/ffi/type.c_float.html)
+- [`ffi::c_int`](https://doc.rust-lang.org/stable/std/ffi/type.c_int.html)
+- [`ffi::c_long`](https://doc.rust-lang.org/stable/std/ffi/type.c_long.html)
+- [`ffi::c_longlong`](https://doc.rust-lang.org/stable/std/ffi/type.c_longlong.html)
+- [`ffi::c_schar`](https://doc.rust-lang.org/stable/std/ffi/type.c_schar.html)
+- [`ffi::c_short`](https://doc.rust-lang.org/stable/std/ffi/type.c_short.html)
+- [`ffi::c_uchar`](https://doc.rust-lang.org/stable/std/ffi/type.c_uchar.html)
+- [`ffi::c_uint`](https://doc.rust-lang.org/stable/std/ffi/type.c_uint.html)
+- [`ffi::c_ulong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulong.html)
+- [`ffi::c_ulonglong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulonglong.html)
+- [`ffi::c_ushort`](https://doc.rust-lang.org/stable/std/ffi/type.c_ushort.html)
+
 These APIs are now usable in const contexts:
 
 - [`slice::from_raw_parts`](https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts.html)
 
 Cargo
 -----
-- Packages can now inherit settings from the workspace so that the settings
-  can be centralized in one place. See
+- [Packages can now inherit settings from the workspace so that the settings
+  can be centralized in one place.](https://github.com/rust-lang/cargo/pull/10859) See
   [`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacepackage-table)
   and
   [`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacedependencies-table)
   for more details on how to define these common settings.
-  [#10859](https://github.com/rust-lang/cargo/pull/10859)
-- Cargo commands can now accept multiple `--target` flags to build for
-  multiple targets at once, and the
+- [Cargo commands can now accept multiple `--target` flags to build for
+  multiple targets at once](https://github.com/rust-lang/cargo/pull/10766), and the
   [`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget)
   config option may now take an array of multiple targets.
-  [#10766](https://github.com/rust-lang/cargo/pull/10766)
-- The `--jobs` argument can now take a negative number to count backwards from
-  the max CPUs.
-  [#10844](https://github.com/rust-lang/cargo/pull/10844)
-- `cargo add` will now update `Cargo.lock`.
-  [#10902](https://github.com/rust-lang/cargo/pull/10902)
-- Added the
+- [The `--jobs` argument can now take a negative number to count backwards from
+  the max CPUs.](https://github.com/rust-lang/cargo/pull/10844)
+- [`cargo add` will now update `Cargo.lock`.](https://github.com/rust-lang/cargo/pull/10902)
+- [Added](https://github.com/rust-lang/cargo/pull/10838) the
   [`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type)
   flag to `cargo rustc` to override the crate type.
-  [#10838](https://github.com/rust-lang/cargo/pull/10838)
-- Significantly improved the performance fetching git dependencies from GitHub
-  when using a hash in the `rev` field.
-  [#10079](https://github.com/rust-lang/cargo/pull/10079)
+- [Significantly improved the performance fetching git dependencies from GitHub
+  when using a hash in the `rev` field.](https://github.com/rust-lang/cargo/pull/10079)
 
 Misc
 ----
-- [Let rust-analyzer ship on stable, non-preview](https://github.com/rust-lang/rust/pull/98640/)
+- [The `rust-analyzer` rustup component is now available on the stable channel.](https://github.com/rust-lang/rust/pull/98640/)
 
 Compatibility Notes
 -------------------
 - The minimum required versions for all `-linux-gnu` targets are now at least kernel 3.2 and glibc 2.17, for targets that previously supported older versions: [Increase the minimum linux-gnu versions](https://github.com/rust-lang/rust/pull/95026/)
-- [Implement network primitives with ideal Rust layout, not C system layout](https://github.com/rust-lang/rust/pull/78802/)
-- [Add assertion that `transmute_copy`'s U is not larger than T](https://github.com/rust-lang/rust/pull/98839/)
+- [Network primitives are now implemented with the ideal Rust layout, not the C system layout](https://github.com/rust-lang/rust/pull/78802/). This can cause problems when transmuting the types.
+- [Add assertion that `transmute_copy`'s `U` is not larger than `T`](https://github.com/rust-lang/rust/pull/98839/)
 - [A soundness bug in `BTreeMap` was fixed](https://github.com/rust-lang/rust/pull/99413/) that allowed data it was borrowing to be dropped before the container.
 - [The Drop behavior of C-like enums cast to ints has changed](https://github.com/rust-lang/rust/pull/96862/). These are already discouraged by a compiler warning.
 - [Relate late-bound closure lifetimes to parent fn in NLL](https://github.com/rust-lang/rust/pull/98835/)
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index 6d323b03cda..df04128135b 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -21,10 +21,7 @@ pub(crate) struct OutlivesConstraintSet<'tcx> {
 
 impl<'tcx> OutlivesConstraintSet<'tcx> {
     pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
-        debug!(
-            "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
-            constraint.sup, constraint.sub, constraint.locations
-        );
+        debug!("OutlivesConstraintSet::push({:?})", constraint);
         if constraint.sup == constraint.sub {
             // 'a: 'a is pretty uninteresting
             return;
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f2204c24263..7fff5988785 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::{
     FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
     ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
 };
-use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
 use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
@@ -2146,7 +2146,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             }
                             StorageDeadOrDrop::Destructor(_) => kind,
                         },
-                        ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
+                        ProjectionElem::OpaqueCast { .. }
+                        | ProjectionElem::Field(..)
+                        | ProjectionElem::Downcast(..) => {
                             match place_ty.ty.kind() {
                                 ty::Adt(def, _) if def.has_dtor(tcx) => {
                                     // Report the outermost adt with a destructor
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 3b58da11e84..1c01e78abd4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt};
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{sym, DesugaringKind, Span};
 
-use crate::region_infer::BlameConstraint;
+use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
 use crate::{
     borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
     WriteKind,
@@ -38,6 +38,7 @@ pub(crate) enum BorrowExplanation<'tcx> {
         span: Span,
         region_name: RegionName,
         opt_place_desc: Option<String>,
+        extra_info: Vec<ExtraConstraintInfo>,
     },
     Unexplained,
 }
@@ -243,6 +244,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 ref region_name,
                 ref opt_place_desc,
                 from_closure: _,
+                ref extra_info,
             } => {
                 region_name.highlight_region_name(err);
 
@@ -268,6 +270,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     );
                 };
 
+                for extra in extra_info {
+                    match extra {
+                        ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
+                            err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
+                        }
+                    }
+                }
+
                 self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
             }
             _ => {}
@@ -309,16 +319,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &self,
         borrow_region: RegionVid,
         outlived_region: RegionVid,
-    ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>) {
-        let BlameConstraint { category, from_closure, cause, variance_info: _ } = self
-            .regioncx
-            .best_blame_constraint(borrow_region, NllRegionVariableOrigin::FreeRegion, |r| {
-                self.regioncx.provides_universal_region(r, borrow_region, outlived_region)
-            });
+    ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
+        let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint(
+            borrow_region,
+            NllRegionVariableOrigin::FreeRegion,
+            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+        );
+        let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;
 
         let outlived_fr_name = self.give_region_a_name(outlived_region);
 
-        (category, from_closure, cause.span, outlived_fr_name)
+        (category, from_closure, cause.span, outlived_fr_name, extra_info)
     }
 
     /// Returns structured explanation for *why* the borrow contains the
@@ -390,7 +401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             None => {
                 if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
-                    let (category, from_closure, span, region_name) =
+                    let (category, from_closure, span, region_name, extra_info) =
                         self.free_region_constraint_info(borrow_region_vid, region);
                     if let Some(region_name) = region_name {
                         let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
@@ -400,6 +411,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             span,
                             region_name,
                             opt_place_desc,
+                            extra_info,
                         }
                     } else {
                         debug!("Could not generate a region name");
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 683084cf09d..baabeea5823 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 }
                 ProjectionElem::Downcast(..) if opt.including_downcast => return None,
                 ProjectionElem::Downcast(..) => (),
+                ProjectionElem::OpaqueCast(..) => (),
                 ProjectionElem::Field(field, _ty) => {
                     // FIXME(project-rfc_2229#36): print capture precisely here.
                     if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
                 }
                 ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
+                ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
                 ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
             },
         };
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6b5014fa909..202729b4744 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -169,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         ..,
                         ProjectionElem::Index(_)
                         | ProjectionElem::ConstantIndex { .. }
+                        | ProjectionElem::OpaqueCast { .. }
                         | ProjectionElem::Subslice { .. }
                         | ProjectionElem::Downcast(..),
                     ],
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index e7681222fc1..34be2874fcb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -31,7 +31,7 @@ use crate::session_diagnostics::{
 };
 
 use super::{OutlivesSuggestionBuilder, RegionName};
-use crate::region_infer::BlameConstraint;
+use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
 use crate::{
     nll::ConstraintDescription,
     region_infer::{values::RegionElement, TypeTest},
@@ -354,10 +354,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     ) {
         debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let BlameConstraint { category, cause, variance_info, from_closure: _ } =
+        let (blame_constraint, extra_info) =
             self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
                 self.regioncx.provides_universal_region(r, fr, outlived_fr)
             });
+        let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
 
         debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
 
@@ -466,6 +467,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
         }
 
+        for extra in extra_info {
+            match extra {
+                ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
+                    diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
+                }
+            }
+        }
+
         self.buffer_error(diag);
     }
 
@@ -557,6 +566,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// LL |     ref_obj(x)
     ///    |     ^^^^^^^^^^ `x` escapes the function body here
     /// ```
+    #[instrument(level = "debug", skip(self))]
     fn report_escaping_data_error(
         &self,
         errci: &ErrorConstraintInfo<'tcx>,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 86da87d0603..cb16bec57ee 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1781,6 +1781,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
+                ProjectionElem::OpaqueCast(_) |
                 ProjectionElem::ConstantIndex { .. } |
                 // assigning to P[i] requires P to be valid.
                 ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@@ -2172,6 +2173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     | ProjectionElem::Index(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. }
+                    | ProjectionElem::OpaqueCast { .. }
                     | ProjectionElem::Downcast(..) => {
                         let upvar_field_projection = self.is_upvar_field_projection(place);
                         if let Some(field) = upvar_field_projection {
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 6e5a96bee97..0e71efd6f8d 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
                 | (ProjectionElem::Index { .. }, _, _)
                 | (ProjectionElem::ConstantIndex { .. }, _, _)
                 | (ProjectionElem::Subslice { .. }, _, _)
+                | (ProjectionElem::OpaqueCast { .. }, _, _)
                 | (ProjectionElem::Downcast { .. }, _, _) => {
                     // Recursive case. This can still be disjoint on a
                     // further iteration if this a shallow access and
@@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
             debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
             Overlap::EqualOrDisjoint
         }
+        (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
+            if v1 == v2 {
+                // same type - recur.
+                debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
+                Overlap::EqualOrDisjoint
+            } else {
+                // Different types. Disjoint!
+                debug!("place_element_conflict: DISJOINT-OPAQUE");
+                Overlap::Disjoint
+            }
+        }
         (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
             if f1 == f2 {
                 // same field (e.g., `a.y` vs. `a.y`) - recur.
@@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::OpaqueCast { .. }
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Downcast(..),
             _,
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index bdf2becb711..2b50cbac9a0 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         }
                         ProjectionElem::Downcast(..)
                         | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::OpaqueCast { .. }
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Index(_) => {
                             cursor = cursor_base;
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 79a3a247c48..244e6e3422d 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -245,6 +245,11 @@ enum Trace<'tcx> {
     NotVisited,
 }
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum ExtraConstraintInfo {
+    PlaceholderFromPredicate(Span),
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Creates a new region inference context with a total of
     /// `num_region_variables` valid inference variables; the first N
@@ -1818,10 +1823,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr1_origin: NllRegionVariableOrigin,
         fr2: RegionVid,
     ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
-        let BlameConstraint { category, cause, .. } =
-            self.best_blame_constraint(fr1, fr1_origin, |r| {
-                self.provides_universal_region(r, fr1, fr2)
-            });
+        let BlameConstraint { category, cause, .. } = self
+            .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
+            .0;
         (category, cause)
     }
 
@@ -2010,7 +2014,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         from_region: RegionVid,
         from_region_origin: NllRegionVariableOrigin,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> BlameConstraint<'tcx> {
+    ) -> (BlameConstraint<'tcx>, Vec<ExtraConstraintInfo>) {
         // Find all paths
         let (path, target_region) =
             self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
@@ -2026,6 +2030,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 .collect::<Vec<_>>()
         );
 
+        let mut extra_info = vec![];
+        for constraint in path.iter() {
+            let outlived = constraint.sub;
+            let Some(origin) = self.var_infos.get(outlived) else { continue; };
+            let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; };
+            debug!(?constraint, ?p);
+            let ConstraintCategory::Predicate(span) = constraint.category else { continue; };
+            extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
+            // We only want to point to one
+            break;
+        }
+
         // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
         // Instead, we use it to produce an improved `ObligationCauseCode`.
         // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate`
@@ -2073,6 +2089,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     from_closure,
                     cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
                     variance_info: constraint.variance_info,
+                    outlives_constraint: *constraint,
                 }
             })
             .collect();
@@ -2174,7 +2191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let best_choice =
             if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
 
-        debug!(?best_choice, ?blame_source);
+        debug!(?best_choice, ?blame_source, ?extra_info);
 
         if let Some(i) = best_choice {
             if let Some(next) = categorized_path.get(i + 1) {
@@ -2183,7 +2200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 {
                     // The return expression is being influenced by the return type being
                     // impl Trait, point at the return type and not the return expr.
-                    return next.clone();
+                    return (next.clone(), extra_info);
                 }
             }
 
@@ -2203,7 +2220,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
             }
 
-            return categorized_path[i].clone();
+            return (categorized_path[i].clone(), extra_info);
         }
 
         // If that search fails, that is.. unusual. Maybe everything
@@ -2213,7 +2230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
         debug!("sorted_path={:#?}", categorized_path);
 
-        categorized_path.remove(0)
+        (categorized_path.remove(0), extra_info)
     }
 
     pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
@@ -2295,7 +2312,13 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
                              outlives_requirement={:?}",
                             region, outlived_region, outlives_requirement,
                         );
-                        ty::Binder::dummy(ty::OutlivesPredicate(region.into(), outlived_region))
+                        (
+                            ty::Binder::dummy(ty::OutlivesPredicate(
+                                region.into(),
+                                outlived_region,
+                            )),
+                            ConstraintCategory::BoringNoLocation,
+                        )
                     }
 
                     ClosureOutlivesSubject::Ty(ty) => {
@@ -2305,7 +2328,10 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
                              outlives_requirement={:?}",
                             ty, outlived_region, outlives_requirement,
                         );
-                        ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region))
+                        (
+                            ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
+                            ConstraintCategory::BoringNoLocation,
+                        )
                     }
                 }
             })
@@ -2319,4 +2345,5 @@ pub struct BlameConstraint<'tcx> {
     pub from_closure: bool,
     pub cause: ObligationCause<'tcx>,
     pub variance_info: ty::VarianceDiagInfo<'tcx>,
+    pub outlives_constraint: OutlivesConstraint<'tcx>,
 }
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 29195b3922f..9271a2f4dc7 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -25,7 +25,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// constraints should occur within this method so that those
     /// constraints can be properly localized!**
     #[instrument(skip(self, op), level = "trace")]
-    pub(super) fn fully_perform_op<R, Op>(
+    pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
         &mut self,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
@@ -39,6 +39,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
 
+        debug!(?output, ?constraints);
+
         if let Some(data) = constraints {
             self.push_region_constraints(locations, category, data);
         }
@@ -102,6 +104,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
     }
 
+    #[instrument(level = "debug", skip(self))]
     pub(super) fn normalize_and_prove_instantiated_predicates(
         &mut self,
         // Keep this parameter for now, in case we start using
@@ -116,8 +119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .zip(instantiated_predicates.spans.into_iter())
         {
             debug!(?predicate);
-            let predicate = self.normalize(predicate, locations);
-            self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
+            let category = ConstraintCategory::Predicate(span);
+            let predicate = self.normalize_with_category(predicate, locations, category);
+            self.prove_predicate(predicate, locations, category);
         }
     }
 
@@ -153,15 +157,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         })
     }
 
-    #[instrument(skip(self), level = "debug")]
     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
     where
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
+        self.normalize_with_category(value, location, ConstraintCategory::Boring)
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    pub(super) fn normalize_with_category<T>(
+        &mut self,
+        value: T,
+        location: impl NormalizeLocation,
+        category: ConstraintCategory<'tcx>,
+    ) -> T
+    where
+        T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
+    {
         let param_env = self.param_env;
         self.fully_perform_op(
             location.to_locations(),
-            ConstraintCategory::Boring,
+            category,
             param_env.and(type_op::normalize::Normalize::new(value)),
         )
         .unwrap_or_else(|NoSolution| {
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 9fab7ad914a..71eae0583cb 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         }
     }
 
-    pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
+    fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
         debug!("generate: constraints at: {:#?}", self.locations);
 
         // Extract out various useful fields we'll need below.
@@ -98,15 +98,18 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         // region constraints like `for<'a> 'a: 'b`. At some point
         // when we move to universes, we will, and this assertion
         // will start to fail.
-        let ty::OutlivesPredicate(k1, r2) = query_constraint.no_bound_vars().unwrap_or_else(|| {
-            bug!("query_constraint {:?} contained bound vars", query_constraint,);
-        });
+        let ty::OutlivesPredicate(k1, r2) =
+            query_constraint.0.no_bound_vars().unwrap_or_else(|| {
+                bug!("query_constraint {:?} contained bound vars", query_constraint,);
+            });
+
+        let constraint_category = query_constraint.1;
 
         match k1.unpack() {
             GenericArgKind::Lifetime(r1) => {
                 let r1_vid = self.to_region_vid(r1);
                 let r2_vid = self.to_region_vid(r2);
-                self.add_outlives(r1_vid, r2_vid);
+                self.add_outlives(r1_vid, r2_vid, constraint_category);
             }
 
             GenericArgKind::Type(t1) => {
@@ -121,7 +124,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
                     Some(implicit_region_bound),
                     param_env,
                 )
-                .type_must_outlive(origin, t1, r2);
+                .type_must_outlive(origin, t1, r2, constraint_category);
             }
 
             GenericArgKind::Const(_) => {
@@ -168,10 +171,19 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         }
     }
 
-    fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
+    fn add_outlives(
+        &mut self,
+        sup: ty::RegionVid,
+        sub: ty::RegionVid,
+        category: ConstraintCategory<'tcx>,
+    ) {
+        let category = match self.category {
+            ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
+            _ => self.category,
+        };
         self.constraints.outlives_constraints.push(OutlivesConstraint {
             locations: self.locations,
-            category: self.category,
+            category,
             span: self.span,
             sub,
             sup,
@@ -191,10 +203,11 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
         _origin: SubregionOrigin<'tcx>,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
+        constraint_category: ConstraintCategory<'tcx>,
     ) {
         let b = self.to_region_vid(b);
         let a = self.to_region_vid(a);
-        self.add_outlives(b, a);
+        self.add_outlives(b, a, constraint_category);
     }
 
     fn push_verify(
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 373411e1b78..c51debdc863 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -312,6 +312,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
     }
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
+        debug!(?constant, ?location, "visit_constant");
+
         self.super_constant(constant, location);
         let ty = self.sanitize_type(constant, constant.literal.ty());
 
@@ -762,6 +764,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 }
                 PlaceTy::from_ty(fty)
             }
+            ProjectionElem::OpaqueCast(ty) => {
+                let ty = self.sanitize_type(place, ty);
+                let ty = self.cx.normalize(ty, location);
+                self.cx
+                    .eq_types(
+                        base.ty,
+                        ty,
+                        location.to_locations(),
+                        ConstraintCategory::TypeAnnotation,
+                    )
+                    .unwrap();
+                PlaceTy::from_ty(ty)
+            }
         }
     }
 
@@ -1168,10 +1183,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 tcx,
                 self.param_env,
                 proj,
-                |this, field, ()| {
+                |this, field, _| {
                     let ty = this.field_ty(tcx, field);
                     self.normalize(ty, locations)
                 },
+                |_, _| unreachable!(),
             );
             curr_projected_ty = projected_ty;
         }
@@ -1815,6 +1831,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     }
 
     fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        debug!(?op, ?location, "check_operand");
+
         if let Operand::Constant(constant) = op {
             let maybe_uneval = match constant.literal {
                 ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
@@ -2499,6 +2517,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
                 ProjectionElem::Field(..)
                 | ProjectionElem::Downcast(..)
+                | ProjectionElem::OpaqueCast(..)
                 | ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
                 | ProjectionElem::Subslice { .. } => {
@@ -2593,7 +2612,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 .enumerate()
                 .filter_map(|(idx, constraint)| {
                     let ty::OutlivesPredicate(k1, r2) =
-                        constraint.no_bound_vars().unwrap_or_else(|| {
+                        constraint.0.no_bound_vars().unwrap_or_else(|| {
                             bug!("query_constraint {:?} contained bound vars", constraint,);
                         });
 
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 8cf9ed53d39..41fba8deb10 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,8 +22,8 @@ use rustc_hir::{BodyOwnerKind, HirId};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use std::iter;
 
 use crate::nll::ToRegionVid;
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 399474d79e3..11540d80081 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -850,6 +850,7 @@ pub(crate) fn codegen_place<'tcx>(
             PlaceElem::Deref => {
                 cplace = cplace.place_deref(fx);
             }
+            PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
             PlaceElem::Field(field, _ty) => {
                 cplace = cplace.place_field(fx, field);
             }
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index cfaadca9491..3fa3e3657cb 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -621,6 +621,14 @@ impl<'tcx> CPlace<'tcx> {
         }
     }
 
+    pub(crate) fn place_opaque_cast(
+        self,
+        fx: &mut FunctionCx<'_, '_, 'tcx>,
+        ty: Ty<'tcx>,
+    ) -> CPlace<'tcx> {
+        CPlace { inner: self.inner, layout: fx.layout_of(ty) }
+    }
+
     pub(crate) fn place_field(
         self,
         fx: &mut FunctionCx<'_, '_, 'tcx>,
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e505543b27c..e0bd7a33f73 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -439,7 +439,10 @@ impl<'a> Linker for GccLinker<'a> {
             }
         }
         self.hint_dynamic();
-        self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib));
+        self.cmd.arg(format!(
+            "-l{}{lib}",
+            if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
+        ));
         if !as_needed {
             if self.sess.target.is_like_osx {
                 // See above FIXME comment
@@ -450,7 +453,10 @@ impl<'a> Linker for GccLinker<'a> {
     }
     fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
         self.hint_static();
-        self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib));
+        self.cmd.arg(format!(
+            "-l{}{lib}",
+            if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
+        ));
     }
     fn link_rlib(&mut self, lib: &Path) {
         self.hint_static();
@@ -504,10 +510,10 @@ impl<'a> Linker for GccLinker<'a> {
         self.hint_static();
         let target = &self.sess.target;
         if !target.is_like_osx {
-            self.linker_arg("--whole-archive").cmd.arg(format!(
-                "-l{}{}",
-                if verbatim { ":" } else { "" },
-                lib
+            self.linker_arg("--whole-archive");
+            self.cmd.arg(format!(
+                "-l{}{lib}",
+                if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
             ));
             self.linker_arg("--no-whole-archive");
         } else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 13d8f6eddd1..9c18df5643f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -400,6 +400,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         downcast
     }
 
+    pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        &self,
+        bx: &mut Bx,
+        ty: Ty<'tcx>,
+    ) -> Self {
+        let mut downcast = *self;
+        downcast.layout = bx.cx().layout_of(ty);
+
+        // Cast to the appropriate type.
+        let variant_ty = bx.cx().backend_type(downcast.layout);
+        downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty));
+
+        downcast
+    }
+
     pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
         bx.lifetime_start(self.llval, self.layout.size);
     }
@@ -442,6 +457,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 mir::ProjectionElem::Field(ref field, _) => {
                     cg_base.project_field(bx, field.index())
                 }
+                mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty),
                 mir::ProjectionElem::Index(index) => {
                     let index = &mir::Operand::Copy(mir::Place::from(index));
                     let index = self.codegen_operand(bx, index);
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index a2f14e753ae..b52cc873f2e 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::pretty::display_allocation;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, subst::Subst, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::source_map::Span;
 use rustc_target::abi::{self, Abi};
 use std::borrow::Cow;
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d37eaeed095..3177537fee2 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -929,11 +929,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     }
 
     #[must_use]
-    pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
+    pub fn generate_stacktrace_from_stack(
+        stack: &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>],
+    ) -> Vec<FrameInfo<'tcx>> {
         let mut frames = Vec::new();
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
         // more than just panics.
-        for frame in self.stack().iter().rev() {
+        for frame in stack.iter().rev() {
             let lint_root = frame.current_source_info().and_then(|source_info| {
                 match &frame.body.source_scopes[source_info.scope].local_data {
                     mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
@@ -947,6 +949,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("generate stacktrace: {:#?}", frames);
         frames
     }
+
+    #[must_use]
+    pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
+        Self::generate_stacktrace_from_stack(self.stack())
+    }
 }
 
 #[doc(hidden)]
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 91f4f042517..0e3867557ad 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -4,7 +4,6 @@ use rustc_ast::Mutability;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::subst::Subst;
 use rustc_span::{Span, Symbol};
 
 use crate::interpret::{
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 77da8f1041e..6b2e2bb8aca 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -350,6 +350,11 @@ where
     ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
         use rustc_middle::mir::ProjectionElem::*;
         Ok(match proj_elem {
+            OpaqueCast(ty) => {
+                let mut place = base.clone();
+                place.layout = self.layout_of(ty)?;
+                place
+            }
             Field(field, _) => self.place_field(base, field.index())?,
             Downcast(_, variant) => self.place_downcast(base, variant)?,
             Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
@@ -374,6 +379,11 @@ where
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         use rustc_middle::mir::ProjectionElem::*;
         Ok(match proj_elem {
+            OpaqueCast(ty) => {
+                let mut op = base.clone();
+                op.layout = self.layout_of(ty)?;
+                op
+            }
             Field(field, _) => self.operand_field(base, field.index())?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
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 7e15858c8c1..a8f6507d594 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -656,6 +656,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
             ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Downcast(..)
+            | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 6c73ef5a8fa..fb22befd0a4 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -308,6 +308,7 @@ where
 
             ProjectionElem::Deref
             | ProjectionElem::Field(_, _)
+            | ProjectionElem::OpaqueCast(_)
             | ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Downcast(_, _)
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index f7a7cc88a52..461051574e5 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -361,7 +361,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                             return Err(Unpromotable);
                         }
                     }
-                    ProjectionElem::Downcast(..) => {
+                    ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
                     }
 
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 4aa98cb13d8..9c95ffca19b 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -13,7 +13,6 @@ use rustc_middle::mir::{
     TerminatorKind, UnOp, START_BLOCK,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
 use rustc_mir_dataflow::storage::always_storage_live_locals;
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index 2899b8304bc..65371a28591 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -110,6 +110,7 @@ infer_relate_param_bound = ...so that the type `{$name}` will meet its required
 infer_relate_param_bound_2 = ...that is required by this bound
 infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
 infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
+infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
 
 infer_nothing = {""}
 
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 64c759f73d4..56e83489879 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -22,6 +22,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
 use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::TypeRelation;
@@ -129,7 +130,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         let region_constraints = self.with_region_constraints(|region_constraints| {
             make_query_region_constraints(
                 tcx,
-                region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)),
+                region_obligations
+                    .iter()
+                    .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
                 region_constraints,
             )
         });
@@ -248,6 +251,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         // the original values `v_o` that was canonicalized into a
         // variable...
 
+        let constraint_category = cause.to_constraint_category();
+
         for (index, original_value) in original_values.var_values.iter().enumerate() {
             // ...with the value `v_r` of that variable from the query.
             let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
@@ -263,12 +268,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 (GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => {
                     // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
                     if v_o != v_r {
-                        output_query_region_constraints
-                            .outlives
-                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
-                        output_query_region_constraints
-                            .outlives
-                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
+                        output_query_region_constraints.outlives.push((
+                            ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)),
+                            constraint_category,
+                        ));
+                        output_query_region_constraints.outlives.push((
+                            ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)),
+                            constraint_category,
+                        ));
                     }
                 }
 
@@ -314,7 +321,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 // Screen out `'a: 'a` cases -- we skip the binder here but
                 // only compare the inner values to one another, so they are still at
                 // consistent binding levels.
-                let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
+                let ty::OutlivesPredicate(k1, r2) = r_c.0.skip_binder();
                 if k1 != r2.into() { Some(r_c) } else { None }
             }),
         );
@@ -559,7 +566,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Obligation<'tcx, ty::Predicate<'tcx>> {
-        let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder();
+        let ty::OutlivesPredicate(k1, r2) = predicate.0.skip_binder();
 
         let atom = match k1.unpack() {
             GenericArgKind::Lifetime(r1) => {
@@ -574,7 +581,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
             }
         };
-        let predicate = predicate.rebind(atom).to_predicate(self.tcx);
+        let predicate = predicate.0.rebind(atom).to_predicate(self.tcx);
 
         Obligation::new(cause, param_env, predicate)
     }
@@ -625,7 +632,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 /// creates query region constraints.
 pub fn make_query_region_constraints<'tcx>(
     tcx: TyCtxt<'tcx>,
-    outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
+    outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
     region_constraints: &RegionConstraintData<'tcx>,
 ) -> QueryRegionConstraints<'tcx> {
     let RegionConstraintData { constraints, verifys, givens, member_constraints } =
@@ -638,26 +645,31 @@ pub fn make_query_region_constraints<'tcx>(
 
     let outlives: Vec<_> = constraints
         .iter()
-        .map(|(k, _)| match *k {
-            // Swap regions because we are going from sub (<=) to outlives
-            // (>=).
-            Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
-                tcx.mk_region(ty::ReVar(v2)).into(),
-                tcx.mk_region(ty::ReVar(v1)),
-            ),
-            Constraint::VarSubReg(v1, r2) => {
-                ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
-            }
-            Constraint::RegSubVar(r1, v2) => {
-                ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
-            }
-            Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
+        .map(|(k, origin)| {
+            // no bound vars in the code above
+            let constraint = ty::Binder::dummy(match *k {
+                // Swap regions because we are going from sub (<=) to outlives
+                // (>=).
+                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
+                    tcx.mk_region(ty::ReVar(v2)).into(),
+                    tcx.mk_region(ty::ReVar(v1)),
+                ),
+                Constraint::VarSubReg(v1, r2) => {
+                    ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
+                }
+                Constraint::RegSubVar(r1, v2) => {
+                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
+                }
+                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
+            });
+            (constraint, origin.to_constraint_category())
         })
-        .map(ty::Binder::dummy) // no bound vars in the code above
         .chain(
             outlives_obligations
-                .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
-                .map(ty::Binder::dummy), // no bound vars in the code above
+                // no bound vars in the code above
+                .map(|(ty, r, constraint_category)| {
+                    (ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category)
+                }),
         )
         .collect();
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 67526c22289..546ab82bc23 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -69,8 +69,8 @@ use rustc_middle::dep_graph::DepContext;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::{
-    self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
-    TypeSuperVisitable, TypeVisitable,
+    self, error::TypeError, Binder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+    TypeVisitable,
 };
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index cb2be93589d..89a448edc9b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -15,8 +15,8 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
 use rustc_middle::ty::{self, DefIdTree, InferConst};
+use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
 use rustc_session::SessionDiagnostic;
 use rustc_span::symbol::{kw, Ident};
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index cffdf56bb6d..adaa47c0140 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -77,6 +77,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             infer::CheckAssociatedTypeBounds { ref parent, .. } => {
                 self.note_region_origin(err, &parent);
             }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                RegionOriginNote::Plain {
+                    span,
+                    msg: fluent::infer::ascribe_user_type_prove_predicate,
+                }
+                .add_to_diagnostic(err);
+            }
         }
     }
 
@@ -356,6 +363,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
                 err
             }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                let mut err =
+                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "lifetime instantiated with ",
+                    sup,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but lifetime must outlive ",
+                    sub,
+                    "",
+                    None,
+                );
+                err
+            }
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index eb20c089dc7..3abed12217c 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -20,6 +20,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
+use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::select;
 use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -408,7 +409,11 @@ pub enum SubregionOrigin<'tcx> {
 
     /// Comparing the signature and requirements of an impl method against
     /// the containing trait.
-    CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
+    CompareImplItemObligation {
+        span: Span,
+        impl_item_def_id: LocalDefId,
+        trait_item_def_id: DefId,
+    },
 
     /// Checking that the bounds of a trait's associated type hold for a given impl
     CheckAssociatedTypeBounds {
@@ -416,12 +421,24 @@ pub enum SubregionOrigin<'tcx> {
         impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     },
+
+    AscribeUserTypeProvePredicate(Span),
 }
 
 // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(SubregionOrigin<'_>, 32);
 
+impl<'tcx> SubregionOrigin<'tcx> {
+    pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
+        match self {
+            Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
+            Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
+            _ => ConstraintCategory::BoringNoLocation,
+        }
+    }
+}
+
 /// Times when we replace late-bound regions with variables:
 #[derive(Clone, Copy, Debug)]
 pub enum LateBoundRegionConversionTime {
@@ -1988,6 +2005,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
             DataBorrowed(_, a) => a,
             ReferenceOutlivesReferent(_, a) => a,
             CompareImplItemObligation { span, .. } => span,
+            AscribeUserTypeProvePredicate(span) => span,
             CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
         }
     }
@@ -2020,6 +2038,10 @@ impl<'tcx> SubregionOrigin<'tcx> {
                 parent: Box::new(default()),
             },
 
+            traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => {
+                SubregionOrigin::AscribeUserTypeProvePredicate(span)
+            }
+
             _ => default(),
         }
     }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 8c9ddf86632..561279e3c8e 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::subst::{GenericArgKind, Subst};
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{
     self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitor,
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 74c8bd88d27..5bd1774f6b1 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -69,6 +69,7 @@ use crate::infer::{
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
 use smallvec::smallvec;
@@ -163,7 +164,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
             let outlives =
                 &mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
-            outlives.type_must_outlive(origin, sup_type, sub_region);
+            let category = origin.to_constraint_category();
+            outlives.type_must_outlive(origin, sup_type, sub_region, category);
         }
     }
 
@@ -207,6 +209,7 @@ pub trait TypeOutlivesDelegate<'tcx> {
         origin: SubregionOrigin<'tcx>,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
+        constraint_category: ConstraintCategory<'tcx>,
     );
 
     fn push_verify(
@@ -255,12 +258,13 @@ where
         origin: infer::SubregionOrigin<'tcx>,
         ty: Ty<'tcx>,
         region: ty::Region<'tcx>,
+        category: ConstraintCategory<'tcx>,
     ) {
         assert!(!ty.has_escaping_bound_vars());
 
         let mut components = smallvec![];
         push_outlives_components(self.tcx, ty, &mut components);
-        self.components_must_outlive(origin, &components, region);
+        self.components_must_outlive(origin, &components, region, category);
     }
 
     fn components_must_outlive(
@@ -268,12 +272,13 @@ where
         origin: infer::SubregionOrigin<'tcx>,
         components: &[Component<'tcx>],
         region: ty::Region<'tcx>,
+        category: ConstraintCategory<'tcx>,
     ) {
         for component in components.iter() {
             let origin = origin.clone();
             match component {
                 Component::Region(region1) => {
-                    self.delegate.push_sub_region_constraint(origin, region, *region1);
+                    self.delegate.push_sub_region_constraint(origin, region, *region1, category);
                 }
                 Component::Param(param_ty) => {
                     self.param_ty_must_outlive(origin, region, *param_ty);
@@ -282,7 +287,7 @@ where
                     self.projection_must_outlive(origin, region, *projection_ty);
                 }
                 Component::EscapingProjection(subcomponents) => {
-                    self.components_must_outlive(origin, &subcomponents, region);
+                    self.components_must_outlive(origin, &subcomponents, region, category);
                 }
                 Component::UnresolvedInferenceVariable(v) => {
                     // ignore this, we presume it will yield an error
@@ -389,13 +394,19 @@ where
         if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
             debug!("projection_must_outlive: no declared bounds");
 
+            let constraint = origin.to_constraint_category();
             for k in projection_ty.substs {
                 match k.unpack() {
                     GenericArgKind::Lifetime(lt) => {
-                        self.delegate.push_sub_region_constraint(origin.clone(), region, lt);
+                        self.delegate.push_sub_region_constraint(
+                            origin.clone(),
+                            region,
+                            lt,
+                            constraint,
+                        );
                     }
                     GenericArgKind::Type(ty) => {
-                        self.type_must_outlive(origin.clone(), ty, region);
+                        self.type_must_outlive(origin.clone(), ty, region, constraint);
                     }
                     GenericArgKind::Const(_) => {
                         // Const parameters don't impose constraints.
@@ -433,7 +444,8 @@ where
             let unique_bound = trait_bounds[0];
             debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound);
             debug!("projection_must_outlive: unique declared bound appears in trait ref");
-            self.delegate.push_sub_region_constraint(origin, region, unique_bound);
+            let category = origin.to_constraint_category();
+            self.delegate.push_sub_region_constraint(origin, region, unique_bound, category);
             return;
         }
 
@@ -455,6 +467,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> {
         origin: SubregionOrigin<'tcx>,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
+        _constraint_category: ConstraintCategory<'tcx>,
     ) {
         self.sub_regions(origin, a, b)
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 75233495040..e344e192a76 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -5,7 +5,7 @@ use crate::infer::{GenericKind, VerifyBound};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, Subst};
+use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt};
 
 use smallvec::smallvec;
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 257741c13f5..2a986c41d72 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -33,28 +33,25 @@ pub fn find_native_static_library(
     search_paths: &[PathBuf],
     sess: &Session,
 ) -> PathBuf {
-    let verbatim = verbatim.unwrap_or(false);
-    // On Windows, static libraries sometimes show up as libfoo.a and other
-    // times show up as foo.lib
-    let oslibname = if verbatim {
-        name.to_string()
+    let formats = if verbatim.unwrap_or(false) {
+        vec![("".into(), "".into())]
     } else {
-        format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix)
+        let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone());
+        // On Windows, static libraries sometimes show up as libfoo.a and other
+        // times show up as foo.lib
+        let unix = ("lib".into(), ".a".into());
+        if os == unix { vec![os] } else { vec![os, unix] }
     };
-    let unixlibname = format!("lib{}.a", name);
 
     for path in search_paths {
-        let test = path.join(&oslibname);
-        if test.exists() {
-            return test;
-        }
-        if oslibname != unixlibname {
-            let test = path.join(&unixlibname);
+        for (prefix, suffix) in &formats {
+            let test = path.join(format!("{}{}{}", prefix, name, suffix));
             if test.exists() {
                 return test;
             }
         }
     }
+
     sess.emit_fatal(MissingNativeLibrary { libname: name });
 }
 
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 6873785ace7..d3cf519b633 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -22,6 +22,7 @@
 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
 
 use crate::infer::MemberConstraint;
+use crate::mir::ConstraintCategory;
 use crate::ty::subst::GenericArg;
 use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
 use rustc_index::vec::IndexVec;
@@ -301,8 +302,10 @@ impl<'tcx, V> Canonical<'tcx, V> {
     }
 }
 
-pub type QueryOutlivesConstraint<'tcx> =
-    ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>;
+pub type QueryOutlivesConstraint<'tcx> = (
+    ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>,
+    ConstraintCategory<'tcx>,
+);
 
 TrivialTypeTraversalAndLiftImpls! {
     for <'tcx> {
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index a171f5711dc..2a1a0bbe2ae 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -2,7 +2,7 @@
 
 use crate::ty;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::ItemLocalId;
 use rustc_macros::HashStable;
@@ -51,10 +51,5 @@ pub struct ResolveLifetimes {
     /// `Region` describing how that region is bound
     pub defs: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Region>>,
 
-    /// Set of lifetime def ids that are late-bound; a region can
-    /// be late-bound if (a) it does NOT appear in a where-clause and
-    /// (b) it DOES appear in the arguments.
-    pub late_bound: FxHashMap<LocalDefId, FxHashSet<LocalDefId>>,
-
     pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 3d7a6230e4d..86ffce8ceb4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -9,10 +9,10 @@ use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
 use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use crate::ty::{self, List, Ty, TyCtxt};
 use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 
 use rustc_data_structures::captures::Captures;
 use rustc_errors::ErrorGuaranteed;
@@ -1380,6 +1380,7 @@ impl<V, T> ProjectionElem<V, T> {
 
             Self::Field(_, _)
             | Self::Index(_)
+            | Self::OpaqueCast(_)
             | Self::ConstantIndex { .. }
             | Self::Subslice { .. }
             | Self::Downcast(_, _) => false,
@@ -1574,7 +1575,9 @@ impl Debug for Place<'_> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         for elem in self.projection.iter().rev() {
             match elem {
-                ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
+                ProjectionElem::OpaqueCast(_)
+                | ProjectionElem::Downcast(_, _)
+                | ProjectionElem::Field(_, _) => {
                     write!(fmt, "(").unwrap();
                 }
                 ProjectionElem::Deref => {
@@ -1590,6 +1593,9 @@ impl Debug for Place<'_> {
 
         for elem in self.projection.iter() {
             match elem {
+                ProjectionElem::OpaqueCast(ty) => {
+                    write!(fmt, " as {})", ty)?;
+                }
                 ProjectionElem::Downcast(Some(name), _index) => {
                     write!(fmt, " as {})", name)?;
                 }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 594c14a642d..d89efe2b3f0 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -327,7 +327,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
 ///
 /// See also `rustc_const_eval::borrow_check::constraints`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(TyEncodable, TyDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
 pub enum ConstraintCategory<'tcx> {
     Return(ReturnConstraint),
     Yield,
@@ -369,7 +369,7 @@ pub enum ConstraintCategory<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(TyEncodable, TyDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
 pub enum ReturnConstraint {
     Normal,
     ClosureUpvar(Field),
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c7d0283aac9..d461b4e434f 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -829,6 +829,9 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 ///    generator has more than one variant, the parent place's variant index must be set, indicating
 ///    which variant is being used. If it has just one variant, the variant index may or may not be
 ///    included - the single possible variant is inferred if it is not included.
+///  - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
+///    given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
+///    opaque type from the current crate is not well-formed.
 ///  - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
 ///    place as described in the documentation for the `ProjectionElem`. The resulting address is
 ///    the parent's address plus that offset, and the type is `T`. This is only legal if the parent
@@ -928,6 +931,10 @@ pub enum ProjectionElem<V, T> {
     ///
     /// The included Symbol is the name of the variant, used for printing MIR.
     Downcast(Option<Symbol>, VariantIdx),
+
+    /// Like an explicit cast from an opaque type to a concrete type, but without
+    /// requiring an intermediate variable.
+    OpaqueCast(T),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 405003156c4..fa3adafd4b8 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -4,7 +4,6 @@
  */
 
 use crate::mir::*;
-use crate::ty::subst::Subst;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
 use rustc_target::abi::VariantIdx;
@@ -57,7 +56,7 @@ impl<'tcx> PlaceTy<'tcx> {
     /// `PlaceElem`, where we can just use the `Ty` that is already
     /// stored inline on field projection elems.
     pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
-        self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
+        self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
     }
 
     /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -71,6 +70,7 @@ impl<'tcx> PlaceTy<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         elem: &ProjectionElem<V, T>,
         mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
+        mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
@@ -109,6 +109,7 @@ impl<'tcx> PlaceTy<'tcx> {
                 PlaceTy { ty: self.ty, variant_index: Some(index) }
             }
             ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
+            ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
         answer
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index d9b24566bf1..ddcf3711bfc 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1084,6 +1084,11 @@ macro_rules! visit_place_fns {
                     self.visit_ty(&mut new_ty, TyContext::Location(location));
                     if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
                 }
+                PlaceElem::OpaqueCast(ty) => {
+                    let mut new_ty = ty;
+                    self.visit_ty(&mut new_ty, TyContext::Location(location));
+                    if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
+                }
                 PlaceElem::Deref
                 | PlaceElem::ConstantIndex { .. }
                 | PlaceElem::Subslice { .. }
@@ -1153,7 +1158,7 @@ macro_rules! visit_place_fns {
             location: Location,
         ) {
             match elem {
-                ProjectionElem::Field(_field, ty) => {
+                ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
                     self.visit_ty(ty, TyContext::Location(location));
                 }
                 ProjectionElem::Index(local) => {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a95e6a61854..68a7af0b8c8 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -10,6 +10,7 @@ mod structural_impls;
 pub mod util;
 
 use crate::infer::canonical::Canonical;
+use crate::mir::ConstraintCategory;
 use crate::ty::abstract_const::NotConstEvaluatable;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, AdtKind, Ty, TyCtxt};
@@ -183,6 +184,16 @@ impl<'tcx> ObligationCause<'tcx> {
             variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code }).into();
         self
     }
+
+    pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
+        match self.code() {
+            MatchImpl(cause, _) => cause.to_constraint_category(),
+            AscribeUserTypeProvePredicate(predicate_span) => {
+                ConstraintCategory::Predicate(*predicate_span)
+            }
+            _ => ConstraintCategory::BoringNoLocation,
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
@@ -418,6 +429,8 @@ pub enum ObligationCauseCode<'tcx> {
         is_lit: bool,
         output_ty: Option<Ty<'tcx>>,
     },
+
+    AscribeUserTypeProvePredicate(Span),
 }
 
 /// The 'location' at which we try to perform HIR-based wf checking.
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 8f79b4705ad..8e0a1f1f9ac 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,7 +1,7 @@
 //! A subset of a mir body used for const evaluatability checking.
 use crate::mir;
 use crate::ty::visit::TypeVisitable;
-use crate::ty::{self, subst::Subst, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt};
+use crate::ty::{self, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use std::cmp;
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 4a9fbc5511c..10c5933574f 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -15,7 +15,6 @@ use crate::mir::{
 use crate::thir::Thir;
 use crate::traits;
 use crate::ty::query::{self, TyCtxtAt};
-use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
     ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy,
@@ -24,6 +23,7 @@ use crate::ty::{
     RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
     Visibility,
 };
+use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 0c8bdde9c8b..19754d1453f 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -1,6 +1,5 @@
 use crate::ty;
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::EarlyBinder;
+use crate::ty::{EarlyBinder, SubstsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 9afd6620756..6c1414f7b8a 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,9 +1,7 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{
-    self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable,
-};
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
+use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::{CrateNum, DefId};
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 042eeec3f46..cc820d9eb2d 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,7 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
 use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::subst::Subst;
 use crate::ty::{
     self, layout_sanity_check::sanity_check_layout, subst::SubstsRef, EarlyBinder, ReprOptions, Ty,
     TyCtxt, TypeVisitable,
@@ -2768,9 +2767,14 @@ impl<'tcx> ty::Instance<'tcx> {
                 // (i.e. due to being inside a projection that got normalized, see
                 // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
                 // track of a polymorphization `ParamEnv` to allow normalizing later.
+                //
+                // We normalize the `fn_sig` again after substituting at a later point.
                 let mut sig = match *ty.kind() {
                     ty::FnDef(def_id, substs) => tcx
-                        .normalize_erasing_regions(tcx.param_env(def_id), tcx.bound_fn_sig(def_id))
+                        .bound_fn_sig(def_id)
+                        .map_bound(|fn_sig| {
+                            tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig)
+                        })
                         .subst(tcx, substs),
                     _ => unreachable!(),
                 };
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e8fe37e7dab..ac4cad8e5d2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -89,9 +89,9 @@ pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
     Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
     BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
-    EarlyBinder, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection,
-    ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts,
-    InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
+    EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
+    FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
+    InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
     PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
     RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
 };
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 9db5a289484..fe303e21b65 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -10,8 +10,7 @@
 use crate::mir;
 use crate::traits::query::NoSolution;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, EarlyBinder, Ty, TyCtxt};
+use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
 
 #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
 pub enum NormalizationError<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index d57cf8f0149..e0a8d58f8a7 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,4 +1,4 @@
-use crate::ty::subst::{GenericArg, Subst};
+use crate::ty::GenericArg;
 use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 
 use rustc_data_structures::fx::FxHashSet;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 97bddb93eb4..b6cd5396b1d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,9 +1,9 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
-use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{
     self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
 };
+use crate::ty::{GenericArg, GenericArgKind};
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::sso::SsoHashSet;
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index af31f54981f..0d97d4acdfc 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -5,8 +5,8 @@
 //! subtyping, type equality, etc.
 
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
 use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_hir as ast;
 use rustc_hir::def_id::DefId;
 use rustc_span::DUMMY_SP;
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index f5fd1f6ffaf..004fcffdc40 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -557,18 +557,6 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> {
     }
 }
 
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::EarlyBinder<T> {
-    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        self.try_map_bound(|ty| ty.try_fold_with(folder))
-    }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::EarlyBinder<T> {
-    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.as_ref().0.visit_with(visitor)
-    }
-}
-
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.try_fold_binder(self)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 36e56085039..d2f73f274f8 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -3,7 +3,7 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
 use crate::infer::canonical::Canonical;
-use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
+use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::visit::ValidateBoundVars;
 use crate::ty::InferTy::*;
 use crate::ty::{
@@ -551,7 +551,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         layout.variant_fields.iter().map(move |variant| {
             variant
                 .iter()
-                .map(move |field| EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
+                .map(move |field| ty::EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
         })
     }
 
@@ -915,73 +915,6 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T>(pub T);
-
-impl<T> EarlyBinder<T> {
-    pub fn as_ref(&self) -> EarlyBinder<&T> {
-        EarlyBinder(&self.0)
-    }
-
-    pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
-    where
-        F: FnOnce(&T) -> U,
-    {
-        self.as_ref().map_bound(f)
-    }
-
-    pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
-    where
-        F: FnOnce(T) -> U,
-    {
-        let value = f(self.0);
-        EarlyBinder(value)
-    }
-
-    pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
-    where
-        F: FnOnce(T) -> Result<U, E>,
-    {
-        let value = f(self.0)?;
-        Ok(EarlyBinder(value))
-    }
-
-    pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
-        EarlyBinder(value)
-    }
-}
-
-impl<T> EarlyBinder<Option<T>> {
-    pub fn transpose(self) -> Option<EarlyBinder<T>> {
-        self.0.map(|v| EarlyBinder(v))
-    }
-}
-
-impl<T, U> EarlyBinder<(T, U)> {
-    pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
-        (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
-    }
-}
-
-pub struct EarlyBinderIter<T> {
-    t: T,
-}
-
-impl<T: IntoIterator> EarlyBinder<T> {
-    pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
-        EarlyBinderIter { t: self.0.into_iter() }
-    }
-}
-
-impl<T: Iterator> Iterator for EarlyBinderIter<T> {
-    type Item = EarlyBinder<T::Item>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.t.next().map(|i| EarlyBinder(i))
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundVariableKind {
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 8e69bf067d0..a939be32fff 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -497,18 +497,79 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
     }
 }
 
-// Just call `foo.subst(tcx, substs)` to perform a substitution across `foo`.
-#[rustc_on_unimplemented(message = "Calling `subst` must now be done through an `EarlyBinder`")]
-pub trait Subst<'tcx>: Sized {
-    type Inner;
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable)]
+pub struct EarlyBinder<T>(pub T);
 
-    fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner;
+/// For early binders, you should first call `subst` before using any visitors.
+impl<'tcx, T> !TypeFoldable<'tcx> for ty::EarlyBinder<T> {}
+impl<'tcx, T> !TypeVisitable<'tcx> for ty::EarlyBinder<T> {}
+
+impl<T> EarlyBinder<T> {
+    pub fn as_ref(&self) -> EarlyBinder<&T> {
+        EarlyBinder(&self.0)
+    }
+
+    pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
+    where
+        F: FnOnce(&T) -> U,
+    {
+        self.as_ref().map_bound(f)
+    }
+
+    pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
+    where
+        F: FnOnce(T) -> U,
+    {
+        let value = f(self.0);
+        EarlyBinder(value)
+    }
+
+    pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
+    where
+        F: FnOnce(T) -> Result<U, E>,
+    {
+        let value = f(self.0)?;
+        Ok(EarlyBinder(value))
+    }
+
+    pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
+        EarlyBinder(value)
+    }
+}
+
+impl<T> EarlyBinder<Option<T>> {
+    pub fn transpose(self) -> Option<EarlyBinder<T>> {
+        self.0.map(|v| EarlyBinder(v))
+    }
 }
 
-impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for ty::EarlyBinder<T> {
-    type Inner = T;
+impl<T, U> EarlyBinder<(T, U)> {
+    pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
+        (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
+    }
+}
+
+pub struct EarlyBinderIter<T> {
+    t: T,
+}
+
+impl<T: IntoIterator> EarlyBinder<T> {
+    pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
+        EarlyBinderIter { t: self.0.into_iter() }
+    }
+}
+
+impl<T: Iterator> Iterator for EarlyBinderIter<T> {
+    type Item = EarlyBinder<T::Item>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.t.next().map(|i| EarlyBinder(i))
+    }
+}
 
-    fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner {
+impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
+    pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
         let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
         self.0.fold_with(&mut folder)
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 23ad4d27d8e..d93aab04e99 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -3,11 +3,11 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
-use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
 use crate::ty::{
     self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitable,
 };
+use crate::ty::{GenericArgKind, SubstsRef};
 use rustc_apfloat::Float as _;
 use rustc_ast as ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 7ab7870c464..4bab583c960 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -232,7 +232,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         pattern,
                         UserTypeProjections::none(),
                         &mut |this, _, _, _, node, span, _, _| {
-                            this.storage_live_binding(block, node, span, OutsideGuard, false);
+                            this.storage_live_binding(block, node, span, OutsideGuard, true);
+                            this.schedule_drop_for_binding(node, span, OutsideGuard);
                         },
                     );
                     let failure = unpack!(
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 ebb56e5a233..4d9e9b7c473 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -69,7 +69,7 @@ pub(crate) enum PlaceBase {
 /// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
 /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
 #[derive(Clone, Debug, PartialEq)]
-pub(crate) struct PlaceBuilder<'tcx> {
+pub(in crate::build) struct PlaceBuilder<'tcx> {
     base: PlaceBase,
     projection: Vec<PlaceElem<'tcx>>,
 }
@@ -102,6 +102,8 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
                 variant = Some(*idx);
                 continue;
             }
+            // These do not affect anything, they just make sure we know the right type.
+            ProjectionElem::OpaqueCast(_) => continue,
             ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Subslice { .. } => {
@@ -168,22 +170,22 @@ fn find_capture_matching_projections<'a, 'tcx>(
 /// `PlaceBuilder` now starts from `PlaceBase::Local`.
 ///
 /// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
-fn to_upvars_resolved_place_builder<'a, 'tcx>(
+#[instrument(level = "trace", skip(cx), ret)]
+fn to_upvars_resolved_place_builder<'tcx>(
     from_builder: PlaceBuilder<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    upvars: &'a CaptureMap<'tcx>,
+    cx: &Builder<'_, 'tcx>,
 ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
     match from_builder.base {
         PlaceBase::Local(_) => Ok(from_builder),
         PlaceBase::Upvar { var_hir_id, closure_def_id } => {
             let Some((capture_index, capture)) =
                 find_capture_matching_projections(
-                    upvars,
+                    &cx.upvars,
                     var_hir_id,
                     &from_builder.projection,
                 ) else {
-                let closure_span = tcx.def_span(closure_def_id);
-                if !enable_precise_capture(tcx, closure_span) {
+                let closure_span = cx.tcx.def_span(closure_def_id);
+                if !enable_precise_capture(cx.tcx, closure_span) {
                     bug!(
                         "No associated capture found for {:?}[{:#?}] even though \
                             capture_disjoint_fields isn't enabled",
@@ -200,12 +202,13 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
             };
 
             // Access the capture by accessing the field within the Closure struct.
-            let capture_info = &upvars[capture_index];
+            let capture_info = &cx.upvars[capture_index];
 
             let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
 
             // We used some of the projections to build the capture itself,
             // now we apply the remaining to the upvar resolved place.
+            trace!(?capture.captured_place, ?from_builder.projection);
             let remaining_projections = strip_prefix(
                 capture.captured_place.place.base_ty,
                 from_builder.projection,
@@ -230,16 +233,21 @@ fn strip_prefix<'tcx>(
     prefix_projections: &[HirProjection<'tcx>],
 ) -> impl Iterator<Item = PlaceElem<'tcx>> {
     let mut iter = projections.into_iter();
+    let mut next = || match iter.next()? {
+        // Filter out opaque casts, they are unnecessary in the prefix.
+        ProjectionElem::OpaqueCast(..) => iter.next(),
+        other => Some(other),
+    };
     for projection in prefix_projections {
         match projection.kind {
             HirProjectionKind::Deref => {
-                assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
+                assert!(matches!(next(), Some(ProjectionElem::Deref)));
             }
             HirProjectionKind::Field(..) => {
                 if base_ty.is_enum() {
-                    assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
+                    assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
                 }
-                assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
+                assert!(matches!(next(), Some(ProjectionElem::Field(..))));
             }
             HirProjectionKind::Index | HirProjectionKind::Subslice => {
                 bug!("unexpected projection kind: {:?}", projection);
@@ -251,24 +259,16 @@ fn strip_prefix<'tcx>(
 }
 
 impl<'tcx> PlaceBuilder<'tcx> {
-    pub(in crate::build) fn into_place<'a>(
-        self,
-        tcx: TyCtxt<'tcx>,
-        upvars: &'a CaptureMap<'tcx>,
-    ) -> Place<'tcx> {
+    pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
         if let PlaceBase::Local(local) = self.base {
-            Place { local, projection: tcx.intern_place_elems(&self.projection) }
+            Place { local, projection: cx.tcx.intern_place_elems(&self.projection) }
         } else {
-            self.expect_upvars_resolved(tcx, upvars).into_place(tcx, upvars)
+            self.expect_upvars_resolved(cx).into_place(cx)
         }
     }
 
-    fn expect_upvars_resolved<'a>(
-        self,
-        tcx: TyCtxt<'tcx>,
-        upvars: &'a CaptureMap<'tcx>,
-    ) -> PlaceBuilder<'tcx> {
-        to_upvars_resolved_place_builder(self, tcx, upvars).unwrap()
+    fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
+        to_upvars_resolved_place_builder(self, cx).unwrap()
     }
 
     /// Attempts to resolve the `PlaceBuilder`.
@@ -282,18 +282,21 @@ impl<'tcx> PlaceBuilder<'tcx> {
     /// not captured. This can happen because the final mir that will be
     /// generated doesn't require a read for this place. Failures will only
     /// happen inside closures.
-    pub(in crate::build) fn try_upvars_resolved<'a>(
+    pub(in crate::build) fn try_upvars_resolved(
         self,
-        tcx: TyCtxt<'tcx>,
-        upvars: &'a CaptureMap<'tcx>,
+        cx: &Builder<'_, 'tcx>,
     ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
-        to_upvars_resolved_place_builder(self, tcx, upvars)
+        to_upvars_resolved_place_builder(self, cx)
     }
 
     pub(crate) fn base(&self) -> PlaceBase {
         self.base
     }
 
+    pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] {
+        &self.projection
+    }
+
     pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
         self.project(PlaceElem::Field(f, ty))
     }
@@ -353,7 +356,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_place_builder(block, expr));
-        block.and(place_builder.into_place(self.tcx, &self.upvars))
+        block.and(place_builder.into_place(self))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -377,7 +380,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
-        block.and(place_builder.into_place(self.tcx, &self.upvars))
+        block.and(place_builder.into_place(self))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -472,7 +475,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             inferred_ty: expr.ty,
                         });
 
-                    let place = place_builder.clone().into_place(this.tcx, &this.upvars);
+                    let place = place_builder.clone().into_place(this);
                     this.cfg.push(
                         block,
                         Statement {
@@ -610,7 +613,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         if is_outermost_index {
             self.read_fake_borrows(block, fake_borrow_temps, source_info)
         } else {
-            base_place = base_place.expect_upvars_resolved(self.tcx, &self.upvars);
+            base_place = base_place.expect_upvars_resolved(self);
             self.add_fake_borrows_of_base(
                 &base_place,
                 block,
@@ -638,12 +641,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let lt = self.temp(bool_ty, expr_span);
 
         // len = len(slice)
-        self.cfg.push_assign(
-            block,
-            source_info,
-            len,
-            Rvalue::Len(slice.into_place(self.tcx, &self.upvars)),
-        );
+        self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
         // lt = idx < len
         self.cfg.push_assign(
             block,
@@ -723,6 +721,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     }
                     ProjectionElem::Field(..)
                     | ProjectionElem::Downcast(..)
+                    | ProjectionElem::OpaqueCast(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. } => (),
                 }
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 98bdaf0bc62..16295b1b19a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -329,10 +329,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let place_builder =
                         unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
 
-                    if let Ok(place_builder_resolved) =
-                        place_builder.try_upvars_resolved(this.tcx, &this.upvars)
-                    {
-                        let mir_place = place_builder_resolved.into_place(this.tcx, &this.upvars);
+                    if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
+                        let mir_place = place_builder_resolved.into_place(this);
                         this.cfg.push_fake_read(
                             block,
                             this.source_info(this.tcx.hir().span(*hir_id)),
@@ -623,8 +621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // by the parent itself. The mutability of the current capture
             // is same as that of the capture in the parent closure.
             PlaceBase::Upvar { .. } => {
-                let enclosing_upvars_resolved =
-                    arg_place_builder.clone().into_place(this.tcx, &this.upvars);
+                let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
 
                 match enclosing_upvars_resolved.as_ref() {
                     PlaceRef {
@@ -661,7 +658,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
         };
 
-        let arg_place = arg_place_builder.into_place(this.tcx, &this.upvars);
+        let arg_place = arg_place_builder.into_place(this);
 
         this.cfg.push_assign(
             block,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index e5dafb820bf..0ca4e374519 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -23,6 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn as_temp_inner(
         &mut self,
         mut block: BasicBlock,
@@ -30,10 +31,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
         mutability: Mutability,
     ) -> BlockAnd<Local> {
-        debug!(
-            "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
-            block, temp_lifetime, expr, mutability
-        );
         let this = self;
 
         let expr_span = expr.span;
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 6ed5f1fc0d3..4b8c134b9d0 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -15,14 +15,13 @@ use std::iter;
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn expr_into_dest(
         &mut self,
         destination: Place<'tcx>,
         mut block: BasicBlock,
         expr: &Expr<'tcx>,
     ) -> BlockAnd<()> {
-        debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
-
         // since we frequently have to reference `self` from within a
         // closure, where `self` would be shadowed, it's easier to
         // just use the name `this` uniformly
@@ -366,7 +365,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             None => {
                                 let place_builder = place_builder.clone();
                                 this.consume_by_copy_or_move(
-                                    place_builder.field(n, *ty).into_place(this.tcx, &this.upvars),
+                                    place_builder.field(n, *ty).into_place(this),
                                 )
                             }
                         })
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index e0727725f68..4fddc24301a 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -220,10 +220,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
         let source_info = self.source_info(scrutinee_span);
 
-        if let Ok(scrutinee_builder) =
-            scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, &self.upvars)
-        {
-            let scrutinee_place = scrutinee_builder.into_place(self.tcx, &self.upvars);
+        if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
+            let scrutinee_place = scrutinee_builder.into_place(self);
             self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
         }
 
@@ -246,7 +244,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .map(|arm| {
                 let arm = &self.thir[arm];
                 let arm_has_guard = arm.guard.is_some();
-                let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
+                let arm_candidate =
+                    Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard, self);
                 (arm, arm_candidate)
             })
             .collect()
@@ -349,9 +348,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
                     let scrutinee_place: Place<'tcx>;
                     if let Ok(scrutinee_builder) =
-                        scrutinee_place_builder.clone().try_upvars_resolved(this.tcx, &this.upvars)
+                        scrutinee_place_builder.clone().try_upvars_resolved(this)
                     {
-                        scrutinee_place = scrutinee_builder.into_place(this.tcx, &this.upvars);
+                        scrutinee_place = scrutinee_builder.into_place(this);
                         opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
                     }
                     let scope = this.declare_bindings(
@@ -371,6 +370,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         Some(arm.span),
                         Some(arm.scope),
                         Some(match_scope),
+                        false,
                     );
 
                     if let Some(source_scope) = scope {
@@ -416,6 +416,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         arm_span: Option<Span>,
         arm_scope: Option<region::Scope>,
         match_scope: Option<region::Scope>,
+        storages_alive: bool,
     ) -> BasicBlock {
         if candidate.subcandidates.is_empty() {
             // Avoid generating another `BasicBlock` when we only have one
@@ -429,6 +430,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 arm_span,
                 match_scope,
                 true,
+                storages_alive,
             )
         } else {
             // It's helpful to avoid scheduling drops multiple times to save
@@ -466,6 +468,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         arm_span,
                         match_scope,
                         schedule_drops,
+                        storages_alive,
                     );
                     if arm_scope.is_none() {
                         schedule_drops = false;
@@ -580,7 +583,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         initializer: PlaceBuilder<'tcx>,
         set_match_place: bool,
     ) -> BlockAnd<()> {
-        let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false);
+        let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false, self);
         let fake_borrow_temps = self.lower_match_tree(
             block,
             irrefutable_pat.span,
@@ -597,12 +600,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             while let Some(next) = {
                 for binding in &candidate_ref.bindings {
                     let local = self.var_local_id(binding.var_id, OutsideGuard);
-
-                    let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
-                        VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
-                    )))) = self.local_decls[local].local_info else {
-                        bug!("Let binding to non-user variable.")
-                    };
                     // `try_upvars_resolved` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
                     // a scrutinee place. `scrutinee_place_builder` will fail for destructured
@@ -617,10 +614,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     //    let (v1, v2) = foo;
                     // };
                     // ```
-                    if let Ok(match_pair_resolved) =
-                        initializer.clone().try_upvars_resolved(self.tcx, &self.upvars)
-                    {
-                        let place = match_pair_resolved.into_place(self.tcx, &self.upvars);
+                    if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
+                        let place = match_pair_resolved.into_place(self);
+
+                        let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                            VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
+                        )))) = self.local_decls[local].local_info else {
+                            bug!("Let binding to non-user variable.")
+                        };
                         *match_place = Some(place);
                     }
                 }
@@ -641,6 +642,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             None,
             None,
             None,
+            false,
         )
         .unit()
     }
@@ -649,6 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// scope for the bindings in these patterns, if such a scope had to be
     /// created. NOTE: Declaring the bindings should always be done in their
     /// drop scope.
+    #[instrument(skip(self), level = "debug")]
     pub(crate) fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
@@ -657,7 +660,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
     ) -> Option<SourceScope> {
-        debug!("declare_bindings: pattern={:?}", pattern);
         self.visit_primary_bindings(
             &pattern,
             UserTypeProjections::none(),
@@ -863,11 +865,16 @@ struct Candidate<'pat, 'tcx> {
 }
 
 impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
-    fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
+    fn new(
+        place: PlaceBuilder<'tcx>,
+        pattern: &'pat Pat<'tcx>,
+        has_guard: bool,
+        cx: &Builder<'_, 'tcx>,
+    ) -> Self {
         Candidate {
             span: pattern.span,
             has_guard,
-            match_pairs: smallvec![MatchPair { place, pattern }],
+            match_pairs: smallvec![MatchPair::new(place, pattern, cx)],
             bindings: Vec::new(),
             ascriptions: Vec::new(),
             subcandidates: Vec::new(),
@@ -1043,6 +1050,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// if `x.0` matches `false` (for the third arm). In the (impossible at
     /// runtime) case when `x.0` is now `true`, we branch to
     /// `otherwise_block`.
+    #[instrument(skip(self, fake_borrows), level = "debug")]
     fn match_candidates<'pat>(
         &mut self,
         span: Span,
@@ -1052,11 +1060,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         candidates: &mut [&mut Candidate<'pat, 'tcx>],
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
     ) {
-        debug!(
-            "matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
-            span, candidates, start_block, otherwise_block,
-        );
-
         // Start by simplifying candidates. Once this process is complete, all
         // the match pairs which remain require some form of test, whether it
         // be a switch or pattern comparison.
@@ -1375,6 +1378,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         )
     }
 
+    #[instrument(
+        skip(self, otherwise, or_span, place, fake_borrows, candidate, pats),
+        level = "debug"
+    )]
     fn test_or_pattern<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
@@ -1384,10 +1391,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         place: PlaceBuilder<'tcx>,
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
     ) {
-        debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
+        debug!("candidate={:#?}\npats={:#?}", candidate, pats);
         let mut or_candidates: Vec<_> = pats
             .iter()
-            .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
+            .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard, self))
             .collect();
         let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
         let otherwise = if candidate.otherwise_block.is_some() {
@@ -1600,9 +1607,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         // Insert a Shallow borrow of any places that is switched on.
         if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
-            match_place.clone().try_upvars_resolved(self.tcx, &self.upvars)
+            match_place.clone().try_upvars_resolved(self)
         {
-            let resolved_place = match_place_resolved.into_place(self.tcx, &self.upvars);
+            let resolved_place = match_place_resolved.into_place(self);
             fb.insert(resolved_place);
         }
 
@@ -1629,9 +1636,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             candidates = rest;
         }
         // at least the first candidate ought to be tested
-        assert!(total_candidate_count > candidates.len());
-        debug!("test_candidates: tested_candidates: {}", total_candidate_count - candidates.len());
-        debug!("test_candidates: untested_candidates: {}", candidates.len());
+        assert!(
+            total_candidate_count > candidates.len(),
+            "{}, {:#?}",
+            total_candidate_count,
+            candidates
+        );
+        debug!("tested_candidates: {}", total_candidate_count - candidates.len());
+        debug!("untested_candidates: {}", candidates.len());
 
         // HACK(matthewjasper) This is a closure so that we can let the test
         // create its blocks before the rest of the match. This currently
@@ -1778,8 +1790,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let expr_span = expr.span;
         let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
         let wildcard = Pat::wildcard_from_ty(pat.ty);
-        let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
-        let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false);
+        let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false, self);
+        let mut otherwise_candidate =
+            Candidate::new(expr_place_builder.clone(), &wildcard, false, self);
         let fake_borrow_temps = self.lower_match_tree(
             block,
             pat.span,
@@ -1789,8 +1802,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         );
         let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
         let expr_place: Place<'tcx>;
-        if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self.tcx, &self.upvars) {
-            expr_place = expr_builder.into_place(self.tcx, &self.upvars);
+        if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
+            expr_place = expr_builder.into_place(self);
             opt_expr_place = Some((Some(&expr_place), expr_span));
         }
         let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
@@ -1813,6 +1826,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             None,
             None,
             None,
+            false,
         );
 
         post_guard_block.unit()
@@ -1836,6 +1850,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         arm_span: Option<Span>,
         match_scope: Option<region::Scope>,
         schedule_drops: bool,
+        storages_alive: bool,
     ) -> BasicBlock {
         debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
 
@@ -2051,7 +2066,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id));
             }
             assert!(schedule_drops, "patterns with guards must schedule drops");
-            self.bind_matched_candidate_for_arm_body(post_guard_block, true, by_value_bindings);
+            self.bind_matched_candidate_for_arm_body(
+                post_guard_block,
+                true,
+                by_value_bindings,
+                storages_alive,
+            );
 
             post_guard_block
         } else {
@@ -2065,6 +2085,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .iter()
                     .flat_map(|(bindings, _)| bindings)
                     .chain(&candidate.bindings),
+                storages_alive,
             );
             block
         }
@@ -2154,6 +2175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block: BasicBlock,
         schedule_drops: bool,
         bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
+        storages_alive: bool,
     ) where
         'tcx: 'b,
     {
@@ -2163,13 +2185,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Assign each of the bindings. This may trigger moves out of the candidate.
         for binding in bindings {
             let source_info = self.source_info(binding.span);
-            let local = self.storage_live_binding(
-                block,
-                binding.var_id,
-                binding.span,
-                OutsideGuard,
-                schedule_drops,
-            );
+            let local = if storages_alive {
+                // Here storages are already alive, probably because this is a binding
+                // from let-else.
+                // We just need to schedule drop for the value.
+                self.var_local_id(binding.var_id, OutsideGuard).into()
+            } else {
+                self.storage_live_binding(
+                    block,
+                    binding.var_id,
+                    binding.span,
+                    OutsideGuard,
+                    schedule_drops,
+                )
+            };
             if schedule_drops {
                 self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
             }
@@ -2188,6 +2217,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// first local is a binding for occurrences of `var` in the guard, which
     /// will have type `&T`. The second local is a binding for occurrences of
     /// `var` in the arm body, which will have type `T`.
+    #[instrument(skip(self), level = "debug")]
     fn declare_binding(
         &mut self,
         source_info: SourceInfo,
@@ -2202,19 +2232,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
     ) {
-        debug!(
-            "declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
-             visibility_scope={:?}, source_info={:?})",
-            var_id, name, mode, var_ty, visibility_scope, source_info
-        );
-
         let tcx = self.tcx;
         let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
         let binding_mode = match mode {
             BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
             BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
         };
-        debug!("declare_binding: user_ty={:?}", user_ty);
         let local = LocalDecl::<'tcx> {
             mutability,
             ty: var_ty,
@@ -2264,7 +2287,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         } else {
             LocalsForNode::One(for_arm_body)
         };
-        debug!("declare_binding: vars={:?}", locals);
+        debug!(?locals);
         self.var_indices.insert(var_id, locals);
     }
 
@@ -2281,8 +2304,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let (matching, failure) = self.in_if_then_scope(*let_else_scope, |this| {
             let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
             let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
-            let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
-            let mut candidate = Candidate::new(scrutinee.clone(), pattern, false);
+            let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this);
+            let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
             let fake_borrow_temps = this.lower_match_tree(
                 block,
                 initializer_span,
@@ -2300,6 +2323,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 None,
                 None,
                 None,
+                true,
             );
             // This block is for the failure case
             let failure = this.bind_pattern(
@@ -2311,6 +2335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 None,
                 None,
                 None,
+                true,
             );
             this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
             matching.unit()
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index df221d35603..828f32db361 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -37,12 +37,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// only generates a single switch. If this happens this method returns
     /// `true`.
+    #[instrument(skip(self, candidate), level = "debug")]
     pub(super) fn simplify_candidate<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
     ) -> bool {
         // repeatedly simplify match pairs until fixed point is reached
-        debug!(?candidate, "simplify_candidate");
+        debug!("{candidate:#?}");
 
         // existing_bindings and new_bindings exists to keep the semantics in order.
         // Reversing the binding order for bindings after `@` changes the binding order in places
@@ -131,7 +132,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> Vec<Candidate<'pat, 'tcx>> {
         pats.iter()
             .map(|box pat| {
-                let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
+                let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
                 self.simplify_candidate(&mut candidate);
                 candidate
             })
@@ -155,17 +156,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ascription: thir::Ascription { ref annotation, variance },
             } => {
                 // Apply the type ascription to the value at `match_pair.place`, which is the
-                if let Ok(place_resolved) =
-                    match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
-                {
+                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
                     candidate.ascriptions.push(Ascription {
                         annotation: annotation.clone(),
-                        source: place_resolved.into_place(self.tcx, &self.upvars),
+                        source: place_resolved.into_place(self),
                         variance,
                     });
                 }
 
-                candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
+                candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
 
                 Ok(())
             }
@@ -184,12 +183,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ref subpattern,
                 is_primary: _,
             } => {
-                if let Ok(place_resolved) =
-                    match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
-                {
+                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
                     candidate.bindings.push(Binding {
                         span: match_pair.pattern.span,
-                        source: place_resolved.into_place(self.tcx, &self.upvars),
+                        source: place_resolved.into_place(self),
                         var_id: var,
                         binding_mode: mode,
                     });
@@ -197,7 +194,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 if let Some(subpattern) = subpattern.as_ref() {
                     // this is the `x @ P` case; have to keep matching against `P` now
-                    candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
+                    candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
                 }
 
                 Ok(())
@@ -308,7 +305,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             PatKind::Deref { ref subpattern } => {
                 let place_builder = match_pair.place.deref();
-                candidate.match_pairs.push(MatchPair::new(place_builder, subpattern));
+                candidate.match_pairs.push(MatchPair::new(place_builder, subpattern, self));
                 Ok(())
             }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 47d05a6e32c..b597ecfaa4d 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -14,8 +14,8 @@ use rustc_hir::{LangItem, RangeEnd};
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
-use rustc_middle::ty::subst::{GenericArg, Subst};
 use rustc_middle::ty::util::IntTypeExt;
+use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Symbol};
@@ -144,6 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    #[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
     pub(super) fn perform_test(
         &mut self,
         match_start_span: Span,
@@ -153,19 +154,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         test: &Test<'tcx>,
         make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
     ) {
-        let place: Place<'tcx>;
-        if let Ok(test_place_builder) = place_builder.try_upvars_resolved(self.tcx, &self.upvars) {
-            place = test_place_builder.into_place(self.tcx, &self.upvars);
-        } else {
-            return;
-        }
-        debug!(
-            "perform_test({:?}, {:?}: {:?}, {:?})",
-            block,
-            place,
-            place.ty(&self.local_decls, self.tcx),
-            test
-        );
+        let place = place_builder.into_place(self);
+        let place_ty = place.ty(&self.local_decls, self.tcx);
+        debug!(?place, ?place_ty,);
 
         let source_info = self.source_info(test.span);
         match test.kind {
@@ -733,14 +724,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
         // we want to create a set of derived match-patterns like
         // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
-        let elem =
-            ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
-        let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
+        let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
         let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
             // e.g., `(x as Variant).0`
             let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
             // e.g., `(x as Variant).0 @ P1`
-            MatchPair::new(place, &subpattern.pattern)
+            MatchPair::new(place, &subpattern.pattern, self)
         });
 
         candidate.match_pairs.extend(consequent_match_pairs);
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index b61c4fe50dd..b854ba47f8f 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,9 +1,11 @@
+use crate::build::expr::as_place::PlaceBase;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::matches::MatchPair;
 use crate::build::Builder;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty;
+use rustc_middle::ty::TypeVisitable;
 use smallvec::SmallVec;
 use std::convert::TryInto;
 
@@ -17,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .iter()
             .map(|fieldpat| {
                 let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty);
-                MatchPair::new(place, &fieldpat.pattern)
+                MatchPair::new(place, &fieldpat.pattern, self)
             })
             .collect()
     }
@@ -31,23 +33,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         suffix: &'pat [Box<Pat<'tcx>>],
     ) {
         let tcx = self.tcx;
-        let (min_length, exact_size) = if let Ok(place_resolved) =
-            place.clone().try_upvars_resolved(tcx, &self.upvars)
-        {
-            match place_resolved.into_place(tcx, &self.upvars).ty(&self.local_decls, tcx).ty.kind()
-            {
-                ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
-                _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
-            }
-        } else {
-            ((prefix.len() + suffix.len()).try_into().unwrap(), false)
-        };
+        let (min_length, exact_size) =
+            if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
+                match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
+                    ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+                    _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
+                }
+            } else {
+                ((prefix.len() + suffix.len()).try_into().unwrap(), false)
+            };
 
         match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
             let elem =
                 ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
             let place = place.clone().project(elem);
-            MatchPair::new(place, subpattern)
+            MatchPair::new(place, subpattern, self)
         }));
 
         if let Some(subslice_pat) = opt_slice {
@@ -57,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 to: if exact_size { min_length - suffix_len } else { suffix_len },
                 from_end: !exact_size,
             });
-            match_pairs.push(MatchPair::new(subslice, subslice_pat));
+            match_pairs.push(MatchPair::new(subslice, subslice_pat, self));
         }
 
         match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
@@ -68,7 +68,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 from_end: !exact_size,
             };
             let place = place.clone().project(elem);
-            MatchPair::new(place, subpattern)
+            MatchPair::new(place, subpattern, self)
         }));
     }
 
@@ -96,10 +96,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 }
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    pub(crate) fn new(
+    pub(in crate::build) fn new(
         place: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
+        cx: &Builder<'_, 'tcx>,
     ) -> MatchPair<'pat, 'tcx> {
+        // Force the place type to the pattern's type.
+        // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
+        let mut place = match place.try_upvars_resolved(cx) {
+            Ok(val) | Err(val) => val,
+        };
+
+        // Only add the OpaqueCast projection if the given place is an opaque type and the
+        // expected type from the pattern is not.
+        let may_need_cast = match place.base() {
+            PlaceBase::Local(local) => {
+                let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
+                ty != pattern.ty && ty.has_opaque_types()
+            }
+            _ => true,
+        };
+        if may_need_cast {
+            place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
+        }
         MatchPair { place, pattern }
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index b2fd9f25bdd..2c7d6a572f4 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -553,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
+    #[instrument(skip(self, f), level = "debug")]
     pub(crate) fn in_scope<F, R>(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
@@ -562,7 +563,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     where
         F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
     {
-        debug!("in_scope(region_scope={:?})", region_scope);
         let source_scope = self.source_scope;
         let tcx = self.tcx;
         if let LintLevel::Explicit(current_hir_id) = lint_level {
@@ -589,7 +589,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let rv = unpack!(block = f(self));
         unpack!(block = self.pop_scope(region_scope, block));
         self.source_scope = source_scope;
-        debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
+        debug!(?block);
         block.and(rv)
     }
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index d059877f8e7..3f8a9d21cd8 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -48,6 +48,8 @@ impl<'tcx> Cx<'tcx> {
             _ => None,
         };
 
+        trace!(?expr.ty);
+
         // Now apply adjustments, if any.
         for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
             trace!(?expr, ?adjustment);
@@ -56,6 +58,8 @@ impl<'tcx> Cx<'tcx> {
                 self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
         }
 
+        trace!(?expr.ty, "after adjustments");
+
         // Next, wrap this up in the expr's scope.
         expr = Expr {
             temp_lifetime,
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 3ef1b263ffd..1d95d6b53fb 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -15,7 +15,7 @@ use rustc_hir::HirId;
 use rustc_hir::Node;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, RvalueScopes, Subst, TyCtxt};
+use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
 use rustc_span::Span;
 
 pub(crate) fn thir_body<'tcx>(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index e712741b7c9..6bb33b5890b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -200,6 +200,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         let mut ty = self.typeck_results.node_type(pat.hir_id);
         let mut span = pat.span;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 115d34ff8fa..02e047afaf3 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -842,7 +842,15 @@ fn is_useful<'p, 'tcx>(
             }
         }
     } else {
-        let ty = v.head().ty();
+        let mut ty = v.head().ty();
+
+        // Opaque types can't get destructured/split, but the patterns can
+        // actually hint at hidden types, so we use the patterns' types instead.
+        if let ty::Opaque(..) = ty.kind() {
+            if let Some(row) = rows.first() {
+                ty = row.head().ty();
+            }
+        }
         let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
         debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
         let pcx = &PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index c0b0cc3c591..702ca2eaf5c 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -893,7 +893,7 @@ where
             }
             ty::Slice(ety) => self.open_drop_for_array(*ety, None),
 
-            _ => bug!("open drop from non-ADT `{:?}`", ty),
+            _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
         }
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index 28936274baa..7806e8f45d3 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
@@ -48,6 +48,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
         match *self {
             ProjectionElem::Deref => ProjectionElem::Deref,
             ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
+            ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()),
             ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
             ProjectionElem::Subslice { from, to, from_end } => {
                 ProjectionElem::Subslice { from, to, from_end }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 53f33a7a0ba..08ba3f9941d 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::{
     RETURN_PLACE,
 };
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
 use rustc_span::{def_id::DefId, Span};
 use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 37e78f4ac07..f16efb365f3 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -21,7 +21,7 @@ use rustc_middle::mir::{
     TerminatorKind, UnOp, RETURN_PLACE,
 };
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
 use rustc_session::lint;
 use rustc_span::Span;
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 294af2455d0..ef8d6bb6559 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -8,7 +8,6 @@ use rustc_index::vec::Idx;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{Ty, TyCtxt};
 
 /// Constructs the types used when accessing a Box's pointer
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 2e4fe1e3e5d..0568eb2ffa6 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -3,11 +3,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{
-    self,
-    subst::{GenericArgKind, Subst, SubstsRef},
-    EarlyBinder, PredicateKind, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 705cf776fb2..c833de3a8a7 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -61,9 +61,8 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::GeneratorSubsts;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::ty::{GeneratorSubsts, SubstsRef};
 use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
 };
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index d00a384cb44..b60bd3cea23 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,7 +7,6 @@ use rustc_index::vec::Idx;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_span::def_id::DefId;
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 88213620029..6ca58ee458c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 79d0ef69ba7..18e7e74741a 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -7,10 +7,10 @@ use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::print::{Print, Printer};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{
     self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, UintTy,
 };
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::symbol::kw;
 use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 292787d4dbb..94de8abce19 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -22,7 +22,6 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index e11a4220144..07e470dc2ae 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -4,7 +4,7 @@ use super::{
 use crate::infer::InferCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, GenericParamDefKind};
 use rustc_span::symbol::sym;
 use std::iter;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 973cddbd179..d90b77fc556 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2256,7 +2256,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             | ObligationCauseCode::QuestionMark
             | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
             | ObligationCauseCode::LetElse
-            | ObligationCauseCode::BinOp { .. } => {}
+            | ObligationCauseCode::BinOp { .. }
+            | ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
             }
@@ -2713,12 +2714,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         Some(t) if t.hir_owner == parent_id => t,
                         _ => self.tcx.typeck(parent_id),
                     };
-                    let ty = typeck_results.expr_ty_adjusted(expr);
-                    let span = expr.peel_blocks().span;
+                    let expr = expr.peel_blocks();
+                    let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                    let span = expr.span;
                     if Some(span) != err.span.primary_span() {
                         err.span_label(
                             span,
-                            &if ty.references_error() {
+                            if ty.references_error() {
                                 String::new()
                             } else {
                                 format!("this tail expression is of type `{:?}`", ty)
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 40596078f04..104a465a3b5 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -34,12 +34,11 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
-    self, DefIdTree, GenericParamDefKind, Subst, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
-    VtblEntry,
+    self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, VtblEntry,
 };
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_span::{sym, Span};
 use smallvec::SmallVec;
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index f2779ce2db1..a54b725753c 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -18,10 +18,10 @@ use rustc_errors::{FatalError, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst};
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
 use rustc_middle::ty::{
     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
 };
+use rustc_middle::ty::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{Predicate, ToPredicate};
 use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a25fb854316..6f41cbeb7af 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -30,7 +30,6 @@ use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
 use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 17afd325f03..88000d46978 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -13,7 +13,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::traits::Normalized;
 use rustc_middle::mir;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
 
@@ -48,10 +47,11 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
         T: TypeFoldable<'tcx>,
     {
         debug!(
-            "normalize::<{}>(value={:?}, param_env={:?})",
+            "normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
             std::any::type_name::<T>(),
             value,
             self.param_env,
+            self.cause,
         );
         if !needs_normalization(&value, self.param_env.reveal()) {
             return Ok(Normalized { value, obligations: vec![] });
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index f6e196e3141..18988861add 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -23,7 +23,7 @@ impl<F, G> CustomTypeOp<F, G> {
     }
 }
 
-impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
+impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
 where
     F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
     G: Fn() -> String,
@@ -89,8 +89,8 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
         infcx.tcx,
         region_obligations
             .iter()
-            .map(|r_o| (r_o.sup_type, r_o.sub_region))
-            .map(|(ty, r)| (infcx.resolve_vars_if_possible(ty), r)),
+            .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()))
+            .map(|(ty, r, cc)| (infcx.resolve_vars_if_possible(ty), r, cc)),
         &region_constraint_data,
     );
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 578e1d00cf9..8a79165702c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -26,7 +26,7 @@ pub use rustc_middle::traits::query::type_op::*;
 /// extract out the resulting region constraints (or an error if it
 /// cannot be completed).
 pub trait TypeOp<'tcx>: Sized + fmt::Debug {
-    type Output;
+    type Output: fmt::Debug;
     type ErrorInfo;
 
     /// Processes the operation and all resulting obligations,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 15d8205e157..52bc8115fa0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,8 +11,8 @@ use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
 use rustc_span::def_id::DefId;
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0a802184bb8..e4e02584561 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -37,7 +37,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 7d299e30ae0..56a88749c46 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -19,8 +19,8 @@ use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCau
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, ImplSubject, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
 use rustc_span::{Span, DUMMY_SP};
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 0f5dff01c66..5206e9f649b 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -5,8 +5,8 @@ use smallvec::SmallVec;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
 use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{GenericArg, SubstsRef};
 
 use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 pub use rustc_infer::traits::{self, util::*};
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index ff5ca0cbcb7..0de28b82661 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -7,8 +7,8 @@
 //! `crate::chalk::lowering` (to lower rustc types into Chalk types).
 
 use rustc_middle::traits::ChalkRustInterner as RustInterner;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 
 use rustc_ast::ast;
 use rustc_attr as attr;
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index a20de08b4ef..7fb7c689550 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -4,7 +4,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 60e9b88107d..ff7d1ef00cc 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -3,12 +3,12 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::TraitEngineExt as _;
+use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
 use rustc_middle::ty::{
     self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance,
 };
+use rustc_middle::ty::{GenericArg, UserSelfTy, UserSubsts};
 use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
@@ -22,6 +22,7 @@ use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
 use rustc_trait_selection::traits::query::{Fallible, NoSolution};
 use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
 use std::fmt;
+use std::iter::zip;
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers {
@@ -61,14 +62,15 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
         mir_ty, def_id, user_substs
     );
 
-    let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
-    cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?;
+    let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx };
+    cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
     Ok(())
 }
 
 struct AscribeUserTypeCx<'me, 'tcx> {
     infcx: &'me InferCtxt<'me, 'tcx>,
     param_env: ParamEnv<'tcx>,
+    span: Span,
     fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
 }
 
@@ -77,12 +79,15 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
+        self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID))
+    }
+
+    fn normalize_with_cause<T>(&mut self, value: T, cause: ObligationCause<'tcx>) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
         self.infcx
-            .partially_normalize_associated_types_in(
-                ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID),
-                self.param_env,
-                value,
-            )
+            .partially_normalize_associated_types_in(cause, self.param_env, value)
             .into_value_registering_obligations(self.infcx, self.fulfill_cx)
     }
 
@@ -91,18 +96,13 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         T: ToTrace<'tcx>,
     {
         self.infcx
-            .at(&ObligationCause::dummy(), self.param_env)
+            .at(&ObligationCause::dummy_with_span(self.span), self.param_env)
             .relate(a, variance, b)?
             .into_value_registering_obligations(self.infcx, self.fulfill_cx);
         Ok(())
     }
 
-    fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) {
-        let cause = if let Some(span) = span {
-            ObligationCause::dummy_with_span(span)
-        } else {
-            ObligationCause::dummy()
-        };
+    fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
         self.fulfill_cx.register_predicate_obligation(
             self.infcx,
             Obligation::new(cause, self.param_env, predicate),
@@ -126,7 +126,6 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         mir_ty: Ty<'tcx>,
         def_id: DefId,
         user_substs: UserSubsts<'tcx>,
-        span: Option<Span>,
     ) -> Result<(), NoSolution> {
         let UserSubsts { user_self_ty, substs } = user_substs;
         let tcx = self.tcx();
@@ -145,10 +144,22 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         // outlives" error messages.
         let instantiated_predicates =
             self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+
+        let cause = ObligationCause::dummy_with_span(self.span);
+
         debug!(?instantiated_predicates);
-        for instantiated_predicate in instantiated_predicates.predicates {
-            let instantiated_predicate = self.normalize(instantiated_predicate);
-            self.prove_predicate(instantiated_predicate, span);
+        for (instantiated_predicate, predicate_span) in
+            zip(instantiated_predicates.predicates, instantiated_predicates.spans)
+        {
+            let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
+            let cause = ObligationCause::new(
+                span,
+                hir::CRATE_HIR_ID,
+                ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
+            );
+            let instantiated_predicate =
+                self.normalize_with_cause(instantiated_predicate, cause.clone());
+            self.prove_predicate(instantiated_predicate, cause);
         }
 
         if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
@@ -161,7 +172,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
             self.prove_predicate(
                 ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
                     .to_predicate(self.tcx()),
-                span,
+                cause.clone(),
             );
         }
 
@@ -178,7 +189,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         // which...could happen with normalization...
         self.prove_predicate(
             ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
-            span,
+            cause,
         );
         Ok(())
     }
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index ab5a3d8ae48..ba987c6f763 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,7 +2,6 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 9266e4e3f6e..f7db39dfec3 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -1,7 +1,6 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
 use rustc_trait_selection::traits;
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 6d2ba7c1c95..5432fdbb5e8 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -26,7 +26,7 @@ use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::DynKind;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 20332e75c42..27329f8eab4 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, Subst, ToPredicate, Ty};
+use rustc_middle::ty::{self, ToPredicate, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 0d35c2479dd..c82a31e65cf 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -17,7 +17,7 @@ use rustc_infer::{
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 9b943b160f3..a13d73c471b 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -3,7 +3,6 @@
 use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
 
 use crate::astconv::AstConv;
-use crate::rustc_middle::ty::subst::Subst;
 use hir::def::DefKind;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 0c6d8f26f1d..7c0b815e42a 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -12,8 +12,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::util::ExplicitSelf;
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{
     self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
 };
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index a40478db969..70b9c732ff4 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -20,14 +20,12 @@ use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{
-    self, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSelfTy, UserSubsts,
-};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
     self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef,
     ToPredicate, Ty, UserType,
 };
+use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
@@ -559,7 +557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
     pub fn register_wf_obligation(
         &self,
-        arg: subst::GenericArg<'tcx>,
+        arg: ty::GenericArg<'tcx>,
         span: Span,
         code: traits::ObligationCauseCode<'tcx>,
     ) {
@@ -1271,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &mut self,
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'_>,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
                         <dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
@@ -1295,10 +1293,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             fn inferred_kind(
                 &mut self,
-                substs: Option<&[subst::GenericArg<'tcx>]>,
+                substs: Option<&[ty::GenericArg<'tcx>]>,
                 param: &ty::GenericParamDef,
                 infer_args: bool,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 let tcx = self.fcx.tcx();
                 match param.kind {
                     GenericParamDefKind::Lifetime => {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index ee0ad7b5d0a..c32d1309031 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -14,7 +14,7 @@ use rustc_hir::{
 use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
+use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index c7425ff7865..ae484b4feda 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -10,7 +10,6 @@ use crate::require_same_types;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 59fd5c315ae..30731cbd03d 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -10,7 +10,7 @@ use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{self, Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index 249e9c66ba7..3fe9bea2299 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -18,7 +18,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
 use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index e9f55ab3406..6cd7ced01a3 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -19,9 +19,9 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::middle::stability;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::lev_distance::{
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index cfae63e4a06..618b01fc55f 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -112,8 +112,8 @@ use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::config;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index bc644c694a0..fd5df0d9fa1 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -10,13 +10,14 @@ use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
+use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
     TypeSuperVisitable, TypeVisitable, TypeVisitor,
 };
+use rustc_middle::ty::{GenericArgKind, InternalSubsts};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -663,7 +664,7 @@ fn ty_known_to_outlive<'tcx>(
     resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
         let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
         let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env);
-        outlives.type_must_outlive(origin, ty, region);
+        outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation);
     })
 }
 
@@ -681,7 +682,12 @@ fn region_known_to_outlive<'tcx>(
         use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
         let origin = infer::RelateRegionParamBound(DUMMY_SP);
         // `region_a: region_b` -> `region_b <= region_a`
-        infcx.push_sub_region_constraint(origin, region_b, region_a);
+        infcx.push_sub_region_constraint(
+            origin,
+            region_b,
+            region_a,
+            ConstraintCategory::BoringNoLocation,
+        );
     })
 }
 
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 45a5eca708a..afc8a9600ad 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -3154,6 +3154,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                         E0535,
                         "invalid argument"
                     )
+                    .help("valid inline arguments are `always` and `never`")
                     .emit();
 
                     InlineAttr::None
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 3b779280eda..064a70107fe 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::Span;
 
 use super::explicit::ExplicitPredicatesMap;
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 8619467c2d9..ce71cd600fc 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -109,6 +109,7 @@
 #![feature(core_intrinsics)]
 #![feature(const_eval_select)]
 #![feature(const_pin)]
+#![feature(const_waker)]
 #![feature(cstr_from_bytes_until_nul)]
 #![feature(dispatch_from_dyn)]
 #![cfg_attr(not(bootstrap), feature(error_generic_member_access))]
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index fb4454c94cb..1abbb39497a 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1021,15 +1021,18 @@ impl<T: ?Sized> RefCell<T> {
 
     /// Returns a mutable reference to the underlying data.
     ///
-    /// This call borrows `RefCell` mutably (at compile-time) so there is no
-    /// need for dynamic checks.
-    ///
-    /// However be cautious: this method expects `self` to be mutable, which is
-    /// generally not the case when using a `RefCell`. Take a look at the
-    /// [`borrow_mut`] method instead if `self` isn't mutable.
-    ///
-    /// Also, please be aware that this method is only for special circumstances and is usually
-    /// not what you want. In case of doubt, use [`borrow_mut`] instead.
+    /// Since this method borrows `RefCell` mutably, it is statically guaranteed
+    /// that no borrows to the underlying data exist. The dynamic checks inherent
+    /// in [`borrow_mut`] and most other methods of `RefCell` are therefor
+    /// unnecessary.
+    ///
+    /// This method can only be called if `RefCell` can be mutably borrowed,
+    /// which in general is only the case directly after the `RefCell` has
+    /// been created. In these situations, skipping the aforementioned dynamic
+    /// borrowing checks may yield better ergonomics and runtime-performance.
+    ///
+    /// In most situations where `RefCell` is used, it can't be borrowed mutably.
+    /// Use [`borrow_mut`] to get mutable access to the underlying data then.
     ///
     /// [`borrow_mut`]: RefCell::borrow_mut()
     ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 5621d15c1cd..c912b933065 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -145,6 +145,7 @@
 #![feature(const_default_impls)]
 #![feature(const_unicode_case_lookup)]
 #![feature(const_unsafecell_get_mut)]
+#![feature(const_waker)]
 #![feature(core_panic)]
 #![feature(duration_consts_float)]
 #![feature(maybe_uninit_uninit_array)]
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 60ecc9c0bdb..0cff972df3a 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -186,17 +186,19 @@ pub struct Context<'a> {
 impl<'a> Context<'a> {
     /// Create a new `Context` from a [`&Waker`](Waker).
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     #[must_use]
     #[inline]
-    pub fn from_waker(waker: &'a Waker) -> Self {
+    pub const fn from_waker(waker: &'a Waker) -> Self {
         Context { waker, _marker: PhantomData }
     }
 
     /// Returns a reference to the [`Waker`] for the current task.
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     #[must_use]
     #[inline]
-    pub fn waker(&self) -> &'a Waker {
+    pub const fn waker(&self) -> &'a Waker {
         &self.waker
     }
 }
@@ -311,7 +313,8 @@ impl Waker {
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
-    pub unsafe fn from_raw(waker: RawWaker) -> Waker {
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
         Waker { waker }
     }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 4a0e162bc4a..46f603eaeba 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -74,6 +74,7 @@
 #![feature(iterator_try_reduce)]
 #![feature(const_mut_refs)]
 #![feature(const_pin)]
+#![feature(const_waker)]
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
 #![feature(pointer_byte_offsets)]
diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs
index d71fef9e5c8..56be30e9282 100644
--- a/library/core/tests/task.rs
+++ b/library/core/tests/task.rs
@@ -1,4 +1,4 @@
-use core::task::Poll;
+use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
 
 #[test]
 fn poll_const() {
@@ -12,3 +12,18 @@ fn poll_const() {
     const IS_PENDING: bool = POLL.is_pending();
     assert!(IS_PENDING);
 }
+
+#[test]
+fn waker_const() {
+    const VOID_TABLE: RawWakerVTable = RawWakerVTable::new(|_| VOID_WAKER, |_| {}, |_| {}, |_| {});
+
+    const VOID_WAKER: RawWaker = RawWaker::new(&(), &VOID_TABLE);
+
+    static WAKER: Waker = unsafe { Waker::from_raw(VOID_WAKER) };
+
+    static CONTEXT: Context<'static> = Context::from_waker(&WAKER);
+
+    static WAKER_REF: &'static Waker = CONTEXT.waker();
+
+    WAKER_REF.wake_by_ref();
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index bc4f1b27c2a..07b40f64ac2 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -315,6 +315,7 @@
 #![feature(strict_provenance)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_uninit_array)]
+#![feature(const_waker)]
 //
 // Library features (alloc):
 #![feature(alloc_layout_extra)]
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 36f990b72ff..bc6283ef467 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -708,6 +708,7 @@ impl<'a> Builder<'a> {
             Kind::Dist => describe!(
                 dist::Docs,
                 dist::RustcDocs,
+                dist::JsonDocs,
                 dist::Mingw,
                 dist::Rustc,
                 dist::Std,
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 280eba75f0c..88bbcc93d07 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -236,7 +236,7 @@ mod defaults {
     fn doc_default() {
         let mut config = configure("doc", &["A"], &["A"]);
         config.compiler_docs = true;
-        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
         let mut cache = run_build(&[], config);
         let a = TargetSelection::from_user("A");
 
@@ -587,7 +587,7 @@ mod dist {
     fn doc_ci() {
         let mut config = configure(&["A"], &["A"]);
         config.compiler_docs = true;
-        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 1a59b3958f1..c9ee3c1c7d6 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -87,6 +87,45 @@ impl Step for Docs {
     }
 }
 
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct JsonDocs {
+    pub host: TargetSelection,
+}
+
+impl Step for JsonDocs {
+    type Output = Option<GeneratedTarball>;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        let default = run.builder.config.docs;
+        run.alias("rust-json-docs").default_condition(default)
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(JsonDocs { host: run.target });
+    }
+
+    /// Builds the `rust-json-docs` installer component.
+    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
+        // This prevents JSON docs from being built for "dist" or "install"
+        // on the stable/beta channels. The JSON format is not stable yet and
+        // should not be included in stable/beta toolchains.
+        if !builder.build.unstable_features() {
+            return None;
+        }
+
+        let host = self.host;
+        builder.ensure(crate::doc::JsonStd { stage: builder.top_stage, target: host });
+
+        let dest = "share/doc/rust/json";
+
+        let mut tarball = Tarball::new(builder, "rust-json-docs", &host.triple);
+        tarball.set_product_name("Rust Documentation In JSON Format");
+        tarball.add_bulk_dir(&builder.json_doc_out(host), dest);
+        Some(tarball.generate())
+    }
+}
+
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct RustcDocs {
     pub host: TargetSelection,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 791511609df..819af658748 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -7,6 +7,7 @@
 //! Everything here is basically just a shim around calling either `rustbook` or
 //! `rustdoc`.
 
+use std::ffi::OsStr;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -425,49 +426,24 @@ impl Step for Std {
     fn run(self, builder: &Builder<'_>) {
         let stage = self.stage;
         let target = self.target;
-        builder.info(&format!("Documenting stage{} std ({})", stage, target));
-        if builder.no_std(target) == Some(true) {
-            panic!(
-                "building std documentation for no_std target {target} is not supported\n\
-                 Set `docs = false` in the config to disable documentation."
-            );
-        }
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler(stage, builder.config.build);
-
-        let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
-
         t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
 
-        let run_cargo_rustdoc_for = |package: &str| {
-            let mut cargo =
-                builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
-            compile::std_cargo(builder, target, compiler.stage, &mut cargo);
-
-            cargo
-                .arg("-p")
-                .arg(package)
-                .arg("-Zskip-rustdoc-fingerprint")
-                .arg("--")
-                .arg("--markdown-css")
-                .arg("rust.css")
-                .arg("--markdown-no-toc")
-                .arg("-Z")
-                .arg("unstable-options")
-                .arg("--resource-suffix")
-                .arg(&builder.version)
-                .arg("--index-page")
-                .arg(&builder.src.join("src/doc/index.md"));
-
-            if !builder.config.docs_minification {
-                cargo.arg("--disable-minification");
-            }
-
-            builder.run(&mut cargo.into());
-        };
+        let index_page = builder.src.join("src/doc/index.md").into_os_string();
+        let mut extra_args = vec![
+            OsStr::new("--markdown-css"),
+            OsStr::new("rust.css"),
+            OsStr::new("--markdown-no-toc"),
+            OsStr::new("--index-page"),
+            &index_page,
+        ];
+
+        if !builder.config.docs_minification {
+            extra_args.push(OsStr::new("--disable-minification"));
+        }
 
-        let paths = builder
+        let requested_crates = builder
             .paths
             .iter()
             .map(components_simplified)
@@ -485,30 +461,20 @@ impl Step for Std {
             })
             .collect::<Vec<_>>();
 
-        // Only build the following crates. While we could just iterate over the
-        // folder structure, that would also build internal crates that we do
-        // not want to show in documentation. These crates will later be visited
-        // by the rustc step, so internal documentation will show them.
-        //
-        // Note that the order here is important! The crates need to be
-        // processed starting from the leaves, otherwise rustdoc will not
-        // create correct links between crates because rustdoc depends on the
-        // existence of the output directories to know if it should be a local
-        // or remote link.
-        let krates = ["core", "alloc", "std", "proc_macro", "test"];
-        for krate in &krates {
-            run_cargo_rustdoc_for(krate);
-            if paths.iter().any(|p| p == krate) {
-                // No need to document more of the libraries if we have the one we want.
-                break;
-            }
-        }
-        builder.cp_r(&out_dir, &out);
+        doc_std(
+            builder,
+            DocumentationFormat::HTML,
+            stage,
+            target,
+            &out,
+            &extra_args,
+            &requested_crates,
+        );
 
         // Look for library/std, library/core etc in the `x.py doc` arguments and
         // open the corresponding rendered docs.
-        for requested_crate in paths {
-            if krates.iter().any(|k| *k == requested_crate.as_str()) {
+        for requested_crate in requested_crates {
+            if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) {
                 let index = out.join(requested_crate).join("index.html");
                 open(builder, &index);
             }
@@ -517,6 +483,134 @@ impl Step for Std {
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct JsonStd {
+    pub stage: u32,
+    pub target: TargetSelection,
+}
+
+impl Step for JsonStd {
+    type Output = ();
+    const DEFAULT: bool = false;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        let default = run.builder.config.docs && run.builder.config.cmd.json();
+        run.all_krates("test").path("library").default_condition(default)
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target });
+    }
+
+    /// Build JSON documentation for the standard library crates.
+    ///
+    /// This is largely just a wrapper around `cargo doc`.
+    fn run(self, builder: &Builder<'_>) {
+        let stage = self.stage;
+        let target = self.target;
+        let out = builder.json_doc_out(target);
+        t!(fs::create_dir_all(&out));
+        let extra_args = [OsStr::new("--output-format"), OsStr::new("json")];
+        doc_std(builder, DocumentationFormat::JSON, stage, target, &out, &extra_args, &[])
+    }
+}
+
+/// Name of the crates that are visible to consumers of the standard library.
+/// Documentation for internal crates is handled by the rustc step, so internal crates will show
+/// up there.
+///
+/// Order here is important!
+/// Crates need to be processed starting from the leaves, otherwise rustdoc will not
+/// create correct links between crates because rustdoc depends on the
+/// existence of the output directories to know if it should be a local
+/// or remote link.
+const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+enum DocumentationFormat {
+    HTML,
+    JSON,
+}
+
+impl DocumentationFormat {
+    fn as_str(&self) -> &str {
+        match self {
+            DocumentationFormat::HTML => "HTML",
+            DocumentationFormat::JSON => "JSON",
+        }
+    }
+}
+
+/// Build the documentation for public standard library crates.
+///
+/// `requested_crates` can be used to build only a subset of the crates. If empty, all crates will
+/// be built.
+fn doc_std(
+    builder: &Builder<'_>,
+    format: DocumentationFormat,
+    stage: u32,
+    target: TargetSelection,
+    out: &Path,
+    extra_args: &[&OsStr],
+    requested_crates: &[String],
+) {
+    builder.info(&format!(
+        "Documenting stage{} std ({}) in {} format",
+        stage,
+        target,
+        format.as_str()
+    ));
+    if builder.no_std(target) == Some(true) {
+        panic!(
+            "building std documentation for no_std target {target} is not supported\n\
+             Set `docs = false` in the config to disable documentation."
+        );
+    }
+    let compiler = builder.compiler(stage, builder.config.build);
+    // This is directory where the compiler will place the output of the command.
+    // We will then copy the files from this directory into the final `out` directory, the specified
+    // as a function parameter.
+    let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
+    // `cargo` uses the same directory for both JSON docs and HTML docs.
+    // This could lead to cross-contamination when copying files into the specified `out` directory.
+    // For example:
+    // ```bash
+    // x doc std
+    // x doc std --json
+    // ```
+    // could lead to HTML docs being copied into the JSON docs output directory.
+    // To avoid this issue, we clean the doc folder before invoking `cargo`.
+    if out_dir.exists() {
+        builder.remove_dir(&out_dir);
+    }
+
+    let run_cargo_rustdoc_for = |package: &str| {
+        let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
+        compile::std_cargo(builder, target, compiler.stage, &mut cargo);
+        cargo
+            .arg("-p")
+            .arg(package)
+            .arg("-Zskip-rustdoc-fingerprint")
+            .arg("--")
+            .arg("-Z")
+            .arg("unstable-options")
+            .arg("--resource-suffix")
+            .arg(&builder.version)
+            .args(extra_args);
+        builder.run(&mut cargo.into());
+    };
+
+    for krate in STD_PUBLIC_CRATES {
+        run_cargo_rustdoc_for(krate);
+        if requested_crates.iter().any(|p| p == krate) {
+            // No need to document more of the libraries if we have the one we want.
+            break;
+        }
+    }
+
+    builder.cp_r(&out_dir, &out);
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Rustc {
     pub stage: u32,
     pub target: TargetSelection,
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 789da748100..802b49d748a 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -107,6 +107,7 @@ pub enum Subcommand {
     Doc {
         paths: Vec<PathBuf>,
         open: bool,
+        json: bool,
     },
     Test {
         paths: Vec<PathBuf>,
@@ -325,6 +326,11 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
             }
             Kind::Doc => {
                 opts.optflag("", "open", "open the docs in a browser");
+                opts.optflag(
+                    "",
+                    "json",
+                    "render the documentation in JSON format in addition to the usual HTML format",
+                );
             }
             Kind::Clean => {
                 opts.optflag("", "all", "clean all build artifacts");
@@ -493,6 +499,7 @@ Arguments:
         ./x.py doc src/doc/book
         ./x.py doc src/doc/nomicon
         ./x.py doc src/doc/book library/std
+        ./x.py doc library/std --json
         ./x.py doc library/std --open
 
     If no arguments are passed then everything is documented:
@@ -581,7 +588,11 @@ Arguments:
                 },
             },
             Kind::Bench => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
-            Kind::Doc => Subcommand::Doc { paths, open: matches.opt_present("open") },
+            Kind::Doc => Subcommand::Doc {
+                paths,
+                open: matches.opt_present("open"),
+                json: matches.opt_present("json"),
+            },
             Kind::Clean => {
                 if !paths.is_empty() {
                     println!("\nclean does not take a path argument\n");
@@ -787,6 +798,13 @@ impl Subcommand {
             _ => false,
         }
     }
+
+    pub fn json(&self) -> bool {
+        match *self {
+            Subcommand::Doc { json, .. } => json,
+            _ => false,
+        }
+    }
 }
 
 fn split(s: &[String]) -> Vec<String> {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index fade44ecb15..b7d271e6494 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -825,6 +825,11 @@ impl Build {
         self.out.join(&*target.triple).join("doc")
     }
 
+    /// Output directory for all JSON-formatted documentation for a target
+    fn json_doc_out(&self, target: TargetSelection) -> PathBuf {
+        self.out.join(&*target.triple).join("json-doc")
+    }
+
     fn test_out(&self, target: TargetSelection) -> PathBuf {
         self.out.join(&*target.triple).join("test")
     }
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 7826fd51409..f020c31079e 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -264,6 +264,9 @@ on:
     branches:
       - "**"
 
+permissions:
+  contents: read
+
 defaults:
   run:
     # On Linux, macOS, and Windows, use the system-provided bash as the default
@@ -273,6 +276,8 @@ defaults:
 
 jobs:
   pr:
+    permissions:
+      actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
     <<: *base-ci-job
     name: PR
     env:
@@ -293,6 +298,8 @@ jobs:
             <<: *job-linux-xl
 
   auto:
+    permissions:
+      actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
     <<: *base-ci-job
     name: auto
     env:
@@ -719,6 +726,8 @@ jobs:
             <<: *job-windows-xl
 
   try:
+    permissions:
+      actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
     <<: *base-ci-job
     name: try
     env:
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index cc734389e07..fd169f64885 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -2,7 +2,6 @@ use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtE
 use rustc_hir as hir;
 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
 use rustc_infer::traits;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::ToPredicate;
 use rustc_span::DUMMY_SP;
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c8875c272bb..375737e9bc4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,7 +20,7 @@ use rustc_hir::PredicateOrigin;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Lift, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index f458a4f59ae..b4f5bf933a6 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1152,10 +1152,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	font-size: 1rem;
 }
 
-td.summary-column {
-	width: 100%;
-}
-
 .summary {
 	padding-right: 0px;
 }
diff --git a/src/test/mir-opt/issue-101867.rs b/src/test/mir-opt/issue-101867.rs
new file mode 100644
index 00000000000..931396e2171
--- /dev/null
+++ b/src/test/mir-opt/issue-101867.rs
@@ -0,0 +1,9 @@
+#![cfg_attr(bootstrap, feature(let_else))]
+
+// EMIT_MIR issue_101867.main.mir_map.0.mir
+fn main() {
+    let x: Option<u8> = Some(1);
+    let Some(y) = x else {
+        panic!();
+    };
+}
diff --git a/src/test/mir-opt/issue_101867.main.mir_map.0.mir b/src/test/mir-opt/issue_101867.main.mir_map.0.mir
new file mode 100644
index 00000000000..98501ac8c9d
--- /dev/null
+++ b/src/test/mir-opt/issue_101867.main.mir_map.0.mir
@@ -0,0 +1,75 @@
+// MIR for `main` 0 mir_map
+
+| User Type Annotations
+| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
+|
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-101867.rs:+0:11: +0:11
+    let _1: std::option::Option<u8> as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-101867.rs:+1:9: +1:10
+    let mut _2: !;                       // in scope 0 at $DIR/issue-101867.rs:+2:26: +4:6
+    let _3: ();                          // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
+    let mut _4: !;                       // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
+    let mut _6: isize;                   // in scope 0 at $DIR/issue-101867.rs:+2:9: +2:16
+    scope 1 {
+        debug x => _1;                   // in scope 1 at $DIR/issue-101867.rs:+1:9: +1:10
+        let _5: u8;                      // in scope 1 at $DIR/issue-101867.rs:+2:14: +2:15
+        scope 2 {
+            debug y => _5;               // in scope 2 at $DIR/issue-101867.rs:+2:14: +2:15
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/issue-101867.rs:+1:9: +1:10
+        _1 = Option::<u8>::Some(const 1_u8); // scope 0 at $DIR/issue-101867.rs:+1:25: +1:32
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/issue-101867.rs:+1:9: +1:10
+        AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-101867.rs:+1:12: +1:22
+        StorageLive(_5);                 // scope 1 at $DIR/issue-101867.rs:+2:14: +2:15
+        FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20
+        _6 = discriminant(_1);           // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20
+        switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-101867.rs:+2:9: +2:16
+    }
+
+    bb1: {
+        StorageLive(_3);                 // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
+        StorageLive(_4);                 // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
+        _4 = begin_panic::<&str>(const "explicit panic") -> bb7; // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/std/src/panic.rs:LL:COL
+                                         // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(<ZST>) }
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/std/src/panic.rs:LL:COL
+                                         // + literal: Const { ty: &str, val: Value(Slice(..)) }
+    }
+
+    bb2: {
+        StorageDead(_4);                 // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $DIR/issue-101867.rs:+3:16: +3:17
+        unreachable;                     // scope 1 at $DIR/issue-101867.rs:+2:26: +4:6
+    }
+
+    bb3: {
+        goto -> bb6;                     // scope 1 at $DIR/issue-101867.rs:+2:19: +2:20
+    }
+
+    bb4: {
+        falseEdge -> [real: bb5, imaginary: bb3]; // scope 1 at $DIR/issue-101867.rs:+2:9: +2:16
+    }
+
+    bb5: {
+        _5 = ((_1 as Some).0: u8);       // scope 1 at $DIR/issue-101867.rs:+2:14: +2:15
+        _0 = const ();                   // scope 0 at $DIR/issue-101867.rs:+0:11: +5:2
+        StorageDead(_5);                 // scope 1 at $DIR/issue-101867.rs:+5:1: +5:2
+        StorageDead(_1);                 // scope 0 at $DIR/issue-101867.rs:+5:1: +5:2
+        return;                          // scope 0 at $DIR/issue-101867.rs:+5:2: +5:2
+    }
+
+    bb6: {
+        StorageDead(_5);                 // scope 1 at $DIR/issue-101867.rs:+5:1: +5:2
+        goto -> bb1;                     // scope 0 at $DIR/issue-101867.rs:+0:11: +5:2
+    }
+
+    bb7 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-101867.rs:+0:1: +5:2
+    }
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/Makefile b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile
new file mode 100644
index 00000000000..e56e1e94ec5
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile
@@ -0,0 +1,15 @@
+# ignore-cross-compile
+# ignore-macos
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Verbatim allows specify precise name.
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_some_strange_name.ext
+	$(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_some_strange_name.ext
+
+	# With verbatim any other name cannot be used (local).
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/liblocal_native_dep.a
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.a
+	$(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.lib
+	$(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_native_dep 2>&1 | $(CGREP) "local_native_dep"
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs b/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
new file mode 100644
index 00000000000..59b6c92d293
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn local_native_f() -> i32 {
+    return 0;
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/main.rs b/src/test/run-make/native-link-modifier-verbatim-linker/main.rs
new file mode 100644
index 00000000000..71b73a489c7
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/main.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn local_native_f() -> i32;
+}
+
+pub fn main() {
+    unsafe {
+        assert!(local_native_f() == 0);
+    };
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile
new file mode 100644
index 00000000000..1093b1cd369
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile
@@ -0,0 +1,12 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Verbatim allows specify precise name.
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_some_strange_name.ext
+	$(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_some_strange_name.ext --crate-type rlib
+
+	# With verbatim any other name cannot be used (upstream).
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/libupstream_native_dep.a
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.a
+	$(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.lib
+	$(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_native_dep --crate-type rlib 2>&1 | $(CGREP) "upstream_native_dep"
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs b/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
new file mode 100644
index 00000000000..e9517218e0d
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn upstream_native_f() -> i32;
+}
+
+pub fn rust_dep() {
+    unsafe {
+        assert!(upstream_native_f() == 0);
+    }
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs b/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
new file mode 100644
index 00000000000..8396862333d
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn upstream_native_f() -> i32 {
+    return 0;
+}
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
index 9db9cfc7ff0..759d79493a9 100644
--- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
@@ -14,7 +14,7 @@ LL |       let p = Some(45).and_then({
 LL | |
 LL | |         |x| println!("doubling {}", x);
 LL | |         Some(x * 2)
-   | |         -----------
+   | |         ----------- this tail expression is of type `std::option::Option<_>`
 LL | |
 LL | |     });
    | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs
new file mode 100644
index 00000000000..719d1bd5a4c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs
@@ -0,0 +1,35 @@
+// check-fail
+// known-bug
+
+// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
+// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
+
+use std::fmt::Debug;
+
+pub trait LendingIterator {
+    type Item<'this>
+    where
+        Self: 'this;
+}
+
+pub struct WindowsMut<'x> {
+    slice: &'x (),
+}
+
+impl<'y> LendingIterator for WindowsMut<'y> {
+    type Item<'this> = &'this mut () where 'y: 'this;
+}
+
+fn print_items<I>(_iter: I)
+where
+    I: LendingIterator,
+    for<'a> I::Item<'a>: Debug,
+{
+}
+
+fn main() {
+    let slice = &mut ();
+    //~^ temporary value dropped while borrowed
+    let windows = WindowsMut { slice };
+    print_items::<WindowsMut<'_>>(windows);
+}
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
new file mode 100644
index 00000000000..414999881d4
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
@@ -0,0 +1,20 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/hrtb-implied-1.rs:31:22
+   |
+LL |     let slice = &mut ();
+   |                      ^^ creates a temporary which is freed while still in use
+...
+LL |     print_items::<WindowsMut<'_>>(windows);
+   |     -------------------------------------- argument requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-implied-1.rs:26:26
+   |
+LL |     for<'a> I::Item<'a>: Debug,
+   |                          ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs
new file mode 100644
index 00000000000..8e6c5348e71
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs
@@ -0,0 +1,40 @@
+// check-fail
+// known-bug
+
+// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
+// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
+
+trait LendingIterator: Sized {
+    type Item<'a>
+    where
+        Self: 'a;
+    fn next(&mut self) -> Self::Item<'_>;
+}
+fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
+where
+    F: FnMut(I::Item<'_>),
+{
+    let mut iter2 = Eat(iter, f);
+    let _next = iter2.next();
+    //~^ borrowed data escapes
+    true
+}
+impl<I: LendingIterator> LendingIterator for &mut I {
+    type Item<'a> = I::Item<'a> where Self:'a;
+    fn next(&mut self) -> Self::Item<'_> {
+        (**self).next()
+    }
+}
+
+struct Eat<I, F>(I, F);
+impl<I: LendingIterator, F> Iterator for Eat<I, F>
+where
+    F: FnMut(I::Item<'_>),
+{
+    type Item = ();
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr
new file mode 100644
index 00000000000..1ee270398de
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr
@@ -0,0 +1,22 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/hrtb-implied-2.rs:18:17
+   |
+LL | fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
+   |                                 ----  - let's call the lifetime of this reference `'1`
+   |                                 |
+   |                                 `iter` is a reference that is only valid in the function body
+...
+LL |     let _next = iter2.next();
+   |                 ^^^^^^^^^^^^
+   |                 |
+   |                 `iter` escapes the function body here
+   |                 argument requires that `'1` must outlive `'static`
+   |
+   = note: requirement occurs because of a mutable reference to `Eat<&mut I, F>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+   = note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs
new file mode 100644
index 00000000000..bc9e6c8aea8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs
@@ -0,0 +1,23 @@
+trait LendingIterator {
+    type Item<'a>
+    where
+        Self: 'a;
+}
+
+impl LendingIterator for &str {
+    type Item<'a> = () where Self:'a;
+}
+
+fn trivial_bound<I>(_: I)
+where
+    I: LendingIterator,
+    for<'a> I::Item<'a>: Sized,
+{
+}
+
+fn fails(iter: &str) {
+    trivial_bound(iter);
+    //~^ borrowed data escapes
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr
new file mode 100644
index 00000000000..c67e02437cd
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr
@@ -0,0 +1,22 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/hrtb-implied-3.rs:19:5
+   |
+LL | fn fails(iter: &str) {
+   |          ----  - let's call the lifetime of this reference `'1`
+   |          |
+   |          `iter` is a reference that is only valid in the function body
+LL |     trivial_bound(iter);
+   |     ^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `iter` escapes the function body here
+   |     argument requires that `'1` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-implied-3.rs:14:26
+   |
+LL |     for<'a> I::Item<'a>: Sized,
+   |                          ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/generic-associated-types/trait-objects.extended.stderr b/src/test/ui/generic-associated-types/trait-objects.extended.stderr
index 086177cc106..45b64d2b024 100644
--- a/src/test/ui/generic-associated-types/trait-objects.extended.stderr
+++ b/src/test/ui/generic-associated-types/trait-objects.extended.stderr
@@ -11,6 +11,8 @@ LL |     x.size_hint().0
    |     |
    |     `x` escapes the function body here
    |     argument requires that `'1` must outlive `'static`
+   |
+   = note: due to current limitations in the borrow checker, this implies a `'static` lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr
index b4312091edb..31e11e12835 100644
--- a/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr
@@ -14,6 +14,12 @@ LL | fn give_some<'a>() {
    |              -- lifetime `'a` defined here
 LL |     want_hrtb::<&'a u32>()
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-just-for-static.rs:9:15
+   |
+LL |     where T : for<'a> Foo<&'a isize>
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of `Foo` is not general enough
   --> $DIR/hrtb-just-for-static.rs:30:5
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
index 1461e7fd2dd..5e75a4cc8af 100644
--- a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
@@ -46,6 +46,12 @@ LL | fn foo_hrtb_bar_not<'b, T>(mut t: T)
 ...
 LL |     foo_hrtb_bar_not(&mut t);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-perfect-forwarding.rs:37:8
+   |
+LL |     T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of `Bar` is not general enough
   --> $DIR/hrtb-perfect-forwarding.rs:43:5
diff --git a/src/test/ui/invalid/invalid-inline.rs b/src/test/ui/invalid/invalid-inline.rs
index 8aa8f99f522..2501b1e23f2 100644
--- a/src/test/ui/invalid/invalid-inline.rs
+++ b/src/test/ui/invalid/invalid-inline.rs
@@ -1,19 +1,14 @@
 #![allow(dead_code)]
 
-#[inline(please_no)] //~ ERROR invalid argument
-fn a() {
-}
-
 #[inline(please,no)] //~ ERROR expected one argument
-fn b() {
+fn a() {
 }
 
 #[inline()] //~ ERROR expected one argument
-fn c() {
+fn b() {
 }
 
 fn main() {
     a();
     b();
-    c();
 }
diff --git a/src/test/ui/invalid/invalid-inline.stderr b/src/test/ui/invalid/invalid-inline.stderr
index f3d04264197..7edbf936b1b 100644
--- a/src/test/ui/invalid/invalid-inline.stderr
+++ b/src/test/ui/invalid/invalid-inline.stderr
@@ -1,22 +1,15 @@
-error[E0535]: invalid argument
-  --> $DIR/invalid-inline.rs:3:10
-   |
-LL | #[inline(please_no)]
-   |          ^^^^^^^^^
-
 error[E0534]: expected one argument
-  --> $DIR/invalid-inline.rs:7:1
+  --> $DIR/invalid-inline.rs:3:1
    |
 LL | #[inline(please,no)]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0534]: expected one argument
-  --> $DIR/invalid-inline.rs:11:1
+  --> $DIR/invalid-inline.rs:7:1
    |
 LL | #[inline()]
    | ^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0534, E0535.
-For more information about an error, try `rustc --explain E0534`.
+For more information about this error, try `rustc --explain E0534`.
diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr
index c7601caacdc..73c772205c3 100644
--- a/src/test/ui/issues/issue-26217.stderr
+++ b/src/test/ui/issues/issue-26217.stderr
@@ -5,6 +5,12 @@ LL | fn bar<'a>() {
    |        -- lifetime `'a` defined here
 LL |     foo::<&'a i32>();
    |     ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/issue-26217.rs:1:30
+   |
+LL | fn foo<T>() where for<'a> T: 'a {}
+   |                              ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/let-else/const-fn.rs b/src/test/ui/let-else/const-fn.rs
new file mode 100644
index 00000000000..336b0b4b72a
--- /dev/null
+++ b/src/test/ui/let-else/const-fn.rs
@@ -0,0 +1,19 @@
+// run-pass
+// issue #101932
+
+#![cfg_attr(bootstrap, feature(let_else))]
+
+const fn foo(a: Option<i32>) -> i32 {
+    let Some(a) = a else {
+        return 42
+    };
+
+    a + 1
+}
+
+fn main() {
+    const A: i32 = foo(None);
+    const B: i32 = foo(Some(1));
+
+    println!("{} {}", A, B);
+}
diff --git a/src/test/ui/lexer/lex-emoji-identifiers.rs b/src/test/ui/lexer/lex-emoji-identifiers.rs
new file mode 100644
index 00000000000..91b5929c0fe
--- /dev/null
+++ b/src/test/ui/lexer/lex-emoji-identifiers.rs
@@ -0,0 +1,17 @@
+fn invalid_emoji_usages() {
+    let arrow↔️ = "basic emoji"; //~ ERROR: identifiers cannot contain emoji
+    // FIXME
+    let planet🪐 = "basic emoji"; //~ ERROR: unknown start of token
+    // FIXME
+    let wireless🛜 = "basic emoji"; //~ ERROR: unknown start of token
+    // FIXME
+    let key1️⃣ = "keycap sequence"; //~ ERROR: unknown start of token
+                                    //~^ WARN: identifier contains uncommon Unicode codepoints
+    let flag🇺🇳 = "flag sequence"; //~ ERROR: identifiers cannot contain emoji
+    let wales🏴 = "tag sequence"; //~ ERROR: identifiers cannot contain emoji
+    let folded🙏🏿 = "modifier sequence"; //~ ERROR: identifiers cannot contain emoji
+}
+
+fn main() {
+    invalid_emoji_usages();
+}
diff --git a/src/test/ui/lexer/lex-emoji-identifiers.stderr b/src/test/ui/lexer/lex-emoji-identifiers.stderr
new file mode 100644
index 00000000000..6237c5d0236
--- /dev/null
+++ b/src/test/ui/lexer/lex-emoji-identifiers.stderr
@@ -0,0 +1,52 @@
+error: unknown start of token: \u{1fa90}
+  --> $DIR/lex-emoji-identifiers.rs:4:15
+   |
+LL |     let planet🪐 = "basic emoji";
+   |               ^^
+
+error: unknown start of token: \u{1f6dc}
+  --> $DIR/lex-emoji-identifiers.rs:6:17
+   |
+LL |     let wireless🛜 = "basic emoji";
+   |                 ^^
+
+error: unknown start of token: \u{20e3}
+  --> $DIR/lex-emoji-identifiers.rs:8:14
+   |
+LL |     let key1️⃣ = "keycap sequence";
+   |             ^
+
+error: identifiers cannot contain emoji: `arrow↔️`
+  --> $DIR/lex-emoji-identifiers.rs:2:9
+   |
+LL |     let arrow↔️ = "basic emoji";
+   |         ^^^^^^
+
+error: identifiers cannot contain emoji: `flag🇺🇳`
+  --> $DIR/lex-emoji-identifiers.rs:10:9
+   |
+LL |     let flag🇺🇳 = "flag sequence";
+   |         ^^^^^^
+
+error: identifiers cannot contain emoji: `wales🏴`
+  --> $DIR/lex-emoji-identifiers.rs:11:9
+   |
+LL |     let wales🏴 = "tag sequence";
+   |         ^^^^^^^
+
+error: identifiers cannot contain emoji: `folded🙏🏿`
+  --> $DIR/lex-emoji-identifiers.rs:12:9
+   |
+LL |     let folded🙏🏿 = "modifier sequence";
+   |         ^^^^^^^^^^
+
+warning: identifier contains uncommon Unicode codepoints
+  --> $DIR/lex-emoji-identifiers.rs:8:9
+   |
+LL |     let key1️⃣ = "keycap sequence";
+   |         ^^^^
+   |
+   = note: `#[warn(uncommon_codepoints)]` on by default
+
+error: aborting due to 7 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr
index 61009da49ff..f5c10f3ddea 100644
--- a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr
+++ b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr
@@ -9,6 +9,12 @@ LL |     assert_static_via_hrtb(&local);
 LL |     assert_static_via_hrtb_with_assoc_type(&&local);
 LL | }
    | - `local` dropped here while still borrowed
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/local-outlives-static-via-hrtb.rs:15:53
+   |
+LL | fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {}
+   |                                                     ^^^^^^^^^^^^
 
 error[E0597]: `local` does not live long enough
   --> $DIR/local-outlives-static-via-hrtb.rs:25:45
@@ -20,6 +26,12 @@ LL |     assert_static_via_hrtb_with_assoc_type(&&local);
    |     argument requires that `local` is borrowed for `'static`
 LL | }
    | - `local` dropped here while still borrowed
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/local-outlives-static-via-hrtb.rs:19:20
+   |
+LL |     for<'a> &'a T: Reference<AssociatedType = &'a ()>,
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/type-test-universe.stderr b/src/test/ui/nll/type-test-universe.stderr
index 242486c360a..31e17d64b8c 100644
--- a/src/test/ui/nll/type-test-universe.stderr
+++ b/src/test/ui/nll/type-test-universe.stderr
@@ -11,6 +11,12 @@ LL | fn test2<'a>() {
    |          -- lifetime `'a` defined here
 LL |     outlives_forall::<Value<'a>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/type-test-universe.rs:6:16
+   |
+LL |     for<'u> T: 'u,
+   |                ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr
index f52c3f9f2c0..b1411bc436a 100644
--- a/src/test/ui/span/E0535.stderr
+++ b/src/test/ui/span/E0535.stderr
@@ -3,6 +3,8 @@ error[E0535]: invalid argument
    |
 LL | #[inline(unknown)]
    |          ^^^^^^^
+   |
+   = help: valid inline arguments are `always` and `never`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/issue-101623.rs b/src/test/ui/suggestions/issue-101623.rs
new file mode 100644
index 00000000000..d18a4a21f0a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101623.rs
@@ -0,0 +1,25 @@
+pub struct Stuff {
+    inner: *mut (),
+}
+
+pub struct Wrap<T>(T);
+
+fn fun<T>(t: T) -> Wrap<T> {
+    todo!()
+}
+
+pub trait Trait<'de> {
+    fn do_stuff(_: Wrap<&'de mut Self>);
+}
+
+impl<'a> Trait<'a> for () {
+    fn do_stuff(_: Wrap<&'a mut Self>) {}
+}
+
+fn fun2(t: &mut Stuff) -> () {
+    let Stuff { inner, .. } = t;
+    Trait::do_stuff({ fun(&mut *inner) });
+    //~^ ERROR the trait bound `*mut (): Trait<'_>` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-101623.stderr b/src/test/ui/suggestions/issue-101623.stderr
new file mode 100644
index 00000000000..361483cc08d
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101623.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `*mut (): Trait<'_>` is not satisfied
+  --> $DIR/issue-101623.rs:21:21
+   |
+LL |     Trait::do_stuff({ fun(&mut *inner) });
+   |     --------------- ^^----------------^^
+   |     |               |
+   |     |               the trait `Trait<'_>` is not implemented for `*mut ()`
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Trait<'a>` is implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
index 811832848d9..9a50c0f988a 100644
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
+++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
@@ -1,8 +1,9 @@
 // compile-flags: --edition=2021
+// check-pass
 #![feature(type_alias_impl_trait)]
 
 fn main() {
-    type T = impl Copy; //~ ERROR unconstrained opaque type
+    type T = impl Copy;
     let foo: T = (1u32, 2u32);
     let (a, b): (u32, u32) = foo;
 }
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr
deleted file mode 100644
index 03b172e6de5..00000000000
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
-  --> $DIR/cross_inference_pattern_bug.rs:5:14
-   |
-LL |     type T = impl Copy;
-   |              ^^^^^^^^^
-   |
-   = note: `T` must be used in combination with a concrete type within the same module
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
index 328096d44b4..b929122a6c2 100644
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
+++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
@@ -1,13 +1,13 @@
-// known-bug: #96572
 // compile-flags: --edition=2021 --crate-type=lib
 // rustc-env:RUST_BACKTRACE=0
+// check-pass
 
 // tracked in https://github.com/rust-lang/rust/issues/96572
 
 #![feature(type_alias_impl_trait)]
 
 fn main() {
-    type T = impl Copy;  // error: unconstrained opaque type
+    type T = impl Copy;
     let foo: T = (1u32, 2u32);
-    let (a, b) = foo; // removing this line makes the code compile
+    let (a, b) = foo; // this line used to make the code fail
 }
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr
deleted file mode 100644
index 8aa1f495639..00000000000
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
-  --> $DIR/cross_inference_pattern_bug_no_type.rs:10:14
-   |
-LL |     type T = impl Copy;  // error: unconstrained opaque type
-   |              ^^^^^^^^^
-   |
-   = note: `T` must be used in combination with a concrete type within the same module
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs
new file mode 100644
index 00000000000..825710851b0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {
+    type T = impl Copy;
+    let foo: T = Some((1u32, 2u32));
+    match foo {
+        None => (),
+        Some((a, b, c)) => (), //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr
new file mode 100644
index 00000000000..728244a1844
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-96572-unconstrained-mismatch.rs:8:14
+   |
+LL |     match foo {
+   |           --- this expression has type `T`
+LL |         None => (),
+LL |         Some((a, b, c)) => (),
+   |              ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected tuple `(u32, u32)`
+              found tuple `(_, _, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
new file mode 100644
index 00000000000..2c740ccc1ae
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
@@ -0,0 +1,92 @@
+#![feature(type_alias_impl_trait)]
+// check-pass
+
+fn main() {
+    type T = impl Copy;
+    let foo: T = Some((1u32, 2u32));
+    match foo {
+        None => (),
+        Some((a, b)) => (),
+    }
+}
+
+fn upvar() {
+    #[derive(Copy, Clone)]
+    struct Foo((u32, u32));
+
+    type T = impl Copy;
+    let foo: T = Foo((1u32, 2u32));
+    let x = move || {
+        let Foo((a, b)) = foo;
+    };
+}
+
+fn enum_upvar() {
+    type T = impl Copy;
+    let foo: T = Some((1u32, 2u32));
+    let x = move || {
+        match foo {
+            None => (),
+            Some((a, b)) => (),
+        }
+    };
+}
+
+fn r#struct() {
+    #[derive(Copy, Clone)]
+    struct Foo((u32, u32));
+
+    type U = impl Copy;
+    let foo: U = Foo((1u32, 2u32));
+    let Foo((a, b)) = foo;
+}
+
+mod only_pattern {
+    type T = impl Copy;
+
+    fn foo(foo: T) {
+        let (mut x, mut y) = foo;
+        x = 42;
+        y = "foo";
+    }
+
+    type U = impl Copy;
+
+    fn bar(bar: Option<U>) {
+        match bar {
+            Some((mut x, mut y)) => {
+                x = 42;
+                y = "foo";
+            }
+            None => {}
+        }
+    }
+}
+
+mod only_pattern_rpit {
+    #[allow(unconditional_recursion)]
+    fn foo(b: bool) -> impl Copy {
+        let (mut x, mut y) = foo(false);
+        x = 42;
+        y = "foo";
+        if b {
+            panic!()
+        } else {
+            foo(true)
+        }
+    }
+
+    fn bar(b: bool) -> Option<impl Copy> {
+        if b {
+            return None;
+        }
+        match bar(!b) {
+            Some((mut x, mut y)) => {
+                x = 42;
+                y = "foo";
+            }
+            None => {}
+        }
+        None
+    }
+}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 082503982ea0fb7a8fd72210427d43a2e2128a6
+Subproject 73ba3f35e0205844418260722c11602113179c4
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 88e28018e5d..45b5d79d445 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -20,7 +20,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{
-    self, subst::Subst, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
+    self, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
     ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
 };
 use rustc_semver::RustcVersion;
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 53bc617a4f5..598f8c31859 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -11,7 +11,6 @@ use rustc_hir::{Closure, Expr, ExprKind, Param, PatKind, Unsafety};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ClosureKind, Ty, TypeVisitable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index ef7d75aa8ed..eb2eefe0d5a 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,6 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{EarlyBinder, Opaque, PredicateKind::Trait};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 763bfafecef..8d3cede70f7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -1,6 +1,5 @@
 use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
-use crate::rustc_middle::ty::Subst;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 82dc03ef5c5..084c0d471dd 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use std::iter;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index b6d7d9f5b42..ae55a6bf558 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_c_void;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
 use rustc_span::DUMMY_SP;
 
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index e053708edd5..96c55111fba 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -9,7 +9,7 @@ use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind,
 use rustc_lint::LateContext;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
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 8835b932909..405f0228683 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
@@ -260,6 +260,7 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
                 }
             },
             ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Downcast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Deref
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index a8ad6cf4f6a..926ecf96593 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -12,7 +12,7 @@ use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{
     self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, ProjectionTy,
     Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr,
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index b07e80767fa..4cfb70fa31c 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -21,6 +21,12 @@ pub fn filter_dirs(path: &Path) -> bool {
         "src/tools/rust-installer",
         "src/tools/rustfmt",
         "src/doc/book",
+        "src/doc/edition-guide",
+        "src/doc/embedded-book",
+        "src/doc/nomicon",
+        "src/doc/rust-by-example",
+        "src/doc/rustc-dev-guide",
+        "src/doc/reference",
         // Filter RLS output directories
         "target/rls",
         "src/bootstrap/target",