diff --git a/RELEASES.md b/RELEASES.md
index 99733bade32c4..fe557a08a9dc0 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,119 @@
+Version 1.84.0 (2025-01-09)
+==========================
+
+<a id="
+Language"></a>
+
+Language
+--------
+- [Allow `#[deny]` inside `#[forbid]` as a no-op](https://github.com/rust-lang/rust/pull/121560/)
+- [Show a warning when `-Ctarget-feature` is used to toggle features that can lead to unsoundness due to ABI mismatches](https://github.com/rust-lang/rust/pull/129884)
+- [Use the next-generation trait solver in coherence](https://github.com/rust-lang/rust/pull/130654)
+- [Allow coercions to drop the principal of trait objects](https://github.com/rust-lang/rust/pull/131857)
+- [Support `/` as the path separator for `include!()` in all cases on Windows](https://github.com/rust-lang/rust/pull/125205)
+- [Taking a raw ref (`raw (const|mut)`) of a deref of a pointer (`*ptr`) is now safe](https://github.com/rust-lang/rust/pull/129248)
+- [Stabilize s390x inline assembly](https://github.com/rust-lang/rust/pull/131258)
+- [Stabilize Arm64EC inline assembly](https://github.com/rust-lang/rust/pull/131781)
+- [Lint against creating pointers to immediately dropped temporaries](https://github.com/rust-lang/rust/pull/128985)
+- [Execute drop glue when unwinding in an `extern "C"` function](https://github.com/rust-lang/rust/pull/129582)
+
+<a id="1.84.0-Compiler"></a>
+
+Compiler
+--------
+- [Add `--print host-tuple` flag to print the host target tuple and affirm the "target tuple" terminology over "target triple"](https://github.com/rust-lang/rust/pull/125579)
+- [Declaring functions with a calling convention not supported on the current target now triggers a hard error](https://github.com/rust-lang/rust/pull/129935)
+- [Set up indirect access to external data for `loongarch64-unknown-linux-{musl,ohos}`](https://github.com/rust-lang/rust/pull/131583)
+- [Enable XRay instrumentation for LoongArch Linux targets](https://github.com/rust-lang/rust/pull/131818)
+- [Extend the `unexpected_cfgs` lint to also warn in external macros](https://github.com/rust-lang/rust/pull/132577)
+- [Stabilize WebAssembly `multivalue`, `reference-types`, and `tail-call` target features](https://github.com/rust-lang/rust/pull/131080)
+- [Added Tier 2 support for the `wasm32v1-none` target](https://github.com/rust-lang/rust/pull/131487)
+
+<a id="1.84.0-Libraries"></a>
+
+Libraries
+---------
+- [Implement `From<&mut {slice}>` for `Box/Rc/Arc<{slice}>`](https://github.com/rust-lang/rust/pull/129329)
+- [Move `<float>::copysign`, `<float>::abs`, `<float>::signum` to `core`](https://github.com/rust-lang/rust/pull/131304)
+- [Add `LowerExp` and `UpperExp` implementations to `NonZero`](https://github.com/rust-lang/rust/pull/131377)
+- [Implement `FromStr` for `CString` and `TryFrom<CString>` for `String`](https://github.com/rust-lang/rust/pull/130608)
+- [`std::os::darwin` has been made public](https://github.com/rust-lang/rust/pull/130635)
+
+<a id="1.84.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`Ipv6Addr::is_unique_local`](https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.is_unique_local)
+- [`Ipv6Addr::is_unicast_link_local`](https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.is_unicast_link_local)
+- [`core::ptr::with_exposed_provenance`](https://doc.rust-lang.org/stable/core/ptr/fn.with_exposed_provenance.html)
+- [`core::ptr::with_exposed_provenance_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.with_exposed_provenance_mut.html)
+- [`<ptr>::addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.addr)
+- [`<ptr>::expose_provenance`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.expose_provenance)
+- [`<ptr>::with_addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.with_addr)
+- [`<ptr>::map_addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.map_addr)
+- [`<int>::isqrt`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.isqrt)
+- [`<int>::checked_isqrt`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.checked_isqrt)
+- [`<uint>::isqrt`](https://doc.rust-lang.org/stable/core/primitive.u32.html#method.isqrt)
+- [`NonZero::isqrt`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html#impl-NonZero%3Cu128%3E/method.isqrt)
+- [`core::ptr::without_provenance`](https://doc.rust-lang.org/stable/core/ptr/fn.without_provenance.html)
+- [`core::ptr::without_provenance_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.without_provenance_mut.html)
+- [`core::ptr::dangling`](https://doc.rust-lang.org/stable/core/ptr/fn.dangling.html)
+- [`core::ptr::dangling_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.dangling_mut.html)
+
+These APIs are now stable in const contexts
+
+- [`AtomicBool::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.from_ptr)
+- [`AtomicPtr::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicPtr.html#method.from_ptr)
+- [`AtomicU8::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU8.html#method.from_ptr)
+- [`AtomicU16::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU16.html#method.from_ptr)
+- [`AtomicU32::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.from_ptr)
+- [`AtomicU64::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU64.html#method.from_ptr)
+- [`AtomicUsize::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicUsize.html#method.from_ptr)
+- [`AtomicI8::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI8.html#method.from_ptr)
+- [`AtomicI16::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI16.html#method.from_ptr)
+- [`AtomicI32::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI32.html#method.from_ptr)
+- [`AtomicI64::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI64.html#method.from_ptr)
+- [`AtomicIsize::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicIsize.html#method.from_ptr)
+- [`<ptr>::is_null`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_null-1)
+- [`<ptr>::as_ref`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.as_ref-1)
+- [`<ptr>::as_mut`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.as_mut)
+- [`Pin::new`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.new)
+- [`Pin::new_unchecked`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.new_unchecked)
+- [`Pin::get_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_ref)
+- [`Pin::into_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.into_ref)
+- [`Pin::get_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_mut)
+- [`Pin::get_unchecked_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_unchecked_mut)
+- [`Pin::static_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.static_ref)
+- [`Pin::static_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.static_mut)
+
+<a id="1.84.0-Cargo"></a>
+
+Cargo
+-----
+- [Stabilize MSRV-aware resolver config](https://github.com/rust-lang/cargo/pull/14639/)
+- [Stabilize resolver v3](https://github.com/rust-lang/cargo/pull/14754/)
+
+<a id="1.84-Rustdoc"></a>
+
+Rustdoc
+-------
+
+- [rustdoc-search: improve type-driven search](https://github.com/rust-lang/rust/pull/127589)
+
+<a id="1.84.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+- [Enable by default the `LSX` target feature for LoongArch Linux targets](https://github.com/rust-lang/rust/pull/132140)
+- [The unstable `-Zprofile` flag (“gcov-style” coverage instrumentation) has been removed.](https://github.com/rust-lang/rust/pull/131829) This does not affect the stable flags for coverage instrumentation (`-Cinstrument-coverage`) and profile-guided optimization (`-Cprofile-generate`, `-Cprofile-use`), which are unrelated and remain available.
+- Support for the target named `wasm32-wasi` has been removed as the target is now named `wasm32-wasip1`. This completes the [transition](https://github.com/rust-lang/compiler-team/issues/607) [plan](https://github.com/rust-lang/compiler-team/issues/695) for this target following [the introduction of `wasm32-wasip1`](https://github.com/rust-lang/rust/pull/120468) in Rust 1.78. Compiler warnings on [use of `wasm32-wasi`](https://github.com/rust-lang/rust/pull/126662) introduced in Rust 1.81 are now gone as well as the target is removed.
+- [The syntax `&pin (mut|const) T` is now parsed as a type which in theory could affect macro expansion results in some edge cases](https://github.com/rust-lang/rust/pull/130635#issuecomment-2375462821)
+- [Legacy syntax for calling `std::arch` functions is no longer permitted to declare items or bodies (such as closures, inline consts, or async blocks).](https://github.com/rust-lang/rust/pull/130443#issuecomment-2445678945)
+- The `wasm32-unknown-emscripten` target's binary release of the standard library is now [built with the latest emsdk 3.1.68](https://github.com/rust-lang/rust/pull/131533), which fixes an ABI-incompatibility with Emscripten >= 3.1.42. If you are locally using a version of emsdk with an incompatible ABI (e.g. before 3.1.42 or a future one), you should build your code with `-Zbuild-std` to ensure that `std` uses the correct ABI.
+- [Declaring functions with a calling convention not supported on the current target now triggers a hard error](https://github.com/rust-lang/rust/pull/129935)
+- [The next-generation trait solver is now enabled for coherence, fixing multiple soundness issues](https://github.com/rust-lang/rust/pull/130654)
+
 Version 1.83.0 (2024-11-28)
 ==========================
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index e18e91e569f5e..c3d7c217861fb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -109,7 +109,10 @@ unsafe fn configure_llvm(sess: &Session) {
             add("-wasm-enable-eh", false);
         }
 
-        if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind {
+        if sess.target.os == "emscripten"
+            && !sess.opts.unstable_opts.emscripten_wasm_eh
+            && sess.panic_strategy() == PanicStrategy::Unwind
+        {
             add("-enable-emscripten-cxx-exceptions", false);
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 2587d6dfdc4b3..e4b3ad198018f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2451,10 +2451,12 @@ fn add_order_independent_options(
     }
 
     if sess.target.os == "emscripten" {
-        cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
-            "DISABLE_EXCEPTION_CATCHING=1"
+        cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
+            "-sDISABLE_EXCEPTION_CATCHING=1"
+        } else if sess.opts.unstable_opts.emscripten_wasm_eh {
+            "-fwasm-exceptions"
         } else {
-            "DISABLE_EXCEPTION_CATCHING=0"
+            "-sDISABLE_EXCEPTION_CATCHING=0"
         });
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 77e1fed720dfb..544578b29f107 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -388,7 +388,8 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 // exceptions. This means that the VM does the unwinding for
 // us
 pub fn wants_wasm_eh(sess: &Session) -> bool {
-    sess.target.is_like_wasm && sess.target.os != "emscripten"
+    sess.target.is_like_wasm
+        && (sess.target.os != "emscripten" || sess.opts.unstable_opts.emscripten_wasm_eh)
 }
 
 /// Returns `true` if this session's target will use SEH-based unwinding.
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 90f382e72268b..0413e5e86348b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -52,8 +52,8 @@ use rustc_metadata::locator;
 use rustc_middle::ty::TyCtxt;
 use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_session::config::{
-    CG_OPTIONS, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, Z_OPTIONS,
-    nightly_options,
+    CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions,
+    Z_OPTIONS, nightly_options,
 };
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
@@ -1124,14 +1124,6 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
         return true;
     }
 
-    if cg_flags.iter().any(|x| *x == "no-stack-check") {
-        early_dcx.early_warn("the `-Cno-stack-check` flag is deprecated and does nothing");
-    }
-
-    if cg_flags.iter().any(|x| x.starts_with("inline-threshold")) {
-        early_dcx.early_warn("the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)");
-    }
-
     if cg_flags.iter().any(|x| *x == "passes=list") {
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
 
@@ -1156,18 +1148,16 @@ fn describe_codegen_flags() {
     print_flag_list("-C", config::CG_OPTIONS);
 }
 
-fn print_flag_list<T>(
-    cmdline_opt: &str,
-    flag_list: &[(&'static str, T, &'static str, &'static str)],
-) {
-    let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
+fn print_flag_list<T>(cmdline_opt: &str, flag_list: &[OptionDesc<T>]) {
+    let max_len =
+        flag_list.iter().map(|opt_desc| opt_desc.name().chars().count()).max().unwrap_or(0);
 
-    for &(name, _, _, desc) in flag_list {
+    for opt_desc in flag_list {
         safe_println!(
             "    {} {:>width$}=val -- {}",
             cmdline_opt,
-            name.replace('_', "-"),
-            desc,
+            opt_desc.name().replace('_', "-"),
+            opt_desc.desc(),
             width = max_len
         );
     }
@@ -1221,8 +1211,8 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
         let msg: Option<String> = match e {
             getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
                 .iter()
-                .map(|&(name, ..)| ('C', name))
-                .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+                .map(|opt_desc| ('C', opt_desc.name()))
+                .chain(Z_OPTIONS.iter().map(|opt_desc| ('Z', opt_desc.name())))
                 .find(|&(_, name)| *opt == name.replace('_', "-"))
                 .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
             getopts::Fail::ArgumentMissing(ref opt) => {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 00bb4d6557906..5421517046d86 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -37,6 +37,7 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
     // this is consistent with naming of the compiler flag it's for
     (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
+    (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d40823d2ed627..8cc4c18c02abf 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -202,6 +202,8 @@ declare_features! (
     (internal, allow_internal_unstable, "1.0.0", None),
     /// Allows using anonymous lifetimes in argument-position impl-trait.
     (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
+    /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
+    (internal, cfg_emscripten_wasm_eh, "CURRENT_RUSTC_VERSION", None),
     /// Allows identifying the `compiler_builtins` crate.
     (internal, compiler_builtins, "1.13.0", None),
     /// Allows writing custom MIR
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 789530d35dd81..f4929aae59901 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -40,13 +40,25 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    /// FIXME: Move this check out of typeck, since it'll easily cycle when revealing opaques,
+    /// and we shouldn't need to check anything here if the typeck results are tainted.
     pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
         let tcx = self.tcx;
         let dl = &tcx.data_layout;
         let span = tcx.hir().span(hir_id);
         let normalize = |ty| {
             let ty = self.resolve_vars_if_possible(ty);
-            self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty)
+            if let Ok(ty) =
+                self.tcx.try_normalize_erasing_regions(self.typing_env(self.param_env), ty)
+            {
+                ty
+            } else {
+                Ty::new_error_with_message(
+                    tcx,
+                    span,
+                    "tried to normalize non-wf type in check_transmute",
+                )
+            }
         };
         let from = normalize(from);
         let to = normalize(to);
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0b008fd10b507..b4f1dcfb9cc8a 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items::LangItem;
@@ -690,6 +690,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
 
+            // Check if we wrote `Self::Assoc(1)` as if it were a tuple ctor.
+            if let SelfSource::QPath(ty) = source
+                && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+                && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res
+                && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id)
+                && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
+                    self.tcx,
+                    item_name,
+                    ty::AssocKind::Type,
+                    impl_def_id,
+                )
+                && let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
+                && adt_def.is_struct()
+                && adt_def.non_enum_variant().ctor_kind() == Some(CtorKind::Fn)
+            {
+                let def_path = tcx.def_path_str(adt_def.did());
+                err.span_suggestion(
+                    ty.span.to(item_name.span),
+                    format!("to construct a value of type `{}`, use the explicit path", def_path),
+                    def_path,
+                    Applicability::MachineApplicable,
+                );
+            }
+
             err
         };
         if tcx.sess.source_map().is_multiline(sugg_span) {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 9ad690399140e..53d7c84ac3f8f 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -582,6 +582,7 @@ fn test_codegen_options_tracking_hash() {
     untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
     untracked!(extra_filename, String::from("extra-filename"));
     untracked!(incremental, Some(String::from("abc")));
+    untracked!(inline_threshold, Some(0xf007ba11));
     // `link_arg` is omitted because it just forwards to `link_args`.
     untracked!(link_args, vec![String::from("abc"), String::from("def")]);
     untracked!(link_self_contained, LinkSelfContained::on());
@@ -613,7 +614,6 @@ fn test_codegen_options_tracking_hash() {
     tracked!(embed_bitcode, false);
     tracked!(force_frame_pointers, FramePointer::Always);
     tracked!(force_unwind_tables, Some(true));
-    tracked!(inline_threshold, Some(0xf007ba11));
     tracked!(instrument_coverage, InstrumentCoverage::Yes);
     tracked!(link_dead_code, Some(true));
     tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
@@ -782,6 +782,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(dwarf_version, Some(5));
     tracked!(embed_source, true);
     tracked!(emit_thin_lto, false);
+    tracked!(emscripten_wasm_eh, true);
     tracked!(export_executable_symbols, true);
     tracked!(fewer_names, Some(true));
     tracked!(fixed_x18, true);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 99211c1f92440..db2bb8a7248a6 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -125,6 +125,15 @@ impl<'tcx> ObligationCause<'tcx> {
         self
     }
 
+    pub fn derived_host_cause(
+        mut self,
+        parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+        variant: impl FnOnce(DerivedHostCause<'tcx>) -> ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx> {
+        self.code = variant(DerivedHostCause { parent_host_pred, parent_code: self.code }).into();
+        self
+    }
+
     pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
         match self.code() {
             ObligationCauseCode::MatchImpl(cause, _) => cause.to_constraint_category(),
@@ -278,6 +287,14 @@ pub enum ObligationCauseCode<'tcx> {
     /// Derived obligation for WF goals.
     WellFormedDerived(DerivedCause<'tcx>),
 
+    /// Derived obligation (i.e. `where` clause) on an user-provided impl
+    /// or a trait alias.
+    ImplDerivedHost(Box<ImplDerivedHostCause<'tcx>>),
+
+    /// Derived obligation (i.e. `where` clause) on an user-provided impl
+    /// or a trait alias.
+    BuiltinDerivedHost(DerivedHostCause<'tcx>),
+
     /// Derived obligation refined to point at a specific argument in
     /// a call or method expression.
     FunctionArg {
@@ -437,36 +454,38 @@ pub enum WellFormedLoc {
     },
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-#[derive(TypeVisitable, TypeFoldable)]
-pub struct ImplDerivedCause<'tcx> {
-    pub derived: DerivedCause<'tcx>,
-    /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
-    /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
-    /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
-    /// that exceptional case where appropriate.
-    pub impl_or_alias_def_id: DefId,
-    /// The index of the derived predicate in the parent impl's predicates.
-    pub impl_def_predicate_index: Option<usize>,
-    pub span: Span,
-}
-
 impl<'tcx> ObligationCauseCode<'tcx> {
     /// Returns the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
         let mut base_cause = self;
-        while let Some((parent_code, _)) = base_cause.parent() {
+        while let Some(parent_code) = base_cause.parent() {
             base_cause = parent_code;
         }
         base_cause
     }
 
+    pub fn parent(&self) -> Option<&Self> {
+        match self {
+            ObligationCauseCode::FunctionArg { parent_code, .. } => Some(parent_code),
+            ObligationCauseCode::BuiltinDerived(derived)
+            | ObligationCauseCode::WellFormedDerived(derived)
+            | ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => {
+                Some(&derived.parent_code)
+            }
+            ObligationCauseCode::BuiltinDerivedHost(derived)
+            | ObligationCauseCode::ImplDerivedHost(box ImplDerivedHostCause { derived, .. }) => {
+                Some(&derived.parent_code)
+            }
+            _ => None,
+        }
+    }
+
     /// Returns the base obligation and the base trait predicate, if any, ignoring
     /// derived obligations.
     pub fn peel_derives_with_predicate(&self) -> (&Self, Option<ty::PolyTraitPredicate<'tcx>>) {
         let mut base_cause = self;
         let mut base_trait_pred = None;
-        while let Some((parent_code, parent_pred)) = base_cause.parent() {
+        while let Some((parent_code, parent_pred)) = base_cause.parent_with_predicate() {
             base_cause = parent_code;
             if let Some(parent_pred) = parent_pred {
                 base_trait_pred = Some(parent_pred);
@@ -476,7 +495,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
         (base_cause, base_trait_pred)
     }
 
-    pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
+    pub fn parent_with_predicate(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
         match self {
             ObligationCauseCode::FunctionArg { parent_code, .. } => Some((parent_code, None)),
             ObligationCauseCode::BuiltinDerived(derived)
@@ -573,6 +592,42 @@ pub struct DerivedCause<'tcx> {
     pub parent_code: InternedObligationCauseCode<'tcx>,
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct ImplDerivedCause<'tcx> {
+    pub derived: DerivedCause<'tcx>,
+    /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+    /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
+    /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
+    /// that exceptional case where appropriate.
+    pub impl_or_alias_def_id: DefId,
+    /// The index of the derived predicate in the parent impl's predicates.
+    pub impl_def_predicate_index: Option<usize>,
+    pub span: Span,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct DerivedHostCause<'tcx> {
+    /// The trait predicate of the parent obligation that led to the
+    /// current obligation. Note that only trait obligations lead to
+    /// derived obligations, so we just store the trait predicate here
+    /// directly.
+    pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+
+    /// The parent trait had this cause.
+    pub parent_code: InternedObligationCauseCode<'tcx>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct ImplDerivedHostCause<'tcx> {
+    pub derived: DerivedHostCause<'tcx>,
+    /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+    pub impl_def_id: DefId,
+    pub span: Span,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
 pub enum SelectionError<'tcx> {
     /// The trait is not implemented.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5e929fbec0bf8..2d69386176b80 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `arg` is
     /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).instantiate(tcx, arg)
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).instantiate(tcx, args)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 3ecaa3e22d39c..32d6455e82557 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -634,6 +634,28 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'t
     }
 }
 
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
+    for Predicate<'tcx>
+{
+    fn upcast_from(
+        from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+        tcx: TyCtxt<'tcx>,
+    ) -> Self {
+        from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
+    }
+}
+
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
+    for Clause<'tcx>
+{
+    fn upcast_from(
+        from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+        tcx: TyCtxt<'tcx>,
+    ) -> Self {
+        from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
+    }
+}
+
 impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
     fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
         PredicateKind::NormalizesTo(from).upcast(tcx)
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7da4f5e010754..3c5d9b95e772d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
     }
 }
 
+// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
+// the old solver, for as long as that exists.
 pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
     cx: I,
     self_ty: I::Ty,
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index ce7552e30f0fe..7669a305d58d1 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -103,7 +103,7 @@ where
                 |ecx| {
                     // Const conditions must hold for the implied const bound to hold.
                     ecx.add_goals(
-                        GoalSource::Misc,
+                        GoalSource::AliasBoundConstCondition,
                         cx.const_conditions(alias_ty.def_id)
                             .iter_instantiated(cx, alias_ty.args)
                             .map(|trait_ref| {
@@ -353,7 +353,7 @@ where
 
         ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
             ecx.add_goals(
-                GoalSource::Misc,
+                GoalSource::AliasBoundConstCondition,
                 const_conditions.into_iter().map(|trait_ref| {
                     goal.with(
                         cx,
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 020128f29c59b..701f500e4f60b 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -26,7 +26,10 @@ pub(crate) fn check_crate(
     if items.eh_personality().is_none() {
         items.missing.push(LangItem::EhPersonality);
     }
-    if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() {
+    if tcx.sess.target.os == "emscripten"
+        && items.eh_catch_typeinfo().is_none()
+        && !tcx.sess.opts.unstable_opts.emscripten_wasm_eh
+    {
         items.missing.push(LangItem::EhCatchTypeinfo);
     }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 5c36c98649020..683993095c51b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2678,7 +2678,14 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib" => CrateType::Cdylib,
                 "bin" => CrateType::Executable,
                 "proc-macro" => CrateType::ProcMacro,
-                _ => return Err(format!("unknown crate type: `{part}`")),
+                _ => {
+                    return Err(format!(
+                        "unknown crate type: `{part}`, expected one of: {display}",
+                        display =
+                            ["lib", "rlib", "staticlib", "dylib", "cdylib", "bin", "proc-macro"]
+                                .join(", ")
+                    ));
+                }
             };
             if !crate_types.contains(&new_part) {
                 crate_types.push(new_part)
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index b68dfeffa3451..d586f913335e0 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -143,6 +143,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
             | (sym::target_has_atomic_load_store, Some(_))
             | (sym::target_thread_local, None) => disallow(cfg, "--target"),
             (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
+            (sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),
             _ => {}
         }
     }
@@ -295,6 +296,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
         ins_none!(sym::ub_checks);
     }
 
+    // Nightly-only implementation detail for the `panic_unwind` and `unwind` crates.
+    if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh {
+        ins_none!(sym::emscripten_wasm_eh);
+    }
     ret
 }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3772a4a08af01..c1fba4c513da5 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -239,7 +239,8 @@ macro_rules! options {
         $init:expr,
         $parse:ident,
         [$dep_tracking_marker:ident],
-        $desc:expr)
+        $desc:expr
+        $(, deprecated_do_nothing: $dnn:literal )?)
      ),* ,) =>
 (
     #[derive(Clone)]
@@ -280,7 +281,8 @@ macro_rules! options {
     }
 
     pub const $stat: OptionDescrs<$struct_name> =
-        &[ $( (stringify!($opt), $optmod::$opt, desc::$parse, $desc) ),* ];
+        &[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt,
+            type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )? } ),* ];
 
     mod $optmod {
     $(
@@ -315,7 +317,27 @@ macro_rules! redirect_field {
 }
 
 type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
-type OptionDescrs<O> = &'static [(&'static str, OptionSetter<O>, &'static str, &'static str)];
+type OptionDescrs<O> = &'static [OptionDesc<O>];
+
+pub struct OptionDesc<O> {
+    name: &'static str,
+    setter: OptionSetter<O>,
+    // description for return value/type from mod desc
+    type_desc: &'static str,
+    // description for option from options table
+    desc: &'static str,
+    is_deprecated_and_do_nothing: bool,
+}
+
+impl<O> OptionDesc<O> {
+    pub fn name(&self) -> &'static str {
+        self.name
+    }
+
+    pub fn desc(&self) -> &'static str {
+        self.desc
+    }
+}
 
 #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn build_options<O: Default>(
@@ -333,8 +355,13 @@ fn build_options<O: Default>(
         };
 
         let option_to_lookup = key.replace('-', "_");
-        match descrs.iter().find(|(name, ..)| *name == option_to_lookup) {
-            Some((_, setter, type_desc, _)) => {
+        match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) {
+            Some(OptionDesc { name: _, setter, type_desc, desc, is_deprecated_and_do_nothing }) => {
+                if *is_deprecated_and_do_nothing {
+                    // deprecation works for prefixed options only
+                    assert!(!prefix.is_empty());
+                    early_dcx.early_warn(format!("`-{prefix} {key}`: {desc}"));
+                }
                 if !setter(&mut op, value) {
                     match value {
                         None => early_dcx.early_fatal(
@@ -1546,7 +1573,8 @@ options! {
     // tidy-alphabetical-start
     #[rustc_lint_opt_deny_field_access("documented to do nothing")]
     ar: String = (String::new(), parse_string, [UNTRACKED],
-        "this option is deprecated and does nothing"),
+        "this option is deprecated and does nothing",
+        deprecated_do_nothing: true),
     #[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")]
     code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
         "choose the code model to use (`rustc --print code-models` for details)"),
@@ -1578,9 +1606,10 @@ options! {
     incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
         "enable incremental compilation"),
     #[rustc_lint_opt_deny_field_access("documented to do nothing")]
-    inline_threshold: Option<u32> = (None, parse_opt_number, [TRACKED],
+    inline_threshold: Option<u32> = (None, parse_opt_number, [UNTRACKED],
         "this option is deprecated and does nothing \
-        (consider using `-Cllvm-args=--inline-threshold=...`)"),
+        (consider using `-Cllvm-args=--inline-threshold=...`)",
+        deprecated_do_nothing: true),
     #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
     instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
         "instrument the generated code to support LLVM source-based code coverage reports \
@@ -1616,7 +1645,8 @@ options! {
         "disable the use of the redzone"),
     #[rustc_lint_opt_deny_field_access("documented to do nothing")]
     no_stack_check: bool = (false, parse_no_value, [UNTRACKED],
-        "this option is deprecated and does nothing"),
+        "this option is deprecated and does nothing",
+        deprecated_do_nothing: true),
     no_vectorize_loops: bool = (false, parse_no_value, [TRACKED],
         "disable loop vectorization optimization passes"),
     no_vectorize_slp: bool = (false, parse_no_value, [TRACKED],
@@ -1771,6 +1801,8 @@ options! {
         "emit a section containing stack size metadata (default: no)"),
     emit_thin_lto: bool = (true, parse_bool, [TRACKED],
         "emit the bc module with thin LTO info (default: yes)"),
+    emscripten_wasm_eh: bool = (false, parse_bool, [TRACKED],
+        "Use WebAssembly error handling for wasm32-unknown-emscripten"),
     enforce_type_length_limit: bool = (false, parse_bool, [TRACKED],
         "enforce the type length limit when monomorphizing instances in codegen"),
     export_executable_symbols: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bdfbfb1e38dd3..0dcf38e349365 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -570,6 +570,7 @@ symbols! {
         cfg_autodiff_fallback,
         cfg_boolean_literals,
         cfg_doctest,
+        cfg_emscripten_wasm_eh,
         cfg_eval,
         cfg_fmt_debug,
         cfg_hide,
@@ -823,6 +824,7 @@ symbols! {
         emit_enum_variant_arg,
         emit_struct,
         emit_struct_field,
+        emscripten_wasm_eh,
         enable,
         encode,
         end,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 14639039ae946..7ba87e180d0bc 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -737,7 +737,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     applied_do_not_recommend = true;
                 }
             }
-            if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
+            if let Some(parent_cause) = base_cause.parent() {
                 base_cause = parent_cause.clone();
             } else {
                 break;
@@ -797,7 +797,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
             && !found_kind.extends(expected_kind)
         {
-            if let Some((_, Some(parent))) = obligation.cause.code().parent() {
+            if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() {
                 // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
                 trait_ref = parent.to_poly_trait_ref();
             } else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
@@ -945,7 +945,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let Some(typeck) = &self.typeck_results else {
             return false;
         };
-        let Some((ObligationCauseCode::QuestionMark, Some(y))) = obligation.cause.code().parent()
+        let Some((ObligationCauseCode::QuestionMark, Some(y))) =
+            obligation.cause.code().parent_with_predicate()
         else {
             return false;
         };
@@ -1198,7 +1199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let mut code = obligation.cause.code();
         let mut pred = obligation.predicate.as_trait_clause();
-        while let Some((next_code, next_pred)) = code.parent() {
+        while let Some((next_code, next_pred)) = code.parent_with_predicate() {
             if let Some(pred) = pred {
                 self.enter_forall(pred, |pred| {
                     diag.note(format!(
@@ -2114,7 +2115,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let mut code = obligation.cause.code();
         let mut trait_pred = trait_predicate;
         let mut peeled = false;
-        while let Some((parent_code, parent_trait_pred)) = code.parent() {
+        while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
             code = parent_code;
             if let Some(parent_trait_pred) = parent_trait_pred {
                 trait_pred = parent_trait_pred;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 007a220ae697f..9d85ca1dd4dd7 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -464,7 +464,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
             // Get the root obligation, since the leaf obligation we have may be unhelpful (#87437)
             let mut real_trait_pred = trait_pred;
-            while let Some((parent_code, parent_trait_pred)) = code.parent() {
+            while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
                 code = parent_code;
                 if let Some(parent_trait_pred) = parent_trait_pred {
                     real_trait_pred = parent_trait_pred;
@@ -1447,7 +1447,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let mut span = obligation.cause.span;
         let mut trait_pred = trait_pred;
         let mut code = obligation.cause.code();
-        while let Some((c, Some(parent_trait_pred))) = code.parent() {
+        while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
             // We want the root obligation, in order to detect properly handle
             // `for _ in &mut &mut vec![] {}`.
             code = c;
@@ -3470,6 +3470,59 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     )
                 });
             }
+            ObligationCauseCode::ImplDerivedHost(ref data) => {
+                let self_ty =
+                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty());
+                let msg = format!(
+                    "required for `{self_ty}` to implement `{} {}`",
+                    data.derived.parent_host_pred.skip_binder().constness,
+                    data.derived
+                        .parent_host_pred
+                        .map_bound(|pred| pred.trait_ref)
+                        .print_only_trait_path(),
+                );
+                match tcx.hir().get_if_local(data.impl_def_id) {
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                        ..
+                    })) => {
+                        let mut spans = vec![self_ty.span];
+                        spans.extend(of_trait.as_ref().map(|t| t.path.span));
+                        let mut spans: MultiSpan = spans.into();
+                        spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
+                        err.span_note(spans, msg);
+                    }
+                    _ => {
+                        err.note(msg);
+                    }
+                }
+                ensure_sufficient_stack(|| {
+                    self.note_obligation_cause_code(
+                        body_id,
+                        err,
+                        data.derived.parent_host_pred,
+                        param_env,
+                        &data.derived.parent_code,
+                        obligated_types,
+                        seen_requirements,
+                        long_ty_file,
+                    )
+                });
+            }
+            ObligationCauseCode::BuiltinDerivedHost(ref data) => {
+                ensure_sufficient_stack(|| {
+                    self.note_obligation_cause_code(
+                        body_id,
+                        err,
+                        data.parent_host_pred,
+                        param_env,
+                        &data.parent_code,
+                        obligated_types,
+                        seen_requirements,
+                        long_ty_file,
+                    )
+                });
+            }
             ObligationCauseCode::WellFormedDerived(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
                 let parent_predicate = parent_trait_ref;
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index c79a8abca2049..7db0f2bb5a7cc 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -430,6 +430,7 @@ impl<'tcx> BestObligation<'tcx> {
                                     matches!(
                                         nested_goal.source(),
                                         GoalSource::ImplWhereBound
+                                            | GoalSource::AliasBoundConstCondition
                                             | GoalSource::InstantiateHigherRanked
                                             | GoalSource::AliasWellFormed
                                     ) && match self.consider_ambiguities {
@@ -491,8 +492,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         // for normalizes-to.
         let pred_kind = goal.goal().predicate.kind();
         let child_mode = match pred_kind.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
-                ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
+            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                ChildMode::Trait(pred_kind.rebind(pred))
+            }
+            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => {
+                ChildMode::Host(pred_kind.rebind(pred))
             }
             ty::PredicateKind::NormalizesTo(normalizes_to)
                 if matches!(
@@ -521,7 +525,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
 
             let obligation;
             match (child_mode, nested_goal.source()) {
-                (ChildMode::Trait(_), GoalSource::Misc) => {
+                (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => {
                     continue;
                 }
                 (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
@@ -534,11 +538,25 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                     ));
                     impl_where_bound_count += 1;
                 }
+                (
+                    ChildMode::Host(parent_host_pred),
+                    GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
+                ) => {
+                    obligation = make_obligation(derive_host_cause(
+                        tcx,
+                        candidate.kind(),
+                        self.obligation.cause.clone(),
+                        impl_where_bound_count,
+                        parent_host_pred,
+                    ));
+                    impl_where_bound_count += 1;
+                }
                 // Skip over a higher-ranked predicate.
                 (_, GoalSource::InstantiateHigherRanked) => {
                     obligation = self.obligation.clone();
                 }
-                (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
+                (ChildMode::PassThrough, _)
+                | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
                     obligation = make_obligation(self.obligation.cause.clone());
                 }
             }
@@ -592,6 +610,10 @@ enum ChildMode<'tcx> {
     // and skip all `GoalSource::Misc`, which represent useless obligations
     // such as alias-eq which may not hold.
     Trait(ty::PolyTraitPredicate<'tcx>),
+    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
+    // and skip all `GoalSource::Misc`, which represent useless obligations
+    // such as alias-eq which may not hold.
+    Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>),
     // Skip trying to derive an `ObligationCause` from this obligation, and
     // report *all* sub-obligations as if they came directly from the parent
     // obligation.
@@ -633,3 +655,52 @@ fn derive_cause<'tcx>(
     };
     cause
 }
+
+fn derive_host_cause<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
+    mut cause: ObligationCause<'tcx>,
+    idx: usize,
+    parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+) -> ObligationCause<'tcx> {
+    match candidate_kind {
+        inspect::ProbeKind::TraitCandidate {
+            source: CandidateSource::Impl(impl_def_id),
+            result: _,
+        } => {
+            if let Some((_, span)) = tcx
+                .predicates_of(impl_def_id)
+                .instantiate_identity(tcx)
+                .into_iter()
+                .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
+                    |(trait_ref, span)| {
+                        (
+                            trait_ref.to_host_effect_clause(
+                                tcx,
+                                parent_host_pred.skip_binder().constness,
+                            ),
+                            span,
+                        )
+                    },
+                ))
+                .nth(idx)
+            {
+                cause =
+                    cause.derived_host_cause(parent_host_pred, |derived| {
+                        ObligationCauseCode::ImplDerivedHost(Box::new(
+                            traits::ImplDerivedHostCause { derived, impl_def_id, span },
+                        ))
+                    })
+            }
+        }
+        inspect::ProbeKind::TraitCandidate {
+            source: CandidateSource::BuiltinImpl(..),
+            result: _,
+        } => {
+            cause =
+                cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost);
+        }
+        _ => {}
+    };
+    cause
+}
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 91484ef99dbb8..b32909efe0be7 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,6 +1,8 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
-use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
+use rustc_infer::traits::{
+    ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
+};
 use rustc_middle::span_bug;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, TypingMode};
@@ -46,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
         Err(EvaluationFailure::NoSolution) => {}
     }
 
+    match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
     match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
         Ok(result) => return Ok(result),
         Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -226,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
     }
 }
 
+fn evaluate_host_effect_from_builtin_impls<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
+        Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+        _ => Err(EvaluationFailure::NoSolution),
+    }
+}
+
+// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
+fn evaluate_host_effect_for_destruct_goal<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
+    let self_ty = obligation.predicate.self_ty();
+
+    let const_conditions = match *self_ty.kind() {
+        // An ADT is `~const Destruct` only if all of the fields are,
+        // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
+        ty::Adt(adt_def, args) => {
+            let mut const_conditions: ThinVec<_> = adt_def
+                .all_fields()
+                .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
+                .collect();
+            match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+                // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
+                Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
+                // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
+                Some(hir::Constness::Const) => {
+                    let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
+                    let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
+                    const_conditions.push(drop_trait_ref);
+                }
+                // No `Drop` impl, no need to require anything else.
+                None => {}
+            }
+            const_conditions
+        }
+
+        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
+            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
+        }
+
+        ty::Tuple(tys) => {
+            tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
+        }
+
+        // Trivially implement `~const Destruct`
+        ty::Bool
+        | ty::Char
+        | ty::Int(..)
+        | ty::Uint(..)
+        | ty::Float(..)
+        | ty::Str
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(..)
+        | ty::Never
+        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+        | ty::Error(_) => thin_vec![],
+
+        // Coroutines and closures could implement `~const Drop`,
+        // but they don't really need to right now.
+        ty::Closure(_, _)
+        | ty::CoroutineClosure(_, _)
+        | ty::Coroutine(_, _)
+        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+
+        // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
+        // if their inner type implements it.
+        ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
+
+        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
+
+        ty::Bound(..)
+        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            panic!("unexpected type `{self_ty:?}`")
+        }
+    };
+
+    Ok(const_conditions
+        .into_iter()
+        .map(|trait_ref| {
+            obligation.with(
+                tcx,
+                ty::Binder::dummy(trait_ref)
+                    .to_host_effect_clause(tcx, obligation.predicate.constness),
+            )
+        })
+        .collect())
+}
+
 fn evaluate_host_effect_from_selection_candiate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &HostEffectObligation<'tcx>,
@@ -248,9 +354,22 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
                         tcx.const_conditions(impl_.impl_def_id)
                             .instantiate(tcx, impl_.args)
                             .into_iter()
-                            .map(|(trait_ref, _)| {
-                                obligation.with(
+                            .map(|(trait_ref, span)| {
+                                Obligation::new(
                                     tcx,
+                                    obligation.cause.clone().derived_host_cause(
+                                        ty::Binder::dummy(obligation.predicate),
+                                        |derived| {
+                                            ObligationCauseCode::ImplDerivedHost(Box::new(
+                                                ImplDerivedHostCause {
+                                                    derived,
+                                                    impl_def_id: impl_.impl_def_id,
+                                                    span,
+                                                },
+                                            ))
+                                        },
+                                    ),
+                                    obligation.param_env,
                                     trait_ref
                                         .to_host_effect_clause(tcx, obligation.predicate.constness),
                                 )
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 47447af22158d..cb59bc608c203 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -89,6 +89,7 @@ impl_binder_encode_decode! {
     ty::ExistentialPredicate<I>,
     ty::TraitRef<I>,
     ty::ExistentialTraitRef<I>,
+    ty::HostEffectPredicate<I>,
 }
 
 impl<I: Interner, T> Binder<I, T>
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 8fe512026e5d9..1ae904d50e066 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -68,6 +68,10 @@ pub enum GoalSource {
     /// FIXME(-Znext-solver=coinductive): Explain how and why this
     /// changes whether cycles are coinductive.
     ImplWhereBound,
+    /// Const conditions that need to hold for `~const` alias bounds to hold.
+    ///
+    /// FIXME(-Znext-solver=coinductive): Are these even coinductive?
+    AliasBoundConstCondition,
     /// Instantiating a higher-ranked goal and re-proving it.
     InstantiateHigherRanked,
     /// Predicate required for an alias projection to be well-formed.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index c2c78dd9c67eb..a033b8bd30514 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -596,7 +596,7 @@ impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
     #[inline]
-    pub fn new_v1<const P: usize, const A: usize>(
+    pub const fn new_v1<const P: usize, const A: usize>(
         pieces: &'a [&'static str; P],
         args: &'a [rt::Argument<'a>; A],
     ) -> Arguments<'a> {
@@ -612,7 +612,7 @@ impl<'a> Arguments<'a> {
     /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
     /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
     #[inline]
-    pub fn new_v1_formatted(
+    pub const fn new_v1_formatted(
         pieces: &'a [&'static str],
         args: &'a [rt::Argument<'a>],
         fmt: &'a [rt::Placeholder],
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 94341a4da66cd..85d089a079082 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -96,12 +96,12 @@ pub struct Argument<'a> {
 #[rustc_diagnostic_item = "ArgumentMethods"]
 impl Argument<'_> {
     #[inline]
-    fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
+    const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
         Argument {
             // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
             // a `fn(&T, ...)`, so the invariant is maintained.
             ty: ArgumentType::Placeholder {
-                value: NonNull::from(x).cast(),
+                value: NonNull::from_ref(x).cast(),
                 // SAFETY: function pointers always have the same layout.
                 formatter: unsafe { mem::transmute(f) },
                 _lifetime: PhantomData,
@@ -150,7 +150,7 @@ impl Argument<'_> {
         Self::new(x, UpperExp::fmt)
     }
     #[inline]
-    pub fn from_usize(x: &usize) -> Argument<'_> {
+    pub const fn from_usize(x: &usize) -> Argument<'_> {
         Argument { ty: ArgumentType::Count(*x) }
     }
 
@@ -181,7 +181,7 @@ impl Argument<'_> {
     }
 
     #[inline]
-    pub(super) fn as_usize(&self) -> Option<usize> {
+    pub(super) const fn as_usize(&self) -> Option<usize> {
         match self.ty {
             ArgumentType::Count(count) => Some(count),
             ArgumentType::Placeholder { .. } => None,
@@ -199,7 +199,7 @@ impl Argument<'_> {
     /// println!("{f}");
     /// ```
     #[inline]
-    pub fn none() -> [Self; 0] {
+    pub const fn none() -> [Self; 0] {
         []
     }
 }
@@ -216,7 +216,7 @@ impl UnsafeArg {
     /// See documentation where `UnsafeArg` is required to know when it is safe to
     /// create and use `UnsafeArg`.
     #[inline]
-    pub unsafe fn new() -> Self {
+    pub const unsafe fn new() -> Self {
         Self { _private: () }
     }
 }
diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml
index 252f118fecfbb..c2abb79192e9f 100644
--- a/library/panic_unwind/Cargo.toml
+++ b/library/panic_unwind/Cargo.toml
@@ -23,4 +23,4 @@ libc = { version = "0.2", default-features = false }
 
 [lints.rust.unexpected_cfgs]
 level = "warn"
-check-cfg = []
+check-cfg = ['cfg(emscripten_wasm_eh)']
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 8c28bb5c5b033..dc78be76cb4d5 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -25,13 +25,14 @@
 // `real_imp` is unused with Miri, so silence warnings.
 #![cfg_attr(miri, allow(dead_code))]
 #![allow(internal_features)]
+#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
 
 use alloc::boxed::Box;
 use core::any::Any;
 use core::panic::PanicPayload;
 
 cfg_if::cfg_if! {
-    if #[cfg(target_os = "emscripten")] {
+    if #[cfg(all(target_os = "emscripten", not(emscripten_wasm_eh)))] {
         #[path = "emcc.rs"]
         mod imp;
     } else if #[cfg(target_os = "hermit")] {
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml
index e13c9a06c05d1..66e8d1a3ffe5f 100644
--- a/library/unwind/Cargo.toml
+++ b/library/unwind/Cargo.toml
@@ -37,4 +37,4 @@ system-llvm-libunwind = []
 
 [lints.rust.unexpected_cfgs]
 level = "warn"
-check-cfg = []
+check-cfg = ['cfg(emscripten_wasm_eh)']
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 7af1882ab73a9..e4ba2bc1ed874 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -4,10 +4,11 @@
 #![feature(staged_api)]
 #![cfg_attr(not(target_env = "msvc"), feature(libc))]
 #![cfg_attr(
-    all(target_family = "wasm", not(target_os = "emscripten")),
+    all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
     feature(simd_wasm64, wasm_exception_handling_intrinsics)
 )]
 #![allow(internal_features)]
+#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
 
 // Force libc to be included even if unused. This is required by many platforms.
 #[cfg(not(all(windows, target_env = "msvc")))]
diff --git a/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md
new file mode 100644
index 0000000000000..eab29a1744b67
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md
@@ -0,0 +1,6 @@
+# `emscripten-wasm-eh`
+
+Use the WebAssembly exception handling ABI to unwind for the
+`wasm32-unknown-emscripten`. If compiling with this setting, the `emcc` linker
+should be invoked with `-fwasm-exceptions`. If linking with C/C++ files, the
+C/C++ files should also be compiled with `-fwasm-exceptions`.
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index af39d15f67175..881df8b005017 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -357,7 +357,7 @@ fn sidebar_type_alias<'a>(
     deref_id_map: &'a DefIdMap<String>,
 ) {
     if let Some(inner_type) = &t.inner_type {
-        items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type"));
+        items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased Type"), "type"));
         match inner_type {
             clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive: _ } => {
                 let mut variants = variants
diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs
similarity index 100%
rename from tests/codegen/emcripten-catch-unwind.rs
rename to tests/codegen/emscripten-catch-unwind-js-eh.rs
diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs
new file mode 100644
index 0000000000000..72395f432d5f8
--- /dev/null
+++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs
@@ -0,0 +1,65 @@
+//@ compile-flags: -O --target wasm32-unknown-emscripten -Z emscripten-wasm-eh
+//@ needs-llvm-components: webassembly
+
+// Emscripten catch_unwind using wasm exceptions
+
+#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "freeze"]
+trait Freeze {}
+#[lang = "copy"]
+trait Copy {}
+
+impl<T> Copy for *mut T {}
+
+#[rustc_intrinsic]
+fn size_of<T>() -> usize {
+    loop {}
+}
+
+extern "rust-intrinsic" {
+    fn catch_unwind(
+        try_fn: fn(_: *mut u8),
+        data: *mut u8,
+        catch_fn: fn(_: *mut u8, _: *mut u8),
+    ) -> i32;
+}
+
+// CHECK-LABEL: @ptr_size
+#[no_mangle]
+pub fn ptr_size() -> usize {
+    // CHECK: ret [[PTR_SIZE:.*]]
+    size_of::<*mut u8>()
+}
+
+// CHECK-LABEL: @test_catch_unwind
+#[no_mangle]
+pub unsafe fn test_catch_unwind(
+    try_fn: fn(_: *mut u8),
+    data: *mut u8,
+    catch_fn: fn(_: *mut u8, _: *mut u8),
+) -> i32 {
+    // CHECK: start:
+    // CHECK: invoke void %try_fn(ptr %data)
+    // CHECK:         to label %__rust_try.exit unwind label %catchswitch.i
+    // CHECK:   catchswitch.i:                                    ; preds = %start
+    // CHECK:   %catchswitch1.i = catchswitch within none [label %catchpad.i] unwind to caller
+
+    // CHECK: catchpad.i:                                       ; preds = %catchswitch.i
+    // CHECK:   %catchpad2.i = catchpad within %catchswitch1.i [ptr null]
+    // CHECK:   %0 = tail call ptr @llvm.wasm.get.exception(token %catchpad2.i)
+    // CHECK:   %1 = tail call i32 @llvm.wasm.get.ehselector(token %catchpad2.i)
+    // CHECK:   call void %catch_fn(ptr %data, ptr %0) [ "funclet"(token %catchpad2.i) ]
+    // CHECK:   catchret from %catchpad2.i to label %__rust_try.exit
+
+    // CHECK: __rust_try.exit:                                  ; preds = %start, %catchpad.i
+    // CHECK:   %common.ret.op.i = phi i32 [ 0, %start ], [ 1, %catchpad.i ]
+    // CHECK:   ret i32 %common.ret.op.i
+
+    catch_unwind(try_fn, data, catch_fn)
+}
diff --git a/tests/rustdoc/type-alias/deref-32077.rs b/tests/rustdoc/type-alias/deref-32077.rs
index 79a833813406e..faab4b6f522ba 100644
--- a/tests/rustdoc/type-alias/deref-32077.rs
+++ b/tests/rustdoc/type-alias/deref-32077.rs
@@ -19,8 +19,8 @@ impl<T> Foo for GenericStruct<T> {}
 impl Bar for GenericStruct<u32> {}
 
 //@ has 'foo/type.TypedefStruct.html'
-// We check that "Aliased type" is also present as a title in the sidebar.
-//@ has - '//*[@class="sidebar-elems"]//h3/a[@href="#aliased-type"]' 'Aliased type'
+// We check that "Aliased Type" is also present as a title in the sidebar.
+//@ has - '//*[@class="sidebar-elems"]//h3/a[@href="#aliased-type"]' 'Aliased Type'
 // We check that we have the implementation of the type alias itself.
 //@ has - '//*[@id="impl-GenericStruct%3Cu8%3E"]/h3' 'impl TypedefStruct'
 //@ has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()'
diff --git a/tests/ui/associated-types/invalid-ctor.fixed b/tests/ui/associated-types/invalid-ctor.fixed
new file mode 100644
index 0000000000000..eba3820de0c1c
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.fixed
@@ -0,0 +1,22 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+struct Constructor(i32);
+
+trait Trait {
+    type Out;
+
+    fn mk() -> Self::Out;
+}
+
+impl Trait for () {
+    type Out = Constructor;
+
+    fn mk() -> Self::Out {
+        Constructor(1)
+        //~^ ERROR no associated item named `Out` found for unit type `()`
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/invalid-ctor.rs b/tests/ui/associated-types/invalid-ctor.rs
new file mode 100644
index 0000000000000..73335c065c2ae
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.rs
@@ -0,0 +1,22 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+struct Constructor(i32);
+
+trait Trait {
+    type Out;
+
+    fn mk() -> Self::Out;
+}
+
+impl Trait for () {
+    type Out = Constructor;
+
+    fn mk() -> Self::Out {
+        Self::Out(1)
+        //~^ ERROR no associated item named `Out` found for unit type `()`
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/invalid-ctor.stderr b/tests/ui/associated-types/invalid-ctor.stderr
new file mode 100644
index 0000000000000..b545c95a76814
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no associated item named `Out` found for unit type `()` in the current scope
+  --> $DIR/invalid-ctor.rs:17:15
+   |
+LL |         Self::Out(1)
+   |               ^^^ associated item not found in `()`
+   |
+help: to construct a value of type `Constructor`, use the explicit path
+   |
+LL |         Constructor(1)
+   |         ~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr
new file mode 100644
index 0000000000000..8b2ee0e5c0c3d
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg emscripten_wasm_eh` flag
+   |
+   = note: config `emscripten_wasm_eh` is only supposed to be controlled by `-Z emscripten_wasm_eh`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
index 3c9ee87f28ab8..cae9c65cb45ac 100644
--- a/tests/ui/cfg/disallowed-cli-cfgs.rs
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -7,6 +7,7 @@
 //@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_
 //@ revisions: target_thread_local_ relocation_model_
 //@ revisions: fmt_debug_
+//@ revisions: emscripten_wasm_eh_
 
 //@ [overflow_checks_]compile-flags: --cfg overflow_checks
 //@ [debug_assertions_]compile-flags: --cfg debug_assertions
@@ -33,5 +34,6 @@
 //@ [target_thread_local_]compile-flags: --cfg target_thread_local
 //@ [relocation_model_]compile-flags: --cfg relocation_model="a"
 //@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
+//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
 
 fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr
index 370244fe8c984..f219c90849a26 100644
--- a/tests/ui/const-generics/issues/issue-88119.stderr
+++ b/tests/ui/const-generics/issues/issue-88119.stderr
@@ -11,12 +11,30 @@ error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{con
    |
 LL | impl<T: ?Sized + ConstName> const ConstName for &T
    |                                                 ^^ cannot normalize `<&T as ConstName>::{constant#0}`
+   |
+note: required for `&T` to implement `~const ConstName`
+  --> $DIR/issue-88119.rs:19:35
+   |
+LL | impl<T: ?Sized + ConstName> const ConstName for &T
+   |                                   ^^^^^^^^^     ^^
+LL | where
+LL |     [(); name_len::<T>()]:,
+   |     --------------------- unsatisfied trait bound introduced here
 
 error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
   --> $DIR/issue-88119.rs:26:49
    |
 LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
    |                                                 ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
+   |
+note: required for `&mut T` to implement `~const ConstName`
+  --> $DIR/issue-88119.rs:26:35
+   |
+LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
+   |                                   ^^^^^^^^^     ^^^^^^
+LL | where
+LL |     [(); name_len::<T>()]:,
+   |     --------------------- unsatisfied trait bound introduced here
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-eval/format.rs b/tests/ui/consts/const-eval/format.rs
index e56d15e935bc5..1878fc0382767 100644
--- a/tests/ui/consts/const-eval/format.rs
+++ b/tests/ui/consts/const-eval/format.rs
@@ -1,13 +1,11 @@
 const fn failure() {
     panic!("{:?}", 0);
     //~^ ERROR cannot call non-const formatting macro in constant functions
-    //~| ERROR cannot call non-const associated function `Arguments::<'_>::new_v1::<1, 1>` in constant functions
 }
 
 const fn print() {
     println!("{:?}", 0);
     //~^ ERROR cannot call non-const formatting macro in constant functions
-    //~| ERROR cannot call non-const associated function `Arguments::<'_>::new_v1::<2, 1>` in constant functions
     //~| ERROR cannot call non-const function `_print` in constant functions
 }
 
diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr
index 25ed44e0f3382..af90acc2a2605 100644
--- a/tests/ui/consts/const-eval/format.stderr
+++ b/tests/ui/consts/const-eval/format.stderr
@@ -7,17 +7,8 @@ LL |     panic!("{:?}", 0);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0015]: cannot call non-const associated function `Arguments::<'_>::new_v1::<1, 1>` in constant functions
-  --> $DIR/format.rs:2:5
-   |
-LL |     panic!("{:?}", 0);
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0015]: cannot call non-const formatting macro in constant functions
-  --> $DIR/format.rs:8:15
+  --> $DIR/format.rs:7:15
    |
 LL |     println!("{:?}", 0);
    |               ^^^^
@@ -25,17 +16,8 @@ LL |     println!("{:?}", 0);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0015]: cannot call non-const associated function `Arguments::<'_>::new_v1::<2, 1>` in constant functions
-  --> $DIR/format.rs:8:5
-   |
-LL |     println!("{:?}", 0);
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0015]: cannot call non-const function `_print` in constant functions
-  --> $DIR/format.rs:8:5
+  --> $DIR/format.rs:7:5
    |
 LL |     println!("{:?}", 0);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -43,6 +25,6 @@ LL |     println!("{:?}", 0);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index e0dbecff8e587..d688bfbde2bc2 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:70:32
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:71:17
    |
-LL |         let test_one = test_fn(one);
-   |                        ------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
+LL |         assert!(test_one == (1, 1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `test_fn`
-  --> $DIR/fn_trait_refs.rs:35:24
-   |
-LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
-   |          ------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `test_fn`
-
-error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:73:36
-   |
-LL |         let test_two = test_fn_mut(two);
-   |                        ----------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
-   |
-note: required by a bound in `test_fn_mut`
-  --> $DIR/fn_trait_refs.rs:49:27
-   |
-LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
-   |          ----------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `test_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:39:19
-   |
-LL |         tester_fn(&f),
-   |         --------- ^^
-   |         |
-   |         required by a bound introduced by this call
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:74:17
    |
-note: required by a bound in `tester_fn`
-  --> $DIR/fn_trait_refs.rs:14:24
+LL |         assert!(test_two == (2, 2));
+   |                 ^^^^^^^^^^^^^^^^^^
    |
-LL | const fn tester_fn<T>(f: T) -> T::Output
-   |          --------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `tester_fn`
-
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:41:23
-   |
-LL |         tester_fn_mut(&f),
-   |         ------------- ^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
-
-error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:53:23
-   |
-LL |         tester_fn_mut(&mut f),
-   |         ------------- ^^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL |     f()
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 25 previous errors
+error: aborting due to 22 previous errors
 
-Some errors have detailed explanations: E0015, E0277, E0635.
+Some errors have detailed explanations: E0015, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr
index dd70bb601c47d..40c6d083b066f 100644
--- a/tests/ui/consts/promoted_const_call.stderr
+++ b/tests/ui/consts/promoted_const_call.stderr
@@ -5,6 +5,10 @@ LL |     let _: &'static _ = &id(&Panic);
    |                              ^^^^^ - value is dropped here
    |                              |
    |                              the destructor for this type cannot be evaluated in constants
+   |
+   = note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
+   = help: add `#![feature(const_destruct)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_call.rs:16:26
diff --git a/tests/ui/crate_type_flag.rs b/tests/ui/crate_type_flag.rs
new file mode 100644
index 0000000000000..bd71c61cb2664
--- /dev/null
+++ b/tests/ui/crate_type_flag.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: --crate-type dynlib
+//@ error-pattern: unknown crate type: `dynlib`, expected one of: lib, rlib, staticlib, dylib, cdylib, bin, proc-macro
+
+fn main() {}
diff --git a/tests/ui/crate_type_flag.stderr b/tests/ui/crate_type_flag.stderr
new file mode 100644
index 0000000000000..fa3065e3ccf60
--- /dev/null
+++ b/tests/ui/crate_type_flag.stderr
@@ -0,0 +1,2 @@
+error: unknown crate type: `dynlib`, expected one of: lib, rlib, staticlib, dylib, cdylib, bin, proc-macro
+
diff --git a/tests/ui/deprecation/deprecated_ar.rs b/tests/ui/deprecation/deprecated_ar.rs
new file mode 100644
index 0000000000000..404d062e6a449
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_ar.rs
@@ -0,0 +1,4 @@
+//@ check-pass
+//@ compile-flags: -Car=foo
+
+fn main() {}
diff --git a/tests/ui/deprecation/deprecated_ar.stderr b/tests/ui/deprecation/deprecated_ar.stderr
new file mode 100644
index 0000000000000..de776c674996a
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_ar.stderr
@@ -0,0 +1,2 @@
+warning: `-C ar`: this option is deprecated and does nothing
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr
new file mode 100644
index 0000000000000..2e7a99010ae9b
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr
@@ -0,0 +1,4 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
+error: incorrect value `asd` for codegen option `inline-threshold` - a number was expected
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr
new file mode 100644
index 0000000000000..2d6f3652d252e
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr
@@ -0,0 +1,2 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr
new file mode 100644
index 0000000000000..25104e637e001
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr
@@ -0,0 +1,4 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
+error: codegen option `inline-threshold` requires a number (C inline-threshold=<value>)
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.rs b/tests/ui/deprecation/deprecated_inline_threshold.rs
index 56e033b8cf547..b54fa36397af0 100644
--- a/tests/ui/deprecation/deprecated_inline_threshold.rs
+++ b/tests/ui/deprecation/deprecated_inline_threshold.rs
@@ -1,4 +1,8 @@
-//@ check-pass
-//@ compile-flags: -Cinline-threshold=666
+//@ revisions: good_val bad_val no_val
+//
+//@[good_val] compile-flags: -Cinline-threshold=666
+//@[good_val] check-pass
+//@[bad_val] compile-flags: -Cinline-threshold=asd
+//@[no_val] compile-flags: -Cinline-threshold
 
 fn main() {}
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.stderr b/tests/ui/deprecation/deprecated_inline_threshold.stderr
deleted file mode 100644
index c4f8ff092b29a..0000000000000
--- a/tests/ui/deprecation/deprecated_inline_threshold.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-warning: the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
-
diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
new file mode 100644
index 0000000000000..62584ec23e336
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
@@ -0,0 +1,4 @@
+//@ check-pass
+//@ compile-flags: -Cno-stack-check
+
+fn main() {}
diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr b/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr
new file mode 100644
index 0000000000000..17efba787f070
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr
@@ -0,0 +1,2 @@
+warning: `-C no-stack-check`: this option is deprecated and does nothing
+
diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs
new file mode 100644
index 0000000000000..cff98b43fe745
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh)
+#[cfg(not(emscripten_wasm_eh))]
+//~^ `cfg(emscripten_wasm_eh)` is experimental
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr
new file mode 100644
index 0000000000000..67769e3c7586b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(emscripten_wasm_eh)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-emscripten-wasm-eh.rs:2:11
+   |
+LL | #[cfg(not(emscripten_wasm_eh))]
+   |           ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(cfg_emscripten_wasm_eh)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 0f79cefeaecb7..f4e8a872cec12 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
-  --> $DIR/normalize-tait-in-const.rs:33:19
-   |
-LL |     with_positive(foo);
-   |     ------------- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `with_positive`
-  --> $DIR/normalize-tait-in-const.rs:26:62
-   |
-LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
-   |                                                              ^^^^^^ required by this bound in `with_positive`
-
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:27:5
    |
@@ -39,7 +25,6 @@ LL |     fun(filter_positive());
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
index 03da9159bea0b..4cd87002e4910 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
@@ -5,7 +5,7 @@ LL |     T::Assoc::<U>::func();
    |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `U: ~const Other` is not satisfied
-  --> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
+  --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
    |
 LL |     <T as Trait>::Assoc::<U>::func();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
index ce58b486a16ef..4cd87002e4910 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
@@ -1,11 +1,11 @@
-error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
+error[E0277]: the trait bound `U: ~const Other` is not satisfied
   --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
    |
 LL |     T::Assoc::<U>::func();
    |     ^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
-  --> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
+error[E0277]: the trait bound `U: ~const Other` is not satisfied
+  --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
    |
 LL |     <T as Trait>::Assoc::<U>::func();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
index bdd98eaf541f8..e1c30b5361124 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
@@ -22,11 +22,9 @@ trait Other {}
 
 const fn fails<T: ~const Trait, U: Other>() {
     T::Assoc::<U>::func();
-    //[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
-    //[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
+    //~^ ERROR the trait bound `U: ~const Other` is not satisfied
     <T as Trait>::Assoc::<U>::func();
-    //[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
-    //[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
+    //~^ ERROR the trait bound `U: ~const Other` is not satisfied
 }
 
 const fn works<T: ~const Trait, U: ~const Other>() {
diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs
index 398fb39064055..4819da7c3a403 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.rs
+++ b/tests/ui/traits/const-traits/const-drop-bound.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(const_precise_live_drops, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
deleted file mode 100644
index 78ba0279566de..0000000000000
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Foo<E>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-bound.rs:23:9
-   |
-LL |     foo(res)
-   |     --- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/const-drop-bound.rs:9:61
-   |
-LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
-   |                                                             ^^^^^^ required by this bound in `foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
index 7b2cafb612441..7a32a6c4a15ac 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
index 7b2cafb612441..7a32a6c4a15ac 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
similarity index 87%
rename from tests/ui/traits/const-traits/const-drop-fail.precise.stderr
rename to tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
index 8b3e777a0b098..682f48fe07af6 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
similarity index 87%
rename from tests/ui/traits/const-traits/const-drop-fail.stock.stderr
rename to tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
index 8b3e777a0b098..682f48fe07af6 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
new file mode 100644
index 0000000000000..682f48fe07af6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
new file mode 100644
index 0000000000000..682f48fe07af6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs
index 5e05b9db474a6..a7f3d5654de93 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.rs
+++ b/tests/ui/traits/const-traits/const-drop-fail.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -Znext-solver
-//@ revisions: stock precise
+//@[new_precise] compile-flags: -Znext-solver
+//@[new_stock] compile-flags: -Znext-solver
+//@ revisions: new_stock old_stock new_precise old_precise
 
 #![feature(const_trait_impl, const_destruct)]
-#![cfg_attr(precise, feature(const_precise_live_drops))]
+#![cfg_attr(any(new_precise, old_precise), feature(const_precise_live_drops))]
 
 use std::marker::{Destruct, PhantomData};
 
diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
index 3fc6f58470947..0d53bc5897ef3 100644
--- a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
+++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
@@ -16,6 +16,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
 LL |     type Assoc<T> = C<T>
    |                     ^^^^
    |
+note: required for `C<T>` to implement `~const Bar`
+  --> $DIR/item-bound-entailment-fails.rs:14:15
+   |
+LL | impl<T> const Bar for C<T> where T: ~const Bar {}
+   |               ^^^     ^^^^          ------ unsatisfied trait bound introduced here
 note: required by a bound in `Foo::Assoc`
   --> $DIR/item-bound-entailment-fails.rs:5:20
    |
diff --git a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs
new file mode 100644
index 0000000000000..129e90a07f43a
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Znext-solver
+
+trait Trait<'a> {
+    type Assoc;
+}
+
+fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+    //~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+    unsafe { std::mem::transmute::<_, ()>(x); }
+    //~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr
new file mode 100644
index 0000000000000..2d42fedae4381
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr
@@ -0,0 +1,75 @@
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:11
+   |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:8
+   |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+   |        ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:14
+   |
+LL |     unsafe { std::mem::transmute::<_, ()>(x); }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:36
+   |
+LL |     unsafe { std::mem::transmute::<_, ()>(x); }
+   |                                    ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:43
+   |
+LL |     unsafe { std::mem::transmute::<_, ()>(x); }
+   |                                           ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:1
+   |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+   |
+LL | trait Trait<'a> {
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index 7efa63c2642fd..2a0ad610c1a00 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -824,7 +824,7 @@ cc = ["@rust-lang/rustfmt"]
 
 [mentions."compiler/rustc_middle/src/mir/syntax.rs"]
 message = "This PR changes MIR"
-cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"]
+cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@vakaras"]
 
 [mentions."compiler/rustc_error_messages"]
 message = "`rustc_error_messages` was changed"
@@ -1004,7 +1004,6 @@ warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "jyn514",
-    "celinval",
     "nnethercote",
     "spastorino",
     "workingjubilee",