about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-05 06:19:41 +0000
committerbors <bors@rust-lang.org>2023-12-05 06:19:41 +0000
commit88d905cb3a09054665b9cee9b7a3ee0c139f8df7 (patch)
treef05f1c5f46ff2e217f60efad55acdae725e4bff2
parente27da142efd0f03795e2bb9a2925ba9611b2cd83 (diff)
parent0d5fdcca6c935f41bc9895bfe40917e8888a1be1 (diff)
downloadrust-88d905cb3a09054665b9cee9b7a3ee0c139f8df7.tar.gz
rust-88d905cb3a09054665b9cee9b7a3ee0c139f8df7.zip
Auto merge of #3210 - rust-lang:rustup-2023-12-05, r=RalfJung
Automatic Rustup
-rw-r--r--compiler/rustc_arena/src/lib.rs41
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs12
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs82
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs12
-rw-r--r--compiler/rustc_hir/src/def.rs37
-rw-r--r--compiler/rustc_hir/src/definitions.rs18
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs64
-rw-r--r--compiler/rustc_infer/src/infer/generalize.rs87
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/context.rs3
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs23
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs103
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs125
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs45
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs19
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/visitor.rs7
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs37
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs14
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs128
-rw-r--r--compiler/rustc_resolve/src/lib.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs5
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs5
-rw-r--r--compiler/rustc_trait_selection/messages.ftl3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs147
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs12
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs7
-rw-r--r--library/core/src/slice/index.rs5
-rw-r--r--library/core/src/slice/mod.rs10
-rw-r--r--library/portable-simd/crates/core_simd/tests/pointers.rs2
-rw-r--r--src/librustdoc/html/escape.rs36
-rw-r--r--src/librustdoc/html/highlight.rs12
-rw-r--r--src/librustdoc/html/highlight/fixtures/dos_line.html2
-rw-r--r--src/librustdoc/html/highlight/fixtures/sample.html8
-rw-r--r--src/librustdoc/html/render/print_item.rs9
-rw-r--r--src/tools/cargotest/main.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs3
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr24
-rw-r--r--src/tools/miri/tests/fail/uninit/uninit_byte_read.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr4
-rw-r--r--src/tools/miri/tests/pass/float_nan.rs4
-rw-r--r--src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs37
-rw-r--r--src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs40
-rw-r--r--src/tools/rust-analyzer/Cargo.lock4
-rw-r--r--src/tools/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs116
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs204
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs10
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs95
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast66
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast30
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs11
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs4
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc5
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json5
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts27
-rw-r--r--src/tools/rust-analyzer/editors/code/src/toolchain.ts14
-rw-r--r--tests/codegen/issues/issue-116878.rs13
-rw-r--r--tests/rustdoc/enum-variant-fields-heading.rs18
-rw-r--r--tests/rustdoc/enum-variant-fields-heading.variants.html3
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.next.stderr25
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.old.stderr25
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.rs45
-rw-r--r--tests/ui/coherence/occurs-check/opaques.next.stderr12
-rw-r--r--tests/ui/coherence/occurs-check/opaques.rs37
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs67
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr305
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs8
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr54
-rw-r--r--tests/ui/packed/issue-118537-field-offset-ice.rs39
-rw-r--r--tests/ui/packed/issue-118537-field-offset.rs36
-rw-r--r--tests/ui/traits/new-solver/equating-projection-cyclically.rs5
-rw-r--r--tests/ui/traits/new-solver/equating-projection-cyclically.stderr9
-rw-r--r--tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr9
-rw-r--r--tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs37
108 files changed, 2301 insertions, 769 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index bd35364509a..756af7269f2 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -197,23 +197,24 @@ impl<T> TypedArena<T> {
         start_ptr
     }
 
+    /// Allocates the elements of this iterator into a contiguous slice in the `TypedArena`.
+    ///
+    /// Note: for reasons of reentrancy and panic safety we collect into a `SmallVec<[_; 8]>` before
+    /// storing the elements in the arena.
     #[inline]
     pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
-        // This implementation is entirely separate to
-        // `DroplessIterator::alloc_from_iter`, even though conceptually they
-        // are the same.
+        // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason
+        // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a
+        // reference to `self` and adding elements to the arena during iteration.
         //
-        // `DroplessIterator` (in the fast case) writes elements from the
-        // iterator one at a time into the allocated memory. That's easy
-        // because the elements don't implement `Drop`. But for `TypedArena`
-        // they do implement `Drop`, which means that if the iterator panics we
-        // could end up with some allocated-but-uninitialized elements, which
-        // will then cause UB in `TypedArena::drop`.
+        // For this reason, if we pre-allocated any space for the elements of this iterator, we'd
+        // have to track that some uninitialized elements are followed by some initialized elements,
+        // else we might accidentally drop uninitialized memory if something panics or if the
+        // iterator doesn't fill all the length we expected.
         //
-        // Instead we use an approach where any iterator panic will occur
-        // before the memory is allocated. This function is much less hot than
-        // `DroplessArena::alloc_from_iter`, so it doesn't need to be
-        // hyper-optimized.
+        // So we collect all the elements beforehand, which takes care of reentrancy and panic
+        // safety. This function is much less hot than `DroplessArena::alloc_from_iter`, so it
+        // doesn't need to be hyper-optimized.
         assert!(mem::size_of::<T>() != 0);
 
         let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
@@ -485,8 +486,9 @@ impl DroplessArena {
 
     /// # Safety
     ///
-    /// The caller must ensure that `mem` is valid for writes up to
-    /// `size_of::<T>() * len`.
+    /// The caller must ensure that `mem` is valid for writes up to `size_of::<T>() * len`, and that
+    /// that memory stays allocated and not shared for the lifetime of `self`. This must hold even
+    /// if `iter.next()` allocates onto `self`.
     #[inline]
     unsafe fn write_from_iter<T, I: Iterator<Item = T>>(
         &self,
@@ -516,6 +518,8 @@ impl DroplessArena {
 
     #[inline]
     pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
+        // Warning: this function is reentrant: `iter` could hold a reference to `&self` and
+        // allocate additional elements while we're iterating.
         let iter = iter.into_iter();
         assert!(mem::size_of::<T>() != 0);
         assert!(!mem::needs_drop::<T>());
@@ -524,7 +528,7 @@ impl DroplessArena {
 
         match size_hint {
             (min, Some(max)) if min == max => {
-                // We know the exact number of elements the iterator will produce here
+                // We know the exact number of elements the iterator expects to produce here.
                 let len = min;
 
                 if len == 0 {
@@ -532,10 +536,15 @@ impl DroplessArena {
                 }
 
                 let mem = self.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
+                // SAFETY: `write_from_iter` doesn't touch `self`. It only touches the slice we just
+                // reserved. If the iterator panics or doesn't output `len` elements, this will
+                // leave some unallocated slots in the arena, which is fine because we do not call
+                // `drop`.
                 unsafe { self.write_from_iter(iter, len, mem) }
             }
             (_, _) => {
                 outline(move || -> &mut [T] {
+                    // Takes care of reentrancy.
                     let mut vec: SmallVec<[_; 8]> = iter.collect();
                     if vec.is_empty() {
                         return &mut [];
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index b75a686b819..7111daa2ea9 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -14,8 +14,8 @@ use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::definitions::DefPathData;
 use rustc_session::parse::feature_err;
+use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
@@ -227,7 +227,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             self.create_def(
                                 parent_def_id.def_id,
                                 node_id,
-                                DefPathData::AnonConst,
+                                kw::Empty,
                                 DefKind::AnonConst,
                                 *op_sp,
                             );
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 5b07299d411..eb1a1d15027 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -13,10 +13,9 @@ use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::definitions::DefPathData;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, Spanned};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use rustc_span::{DesugaringKind, Span};
 use thin_vec::{thin_vec, ThinVec};
@@ -376,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.create_def(
                     parent_def_id.def_id,
                     node_id,
-                    DefPathData::AnonConst,
+                    kw::Empty,
                     DefKind::AnonConst,
                     f.span,
                 );
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index fbbb9d7a52a..f0f3e2c3c74 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -3,7 +3,6 @@ use super::ResolverAstLoweringExt;
 use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
 use super::{FnDeclKind, LoweringContext, ParamMode};
 
-use hir::definitions::DefPathData;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
@@ -1367,7 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let def_id = self.create_def(
                     self.local_def_id(parent_node_id),
                     param_node_id,
-                    DefPathData::TypeNs(sym::host),
+                    sym::host,
                     DefKind::ConstParam,
                     span,
                 );
@@ -1427,13 +1426,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         if let Some((span, hir_id, def_id)) = host_param_parts {
             let const_node_id = self.next_node_id();
-            let anon_const = self.create_def(
-                def_id,
-                const_node_id,
-                DefPathData::AnonConst,
-                DefKind::AnonConst,
-                span,
-            );
+            let anon_const =
+                self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
 
             let const_id = self.next_id();
             let const_expr_id = self.next_id();
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index eb6d11a72e6..aa8ad978451 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -58,7 +58,6 @@ use rustc_errors::{DiagnosticArgFromDisplay, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::{
@@ -499,20 +498,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         parent: LocalDefId,
         node_id: ast::NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
         debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
         assert!(
             self.opt_local_def_id(node_id).is_none(),
-            "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
+            "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
             node_id,
-            data,
+            def_kind,
             self.tcx.hir().def_key(self.local_def_id(node_id)),
         );
 
-        let def_id = self.tcx.at(span).create_def(parent, data, def_kind).def_id();
+        let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
 
         debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
         self.resolver.node_id_to_def_id.insert(node_id, def_id);
@@ -809,7 +808,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let _def_id = self.create_def(
                     self.current_hir_id_owner.def_id,
                     param,
-                    DefPathData::LifetimeNs(kw::UnderscoreLifetime),
+                    kw::UnderscoreLifetime,
                     DefKind::LifetimeParam,
                     ident.span,
                 );
@@ -1227,7 +1226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 let def_id = self.create_def(
                                     parent_def_id.def_id,
                                     node_id,
-                                    DefPathData::AnonConst,
+                                    kw::Empty,
                                     DefKind::AnonConst,
                                     span,
                                 );
@@ -1465,7 +1464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         self.create_def(
                             self.current_hir_id_owner.def_id,
                             *def_node_id,
-                            DefPathData::TypeNs(ident.name),
+                            ident.name,
                             DefKind::TyParam,
                             span,
                         );
@@ -1619,7 +1618,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_def_id = self.create_def(
             self.current_hir_id_owner.def_id,
             opaque_ty_node_id,
-            DefPathData::ImplTrait,
+            kw::Empty,
             DefKind::OpaqueTy,
             opaque_ty_span,
         );
@@ -1674,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let duplicated_lifetime_def_id = self.create_def(
                     opaque_ty_def_id,
                     duplicated_lifetime_node_id,
-                    DefPathData::LifetimeNs(lifetime.ident.name),
+                    lifetime.ident.name,
                     DefKind::LifetimeParam,
                     lifetime.ident.span,
                 );
@@ -2549,7 +2548,7 @@ impl<'hir> GenericArgsCtor<'hir> {
         let def_id = lcx.create_def(
             lcx.current_hir_id_owner.def_id,
             id,
-            DefPathData::AnonConst,
+            kw::Empty,
             DefKind::AnonConst,
             span,
         );
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 7b259055d40..acd85dd9a2d 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     #[instrument(level = "trace", skip(self))]
     fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
+        if place.layout.is_unsized() {
+            let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {});
+            if matches!(tail.kind(), ty::Foreign(..)) {
+                // Unsized locals and, at least conceptually, even unsized arguments must be copied
+                // around, which requires dynamically determining their size. Therefore, we cannot
+                // allow `extern` types here. Consult t-opsem before removing this check.
+                panic!("unsized locals must not be `extern` types");
+            }
+        }
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 839cc4dabe3..8630e5623e1 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -594,7 +594,7 @@ fn push_unqualified_item_name(
         DefPathData::CrateRoot => {
             output.push_str(tcx.crate_name(def_id.krate).as_str());
         }
-        DefPathData::ClosureExpr => {
+        DefPathData::Closure => {
             let label = coroutine_kind_label(tcx.coroutine_kind(def_id));
 
             push_disambiguated_special_name(
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 0ab2b7ecd9c..6661f1f81e6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
                 // value is through `undef`/`poison`, and the store itself is useless.
             }
             OperandValue::Ref(r, None, source_align) => {
+                assert!(dest.layout.is_sized(), "cannot directly store unsized values");
                 if flags.contains(MemFlags::NONTEMPORAL) {
                     // HACK(nox): This is inefficient but there is no nontemporal memcpy.
                     let ty = bx.backend_type(dest.layout);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 45795a7f735..83425dee1a8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         // Simple cases, which don't need DST adjustment:
         //   * no metadata available - just log the case
         //   * known alignment - sized types, `[T]`, `str` or a foreign type
-        //   * packed struct - there is no alignment padding
+        // Note that looking at `field.align` is incorrect since that is not necessarily equal
+        // to the dynamic alignment of the type.
         match field.ty.kind() {
             _ if self.llextra.is_none() => {
                 debug!(
@@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             }
             _ if field.is_sized() => return simple(),
             ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
-            ty::Adt(def, _) => {
-                if def.repr().packed() {
-                    // FIXME(eddyb) generalize the adjustment when we
-                    // start supporting packing to larger alignments.
-                    assert_eq!(self.layout.align.abi.bytes(), 1);
-                    return simple();
-                }
-            }
             _ => {}
         }
 
@@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         let unaligned_offset = bx.cx().const_usize(offset.bytes());
 
         // Get the alignment of the field
-        let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
+        let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
+
+        // For packed types, we need to cap alignment.
+        if let ty::Adt(def, _) = self.layout.ty.kind()
+            && let Some(packed) = def.repr().pack
+        {
+            let packed = bx.const_usize(packed.bytes());
+            let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed);
+            unsized_align = bx.select(cmp, unsized_align, packed)
+        }
 
         // Bump the unaligned offset up to the appropriate alignment
         let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index c0a20e51482..04e5b550d6d 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -282,9 +282,7 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
-            if tcx.def_key(self.instance.def_id()).disambiguated_data.data
-                == DefPathData::ClosureExpr
-            {
+            if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
                 write!(f, "inside closure")
             } else {
                 // Note: this triggers a `good_path_delayed_bug` state, which means that if we ever
@@ -299,7 +297,7 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
 impl<'tcx> FrameInfo<'tcx> {
     pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
         let span = self.span;
-        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr {
+        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
             errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
         } else {
             let instance = format!("{}", self.instance);
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 80e14f5a884..c29f23b913f 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -3,17 +3,22 @@
 //! and miri.
 
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::{
-    self,
-    interpret::{Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar},
-    BinOp, ConstValue, NonDivergingIntrinsic,
-};
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::{
+    mir::{
+        self,
+        interpret::{
+            Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar,
+        },
+        BinOp, ConstValue, NonDivergingIntrinsic,
+    },
+    ty::layout::TyAndLayout,
+};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, Primitive, Size};
+use rustc_target::abi::Size;
 
 use super::{
     util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
@@ -22,23 +27,6 @@ use super::{
 
 use crate::fluent_generated as fluent;
 
-fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
-    let size = match kind {
-        Primitive::Int(integer, _) => integer.size(),
-        _ => bug!("invalid `{}` argument: {:?}", name, bits),
-    };
-    let extra = 128 - u128::from(size.bits());
-    let bits_out = match name {
-        sym::ctpop => u128::from(bits.count_ones()),
-        sym::ctlz => u128::from(bits.leading_zeros()) - extra,
-        sym::cttz => u128::from((bits << extra).trailing_zeros()) - extra,
-        sym::bswap => (bits << extra).swap_bytes(),
-        sym::bitreverse => (bits << extra).reverse_bits(),
-        _ => bug!("not a numeric intrinsic: {}", name),
-    };
-    Scalar::from_uint(bits_out, size)
-}
-
 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
 pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
     let path = crate::util::type_name(tcx, ty);
@@ -179,30 +167,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | sym::bswap
             | sym::bitreverse => {
                 let ty = instance_args.type_at(0);
-                let layout_of = self.layout_of(ty)?;
+                let layout = self.layout_of(ty)?;
                 let val = self.read_scalar(&args[0])?;
-                let bits = val.to_bits(layout_of.size)?;
-                let kind = match layout_of.abi {
-                    Abi::Scalar(scalar) => scalar.primitive(),
-                    _ => span_bug!(
-                        self.cur_span(),
-                        "{} called on invalid type {:?}",
-                        intrinsic_name,
-                        ty
-                    ),
-                };
-                let (nonzero, actual_intrinsic_name) = match intrinsic_name {
-                    sym::cttz_nonzero => (true, sym::cttz),
-                    sym::ctlz_nonzero => (true, sym::ctlz),
-                    other => (false, other),
-                };
-                if nonzero && bits == 0 {
-                    throw_ub_custom!(
-                        fluent::const_eval_call_nonzero_intrinsic,
-                        name = intrinsic_name,
-                    );
-                }
-                let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind);
+                let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
                 self.write_scalar(out_val, dest)?;
             }
             sym::saturating_add | sym::saturating_sub => {
@@ -493,6 +460,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
+    pub fn numeric_intrinsic(
+        &self,
+        name: Symbol,
+        val: Scalar<M::Provenance>,
+        layout: TyAndLayout<'tcx>,
+    ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
+        assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
+        let bits = val.to_bits(layout.size)?;
+        let extra = 128 - u128::from(layout.size.bits());
+        let bits_out = match name {
+            sym::ctpop => u128::from(bits.count_ones()),
+            sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => {
+                throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,);
+            }
+            sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra,
+            sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra,
+            sym::bswap => (bits << extra).swap_bytes(),
+            sym::bitreverse => (bits << extra).reverse_bits(),
+            _ => bug!("not a numeric intrinsic: {}", name),
+        };
+        Ok(Scalar::from_uint(bits_out, layout.size))
+    }
+
     pub fn exact_div(
         &mut self,
         a: &ImmTy<'tcx, M::Provenance>,
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index c8977aac0fc..4d9e296d544 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -163,7 +163,17 @@ where
             // With custom DSTS, this *will* execute user-defined code, but the same
             // happens at run-time so that's okay.
             match self.size_and_align_of(&base_meta, &field_layout)? {
-                Some((_, align)) => (base_meta, offset.align_to(align)),
+                Some((_, align)) => {
+                    // For packed types, we need to cap alignment.
+                    let align = if let ty::Adt(def, _) = base.layout().ty.kind()
+                        && let Some(packed) = def.repr().pack
+                    {
+                        align.min(packed)
+                    } else {
+                        align
+                    };
+                    (base_meta, offset.align_to(align))
+                }
                 None => {
                     // For unsized types with an extern type tail we perform no adjustments.
                     // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index fedd380cada..258d6710bc5 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -1,3 +1,4 @@
+use crate::definitions::DefPathData;
 use crate::hir;
 
 use rustc_ast as ast;
@@ -45,6 +46,7 @@ pub enum NonMacroAttrKind {
 }
 
 /// What kind of definition something is; e.g., `mod` vs `struct`.
+/// `enum DefPathData` may need to be updated if a new variant is added here.
 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
 pub enum DefKind {
     // Type namespace
@@ -221,6 +223,41 @@ impl DefKind {
         }
     }
 
+    pub fn def_path_data(self, name: Symbol) -> DefPathData {
+        match self {
+            DefKind::Mod
+            | DefKind::Struct
+            | DefKind::Union
+            | DefKind::Enum
+            | DefKind::Variant
+            | DefKind::Trait
+            | DefKind::TyAlias
+            | DefKind::ForeignTy
+            | DefKind::TraitAlias
+            | DefKind::AssocTy
+            | DefKind::TyParam
+            | DefKind::ExternCrate => DefPathData::TypeNs(name),
+            DefKind::Fn
+            | DefKind::Const
+            | DefKind::ConstParam
+            | DefKind::Static(..)
+            | DefKind::AssocFn
+            | DefKind::AssocConst
+            | DefKind::Field => DefPathData::ValueNs(name),
+            DefKind::Macro(..) => DefPathData::MacroNs(name),
+            DefKind::LifetimeParam => DefPathData::LifetimeNs(name),
+            DefKind::Ctor(..) => DefPathData::Ctor,
+            DefKind::Use => DefPathData::Use,
+            DefKind::ForeignMod => DefPathData::ForeignMod,
+            DefKind::AnonConst => DefPathData::AnonConst,
+            DefKind::InlineConst => DefPathData::AnonConst,
+            DefKind::OpaqueTy => DefPathData::OpaqueTy,
+            DefKind::GlobalAsm => DefPathData::GlobalAsm,
+            DefKind::Impl { .. } => DefPathData::Impl,
+            DefKind::Closure => DefPathData::Closure,
+        }
+    }
+
     #[inline]
     pub fn is_fn_like(self) -> bool {
         matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure)
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 168b336e374..d222325475d 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -246,6 +246,7 @@ impl DefPath {
     }
 }
 
+/// New variants should only be added in synchronization with `enum DefKind`.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
@@ -271,7 +272,7 @@ pub enum DefPathData {
     /// Something in the lifetime namespace.
     LifetimeNs(Symbol),
     /// A closure expression.
-    ClosureExpr,
+    Closure,
 
     // Subportions of items:
     /// Implicit constructor for a unit or tuple-like struct or enum variant.
@@ -280,9 +281,7 @@ pub enum DefPathData {
     AnonConst,
     /// An existential `impl Trait` type node.
     /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
-    ImplTrait,
-    /// `impl Trait` generated associated type node.
-    ImplTraitAssocTy,
+    OpaqueTy,
 }
 
 impl Definitions {
@@ -403,16 +402,17 @@ impl DefPathData {
     pub fn get_opt_name(&self) -> Option<Symbol> {
         use self::DefPathData::*;
         match *self {
+            TypeNs(name) if name == kw::Empty => None,
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
-
-            Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
-            | ImplTrait | ImplTraitAssocTy => None,
+            Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
+            | OpaqueTy => None,
         }
     }
 
     pub fn name(&self) -> DefPathDataName {
         use self::DefPathData::*;
         match *self {
+            TypeNs(name) if name == kw::Empty => DefPathDataName::Anon { namespace: sym::opaque },
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
                 DefPathDataName::Named(name)
             }
@@ -422,10 +422,10 @@ impl DefPathData {
             ForeignMod => DefPathDataName::Anon { namespace: kw::Extern },
             Use => DefPathDataName::Anon { namespace: kw::Use },
             GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm },
-            ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
+            Closure => DefPathDataName::Anon { namespace: sym::closure },
             Ctor => DefPathDataName::Anon { namespace: sym::constructor },
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
-            ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque },
+            OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c3d07415bb8..759ebaa1d1e 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -326,7 +326,9 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
         let span =
             self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
-        let Generalization { value, needs_wf: _ } = generalize::generalize(
+        // FIXME(generic_const_exprs): Occurs check failures for unevaluated
+        // constants and generic expressions are not yet handled correctly.
+        let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
             self,
             &mut CombineDelegate { infcx: self, span, param_env },
             ct,
@@ -445,7 +447,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         // `'?2` and `?3` are fresh region/type inference
         // variables. (Down below, we will relate `a_ty <: b_ty`,
         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
-        let Generalization { value: b_ty, needs_wf } = generalize::generalize(
+        let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
             self.infcx,
             &mut CombineDelegate {
                 infcx: self.infcx,
@@ -457,7 +459,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             ambient_variance,
         )?;
 
-        debug!(?b_ty);
         self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
 
         if needs_wf {
@@ -477,19 +478,52 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         // relations wind up attributed to the same spans. We need
         // to associate causes/spans with each of the relations in
         // the stack to get this right.
-        match ambient_variance {
-            ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
-            ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
-            ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
-                ty::Contravariant,
-                ty::VarianceDiagInfo::default(),
-                a_ty,
-                b_ty,
-            ),
-            ty::Variance::Bivariant => {
-                unreachable!("no code should be generalizing bivariantly (currently)")
+        if b_ty.is_ty_var() {
+            // This happens for cases like `<?0 as Trait>::Assoc == ?0`.
+            // We can't instantiate `?0` here as that would result in a
+            // cyclic type. We instead delay the unification in case
+            // the alias can be normalized to something which does not
+            // mention `?0`.
+
+            // FIXME(-Ztrait-solver=next): replace this with `AliasRelate`
+            let &ty::Alias(kind, data) = a_ty.kind() else {
+                bug!("generalization should only result in infer vars for aliases");
+            };
+            if !self.infcx.next_trait_solver() {
+                // The old solver only accepts projection predicates for associated types.
+                match kind {
+                    ty::AliasKind::Projection => {}
+                    ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque => {
+                        return Err(TypeError::CyclicTy(a_ty));
+                    }
+                }
             }
-        }?;
+
+            // FIXME: This does not handle subtyping correctly, we should switch to
+            // alias-relate in the new solver and could instead create a new inference
+            // variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
+            // `a_infer <: b_ty`.
+            self.obligations.push(Obligation::new(
+                self.tcx(),
+                self.trace.cause.clone(),
+                self.param_env,
+                ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
+            ))
+        } else {
+            match ambient_variance {
+                ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
+                ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
+                ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
+                    ty::Contravariant,
+                    ty::VarianceDiagInfo::default(),
+                    a_ty,
+                    b_ty,
+                ),
+                ty::Variance::Bivariant => {
+                    unreachable!("no code should be generalizing bivariantly (currently)")
+                }
+            }?;
+        }
 
         Ok(())
     }
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs
index 9e24b020510..4b4017cec57 100644
--- a/compiler/rustc_infer/src/infer/generalize.rs
+++ b/compiler/rustc_infer/src/infer/generalize.rs
@@ -1,13 +1,16 @@
+use std::mem;
+
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::visit::MaxUniverse;
+use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
 use rustc_span::Span;
 
 use crate::infer::nll_relate::TypeRelatingDelegate;
-use crate::infer::type_variable::TypeVariableValue;
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
 use crate::infer::{InferCtxt, RegionVariableOrigin};
 
 /// Attempts to generalize `term` for the type variable `for_vid`.
@@ -38,27 +41,30 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>>
         root_vid,
         for_universe,
         root_term: term.into(),
+        in_alias: false,
         needs_wf: false,
         cache: Default::default(),
     };
 
     assert!(!term.has_escaping_bound_vars());
-    let value = generalizer.relate(term, term)?;
+    let value_may_be_infer = generalizer.relate(term, term)?;
     let needs_wf = generalizer.needs_wf;
-    Ok(Generalization { value, needs_wf })
+    Ok(Generalization { value_may_be_infer, needs_wf })
 }
 
 /// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
 /// in the generalizer code.
-pub trait GeneralizerDelegate<'tcx> {
+pub(super) trait GeneralizerDelegate<'tcx> {
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
     fn forbid_inference_vars() -> bool;
 
+    fn span(&self) -> Span;
+
     fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
 }
 
-pub struct CombineDelegate<'cx, 'tcx> {
+pub(super) struct CombineDelegate<'cx, 'tcx> {
     pub infcx: &'cx InferCtxt<'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
     pub span: Span,
@@ -73,6 +79,10 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
         false
     }
 
+    fn span(&self) -> Span {
+        self.span
+    }
+
     fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
         // FIXME: This is non-ideal because we don't give a
         // very descriptive origin for this region variable.
@@ -93,6 +103,10 @@ where
         <Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
     }
 
+    fn span(&self) -> Span {
+        <Self as TypeRelatingDelegate<'tcx>>::span(&self)
+    }
+
     fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
         <Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
     }
@@ -139,6 +153,13 @@ struct Generalizer<'me, 'tcx, D> {
 
     cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
 
+    /// This is set once we're generalizing the arguments of an alias.
+    ///
+    /// This is necessary to correctly handle
+    /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
+    /// hold by either normalizing the outer or the inner associated type.
+    in_alias: bool,
+
     /// See the field `needs_wf` in `Generalization`.
     needs_wf: bool,
 }
@@ -193,7 +214,7 @@ where
                 opt_variances,
                 a_subst,
                 b_subst,
-                true,
+                false,
             )
         }
     }
@@ -309,6 +330,44 @@ where
                 }
             }
 
+            ty::Alias(kind, data) => {
+                // An occurs check failure inside of an alias does not mean
+                // that the types definitely don't unify. We may be able
+                // to normalize the alias after all.
+                //
+                // We handle this by lazily equating the alias and generalizing
+                // it to an inference variable.
+                let is_nested_alias = mem::replace(&mut self.in_alias, true);
+                let result = match self.relate(data, data) {
+                    Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)),
+                    Err(e) => {
+                        if is_nested_alias {
+                            return Err(e);
+                        } else {
+                            let mut visitor = MaxUniverse::new();
+                            t.visit_with(&mut visitor);
+                            let infer_replacement_is_complete =
+                                self.for_universe.can_name(visitor.max_universe())
+                                    && !t.has_escaping_bound_vars();
+                            if !infer_replacement_is_complete {
+                                warn!("may incompletely handle alias type: {t:?}");
+                            }
+
+                            debug!("generalization failure in alias");
+                            Ok(self.infcx.next_ty_var_in_universe(
+                                TypeVariableOrigin {
+                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    span: self.delegate.span(),
+                                },
+                                self.for_universe,
+                            ))
+                        }
+                    }
+                };
+                self.in_alias = is_nested_alias;
+                result
+            }
+
             _ => relate::structurally_relate_tys(self, t, t),
         }?;
 
@@ -456,8 +515,16 @@ where
 /// not only the generalized type, but also a bool flag
 /// indicating whether further WF checks are needed.
 #[derive(Debug)]
-pub struct Generalization<T> {
-    pub value: T,
+pub(super) struct Generalization<T> {
+    /// When generalizing `<?0 as Trait>::Assoc` or
+    /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
+    /// for `?0` generalization returns an inference
+    /// variable.
+    ///
+    /// This has to be handled wotj care as it can
+    /// otherwise very easily result in infinite
+    /// recursion.
+    pub(super) value_may_be_infer: T,
 
     /// If true, then the generalized type may not be well-formed,
     /// even if the source type is well-formed, so we should add an
@@ -484,5 +551,5 @@ pub struct Generalization<T> {
     /// will force the calling code to check that `WF(Foo<?C, ?D>)`
     /// holds, which in turn implies that `?C::Item == ?D`. So once
     /// `?C` is constrained, that should suffice to restrict `?D`.
-    pub needs_wf: bool,
+    pub(super) needs_wf: bool,
 }
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 77c1d6a7313..d707c30206d 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -214,13 +214,17 @@ where
     }
 
     fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
-        let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
+        let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
             self.infcx,
             &mut self.delegate,
             ty,
             for_vid,
             self.ambient_variance,
         )?;
+
+        if ty.is_ty_var() {
+            span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
+        }
         Ok(ty)
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ff690db7bee..8e71327f82e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -977,7 +977,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
     pub fn create_def(
         self,
         parent: LocalDefId,
-        data: hir::definitions::DefPathData,
+        name: Symbol,
         def_kind: DefKind,
     ) -> TyCtxtFeed<'tcx, LocalDefId> {
         // This function modifies `self.definitions` using a side-effect.
@@ -1000,6 +1000,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
+        let data = def_kind.def_path_data(name);
         let key = self.untracked.definitions.write().create_def(parent, data);
 
         let feed = TyCtxtFeed { tcx: self.tcx, key };
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index cebefbccc11..1c7a7545e2b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> {
         };
         matches!(
             tcx.def_key(def_id).disambiguated_data.data,
-            DefPathData::Ctor | DefPathData::ClosureExpr
+            DefPathData::Ctor | DefPathData::Closure
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 64ae11df5b5..5e09154789a 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized {
 
                     match key.disambiguated_data.data {
                         // Closures' own generics are only captures, don't print them.
-                        DefPathData::ClosureExpr => {}
+                        DefPathData::Closure => {}
                         // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
                         // Anon consts doesn't have their own generics, and inline consts' own
                         // generics are their inferred types, so don't print them.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 68dd8dee87c..25423348638 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1804,13 +1804,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
 // (but also some things just print a `DefId` generally so maybe we need this?)
 fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
     match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
+        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
             Namespace::TypeNS
         }
 
         DefPathData::ValueNs(..)
         | DefPathData::AnonConst
-        | DefPathData::ClosureExpr
+        | DefPathData::Closure
         | DefPathData::Ctor => Namespace::ValueNS,
 
         DefPathData::MacroNs(..) => Namespace::MacroNS,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 8f017833531..a2f829f93e3 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -599,9 +599,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
     // an or-pattern. Panics if `self` is empty.
     fn expand_or_pat<'a>(&'a self) -> impl Iterator<Item = PatStack<'p, 'tcx>> + Captures<'a> {
         self.head().flatten_or_pat().into_iter().map(move |pat| {
-            let mut new_pats = smallvec![pat];
-            new_pats.extend_from_slice(&self.pats[1..]);
-            PatStack { pats: new_pats }
+            let mut new = self.clone();
+            new.pats[0] = pat;
+            new
         })
     }
 
@@ -732,18 +732,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
     }
 
     /// Build a new matrix from an iterator of `MatchArm`s.
-    fn new<'a>(
-        cx: &MatchCheckCtxt<'p, 'tcx>,
-        iter: impl Iterator<Item = &'a MatchArm<'p, 'tcx>>,
-        scrut_ty: Ty<'tcx>,
-    ) -> Self
-    where
-        'p: 'a,
-    {
+    fn new(cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>) -> Self {
         let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP));
         let wildcard_row = PatStack::from_pattern(wild_pattern);
-        let mut matrix = Matrix { rows: vec![], wildcard_row };
-        for (row_id, arm) in iter.enumerate() {
+        let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), wildcard_row };
+        for (row_id, arm) in arms.iter().enumerate() {
             let v = MatrixRow {
                 pats: PatStack::from_pattern(arm.pat),
                 parent_row: row_id, // dummy, we won't read it
@@ -806,7 +799,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
         ctor: &Constructor<'tcx>,
     ) -> Matrix<'p, 'tcx> {
         let wildcard_row = self.wildcard_row.pop_head_constructor(pcx, ctor);
-        let mut matrix = Matrix { rows: vec![], wildcard_row };
+        let mut matrix = Matrix { rows: Vec::new(), wildcard_row };
         for (i, row) in self.rows().enumerate() {
             if ctor.is_covered_by(pcx, row.head().ctor()) {
                 let new_row = row.pop_head_constructor(pcx, ctor, i);
@@ -1386,7 +1379,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
     arms: &[MatchArm<'p, 'tcx>],
     scrut_ty: Ty<'tcx>,
 ) -> UsefulnessReport<'p, 'tcx> {
-    let mut matrix = Matrix::new(cx, arms.iter(), scrut_ty);
+    let mut matrix = Matrix::new(cx, arms, scrut_ty);
     let non_exhaustiveness_witnesses =
         compute_exhaustiveness_and_reachability(cx, &mut matrix, true);
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index c9bce80853d..815f2045942 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -1,60 +1,14 @@
 //! Random access inspection of the results of a dataflow analysis.
 
-use crate::{framework::BitSetExt, CloneAnalysis};
+use crate::framework::BitSetExt;
 
-use std::borrow::{Borrow, BorrowMut};
 use std::cmp::Ordering;
 
 #[cfg(debug_assertions)]
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::{self, BasicBlock, Location};
 
-use super::{Analysis, Direction, Effect, EffectIndex, EntrySets, Results, ResultsCloned};
-
-// `AnalysisResults` is needed as an impl such as the following has an unconstrained type
-// parameter:
-// ```
-// impl<'tcx, A, E, R> ResultsCursor<'_, 'tcx, A, R>
-// where
-//     A: Analysis<'tcx>,
-//     E: Borrow<EntrySets<'tcx, A>>,
-//     R: Results<'tcx, A, E>,
-// {}
-// ```
-
-/// A type representing the analysis results consumed by a `ResultsCursor`.
-pub trait AnalysisResults<'tcx, A>: BorrowMut<Results<'tcx, A, Self::EntrySets>>
-where
-    A: Analysis<'tcx>,
-{
-    /// The type containing the entry sets for this `Results` type.
-    ///
-    /// Should be either `EntrySets<'tcx, A>` or `&EntrySets<'tcx, A>`.
-    type EntrySets: Borrow<EntrySets<'tcx, A>>;
-}
-impl<'tcx, A, E> AnalysisResults<'tcx, A> for Results<'tcx, A, E>
-where
-    A: Analysis<'tcx>,
-    E: Borrow<EntrySets<'tcx, A>>,
-{
-    type EntrySets = E;
-}
-impl<'a, 'tcx, A, E> AnalysisResults<'tcx, A> for &'a mut Results<'tcx, A, E>
-where
-    A: Analysis<'tcx>,
-    E: Borrow<EntrySets<'tcx, A>>,
-{
-    type EntrySets = E;
-}
-
-/// A `ResultsCursor` that borrows the underlying `Results`.
-pub type ResultsRefCursor<'res, 'mir, 'tcx, A> =
-    ResultsCursor<'mir, 'tcx, A, &'res mut Results<'tcx, A>>;
-
-/// A `ResultsCursor` which uses a cloned `Analysis` while borrowing the underlying `Results`. This
-/// allows multiple cursors over the same `Results`.
-pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> =
-    ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>>;
+use super::{Analysis, Direction, Effect, EffectIndex, Results};
 
 /// Allows random access inspection of the results of a dataflow analysis.
 ///
@@ -62,15 +16,12 @@ pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> =
 /// the same order as the `DIRECTION` of the analysis. In the worst case—when statements are
 /// visited in *reverse* order—performance will be quadratic in the number of statements in the
 /// block. The order in which basic blocks are inspected has no impact on performance.
-///
-/// A `ResultsCursor` can either own (the default) or borrow the dataflow results it inspects. The
-/// type of ownership is determined by `R` (see `ResultsRefCursor` above).
-pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>>
+pub struct ResultsCursor<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
     body: &'mir mir::Body<'tcx>,
-    results: R,
+    results: Results<'tcx, A>,
     state: A::Domain,
 
     pos: CursorPosition,
@@ -84,7 +35,7 @@ where
     reachable_blocks: BitSet<BasicBlock>,
 }
 
-impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
+impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
@@ -99,30 +50,13 @@ where
     }
 
     /// Unwraps this cursor, returning the underlying `Results`.
-    pub fn into_results(self) -> R {
+    pub fn into_results(self) -> Results<'tcx, A> {
         self.results
     }
-}
-
-impl<'res, 'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>>
-where
-    A: Analysis<'tcx> + CloneAnalysis,
-{
-    /// Creates a new cursor over the same `Results`. Note that the cursor's position is *not*
-    /// copied.
-    pub fn new_cursor(&self) -> Self {
-        Self::new(self.body, self.results.reclone_analysis())
-    }
-}
 
-impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
-where
-    A: Analysis<'tcx>,
-    R: AnalysisResults<'tcx, A>,
-{
     /// Returns a new cursor that can inspect `results`.
-    pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
-        let bottom_value = results.borrow().analysis.bottom_value(body);
+    pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self {
+        let bottom_value = results.analysis.bottom_value(body);
         ResultsCursor {
             body,
             results,
@@ -147,23 +81,23 @@ where
     }
 
     /// Returns the underlying `Results`.
-    pub fn results(&self) -> &Results<'tcx, A, R::EntrySets> {
-        self.results.borrow()
+    pub fn results(&self) -> &Results<'tcx, A> {
+        &self.results
     }
 
     /// Returns the underlying `Results`.
-    pub fn mut_results(&mut self) -> &mut Results<'tcx, A, R::EntrySets> {
-        self.results.borrow_mut()
+    pub fn mut_results(&mut self) -> &mut Results<'tcx, A> {
+        &mut self.results
     }
 
     /// Returns the `Analysis` used to generate the underlying `Results`.
     pub fn analysis(&self) -> &A {
-        &self.results.borrow().analysis
+        &self.results.analysis
     }
 
     /// Returns the `Analysis` used to generate the underlying `Results`.
     pub fn mut_analysis(&mut self) -> &mut A {
-        &mut self.results.borrow_mut().analysis
+        &mut self.results.analysis
     }
 
     /// Resets the cursor to hold the entry set for the given basic block.
@@ -175,7 +109,7 @@ where
         #[cfg(debug_assertions)]
         assert!(self.reachable_blocks.contains(block));
 
-        self.state.clone_from(self.results.borrow().entry_set_for_block(block));
+        self.state.clone_from(self.results.entry_set_for_block(block));
         self.pos = CursorPosition::block_entry(block);
         self.state_needs_reset = false;
     }
@@ -264,11 +198,10 @@ where
             )
         };
 
-        let analysis = &mut self.results.borrow_mut().analysis;
         let target_effect_index = effect.at_index(target.statement_index);
 
         A::Direction::apply_effects_in_range(
-            analysis,
+            &mut self.results.analysis,
             &mut self.state,
             target.block,
             block_data,
@@ -284,12 +217,12 @@ where
     /// This can be used, e.g., to apply the call return effect directly to the cursor without
     /// creating an extra copy of the dataflow state.
     pub fn apply_custom_effect(&mut self, f: impl FnOnce(&mut A, &mut A::Domain)) {
-        f(&mut self.results.borrow_mut().analysis, &mut self.state);
+        f(&mut self.results.analysis, &mut self.state);
         self.state_needs_reset = true;
     }
 }
 
-impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
+impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>
 where
     A: crate::GenKillAnalysis<'tcx>,
     A::Domain: BitSetExt<A::Idx>,
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index ed82b1e8cdc..784872c7ed7 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -5,9 +5,7 @@ use crate::errors::{
 };
 use crate::framework::BitSetExt;
 
-use std::borrow::Borrow;
 use std::ffi::OsString;
-use std::marker::PhantomData;
 use std::path::PathBuf;
 
 use rustc_ast as ast;
@@ -24,42 +22,37 @@ use rustc_span::symbol::{sym, Symbol};
 use super::fmt::DebugWithContext;
 use super::graphviz;
 use super::{
-    visit_results, Analysis, AnalysisDomain, CloneAnalysis, Direction, GenKill, GenKillAnalysis,
-    GenKillSet, JoinSemiLattice, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
-    ResultsVisitor,
+    visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet,
+    JoinSemiLattice, ResultsCursor, ResultsVisitor,
 };
 
 pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>;
 
 /// A dataflow analysis that has converged to fixpoint.
-pub struct Results<'tcx, A, E = EntrySets<'tcx, A>>
+#[derive(Clone)]
+pub struct Results<'tcx, A>
 where
     A: Analysis<'tcx>,
 {
     pub analysis: A,
-    pub(super) entry_sets: E,
-    pub(super) _marker: PhantomData<&'tcx ()>,
+    pub(super) entry_sets: EntrySets<'tcx, A>,
 }
 
-/// `Results` type with a cloned `Analysis` and borrowed entry sets.
-pub type ResultsCloned<'res, 'tcx, A> = Results<'tcx, A, &'res EntrySets<'tcx, A>>;
-
-impl<'tcx, A, E> Results<'tcx, A, E>
+impl<'tcx, A> Results<'tcx, A>
 where
     A: Analysis<'tcx>,
-    E: Borrow<EntrySets<'tcx, A>>,
 {
     /// Creates a `ResultsCursor` that can inspect these `Results`.
     pub fn into_results_cursor<'mir>(
         self,
         body: &'mir mir::Body<'tcx>,
-    ) -> ResultsCursor<'mir, 'tcx, A, Self> {
+    ) -> ResultsCursor<'mir, 'tcx, A> {
         ResultsCursor::new(body, self)
     }
 
     /// Gets the dataflow state for the given block.
     pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain {
-        &self.entry_sets.borrow()[block]
+        &self.entry_sets[block]
     }
 
     pub fn visit_with<'mir>(
@@ -80,52 +73,6 @@ where
         visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
     }
 }
-impl<'tcx, A> Results<'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    /// Creates a `ResultsCursor` that can inspect these `Results`.
-    pub fn as_results_cursor<'a, 'mir>(
-        &'a mut self,
-        body: &'mir mir::Body<'tcx>,
-    ) -> ResultsRefCursor<'a, 'mir, 'tcx, A> {
-        ResultsCursor::new(body, self)
-    }
-}
-impl<'tcx, A> Results<'tcx, A>
-where
-    A: Analysis<'tcx> + CloneAnalysis,
-{
-    /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets.
-    pub fn clone_analysis(&self) -> ResultsCloned<'_, 'tcx, A> {
-        Results {
-            analysis: self.analysis.clone_analysis(),
-            entry_sets: &self.entry_sets,
-            _marker: PhantomData,
-        }
-    }
-
-    /// Creates a `ResultsCursor` that can inspect these `Results`.
-    pub fn cloned_results_cursor<'mir>(
-        &self,
-        body: &'mir mir::Body<'tcx>,
-    ) -> ResultsClonedCursor<'_, 'mir, 'tcx, A> {
-        self.clone_analysis().into_results_cursor(body)
-    }
-}
-impl<'res, 'tcx, A> Results<'tcx, A, &'res EntrySets<'tcx, A>>
-where
-    A: Analysis<'tcx> + CloneAnalysis,
-{
-    /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets.
-    pub fn reclone_analysis(&self) -> Self {
-        Results {
-            analysis: self.analysis.clone_analysis(),
-            entry_sets: self.entry_sets,
-            _marker: PhantomData,
-        }
-    }
-}
 
 /// A solver for dataflow problems.
 pub struct Engine<'mir, 'tcx, A>
@@ -291,29 +238,31 @@ where
             );
         }
 
-        let mut results = Results { analysis, entry_sets, _marker: PhantomData };
+        let results = Results { analysis, entry_sets };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
-            let res = write_graphviz_results(tcx, body, &mut results, pass_name);
+            let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
             if let Err(e) = res {
                 error!("Failed to write graphviz dataflow results: {}", e);
             }
+            results
+        } else {
+            results
         }
-
-        results
     }
 }
 
 // Graphviz
 
 /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
-/// `rustc_mir` attributes and `-Z dump-mir-dataflow`.
+/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are
+/// the same.
 fn write_graphviz_results<'tcx, A>(
     tcx: TyCtxt<'tcx>,
     body: &mir::Body<'tcx>,
-    results: &mut Results<'tcx, A>,
+    results: Results<'tcx, A>,
     pass_name: Option<&'static str>,
-) -> std::io::Result<()>
+) -> (std::io::Result<()>, Results<'tcx, A>)
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
@@ -324,23 +273,30 @@ where
     let def_id = body.source.def_id();
     let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else {
         // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse`
-        return Ok(());
+        return (Ok(()), results);
     };
 
-    let mut file = match attrs.output_path(A::NAME) {
-        Some(path) => {
-            debug!("printing dataflow results for {:?} to {}", def_id, path.display());
-            if let Some(parent) = path.parent() {
-                fs::create_dir_all(parent)?;
+    let file = try {
+        match attrs.output_path(A::NAME) {
+            Some(path) => {
+                debug!("printing dataflow results for {:?} to {}", def_id, path.display());
+                if let Some(parent) = path.parent() {
+                    fs::create_dir_all(parent)?;
+                }
+                let f = fs::File::create(&path)?;
+                io::BufWriter::new(f)
             }
-            io::BufWriter::new(fs::File::create(&path)?)
-        }
 
-        None if dump_enabled(tcx, A::NAME, def_id) => {
-            create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
-        }
+            None if dump_enabled(tcx, A::NAME, def_id) => {
+                create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
+            }
 
-        _ => return Ok(()),
+            _ => return (Ok(()), results),
+        }
+    };
+    let mut file = match file {
+        Ok(f) => f,
+        Err(e) => return (Err(e), results),
     };
 
     let style = match attrs.formatter {
@@ -356,11 +312,14 @@ where
     if tcx.sess.opts.unstable_opts.graphviz_dark_mode {
         render_opts.push(dot::RenderOption::DarkTheme);
     }
-    with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?);
+    let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts));
 
-    file.write_all(&buf)?;
+    let lhs = try {
+        r?;
+        file.write_all(&buf)?;
+    };
 
-    Ok(())
+    (lhs, graphviz.into_results())
 }
 
 #[derive(Default)]
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 832d1cba9a7..fa16cac3168 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -12,7 +12,7 @@ use rustc_middle::mir::graphviz_safe_def_name;
 use rustc_middle::mir::{self, BasicBlock, Body, Location};
 
 use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
-use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
+use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor};
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub(crate) enum OutputStyle {
@@ -29,27 +29,31 @@ impl OutputStyle {
     }
 }
 
-pub(crate) struct Formatter<'res, 'mir, 'tcx, A>
+pub(crate) struct Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
     body: &'mir Body<'tcx>,
-    results: RefCell<&'res mut Results<'tcx, A>>,
+    results: RefCell<Option<Results<'tcx, A>>>,
     style: OutputStyle,
     reachable: BitSet<BasicBlock>,
 }
 
-impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
+impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
     pub(crate) fn new(
         body: &'mir Body<'tcx>,
-        results: &'res mut Results<'tcx, A>,
+        results: Results<'tcx, A>,
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
-        Formatter { body, results: results.into(), style, reachable }
+        Formatter { body, results: Some(results).into(), style, reachable }
+    }
+
+    pub(crate) fn into_results(self) -> Results<'tcx, A> {
+        self.results.into_inner().unwrap()
     }
 }
 
@@ -69,7 +73,7 @@ fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec<CfgEdge> {
         .collect()
 }
 
-impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, '_, 'tcx, A>
+impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
@@ -88,14 +92,19 @@ where
 
     fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
         let mut label = Vec::new();
-        let mut results = self.results.borrow_mut();
-        let mut fmt = BlockFormatter {
-            results: results.as_results_cursor(self.body),
-            style: self.style,
-            bg: Background::Light,
-        };
+        self.results.replace_with(|results| {
+            // `Formatter::result` is a `RefCell<Option<_>>` so we can replace
+            // the value with `None`, move it into the results cursor, move it
+            // back out, and return it to the refcell wrapped in `Some`.
+            let mut fmt = BlockFormatter {
+                results: results.take().unwrap().into_results_cursor(self.body),
+                style: self.style,
+                bg: Background::Light,
+            };
 
-        fmt.write_node_label(&mut label, *block).unwrap();
+            fmt.write_node_label(&mut label, *block).unwrap();
+            Some(fmt.results.into_results())
+        });
         dot::LabelText::html(String::from_utf8(label).unwrap())
     }
 
@@ -109,7 +118,7 @@ where
     }
 }
 
-impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'_, 'mir, 'tcx, A>
+impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
@@ -143,16 +152,16 @@ where
     }
 }
 
-struct BlockFormatter<'res, 'mir, 'tcx, A>
+struct BlockFormatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    results: ResultsRefCursor<'res, 'mir, 'tcx, A>,
+    results: ResultsCursor<'mir, 'tcx, A>,
     bg: Background,
     style: OutputStyle,
 }
 
-impl<'res, 'mir, 'tcx, A> BlockFormatter<'res, 'mir, 'tcx, A>
+impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index a5ae1edf221..b7dfbe0710d 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -45,9 +45,9 @@ pub mod graphviz;
 pub mod lattice;
 mod visitor;
 
-pub use self::cursor::{ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
+pub use self::cursor::ResultsCursor;
 pub use self::direction::{Backward, Direction, Forward};
-pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
+pub use self::engine::{Engine, Results};
 pub use self::lattice::{JoinSemiLattice, MaybeReachable};
 pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
 
@@ -246,21 +246,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
     }
 }
 
-/// Defines an `Analysis` which can be cloned for use in multiple `ResultsCursor`s or
-/// `ResultsVisitor`s. Note this need not be a full clone, only enough of one to be used with a new
-/// `ResultsCursor` or `ResultsVisitor`
-pub trait CloneAnalysis {
-    fn clone_analysis(&self) -> Self;
-}
-impl<'tcx, A> CloneAnalysis for A
-where
-    A: Analysis<'tcx> + Copy,
-{
-    fn clone_analysis(&self) -> Self {
-        *self
-    }
-}
-
 /// A gen/kill dataflow problem.
 ///
 /// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 9cce5b26cd3..1da5057ff40 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -267,8 +267,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
     let body = analysis.body;
 
     let mut cursor =
-        Results { entry_sets: analysis.mock_entry_sets(), analysis, _marker: PhantomData }
-            .into_results_cursor(body);
+        Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
 
     cursor.allow_unreachable();
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index 3cfa7cc1c02..e3648bb4076 100644
--- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -1,8 +1,6 @@
-use std::borrow::Borrow;
-
 use rustc_middle::mir::{self, BasicBlock, Location};
 
-use super::{Analysis, Direction, EntrySets, Results};
+use super::{Analysis, Direction, Results};
 
 /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
 /// dataflow state at that location.
@@ -143,10 +141,9 @@ pub trait ResultsVisitable<'tcx> {
     );
 }
 
-impl<'tcx, A, E> ResultsVisitable<'tcx> for Results<'tcx, A, E>
+impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
 where
     A: Analysis<'tcx>,
-    E: Borrow<EntrySets<'tcx, A>>,
 {
     type FlowState = A::Domain;
 
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 5a58e3af8be..26fc903973f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -5,7 +5,7 @@ use rustc_middle::mir::*;
 use std::borrow::Cow;
 
 use super::MaybeBorrowedLocals;
-use crate::{GenKill, ResultsClonedCursor};
+use crate::{GenKill, ResultsCursor};
 
 #[derive(Clone)]
 pub struct MaybeStorageLive<'a> {
@@ -18,12 +18,6 @@ impl<'a> MaybeStorageLive<'a> {
     }
 }
 
-impl crate::CloneAnalysis for MaybeStorageLive<'_> {
-    fn clone_analysis(&self) -> Self {
-        self.clone()
-    }
-}
-
 impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
     type Domain = BitSet<Local>;
 
@@ -158,28 +152,21 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
     }
 }
 
-type BorrowedLocalsResults<'res, 'mir, 'tcx> =
-    ResultsClonedCursor<'res, 'mir, 'tcx, MaybeBorrowedLocals>;
+type BorrowedLocalsResults<'mir, 'tcx> = ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>;
 
 /// Dataflow analysis that determines whether each local requires storage at a
 /// given location; i.e. whether its storage can go away without being observed.
-pub struct MaybeRequiresStorage<'res, 'mir, 'tcx> {
-    borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>,
+pub struct MaybeRequiresStorage<'mir, 'tcx> {
+    borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>,
 }
 
-impl<'res, 'mir, 'tcx> MaybeRequiresStorage<'res, 'mir, 'tcx> {
-    pub fn new(borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>) -> Self {
+impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
+    pub fn new(borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>) -> Self {
         MaybeRequiresStorage { borrowed_locals }
     }
 }
 
-impl crate::CloneAnalysis for MaybeRequiresStorage<'_, '_, '_> {
-    fn clone_analysis(&self) -> Self {
-        Self { borrowed_locals: self.borrowed_locals.new_cursor() }
-    }
-}
-
-impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
+impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "requires_storage";
@@ -198,7 +185,7 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
+impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
     type Idx = Local;
 
     fn domain_size(&self, body: &Body<'tcx>) -> usize {
@@ -355,7 +342,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> {
+impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
     /// Kill locals that are fully moved and have not been borrowed.
     fn check_for_move(&mut self, trans: &mut impl GenKill<Local>, loc: Location) {
         let body = self.borrowed_locals.body();
@@ -364,12 +351,12 @@ impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> {
     }
 }
 
-struct MoveVisitor<'a, 'res, 'mir, 'tcx, T> {
-    borrowed_locals: &'a mut BorrowedLocalsResults<'res, 'mir, 'tcx>,
+struct MoveVisitor<'a, 'mir, 'tcx, T> {
+    borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>,
     trans: &'a mut T,
 }
 
-impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx, T>
+impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx, T>
 where
     T: GenKill<Local>,
 {
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index d218f033d62..f0b21fd4184 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
+#![feature(try_blocks)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
@@ -23,7 +24,7 @@ pub use self::framework::{
     fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
     JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor,
 };
-use self::framework::{Backward, CloneAnalysis, ResultsClonedCursor, SwitchIntEdgeEffects};
+use self::framework::{Backward, SwitchIntEdgeEffects};
 use self::move_paths::MoveData;
 
 pub mod debuginfo;
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 1373596fd2b..79a1509531d 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -679,15 +679,15 @@ fn locals_live_across_suspend_points<'tcx>(
     let borrowed_locals_results =
         MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint();
 
-    let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body);
+    let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body);
 
     // Calculate the MIR locals that we actually need to keep storage around
     // for.
-    let mut requires_storage_results =
-        MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body))
+    let mut requires_storage_cursor =
+        MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
             .into_engine(tcx, body)
-            .iterate_to_fixpoint();
-    let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness = MaybeLiveLocals
@@ -763,7 +763,7 @@ fn locals_live_across_suspend_points<'tcx>(
         body,
         &saved_locals,
         always_live_locals.clone(),
-        requires_storage_results,
+        requires_storage_cursor.into_results(),
     );
 
     LivenessInfo {
@@ -828,7 +828,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
     body: &'mir Body<'tcx>,
     saved_locals: &CoroutineSavedLocals,
     always_live_locals: BitSet<Local>,
-    mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'_, 'mir, 'tcx>>,
+    mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
 ) -> BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal> {
     assert_eq!(body.local_decls.len(), saved_locals.domain_size());
 
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 224f3f36a3f..647c92785e1 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -4,9 +4,8 @@ use rustc_ast::*;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::definitions::*;
 use rustc_span::hygiene::LocalExpnId;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
 pub(crate) fn collect_definitions(
@@ -30,16 +29,19 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
     fn create_def(
         &mut self,
         node_id: NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
         let parent_def = self.parent_def;
-        debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
+        debug!(
+            "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
+            node_id, def_kind, parent_def
+        );
         self.resolver.create_def(
             parent_def,
             node_id,
-            data,
+            name,
             def_kind,
             self.expansion.to_expn_id(),
             span.with_parent(None),
@@ -76,8 +78,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
             self.visit_macro_invoc(field.id);
         } else {
             let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
-            let def =
-                self.create_def(field.id, DefPathData::ValueNs(name), DefKind::Field, field.span);
+            let def = self.create_def(field.id, name, DefKind::Field, field.span);
             self.with_parent(def, |this| visit::walk_field_def(this, field));
         }
     }
@@ -97,40 +98,36 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into, the better
         let mut opt_macro_data = None;
-        let ty_data = DefPathData::TypeNs(i.ident.name);
-        let value_data = DefPathData::ValueNs(i.ident.name);
-        let (def_data, def_kind) = match &i.kind {
-            ItemKind::Impl(i) => {
-                (DefPathData::Impl, DefKind::Impl { of_trait: i.of_trait.is_some() })
-            }
-            ItemKind::ForeignMod(..) => (DefPathData::ForeignMod, DefKind::ForeignMod),
-            ItemKind::Mod(..) => (ty_data, DefKind::Mod),
-            ItemKind::Trait(..) => (ty_data, DefKind::Trait),
-            ItemKind::TraitAlias(..) => (ty_data, DefKind::TraitAlias),
-            ItemKind::Enum(..) => (ty_data, DefKind::Enum),
-            ItemKind::Struct(..) => (ty_data, DefKind::Struct),
-            ItemKind::Union(..) => (ty_data, DefKind::Union),
-            ItemKind::ExternCrate(..) => (ty_data, DefKind::ExternCrate),
-            ItemKind::TyAlias(..) => (ty_data, DefKind::TyAlias),
-            ItemKind::Static(s) => (value_data, DefKind::Static(s.mutability)),
-            ItemKind::Const(..) => (value_data, DefKind::Const),
-            ItemKind::Fn(..) => (value_data, DefKind::Fn),
+        let def_kind = match &i.kind {
+            ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() },
+            ItemKind::ForeignMod(..) => DefKind::ForeignMod,
+            ItemKind::Mod(..) => DefKind::Mod,
+            ItemKind::Trait(..) => DefKind::Trait,
+            ItemKind::TraitAlias(..) => DefKind::TraitAlias,
+            ItemKind::Enum(..) => DefKind::Enum,
+            ItemKind::Struct(..) => DefKind::Struct,
+            ItemKind::Union(..) => DefKind::Union,
+            ItemKind::ExternCrate(..) => DefKind::ExternCrate,
+            ItemKind::TyAlias(..) => DefKind::TyAlias,
+            ItemKind::Static(s) => DefKind::Static(s.mutability),
+            ItemKind::Const(..) => DefKind::Const,
+            ItemKind::Fn(..) => DefKind::Fn,
             ItemKind::MacroDef(..) => {
                 let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
                 let macro_kind = macro_data.ext.macro_kind();
                 opt_macro_data = Some(macro_data);
-                (DefPathData::MacroNs(i.ident.name), DefKind::Macro(macro_kind))
+                DefKind::Macro(macro_kind)
             }
             ItemKind::MacCall(..) => {
                 visit::walk_item(self, i);
                 return self.visit_macro_invoc(i.id);
             }
-            ItemKind::GlobalAsm(..) => (DefPathData::GlobalAsm, DefKind::GlobalAsm),
+            ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
             }
         };
-        let def_id = self.create_def(i.id, def_data, def_kind, i.span);
+        let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
 
         if let Some(macro_data) = opt_macro_data {
             self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
@@ -144,7 +141,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
                         if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
                             this.create_def(
                                 ctor_node_id,
-                                DefPathData::Ctor,
+                                kw::Empty,
                                 DefKind::Ctor(CtorOf::Struct, ctor_kind),
                                 i.span,
                             );
@@ -174,12 +171,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
                 // then the closure_def will never be used, and we should avoid generating a
                 // def-id for it.
                 if let Some(body) = body {
-                    let closure_def = self.create_def(
-                        closure_id,
-                        DefPathData::ClosureExpr,
-                        DefKind::Closure,
-                        span,
-                    );
+                    let closure_def =
+                        self.create_def(closure_id, kw::Empty, DefKind::Closure, span);
                     self.with_parent(closure_def, |this| this.visit_block(body));
                 }
                 return;
@@ -190,21 +183,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
-        self.create_def(id, DefPathData::Use, DefKind::Use, use_tree.span);
+        self.create_def(id, kw::Empty, DefKind::Use, use_tree.span);
         visit::walk_use_tree(self, use_tree, id);
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        let (def_data, def_kind) = match fi.kind {
-            ForeignItemKind::Static(_, mt, _) => {
-                (DefPathData::ValueNs(fi.ident.name), DefKind::Static(mt))
-            }
-            ForeignItemKind::Fn(_) => (DefPathData::ValueNs(fi.ident.name), DefKind::Fn),
-            ForeignItemKind::TyAlias(_) => (DefPathData::TypeNs(fi.ident.name), DefKind::ForeignTy),
+        let def_kind = match fi.kind {
+            ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt),
+            ForeignItemKind::Fn(_) => DefKind::Fn,
+            ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
             ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
         };
 
-        let def = self.create_def(fi.id, def_data, def_kind, fi.span);
+        let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span);
 
         self.with_parent(def, |this| visit::walk_foreign_item(this, fi));
     }
@@ -213,13 +204,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
         if v.is_placeholder {
             return self.visit_macro_invoc(v.id);
         }
-        let def =
-            self.create_def(v.id, DefPathData::TypeNs(v.ident.name), DefKind::Variant, v.span);
+        let def = self.create_def(v.id, v.ident.name, DefKind::Variant, v.span);
         self.with_parent(def, |this| {
             if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&v.data) {
                 this.create_def(
                     ctor_node_id,
-                    DefPathData::Ctor,
+                    kw::Empty,
                     DefKind::Ctor(CtorOf::Variant, ctor_kind),
                     v.span,
                 );
@@ -242,15 +232,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             self.visit_macro_invoc(param.id);
             return;
         }
-        let name = param.ident.name;
-        let (def_path_data, def_kind) = match param.kind {
-            GenericParamKind::Lifetime { .. } => {
-                (DefPathData::LifetimeNs(name), DefKind::LifetimeParam)
-            }
-            GenericParamKind::Type { .. } => (DefPathData::TypeNs(name), DefKind::TyParam),
-            GenericParamKind::Const { .. } => (DefPathData::ValueNs(name), DefKind::ConstParam),
+        let def_kind = match param.kind {
+            GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
+            GenericParamKind::Type { .. } => DefKind::TyParam,
+            GenericParamKind::Const { .. } => DefKind::ConstParam,
         };
-        self.create_def(param.id, def_path_data, def_kind, param.ident.span);
+        self.create_def(param.id, param.ident.name, def_kind, param.ident.span);
 
         // impl-Trait can happen inside generic parameters, like
         // ```
@@ -264,14 +251,14 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
-        let (def_data, def_kind) = match &i.kind {
-            AssocItemKind::Fn(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocFn),
-            AssocItemKind::Const(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocConst),
-            AssocItemKind::Type(..) => (DefPathData::TypeNs(i.ident.name), DefKind::AssocTy),
+        let def_kind = match &i.kind {
+            AssocItemKind::Fn(..) => DefKind::AssocFn,
+            AssocItemKind::Const(..) => DefKind::AssocConst,
+            AssocItemKind::Type(..) => DefKind::AssocTy,
             AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
         };
 
-        let def = self.create_def(i.id, def_data, def_kind, i.span);
+        let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
         self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
     }
 
@@ -283,12 +270,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_anon_const(&mut self, constant: &'a AnonConst) {
-        let def = self.create_def(
-            constant.id,
-            DefPathData::AnonConst,
-            DefKind::AnonConst,
-            constant.value.span,
-        );
+        let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
         self.with_parent(def, |this| visit::walk_anon_const(this, constant));
     }
 
@@ -298,25 +280,21 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ExprKind::Closure(ref closure) => {
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
-                let closure_def =
-                    self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span);
+                let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
                 match closure.asyncness {
-                    Async::Yes { closure_id, .. } => self.create_def(
-                        closure_id,
-                        DefPathData::ClosureExpr,
-                        DefKind::Closure,
-                        expr.span,
-                    ),
+                    Async::Yes { closure_id, .. } => {
+                        self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span)
+                    }
                     Async::No => closure_def,
                 }
             }
             ExprKind::Gen(_, _, _) => {
-                self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span)
+                self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
             }
             ExprKind::ConstBlock(ref constant) => {
                 let def = self.create_def(
                     constant.id,
-                    DefPathData::AnonConst,
+                    kw::Empty,
                     DefKind::InlineConst,
                     constant.value.span,
                 );
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 208391cc019..70e0eb12c01 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -45,7 +45,6 @@ use rustc_hir::def::NonMacroAttrKind;
 use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_index::IndexVec;
 use rustc_metadata::creader::{CStore, CrateLoader};
@@ -1212,11 +1211,12 @@ impl<'tcx> Resolver<'_, 'tcx> {
         &mut self,
         parent: LocalDefId,
         node_id: ast::NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         expn_id: ExpnId,
         span: Span,
     ) -> LocalDefId {
+        let data = def_kind.def_path_data(name);
         assert!(
             !self.node_id_to_def_id.contains_key(&node_id),
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 1fd8542b2a6..18ca347de97 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -379,14 +379,13 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             hir::definitions::DefPathData::ForeignMod => "F", // Not specified in v0's <namespace>
             hir::definitions::DefPathData::TypeNs(..) => "t",
             hir::definitions::DefPathData::ValueNs(..) => "v",
-            hir::definitions::DefPathData::ClosureExpr => "C",
+            hir::definitions::DefPathData::Closure => "C",
             hir::definitions::DefPathData::Ctor => "c",
             hir::definitions::DefPathData::AnonConst => "k",
-            hir::definitions::DefPathData::ImplTrait => "i",
+            hir::definitions::DefPathData::OpaqueTy => "i",
             hir::definitions::DefPathData::CrateRoot
             | hir::definitions::DefPathData::Use
             | hir::definitions::DefPathData::GlobalAsm
-            | hir::definitions::DefPathData::ImplTraitAssocTy
             | hir::definitions::DefPathData::MacroNs(..)
             | hir::definitions::DefPathData::LifetimeNs(..) => {
                 bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 88989806997..e002e345ae6 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -770,17 +770,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             // Uppercase categories are more stable than lowercase ones.
             DefPathData::TypeNs(_) => 't',
             DefPathData::ValueNs(_) => 'v',
-            DefPathData::ClosureExpr => 'C',
+            DefPathData::Closure => 'C',
             DefPathData::Ctor => 'c',
             DefPathData::AnonConst => 'k',
-            DefPathData::ImplTrait => 'i',
+            DefPathData::OpaqueTy => 'i',
 
             // These should never show up as `path_append` arguments.
             DefPathData::CrateRoot
             | DefPathData::Use
             | DefPathData::GlobalAsm
             | DefPathData::Impl
-            | DefPathData::ImplTraitAssocTy
             | DefPathData::MacroNs(_)
             | DefPathData::LifetimeNs(_) => {
                 bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index d753aa8618e..41db8059cbe 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -55,3 +55,6 @@ trait_selection_trait_has_no_impls = this trait has no implementations, consider
 
 trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
+
+trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}`
+    .help = expect either a generic argument name or {"`{Self}`"} as format argument
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index ba019c4ff6f..fbe6e2bd5b8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -321,7 +321,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(Symbol, Span);
+pub struct OnUnimplementedFormatString {
+    symbol: Symbol,
+    span: Span,
+    is_diagnostic_namespace_variant: bool,
+}
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -401,6 +405,14 @@ impl IgnoredDiagnosticOption {
     }
 }
 
+#[derive(LintDiagnostic)]
+#[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)]
+#[help]
+pub struct UnknownFormatParameterForOnUnimplementedAttr {
+    argument_name: Symbol,
+    trait_name: Symbol,
+}
+
 impl<'tcx> OnUnimplementedDirective {
     fn parse(
         tcx: TyCtxt<'tcx>,
@@ -414,8 +426,14 @@ impl<'tcx> OnUnimplementedDirective {
         let mut item_iter = items.iter();
 
         let parse_value = |value_str, value_span| {
-            OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span, value_span)
-                .map(Some)
+            OnUnimplementedFormatString::try_parse(
+                tcx,
+                item_def_id,
+                value_str,
+                value_span,
+                is_diagnostic_namespace_variant,
+            )
+            .map(Some)
         };
 
         let condition = if is_root {
@@ -552,15 +570,15 @@ impl<'tcx> OnUnimplementedDirective {
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.message.as_ref().map(|f| f.1),
-                            aggr.message.as_ref().map(|f| f.1),
+                            directive.message.as_ref().map(|f| f.span),
+                            aggr.message.as_ref().map(|f| f.span),
                             "message",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.label.as_ref().map(|f| f.1),
-                            aggr.label.as_ref().map(|f| f.1),
+                            directive.label.as_ref().map(|f| f.span),
+                            aggr.label.as_ref().map(|f| f.span),
                             "label",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
@@ -573,8 +591,8 @@ impl<'tcx> OnUnimplementedDirective {
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.parent_label.as_ref().map(|f| f.1),
-                            aggr.parent_label.as_ref().map(|f| f.1),
+                            directive.parent_label.as_ref().map(|f| f.span),
+                            aggr.parent_label.as_ref().map(|f| f.span),
                             "parent_label",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
@@ -634,7 +652,7 @@ impl<'tcx> OnUnimplementedDirective {
                         item_def_id,
                         value,
                         attr.span,
-                        attr.span,
+                        is_diagnostic_namespace_variant,
                     )?),
                     notes: Vec::new(),
                     parent_label: None,
@@ -713,7 +731,12 @@ impl<'tcx> OnUnimplementedDirective {
                             // `with_no_visible_paths` is also used when generating the options,
                             // so we need to match it here.
                             ty::print::with_no_visible_paths!(
-                                OnUnimplementedFormatString(v, cfg.span).format(
+                                OnUnimplementedFormatString {
+                                    symbol: v,
+                                    span: cfg.span,
+                                    is_diagnostic_namespace_variant: false
+                                }
+                                .format(
                                     tcx,
                                     trait_ref,
                                     &options_map
@@ -761,20 +784,19 @@ impl<'tcx> OnUnimplementedFormatString {
         tcx: TyCtxt<'tcx>,
         item_def_id: DefId,
         from: Symbol,
-        err_sp: Span,
         value_span: Span,
+        is_diagnostic_namespace_variant: bool,
     ) -> Result<Self, ErrorGuaranteed> {
-        let result = OnUnimplementedFormatString(from, value_span);
-        result.verify(tcx, item_def_id, err_sp)?;
+        let result = OnUnimplementedFormatString {
+            symbol: from,
+            span: value_span,
+            is_diagnostic_namespace_variant,
+        };
+        result.verify(tcx, item_def_id)?;
         Ok(result)
     }
 
-    fn verify(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        item_def_id: DefId,
-        span: Span,
-    ) -> Result<(), ErrorGuaranteed> {
+    fn verify(&self, tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<(), ErrorGuaranteed> {
         let trait_def_id = if tcx.is_trait(item_def_id) {
             item_def_id
         } else {
@@ -783,7 +805,7 @@ impl<'tcx> OnUnimplementedFormatString {
         };
         let trait_name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(item_def_id);
-        let s = self.0.as_str();
+        let s = self.symbol.as_str();
         let parser = Parser::new(s, None, None, false, ParseMode::Format);
         let mut result = Ok(());
         for token in parser {
@@ -793,24 +815,40 @@ impl<'tcx> OnUnimplementedFormatString {
                     Position::ArgumentNamed(s) => {
                         match Symbol::intern(s) {
                             // `{ThisTraitsName}` is allowed
-                            s if s == trait_name => (),
-                            s if ALLOWED_FORMAT_SYMBOLS.contains(&s) => (),
+                            s if s == trait_name && !self.is_diagnostic_namespace_variant => (),
+                            s if ALLOWED_FORMAT_SYMBOLS.contains(&s)
+                                && !self.is_diagnostic_namespace_variant =>
+                            {
+                                ()
+                            }
                             // So is `{A}` if A is a type parameter
                             s if generics.params.iter().any(|param| param.name == s) => (),
                             s => {
-                                result = Err(struct_span_err!(
-                                    tcx.sess,
-                                    span,
-                                    E0230,
-                                    "there is no parameter `{}` on {}",
-                                    s,
-                                    if trait_def_id == item_def_id {
-                                        format!("trait `{trait_name}`")
-                                    } else {
-                                        "impl".to_string()
-                                    }
-                                )
-                                .emit());
+                                if self.is_diagnostic_namespace_variant {
+                                    tcx.emit_spanned_lint(
+                                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                                        tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
+                                        self.span,
+                                        UnknownFormatParameterForOnUnimplementedAttr {
+                                            argument_name: s,
+                                            trait_name,
+                                        },
+                                    );
+                                } else {
+                                    result = Err(struct_span_err!(
+                                        tcx.sess,
+                                        self.span,
+                                        E0230,
+                                        "there is no parameter `{}` on {}",
+                                        s,
+                                        if trait_def_id == item_def_id {
+                                            format!("trait `{trait_name}`")
+                                        } else {
+                                            "impl".to_string()
+                                        }
+                                    )
+                                    .emit());
+                                }
                             }
                         }
                     }
@@ -818,7 +856,7 @@ impl<'tcx> OnUnimplementedFormatString {
                     Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
                         let reported = struct_span_err!(
                             tcx.sess,
-                            span,
+                            self.span,
                             E0231,
                             "only named substitution parameters are allowed"
                         )
@@ -857,37 +895,42 @@ impl<'tcx> OnUnimplementedFormatString {
             .collect::<FxHashMap<Symbol, String>>();
         let empty_string = String::new();
 
-        let s = self.0.as_str();
+        let s = self.symbol.as_str();
         let parser = Parser::new(s, None, None, false, ParseMode::Format);
         let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string);
         parser
             .map(|p| match p {
-                Piece::String(s) => s,
+                Piece::String(s) => s.to_owned(),
                 Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => {
-                        let s = Symbol::intern(s);
+                    Position::ArgumentNamed(arg) => {
+                        let s = Symbol::intern(arg);
                         match generic_map.get(&s) {
-                            Some(val) => val,
-                            None if s == name => &trait_str,
+                            Some(val) => val.to_string(),
+                            None if self.is_diagnostic_namespace_variant => {
+                                format!("{{{arg}}}")
+                            }
+                            None if s == name => trait_str.clone(),
                             None => {
                                 if let Some(val) = options.get(&s) {
-                                    val
+                                    val.clone()
                                 } else if s == sym::from_desugaring {
                                     // don't break messages using these two arguments incorrectly
-                                    &empty_string
-                                } else if s == sym::ItemContext {
-                                    item_context
+                                    String::new()
+                                } else if s == sym::ItemContext
+                                    && !self.is_diagnostic_namespace_variant
+                                {
+                                    item_context.clone()
                                 } else if s == sym::integral {
-                                    "{integral}"
+                                    String::from("{integral}")
                                 } else if s == sym::integer_ {
-                                    "{integer}"
+                                    String::from("{integer}")
                                 } else if s == sym::float {
-                                    "{float}"
+                                    String::from("{float}")
                                 } else {
                                     bug!(
                                         "broken on_unimplemented {:?} for {:?}: \
                                       no argument matching {:?}",
-                                        self.0,
+                                        self.symbol,
                                         trait_ref,
                                         s
                                     )
@@ -895,7 +938,7 @@ impl<'tcx> OnUnimplementedFormatString {
                             }
                         }
                     }
-                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
+                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.symbol),
                 },
             })
             .collect()
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index c6ff7e2a9ef..b28e3d5c412 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -424,11 +424,23 @@ fn fn_abi_sanity_check<'tcx>(
             }
             PassMode::Indirect { meta_attrs: None, .. } => {
                 // No metadata, must be sized.
+                // Conceptually, unsized arguments must be copied around, which requires dynamically
+                // determining their size, which we cannot do without metadata. Consult
+                // t-opsem before removing this check.
                 assert!(arg.layout.is_sized());
             }
             PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
                 // With metadata. Must be unsized and not on the stack.
                 assert!(arg.layout.is_unsized() && !on_stack);
+                // Also, must not be `extern` type.
+                let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {});
+                if matches!(tail.kind(), ty::Foreign(..)) {
+                    // These types do not have metadata, so having `meta_attrs` is bogus.
+                    // Conceptually, unsized arguments must be copied around, which requires dynamically
+                    // determining their size. Therefore, we cannot allow `extern` types here. Consult
+                    // t-opsem before removing this check.
+                    panic!("unsized arguments must not be `extern` types");
+                }
             }
         }
     }
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 82cd0cc50d2..7a81570e55b 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
@@ -254,8 +253,7 @@ fn associated_type_for_impl_trait_in_trait(
     assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
 
     let span = tcx.def_span(opaque_ty_def_id);
-    let trait_assoc_ty =
-        tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
+    let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
 
     let local_def_id = trait_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
@@ -356,8 +354,7 @@ fn associated_type_for_impl_trait_in_impl(
         hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
         hir::FnRetTy::Return(ty) => ty.span,
     };
-    let impl_assoc_ty =
-        tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
+    let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, kw::Empty, DefKind::AssocTy);
 
     let local_def_id = impl_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 27afd3b8017..373b4aee47a 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -233,7 +233,10 @@ unsafe impl<T> SliceIndex<[T]> for usize {
         // cannot be longer than `isize::MAX`. They also guarantee that
         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
         // so the call to `add` is safe.
-        unsafe { slice.as_ptr().add(self) }
+        unsafe {
+            crate::intrinsics::assume(self < slice.len());
+            slice.as_ptr().add(self)
+        }
     }
 
     #[inline]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5957f9fd443..dec9f194863 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1045,11 +1045,11 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// let slice = ['r', 'u', 's', 't'];
-    /// let mut iter = slice.windows(2);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
-    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
-    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.windows(3);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
+    /// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
     /// assert!(iter.next().is_none());
     /// ```
     ///
diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs
index a90ff928ced..b9f32d16e01 100644
--- a/library/portable-simd/crates/core_simd/tests/pointers.rs
+++ b/library/portable-simd/crates/core_simd/tests/pointers.rs
@@ -1,4 +1,4 @@
-#![feature(portable_simd, strict_provenance)]
+#![feature(portable_simd, strict_provenance, exposed_provenance)]
 
 use core_simd::simd::{
     ptr::{SimdConstPtr, SimdMutPtr},
diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs
index 4a19d0a44c3..ea4b573aeb9 100644
--- a/src/librustdoc/html/escape.rs
+++ b/src/librustdoc/html/escape.rs
@@ -38,3 +38,39 @@ impl<'a> fmt::Display for Escape<'a> {
         Ok(())
     }
 }
+
+/// Wrapper struct which will emit the HTML-escaped version of the contained
+/// string when passed to a format string.
+///
+/// This is only safe to use for text nodes. If you need your output to be
+/// safely contained in an attribute, use [`Escape`]. If you don't know the
+/// difference, use [`Escape`].
+pub(crate) struct EscapeBodyText<'a>(pub &'a str);
+
+impl<'a> fmt::Display for EscapeBodyText<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Because the internet is always right, turns out there's not that many
+        // characters to escape: http://stackoverflow.com/questions/7381974
+        let EscapeBodyText(s) = *self;
+        let pile_o_bits = s;
+        let mut last = 0;
+        for (i, ch) in s.char_indices() {
+            let s = match ch {
+                '>' => "&gt;",
+                '<' => "&lt;",
+                '&' => "&amp;",
+                _ => continue,
+            };
+            fmt.write_str(&pile_o_bits[last..i])?;
+            fmt.write_str(s)?;
+            // NOTE: we only expect single byte characters here - which is fine as long as we
+            // only match single byte characters
+            last = i + 1;
+        }
+
+        if last < s.len() {
+            fmt.write_str(&pile_o_bits[last..])?;
+        }
+        Ok(())
+    }
+}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b762c8a1ce6..1cdc792a819 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -6,7 +6,7 @@
 //! Use the `render_with_highlighting` to highlight some rust code.
 
 use crate::clean::PrimitiveType;
-use crate::html::escape::Escape;
+use crate::html::escape::EscapeBodyText;
 use crate::html::render::{Context, LinkFromSrc};
 
 use std::collections::VecDeque;
@@ -189,7 +189,7 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> {
             && can_merge(current_class, Some(*parent_class), "")
         {
             for (text, class) in self.pending_elems.iter() {
-                string(self.out, Escape(text), *class, &self.href_context, false);
+                string(self.out, EscapeBodyText(text), *class, &self.href_context, false);
             }
         } else {
             // We only want to "open" the tag ourselves if we have more than one pending and if the
@@ -202,7 +202,13 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> {
                 None
             };
             for (text, class) in self.pending_elems.iter() {
-                string(self.out, Escape(text), *class, &self.href_context, close_tag.is_none());
+                string(
+                    self.out,
+                    EscapeBodyText(text),
+                    *class,
+                    &self.href_context,
+                    close_tag.is_none(),
+                );
             }
             if let Some(close_tag) = close_tag {
                 exit_span(self.out, close_tag);
diff --git a/src/librustdoc/html/highlight/fixtures/dos_line.html b/src/librustdoc/html/highlight/fixtures/dos_line.html
index 30b50ca7c66..b98e6712590 100644
--- a/src/librustdoc/html/highlight/fixtures/dos_line.html
+++ b/src/librustdoc/html/highlight/fixtures/dos_line.html
@@ -1,3 +1,3 @@
 <span class="kw">pub fn </span>foo() {
-<span class="macro">println!</span>(<span class="string">&quot;foo&quot;</span>);
+<span class="macro">println!</span>(<span class="string">"foo"</span>);
 }
diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html
index fced2eacd9e..aa735e81597 100644
--- a/src/librustdoc/html/highlight/fixtures/sample.html
+++ b/src/librustdoc/html/highlight/fixtures/sample.html
@@ -8,12 +8,12 @@
 .lifetime { color: #B76514; }
 .question-mark { color: #ff9011; }
 </style>
-<pre><code><span class="attr">#![crate_type = <span class="string">&quot;lib&quot;</span>]
+<pre><code><span class="attr">#![crate_type = <span class="string">"lib"</span>]
 
 </span><span class="kw">use </span>std::path::{Path, PathBuf};
 
-<span class="attr">#[cfg(target_os = <span class="string">&quot;linux&quot;</span>)]
-#[cfg(target_os = <span class="string">&quot;windows&quot;</span>)]
+<span class="attr">#[cfg(target_os = <span class="string">"linux"</span>)]
+#[cfg(target_os = <span class="string">"windows"</span>)]
 </span><span class="kw">fn </span>main() -&gt; () {
     <span class="kw">let </span>foo = <span class="bool-val">true </span>&amp;&amp; <span class="bool-val">false </span>|| <span class="bool-val">true</span>;
     <span class="kw">let _</span>: <span class="kw-2">*const </span>() = <span class="number">0</span>;
@@ -22,7 +22,7 @@
     <span class="kw">let _ </span>= <span class="kw-2">*</span>foo;
     <span class="macro">mac!</span>(foo, <span class="kw-2">&amp;mut </span>bar);
     <span class="macro">assert!</span>(<span class="self">self</span>.length &lt; N &amp;&amp; index &lt;= <span class="self">self</span>.length);
-    ::std::env::var(<span class="string">&quot;gateau&quot;</span>).is_ok();
+    ::std::env::var(<span class="string">"gateau"</span>).is_ok();
     <span class="attr">#[rustfmt::skip]
     </span><span class="kw">let </span>s:std::path::PathBuf = std::path::PathBuf::new();
     <span class="kw">let </span><span class="kw-2">mut </span>s = String::new();
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 131b1d608e6..ff7ce01e807 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1737,7 +1737,14 @@ fn item_variants(
         w.write_str("</h3></section>");
 
         let heading_and_fields = match &variant_data.kind {
-            clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)),
+            clean::VariantKind::Struct(s) => {
+                // If there is no field to display, no need to add the heading.
+                if s.fields.iter().any(|f| !f.is_doc_hidden()) {
+                    Some(("Fields", &s.fields))
+                } else {
+                    None
+                }
+            }
             clean::VariantKind::Tuple(fields) => {
                 // Documentation on tuple variant fields is rare, so to reduce noise we only emit
                 // the section if at least one field is documented.
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 7044cb89286..a5d2ffb1572 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -140,7 +140,7 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
             let status = Command::new("git")
                 .arg("fetch")
                 .arg(test.repo)
-                .arg("master")
+                .arg(test.sha)
                 .arg(&format!("--depth={}", depth))
                 .current_dir(&out_dir)
                 .status()
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index f3492c3eb04..c60249f35e1 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-c9808f87028e16d134438787cab3d4cc16d05fe2
+317d14a56cb8c748bf0e2f2afff89c2249ab4423
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
index fd51fa6468a..be4dac9957d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
@@ -1,11 +1,10 @@
 //@compile-flags: -Zmiri-strict-provenance
-//@error-in-other-file: /retag .* tag does not exist in the borrow stack/
 
 fn main() {
     unsafe {
         let a = [1, 2, 3];
         let s = &a[0..0];
         assert_eq!(s.len(), 0);
-        assert_eq!(*s.get_unchecked(1), 2);
+        assert_eq!(*s.as_ptr().add(1), 2); //~ ERROR: /retag .* tag does not exist in the borrow stack/
     }
 }
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
index 5568051905c..acae479ced2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
@@ -1,26 +1,22 @@
 error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-  --> RUSTLIB/core/src/slice/mod.rs:LL:CC
+  --> $DIR/zst_slice.rs:LL:CC
    |
-LL |         unsafe { &*index.get_unchecked(self) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-   |                  this error occurs as part of retag at ALLOC[0x4..0x8]
+LL |         assert_eq!(*s.as_ptr().add(1), 2);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
+   |         this error occurs as part of retag at ALLOC[0x4..0x8]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
 help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere
   --> $DIR/zst_slice.rs:LL:CC
    |
-LL |         assert_eq!(*s.get_unchecked(1), 2);
-   |                     ^^^^^^^^^^^^^^^^^^
+LL |         assert_eq!(*s.as_ptr().add(1), 2);
+   |                     ^^^^^^^^^^
    = note: BACKTRACE (of the first span):
-   = note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
-note: inside `main`
-  --> $DIR/zst_slice.rs:LL:CC
-   |
-LL |         assert_eq!(*s.get_unchecked(1), 2);
-   |                     ^^^^^^^^^^^^^^^^^^
+   = note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs b/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs
index f1dace0cff9..9bc2b4338b0 100644
--- a/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs
+++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs
@@ -1,7 +1,7 @@
 //@compile-flags: -Zmiri-disable-stacked-borrows
 fn main() {
     let v: Vec<u8> = Vec::with_capacity(10);
-    let undef = unsafe { *v.get_unchecked(5) }; //~ ERROR: uninitialized
+    let undef = unsafe { *v.as_ptr().add(5) }; //~ ERROR: uninitialized
     let x = undef + 1;
     panic!("this should never print: {}", x);
 }
diff --git a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
index b70f0ad9950..3917d868289 100644
--- a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
+++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
   --> $DIR/uninit_byte_read.rs:LL:CC
    |
-LL |     let undef = unsafe { *v.get_unchecked(5) };
-   |                          ^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+LL |     let undef = unsafe { *v.as_ptr().add(5) };
+   |                          ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs
index 9b0a40c41b9..6ea034e2cda 100644
--- a/src/tools/miri/tests/pass/float_nan.rs
+++ b/src/tools/miri/tests/pass/float_nan.rs
@@ -20,8 +20,8 @@ use NaNKind::*;
 #[track_caller]
 fn check_all_outcomes<T: Eq + Hash + fmt::Display>(expected: HashSet<T>, generate: impl Fn() -> T) {
     let mut seen = HashSet::new();
-    // Let's give it 8x as many tries as we are expecting values.
-    let tries = expected.len() * 8;
+    // Let's give it sixteen times as many tries as we are expecting values.
+    let tries = expected.len() * 16;
     for _ in 0..tries {
         let val = generate();
         assert!(expected.contains(&val), "got an unexpected value: {val}");
diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs
new file mode 100644
index 00000000000..b396f3fa835
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs
@@ -0,0 +1,37 @@
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed, C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed, C)]
+struct PackedUnsized {
+    f: u8,
+    d: [u32],
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() {
+    unsafe {
+        let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+        let p = p.unsize() as *const PackedUnsized;
+        // Make sure the size computation does *not* think there is
+        // any padding in front of the `d` field.
+        assert_eq!(mem::size_of_val_raw(p), 1 + 4 * 4);
+        // And likewise for the offset computation.
+        let d = std::ptr::addr_of!((*p).d);
+        assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+    }
+}
diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs
new file mode 100644
index 00000000000..a5cf337da02
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs
@@ -0,0 +1,40 @@
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed(4))]
+struct Slice([u32]);
+
+#[repr(packed(2), C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed(2), C)]
+struct PackedUnsized {
+    f: u8,
+    d: Slice,
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() {
+    unsafe {
+        let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+        let p = p.unsize() as *const PackedUnsized;
+        // Make sure the size computation correctly adds exact 1 byte of padding
+        // in front of the `d` field.
+        assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4 * 4);
+        // And likewise for the offset computation.
+        let d = std::ptr::addr_of!((*p).d);
+        assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+    }
+}
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 5a8d971c3d4..876fd93aab7 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -2000,9 +2000,9 @@ dependencies = [
 
 [[package]]
 name = "triomphe"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db"
+checksum = "d0c5a71827ac326072b6405552093e2ad2accd25a32fd78d4edc82d98c7f2409"
 
 [[package]]
 name = "tt"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 73bb9c84d2c..272f456bf9f 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -116,7 +116,7 @@ text-size = "1.1.1"
 rayon = "1.8.0"
 serde = { version = "1.0.192", features = ["derive"] }
 serde_json = "1.0.108"
-triomphe = { version = "0.1.8", default-features = false, features = ["std"] }
+triomphe = { version = "0.1.10", default-features = false, features = ["std"] }
 # can't upgrade due to dashmap depending on 0.12.3 currently
 hashbrown = { version = "0.12.3", features = [
   "inline-more",
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 70b96b25739..473ae298c77 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -38,7 +38,6 @@ mod tests;
 use std::{
     fmt::{self, Debug},
     hash::{Hash, Hasher},
-    marker::PhantomData,
     ops::Index,
 };
 
@@ -340,34 +339,37 @@ pub trait ItemTreeNode: Clone {
     fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
 }
 
-pub struct FileItemTreeId<N: ItemTreeNode> {
-    index: Idx<N>,
-    _p: PhantomData<N>,
+pub struct FileItemTreeId<N: ItemTreeNode>(Idx<N>);
+
+impl<N: ItemTreeNode> FileItemTreeId<N> {
+    pub fn index(&self) -> Idx<N> {
+        self.0
+    }
 }
 
 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
     fn clone(&self) -> Self {
-        Self { index: self.index, _p: PhantomData }
+        Self(self.0)
     }
 }
 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
 
 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
     fn eq(&self, other: &FileItemTreeId<N>) -> bool {
-        self.index == other.index
+        self.0 == other.0
     }
 }
 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
 
 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        self.index.hash(state)
+        self.0.hash(state)
     }
 }
 
 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.index.fmt(f)
+        self.0.fmt(f)
     }
 }
 
@@ -548,7 +550,7 @@ impl Index<RawVisibilityId> for ItemTree {
 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
     type Output = N;
     fn index(&self, id: FileItemTreeId<N>) -> &N {
-        N::lookup(self, id.index)
+        N::lookup(self, id.index())
     }
 }
 
@@ -925,23 +927,23 @@ impl ModItem {
 
     pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
         match self {
-            ModItem::Use(it) => tree[it.index].ast_id().upcast(),
-            ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
-            ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Function(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Union(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Enum(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Const(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Static(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Trait(it) => tree[it.index].ast_id().upcast(),
-            ModItem::TraitAlias(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Impl(it) => tree[it.index].ast_id().upcast(),
-            ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
-            ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
-            ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
-            ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
-            ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
+            ModItem::Use(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::ExternCrate(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::ExternBlock(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Function(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Struct(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Union(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Enum(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Const(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Static(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Trait(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::TraitAlias(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Impl(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::TypeAlias(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Mod(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::MacroCall(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::MacroRules(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::MacroDef(it) => tree[it.index()].ast_id().upcast(),
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index c898eb5f921..6807326be5a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -13,7 +13,7 @@ use crate::{
 use super::*;
 
 fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
-    FileItemTreeId { index, _p: PhantomData }
+    FileItemTreeId(index)
 }
 
 pub(super) struct Ctx<'a> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 3d5ed1f93c0..8262edec22c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1152,20 +1152,15 @@ impl<'a> InferenceContext<'a> {
                 (ty, variant)
             }
             TypeNs::TypeAliasId(it) => {
-                let container = it.lookup(self.db.upcast()).container;
-                let parent_subst = match container {
-                    ItemContainerId::TraitId(id) => {
-                        let subst = TyBuilder::subst_for_def(self.db, id, None)
-                            .fill_with_inference_vars(&mut self.table)
-                            .build();
-                        Some(subst)
-                    }
-                    // Type aliases do not exist in impls.
-                    _ => None,
+                let resolved_seg = match unresolved {
+                    None => path.segments().last().unwrap(),
+                    Some(n) => path.segments().get(path.segments().len() - n - 1).unwrap(),
                 };
-                let ty = TyBuilder::def_ty(self.db, it.into(), parent_subst)
-                    .fill_with_inference_vars(&mut self.table)
-                    .build();
+                let substs =
+                    ctx.substs_from_path_segment(resolved_seg, Some(it.into()), true, None);
+                let ty = self.db.ty(it.into());
+                let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
+
                 self.resolve_variant_on_alias(ty, unresolved, mod_path)
             }
             TypeNs::AdtSelfType(_) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 04005311b67..9f5b59b239a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -768,7 +768,7 @@ impl<'a> TyLoweringContext<'a> {
         }
     }
 
-    fn substs_from_path_segment(
+    pub(super) fn substs_from_path_segment(
         &self,
         segment: PathSegment<'_>,
         def: Option<GenericDefId>,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 747ca54858c..2e6fe59d3bd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -269,6 +269,10 @@ impl ProjectionStore {
 impl ProjectionId {
     pub const EMPTY: ProjectionId = ProjectionId(0);
 
+    pub fn is_empty(self) -> bool {
+        self == ProjectionId::EMPTY
+    }
+
     pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] {
         store.id_to_proj.get(&self).unwrap()
     }
@@ -1069,6 +1073,10 @@ pub struct MirBody {
 }
 
 impl MirBody {
+    pub fn local_to_binding_map(&self) -> ArenaMap<LocalId, BindingId> {
+        self.binding_locals.iter().map(|(it, y)| (*y, it)).collect()
+    }
+
     fn walk_places(&mut self, mut f: impl FnMut(&mut Place, &mut ProjectionStore)) {
         fn for_operand(
             op: &mut Operand,
@@ -1188,3 +1196,9 @@ pub enum MirSpan {
 }
 
 impl_from!(ExprId, PatId for MirSpan);
+
+impl From<&ExprId> for MirSpan {
+    fn from(value: &ExprId) -> Self {
+        (*value).into()
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 9905d522146..922aee011cf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -105,9 +105,14 @@ pub enum MirLowerError {
 /// A token to ensuring that each drop scope is popped at most once, thanks to the compiler that checks moves.
 struct DropScopeToken;
 impl DropScopeToken {
-    fn pop_and_drop(self, ctx: &mut MirLowerCtx<'_>, current: BasicBlockId) -> BasicBlockId {
+    fn pop_and_drop(
+        self,
+        ctx: &mut MirLowerCtx<'_>,
+        current: BasicBlockId,
+        span: MirSpan,
+    ) -> BasicBlockId {
         std::mem::forget(self);
-        ctx.pop_drop_scope_internal(current)
+        ctx.pop_drop_scope_internal(current, span)
     }
 
     /// It is useful when we want a drop scope is syntaxically closed, but we don't want to execute any drop
@@ -582,7 +587,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
                     let scope = this.push_drop_scope();
                     if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? {
-                        current = scope.pop_and_drop(this, current);
+                        current = scope.pop_and_drop(this, current, body.into());
                         this.set_goto(current, begin, expr_id.into());
                     } else {
                         scope.pop_assume_dropped(this);
@@ -720,7 +725,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         .ok_or(MirLowerError::ContinueWithoutLoop)?,
                 };
                 let begin = loop_data.begin;
-                current = self.drop_until_scope(loop_data.drop_scope_index, current);
+                current =
+                    self.drop_until_scope(loop_data.drop_scope_index, current, expr_id.into());
                 self.set_goto(current, begin, expr_id.into());
                 Ok(None)
             }
@@ -759,7 +765,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         self.current_loop_blocks.as_ref().unwrap().drop_scope_index,
                     ),
                 };
-                current = self.drop_until_scope(drop_scope, current);
+                current = self.drop_until_scope(drop_scope, current, expr_id.into());
                 self.set_goto(current, end, expr_id.into());
                 Ok(None)
             }
@@ -773,7 +779,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         return Ok(None);
                     }
                 }
-                current = self.drop_until_scope(0, current);
+                current = self.drop_until_scope(0, current, expr_id.into());
                 self.set_terminator(current, TerminatorKind::Return, expr_id.into());
                 Ok(None)
             }
@@ -1782,7 +1788,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         return Ok(None);
                     };
                     self.push_fake_read(c, p, expr.into());
-                    current = scope2.pop_and_drop(self, c);
+                    current = scope2.pop_and_drop(self, c, expr.into());
                 }
             }
         }
@@ -1793,7 +1799,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             };
             current = c;
         }
-        current = scope.pop_and_drop(self, current);
+        current = scope.pop_and_drop(self, current, span);
         Ok(Some(current))
     }
 
@@ -1873,9 +1879,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
         }
     }
 
-    fn drop_until_scope(&mut self, scope_index: usize, mut current: BasicBlockId) -> BasicBlockId {
+    fn drop_until_scope(
+        &mut self,
+        scope_index: usize,
+        mut current: BasicBlockId,
+        span: MirSpan,
+    ) -> BasicBlockId {
         for scope in self.drop_scopes[scope_index..].to_vec().iter().rev() {
-            self.emit_drop_and_storage_dead_for_scope(scope, &mut current);
+            self.emit_drop_and_storage_dead_for_scope(scope, &mut current, span);
         }
         current
     }
@@ -1891,17 +1902,22 @@ impl<'ctx> MirLowerCtx<'ctx> {
     }
 
     /// Don't call directly
-    fn pop_drop_scope_internal(&mut self, mut current: BasicBlockId) -> BasicBlockId {
+    fn pop_drop_scope_internal(
+        &mut self,
+        mut current: BasicBlockId,
+        span: MirSpan,
+    ) -> BasicBlockId {
         let scope = self.drop_scopes.pop().unwrap();
-        self.emit_drop_and_storage_dead_for_scope(&scope, &mut current);
+        self.emit_drop_and_storage_dead_for_scope(&scope, &mut current, span);
         current
     }
 
     fn pop_drop_scope_assert_finished(
         &mut self,
         mut current: BasicBlockId,
+        span: MirSpan,
     ) -> Result<BasicBlockId> {
-        current = self.pop_drop_scope_internal(current);
+        current = self.pop_drop_scope_internal(current, span);
         if !self.drop_scopes.is_empty() {
             implementation_error!("Mismatched count between drop scope push and pops");
         }
@@ -1912,6 +1928,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         &mut self,
         scope: &DropScope,
         current: &mut Idx<BasicBlock>,
+        span: MirSpan,
     ) {
         for &l in scope.locals.iter().rev() {
             if !self.result.locals[l].ty.clone().is_copy(self.db, self.owner) {
@@ -1919,13 +1936,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 self.set_terminator(
                     prev,
                     TerminatorKind::Drop { place: l.into(), target: *current, unwind: None },
-                    MirSpan::Unknown,
+                    span,
                 );
             }
-            self.push_statement(
-                *current,
-                StatementKind::StorageDead(l).with_span(MirSpan::Unknown),
-            );
+            self.push_statement(*current, StatementKind::StorageDead(l).with_span(span));
         }
     }
 }
@@ -2002,7 +2016,7 @@ pub fn mir_body_for_closure_query(
         |_| true,
     )?;
     if let Some(current) = ctx.lower_expr_to_place(*root, return_slot().into(), current)? {
-        let current = ctx.pop_drop_scope_assert_finished(current)?;
+        let current = ctx.pop_drop_scope_assert_finished(current, root.into())?;
         ctx.set_terminator(current, TerminatorKind::Return, (*root).into());
     }
     let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem, usize)>> = FxHashMap::default();
@@ -2146,7 +2160,7 @@ pub fn lower_to_mir(
         ctx.lower_params_and_bindings([].into_iter(), binding_picker)?
     };
     if let Some(current) = ctx.lower_expr_to_place(root_expr, return_slot().into(), current)? {
-        let current = ctx.pop_drop_scope_assert_finished(current)?;
+        let current = ctx.pop_drop_scope_assert_finished(current, root_expr.into())?;
         ctx.set_terminator(current, TerminatorKind::Return, root_expr.into());
     }
     Ok(ctx.result)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
index 6e42bee97f7..a91f90bc249 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
@@ -145,7 +145,7 @@ impl<'a> MirPrettyCtx<'a> {
         let indent = mem::take(&mut self.indent);
         let mut ctx = MirPrettyCtx {
             body: &body,
-            local_to_binding: body.binding_locals.iter().map(|(it, y)| (*y, it)).collect(),
+            local_to_binding: body.local_to_binding_map(),
             result,
             indent,
             ..*self
@@ -167,7 +167,7 @@ impl<'a> MirPrettyCtx<'a> {
     }
 
     fn new(body: &'a MirBody, hir_body: &'a Body, db: &'a dyn HirDatabase) -> Self {
-        let local_to_binding = body.binding_locals.iter().map(|(it, y)| (*y, it)).collect();
+        let local_to_binding = body.local_to_binding_map();
         MirPrettyCtx {
             body,
             db,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index 0f5a3e1752c..5d7bab09c26 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -1129,3 +1129,27 @@ fn foo() {
 "#,
     );
 }
+
+#[test]
+fn generic_alias() {
+    check_types(
+        r#"
+type Wrap<T> = T;
+
+enum X {
+    A { cool: u32, stuff: u32 },
+    B,
+}
+
+fn main() {
+    let wrapped = Wrap::<X>::A {
+        cool: 100,
+        stuff: 100,
+    };
+
+    if let Wrap::<X>::A { cool, ..} = &wrapped {}
+                        //^^^^ &u32
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 1bfbf7212bf..908027a2026 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -67,7 +67,7 @@ use hir_ty::{
     known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
     method_resolution::{self, TyFingerprint},
-    mir::{self, interpret_mir},
+    mir::interpret_mir,
     primitive::UintTy,
     traits::FnTrait,
     AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
@@ -129,9 +129,10 @@ pub use {
     hir_ty::{
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
         layout::LayoutError,
-        mir::MirEvalError,
         PointerCast, Safety,
     },
+    // FIXME: Properly encapsulate mir
+    hir_ty::{mir, Interner as ChalkTyInterner},
 };
 
 // These are negative re-exports: pub using these names is forbidden, they
@@ -1914,17 +1915,20 @@ impl DefWithBody {
                             if let ast::Expr::MatchExpr(match_expr) =
                                 &source_ptr.value.to_node(&root)
                             {
-                                if let Some(scrut_expr) = match_expr.expr() {
-                                    acc.push(
-                                        MissingMatchArms {
-                                            scrutinee_expr: InFile::new(
-                                                source_ptr.file_id,
-                                                AstPtr::new(&scrut_expr),
-                                            ),
-                                            uncovered_patterns,
-                                        }
-                                        .into(),
-                                    );
+                                match match_expr.expr() {
+                                    Some(scrut_expr) if match_expr.match_arm_list().is_some() => {
+                                        acc.push(
+                                            MissingMatchArms {
+                                                scrutinee_expr: InFile::new(
+                                                    source_ptr.file_id,
+                                                    AstPtr::new(&scrut_expr),
+                                                ),
+                                                uncovered_patterns,
+                                            }
+                                            .into(),
+                                        );
+                                    }
+                                    _ => {}
                                 }
                             }
                         }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
index ffc32f80499..0281b29cd42 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
@@ -1,4 +1,4 @@
-use syntax::{ast, AstNode};
+use syntax::{ast, AstNode, SyntaxKind, T};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -39,7 +39,19 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         AssistId("remove_parentheses", AssistKind::Refactor),
         "Remove redundant parentheses",
         target,
-        |builder| builder.replace_ast(parens.into(), expr),
+        |builder| {
+            let prev_token = parens.syntax().first_token().and_then(|it| it.prev_token());
+            let need_to_add_ws = match prev_token {
+                Some(it) => {
+                    let tokens = vec![T![&], T![!], T!['('], T!['['], T!['{']];
+                    it.kind() != SyntaxKind::WHITESPACE && !tokens.contains(&it.kind())
+                }
+                None => false,
+            };
+            let expr = if need_to_add_ws { format!(" {}", expr) } else { expr.to_string() };
+
+            builder.replace(parens.syntax().text_range(), expr)
+        },
     )
 }
 
@@ -50,6 +62,15 @@ mod tests {
     use super::*;
 
     #[test]
+    fn remove_parens_space() {
+        check_assist(
+            remove_parentheses,
+            r#"fn f() { match$0(true) {} }"#,
+            r#"fn f() { match true {} }"#,
+        );
+    }
+
+    #[test]
     fn remove_parens_simple() {
         check_assist(remove_parentheses, r#"fn f() { $0(2) + 2; }"#, r#"fn f() { 2 + 2; }"#);
         check_assist(remove_parentheses, r#"fn f() { ($02) + 2; }"#, r#"fn f() { 2 + 2; }"#);
@@ -94,8 +115,8 @@ mod tests {
         check_assist(remove_parentheses, r#"fn f() { f(($02 + 2)); }"#, r#"fn f() { f(2 + 2); }"#);
         check_assist(
             remove_parentheses,
-            r#"fn f() { (1<2)&&$0(3>4); }"#,
-            r#"fn f() { (1<2)&&3>4; }"#,
+            r#"fn f() { (1<2) &&$0(3>4); }"#,
+            r#"fn f() { (1<2) && 3>4; }"#,
         );
     }
 
@@ -164,8 +185,8 @@ mod tests {
     fn remove_parens_weird_places() {
         check_assist(
             remove_parentheses,
-            r#"fn f() { match () { _=>$0(()) } }"#,
-            r#"fn f() { match () { _=>() } }"#,
+            r#"fn f() { match () { _ =>$0(()) } }"#,
+            r#"fn f() { match () { _ => () } }"#,
         );
 
         check_assist(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index 5bcc867fe18..57e06461099 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -26,17 +26,17 @@ pub(crate) fn complete_dot(
         item.add_to(acc, ctx.db);
     }
 
-    if let DotAccessKind::Method { .. } = dot_access.kind {
-        cov_mark::hit!(test_no_struct_field_completion_for_method_call);
-    } else {
-        complete_fields(
-            acc,
-            ctx,
-            receiver_ty,
-            |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
-            |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
-        );
-    }
+    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+
+    complete_fields(
+        acc,
+        ctx,
+        receiver_ty,
+        |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
+        |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
+        is_field_access,
+    );
+
     complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
 }
 
@@ -82,6 +82,7 @@ pub(crate) fn complete_undotted_self(
             )
         },
         |acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
+        true,
     );
     complete_methods(ctx, &ty, |func| {
         acc.add_method(
@@ -104,18 +105,23 @@ fn complete_fields(
     receiver: &hir::Type,
     mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type),
     mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type),
+    is_field_access: bool,
 ) {
     let mut seen_names = FxHashSet::default();
     for receiver in receiver.autoderef(ctx.db) {
         for (field, ty) in receiver.fields(ctx.db) {
-            if seen_names.insert(field.name(ctx.db)) {
+            if seen_names.insert(field.name(ctx.db))
+                && (is_field_access || ty.is_fn() || ty.is_closure())
+            {
                 named_field(acc, field, ty);
             }
         }
         for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
             // Tuples are always the last type in a deref chain, so just check if the name is
             // already seen without inserting into the hashset.
-            if !seen_names.contains(&hir::Name::new_tuple_field(i)) {
+            if !seen_names.contains(&hir::Name::new_tuple_field(i))
+                && (is_field_access || ty.is_fn() || ty.is_closure())
+            {
                 // Tuple fields are always public (tuple struct fields are handled above).
                 tuple_index(acc, i, ty);
             }
@@ -250,7 +256,6 @@ impl A {
 
     #[test]
     fn test_no_struct_field_completion_for_method_call() {
-        cov_mark::check!(test_no_struct_field_completion_for_method_call);
         check(
             r#"
 struct A { the_field: u32 }
@@ -1172,4 +1177,63 @@ impl<B: Bar, F: core::ops::Deref<Target = B>> Foo<F> {
         "#]],
         );
     }
+
+    #[test]
+    fn test_struct_function_field_completion() {
+        check(
+            r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
+"#,
+            expect![[r#"
+                fd fn_field fn()
+            "#]],
+        );
+
+        check_edit(
+            "fn_field",
+            r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
+"#,
+            r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { (S { va_field: 0, fn_field: || {} }.fn_field)() }
+"#,
+        );
+    }
+
+    #[test]
+    fn test_tuple_function_field_completion() {
+        check(
+            r#"
+struct B(u32, fn())
+fn foo() {
+   let b = B(0, || {});
+   b.$0()
+}
+"#,
+            expect![[r#"
+                fd 1 fn()
+            "#]],
+        );
+
+        check_edit(
+            "1",
+            r#"
+struct B(u32, fn())
+fn foo() {
+   let b = B(0, || {});
+   b.$0()
+}
+"#,
+            r#"
+struct B(u32, fn())
+fn foo() {
+   let b = B(0, || {});
+   (b.1)()
+}
+"#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index 00a9081985b..048730c078d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -18,9 +18,10 @@ use ide_db::{
     RootDatabase, SnippetCap, SymbolKind,
 };
 use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
+use text_edit::TextEdit;
 
 use crate::{
-    context::{DotAccess, PathCompletionCtx, PathKind, PatternContext},
+    context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
     item::{Builder, CompletionRelevanceTypeMatch},
     render::{
         function::render_fn,
@@ -147,7 +148,42 @@ pub(crate) fn render_field(
         .set_documentation(field.docs(db))
         .set_deprecated(is_deprecated)
         .lookup_by(name);
-    item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
+
+    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+    if !is_field_access || ty.is_fn() || ty.is_closure() {
+        let mut builder = TextEdit::builder();
+        // Using TextEdit, insert '(' before the struct name and ')' before the
+        // dot access, then comes the field name and optionally insert function
+        // call parens.
+
+        builder.replace(
+            ctx.source_range(),
+            field_with_receiver(db, receiver.as_ref(), &escaped_name).into(),
+        );
+
+        let expected_fn_type =
+            ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
+
+        if !expected_fn_type {
+            if let Some(receiver) = &dot_access.receiver {
+                if let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone()) {
+                    builder.insert(receiver.syntax().text_range().start(), "(".to_string());
+                    builder.insert(ctx.source_range().end(), ")".to_string());
+                }
+            }
+
+            let is_parens_needed =
+                !matches!(dot_access.kind, DotAccessKind::Method { has_parens: true });
+
+            if is_parens_needed {
+                builder.insert(ctx.source_range().end(), "()".to_string());
+            }
+        }
+
+        item.text_edit(builder.finish());
+    } else {
+        item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
+    }
     if let Some(receiver) = &dot_access.receiver {
         if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
             if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
@@ -1600,7 +1636,7 @@ fn main() {
     fn struct_field_method_ref() {
         check_kinds(
             r#"
-struct Foo { bar: u32 }
+struct Foo { bar: u32, qux: fn() }
 impl Foo { fn baz(&self) -> u32 { 0 } }
 
 fn foo(f: Foo) { let _: &u32 = f.b$0 }
@@ -1610,24 +1646,44 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
                 [
                     CompletionItem {
                         label: "baz()",
-                        source_range: 98..99,
-                        delete: 98..99,
+                        source_range: 109..110,
+                        delete: 109..110,
                         insert: "baz()$0",
                         kind: Method,
                         lookup: "baz",
                         detail: "fn(&self) -> u32",
-                        ref_match: "&@96",
+                        ref_match: "&@107",
                     },
                     CompletionItem {
                         label: "bar",
-                        source_range: 98..99,
-                        delete: 98..99,
+                        source_range: 109..110,
+                        delete: 109..110,
                         insert: "bar",
                         kind: SymbolKind(
                             Field,
                         ),
                         detail: "u32",
-                        ref_match: "&@96",
+                        ref_match: "&@107",
+                    },
+                    CompletionItem {
+                        label: "qux",
+                        source_range: 109..110,
+                        text_edit: TextEdit {
+                            indels: [
+                                Indel {
+                                    insert: "(",
+                                    delete: 107..107,
+                                },
+                                Indel {
+                                    insert: "qux)()",
+                                    delete: 109..110,
+                                },
+                            ],
+                        },
+                        kind: SymbolKind(
+                            Field,
+                        ),
+                        detail: "fn()",
                     },
                 ]
             "#]],
@@ -1635,6 +1691,48 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
     }
 
     #[test]
+    fn expected_fn_type_ref() {
+        check_kinds(
+            r#"
+struct S { field: fn() }
+
+fn foo() {
+    let foo: fn() = S { fields: || {}}.fi$0;
+}
+"#,
+            &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "field",
+                        source_range: 76..78,
+                        delete: 76..78,
+                        insert: "field",
+                        kind: SymbolKind(
+                            Field,
+                        ),
+                        detail: "fn()",
+                        relevance: CompletionRelevance {
+                            exact_name_match: false,
+                            type_match: Some(
+                                Exact,
+                            ),
+                            is_local: false,
+                            is_item_from_trait: false,
+                            is_name_already_imported: false,
+                            requires_import: false,
+                            is_op_method: false,
+                            is_private_editable: false,
+                            postfix_match: None,
+                            is_definite: false,
+                        },
+                    },
+                ]
+            "#]],
+        )
+    }
+
+    #[test]
     fn qualified_path_ref() {
         check_kinds(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
index 8af6cce98f6..b2e8274a84d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
@@ -355,6 +355,35 @@ fn outer(Foo { bar$0 }: Foo) {}
 }
 
 #[test]
+fn completes_in_record_field_pat_with_generic_type_alias() {
+    check_empty(
+        r#"
+type Wrap<T> = T;
+
+enum X {
+    A { cool: u32, stuff: u32 },
+    B,
+}
+
+fn main() {
+    let wrapped = Wrap::<X>::A {
+        cool: 100,
+        stuff: 100,
+    };
+
+    if let Wrap::<X>::A { $0 } = &wrapped {};
+}
+"#,
+        expect![[r#"
+            fd cool  u32
+            fd stuff u32
+            kw mut
+            kw ref
+        "#]],
+    )
+}
+
+#[test]
 fn completes_in_fn_param() {
     check_empty(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
index 84267d3d906..ef6a273ed8e 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
@@ -17,7 +17,10 @@ pub(crate) fn missing_match_arms(
 
 #[cfg(test)]
 mod tests {
-    use crate::tests::check_diagnostics;
+    use crate::{
+        tests::{check_diagnostics, check_diagnostics_with_config},
+        DiagnosticsConfig,
+    };
 
     #[track_caller]
     fn check_diagnostics_no_bails(ra_fixture: &str) {
@@ -26,6 +29,20 @@ mod tests {
     }
 
     #[test]
+    fn empty_body() {
+        let mut config = DiagnosticsConfig::test_sample();
+        config.disabled.insert("syntax-error".to_string());
+        check_diagnostics_with_config(
+            config,
+            r#"
+fn main() {
+    match 0;
+}
+"#,
+        );
+    }
+
+    #[test]
     fn empty_tuple() {
         check_diagnostics_no_bails(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 24f44ca06ff..7ea9d4f1038 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -31,6 +31,7 @@ mod discriminant;
 mod fn_lifetime_fn;
 mod implicit_static;
 mod param_name;
+mod implicit_drop;
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct InlayHintsConfig {
@@ -45,6 +46,7 @@ pub struct InlayHintsConfig {
     pub closure_return_type_hints: ClosureReturnTypeHints,
     pub closure_capture_hints: bool,
     pub binding_mode_hints: bool,
+    pub implicit_drop_hints: bool,
     pub lifetime_elision_hints: LifetimeElisionHints,
     pub param_names_for_lifetime_elision_hints: bool,
     pub hide_named_constructor_hints: bool,
@@ -124,6 +126,7 @@ pub enum InlayKind {
     Lifetime,
     Parameter,
     Type,
+    Drop,
 }
 
 #[derive(Debug)]
@@ -503,7 +506,10 @@ fn hints(
             ast::Item(it) => match it {
                 // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints
                 ast::Item::Impl(_) => None,
-                ast::Item::Fn(it) => fn_lifetime_fn::hints(hints, config, it),
+                ast::Item::Fn(it) => {
+                    implicit_drop::hints(hints, sema, config, &it);
+                    fn_lifetime_fn::hints(hints, config, it)
+                },
                 // static type elisions
                 ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)),
                 ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
@@ -591,6 +597,7 @@ mod tests {
         max_length: None,
         closing_brace_hints_min_lines: None,
         fields_to_resolve: InlayFieldsToResolve::empty(),
+        implicit_drop_hints: false,
     };
     pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
         type_hints: true,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
new file mode 100644
index 00000000000..60f1f3496f6
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -0,0 +1,204 @@
+//! Implementation of "implicit drop" inlay hints:
+//! ```no_run
+//! fn main() {
+//!     let x = vec![2];
+//!     if some_condition() {
+//!         /* drop(x) */return;
+//!     }
+//! }
+//! ```
+use hir::{
+    db::{DefDatabase as _, HirDatabase as _},
+    mir::{MirSpan, TerminatorKind},
+    ChalkTyInterner, DefWithBody, Semantics,
+};
+use ide_db::{base_db::FileRange, RootDatabase};
+
+use syntax::{
+    ast::{self, AstNode},
+    match_ast,
+};
+
+use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
+
+pub(super) fn hints(
+    acc: &mut Vec<InlayHint>,
+    sema: &Semantics<'_, RootDatabase>,
+    config: &InlayHintsConfig,
+    def: &ast::Fn,
+) -> Option<()> {
+    if !config.implicit_drop_hints {
+        return None;
+    }
+
+    let def = sema.to_def(def)?;
+    let def: DefWithBody = def.into();
+
+    let source_map = sema.db.body_with_source_map(def.into()).1;
+
+    let hir = sema.db.body(def.into());
+    let mir = sema.db.mir_body(def.into()).ok()?;
+
+    let local_to_binding = mir.local_to_binding_map();
+
+    for (_, bb) in mir.basic_blocks.iter() {
+        let terminator = bb.terminator.as_ref()?;
+        if let TerminatorKind::Drop { place, .. } = terminator.kind {
+            if !place.projection.is_empty() {
+                continue; // Ignore complex cases for now
+            }
+            if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() {
+                continue; // Arguably only ADTs have significant drop impls
+            }
+            let Some(binding) = local_to_binding.get(place.local) else {
+                continue; // Ignore temporary values
+            };
+            let range = match terminator.span {
+                MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
+                    Ok(s) => {
+                        let root = &s.file_syntax(sema.db);
+                        let expr = s.value.to_node(root);
+                        let expr = expr.syntax();
+                        match_ast! {
+                            match expr {
+                                ast::BlockExpr(x) => x.stmt_list().and_then(|x| x.r_curly_token()).map(|x| x.text_range()).unwrap_or_else(|| expr.text_range()),
+                                _ => expr.text_range(),
+                            }
+                        }
+                    }
+                    Err(_) => continue,
+                },
+                MirSpan::PatId(p) => match source_map.pat_syntax(p) {
+                    Ok(s) => s.value.text_range(),
+                    Err(_) => continue,
+                },
+                MirSpan::Unknown => continue,
+            };
+            let binding = &hir.bindings[*binding];
+            let binding_source = binding
+                .definitions
+                .first()
+                .and_then(|d| source_map.pat_syntax(*d).ok())
+                .and_then(|d| {
+                    Some(FileRange { file_id: d.file_id.file_id()?, range: d.value.text_range() })
+                });
+            let name = binding.name.to_smol_str();
+            if name.starts_with("<ra@") {
+                continue; // Ignore desugared variables
+            }
+            let mut label = InlayHintLabel::simple(
+                name,
+                Some(crate::InlayTooltip::String("moz".into())),
+                binding_source,
+            );
+            label.prepend_str("drop(");
+            label.append_str(")");
+            acc.push(InlayHint {
+                range,
+                position: InlayHintPosition::Before,
+                pad_left: true,
+                pad_right: true,
+                kind: InlayKind::Drop,
+                needs_resolve: label.needs_resolve(),
+                label,
+                text_edit: None,
+            })
+        }
+    }
+
+    Some(())
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::{
+        inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
+        InlayHintsConfig,
+    };
+
+    const ONLY_DROP_CONFIG: InlayHintsConfig =
+        InlayHintsConfig { implicit_drop_hints: true, ..DISABLED_CONFIG };
+
+    #[test]
+    fn basic() {
+        check_with_config(
+            ONLY_DROP_CONFIG,
+            r#"
+    struct X;
+    fn f() {
+        let x = X;
+        if 2 == 5 {
+            return;
+          //^^^^^^ drop(x)
+        }
+    }
+  //^ drop(x)
+"#,
+        );
+    }
+
+    #[test]
+    fn no_hint_for_copy_types_and_mutable_references() {
+        // `T: Copy` and `T = &mut U` types do nothing on drop, so we should hide drop inlay hint for them.
+        check_with_config(
+            ONLY_DROP_CONFIG,
+            r#"
+//- minicore: copy, derive
+
+    struct X(i32, i32);
+    #[derive(Clone, Copy)]
+    struct Y(i32, i32);
+    fn f() {
+        let a = 2;
+        let b = a + 4;
+        let mut x = X(a, b);
+        let mut y = Y(a, b);
+        let mx = &mut x;
+        let my = &mut y;
+        let c = a + b;
+    }
+  //^ drop(x)
+"#,
+        );
+    }
+
+    #[test]
+    fn try_operator() {
+        // We currently show drop inlay hint for every `?` operator that may potentialy drop something. We probably need to
+        // make it configurable as it doesn't seem very useful.
+        check_with_config(
+            ONLY_DROP_CONFIG,
+            r#"
+//- minicore: copy, try, option
+
+    struct X;
+    fn f() -> Option<()> {
+        let x = X;
+        let t_opt = Some(2);
+        let t = t_opt?;
+              //^^^^^^ drop(x)
+        Some(())
+    }
+  //^ drop(x)
+"#,
+        );
+    }
+
+    #[test]
+    fn if_let() {
+        check_with_config(
+            ONLY_DROP_CONFIG,
+            r#"
+    struct X;
+    fn f() {
+        let x = X;
+        if let X = x {
+            let y = X;
+        }
+      //^ drop(y)
+    }
+  //^ drop(x)
+"#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index aabd26da289..b54874d59f8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -118,6 +118,7 @@ impl StaticIndex<'_> {
                     adjustment_hints: crate::AdjustmentHints::Never,
                     adjustment_hints_mode: AdjustmentHintsMode::Prefix,
                     adjustment_hints_hide_outside_unsafe: false,
+                    implicit_drop_hints: false,
                     hide_named_constructor_hints: false,
                     hide_closure_initialization_hints: false,
                     closure_style: hir::ClosureStyle::ImplFn,
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 6a2a9adce15..19da297b58c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -376,6 +376,16 @@ fn error_block(p: &mut Parser<'_>, message: &str) {
     m.complete(p, ERROR);
 }
 
+// test_err top_level_let
+// let ref foo: fn() = 1 + 3;
+fn error_let_stmt(p: &mut Parser<'_>, message: &str) {
+    assert!(p.at(T![let]));
+    let m = p.start();
+    p.error(message);
+    expressions::let_stmt(p, expressions::Semicolon::Optional);
+    m.complete(p, ERROR);
+}
+
 /// The `parser` passed this is required to at least consume one token if it returns `true`.
 /// If the `parser` returns false, parsing will stop.
 fn delimited(
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 1cbd1663230..e346ece2f94 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -59,7 +59,8 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
     attributes::outer_attrs(p);
 
     if p.at(T![let]) {
-        let_stmt(p, m, semicolon);
+        let_stmt(p, semicolon);
+        m.complete(p, LET_STMT);
         return;
     }
 
@@ -109,54 +110,53 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
             m.complete(p, EXPR_STMT);
         }
     }
+}
 
-    // test let_stmt
-    // fn f() { let x: i32 = 92; }
-    fn let_stmt(p: &mut Parser<'_>, m: Marker, with_semi: Semicolon) {
-        p.bump(T![let]);
-        patterns::pattern(p);
-        if p.at(T![:]) {
-            // test let_stmt_ascription
-            // fn f() { let x: i32; }
-            types::ascription(p);
-        }
+// test let_stmt
+// fn f() { let x: i32 = 92; }
+pub(super) fn let_stmt(p: &mut Parser<'_>, with_semi: Semicolon) {
+    p.bump(T![let]);
+    patterns::pattern(p);
+    if p.at(T![:]) {
+        // test let_stmt_ascription
+        // fn f() { let x: i32; }
+        types::ascription(p);
+    }
 
-        let mut expr_after_eq: Option<CompletedMarker> = None;
-        if p.eat(T![=]) {
-            // test let_stmt_init
-            // fn f() { let x = 92; }
-            expr_after_eq = expressions::expr(p);
-        }
+    let mut expr_after_eq: Option<CompletedMarker> = None;
+    if p.eat(T![=]) {
+        // test let_stmt_init
+        // fn f() { let x = 92; }
+        expr_after_eq = expressions::expr(p);
+    }
 
-        if p.at(T![else]) {
-            // test_err let_else_right_curly_brace
-            // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
-            if let Some(expr) = expr_after_eq {
-                if BlockLike::is_blocklike(expr.kind()) {
-                    p.error(
-                        "right curly brace `}` before `else` in a `let...else` statement not allowed",
-                    )
-                }
+    if p.at(T![else]) {
+        // test_err let_else_right_curly_brace
+        // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
+        if let Some(expr) = expr_after_eq {
+            if BlockLike::is_blocklike(expr.kind()) {
+                p.error(
+                    "right curly brace `}` before `else` in a `let...else` statement not allowed",
+                )
             }
-
-            // test let_else
-            // fn f() { let Some(x) = opt else { return }; }
-            let m = p.start();
-            p.bump(T![else]);
-            block_expr(p);
-            m.complete(p, LET_ELSE);
         }
 
-        match with_semi {
-            Semicolon::Forbidden => (),
-            Semicolon::Optional => {
-                p.eat(T![;]);
-            }
-            Semicolon::Required => {
-                p.expect(T![;]);
-            }
+        // test let_else
+        // fn f() { let Some(x) = opt else { return }; }
+        let m = p.start();
+        p.bump(T![else]);
+        block_expr(p);
+        m.complete(p, LET_ELSE);
+    }
+
+    match with_semi {
+        Semicolon::Forbidden => (),
+        Semicolon::Optional => {
+            p.eat(T![;]);
+        }
+        Semicolon::Required => {
+            p.expect(T![;]);
         }
-        m.complete(p, LET_STMT);
     }
 }
 
@@ -693,6 +693,17 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
                 // We permit `.. }` on the left-hand side of a destructuring assignment.
                 if !p.at(T!['}']) {
                     expr(p);
+
+                    if p.at(T![,]) {
+                        // test_err comma_after_functional_update_syntax
+                        // fn foo() {
+                        //     S { ..x, };
+                        //     S { ..x, a: 0 }
+                        // }
+
+                        // Do not bump, so we can support additional fields after this comma.
+                        p.error("cannot use a comma after the base struct");
+                    }
                 }
             }
             T!['{'] => {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index 4e850b1f74d..34fd3420f1c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -79,6 +79,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
             e.complete(p, ERROR);
         }
         EOF | T!['}'] => p.error("expected an item"),
+        T![let] => error_let_stmt(p, "expected an item"),
         _ => p.err_and_bump("expected an item"),
     }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast
new file mode 100644
index 00000000000..0e2fe5988d6
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast
@@ -0,0 +1,66 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
+            WHITESPACE " "
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              DOT2 ".."
+              PATH_EXPR
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "x"
+              COMMA ","
+              WHITESPACE " "
+              R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n    "
+        RECORD_EXPR
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "S"
+          WHITESPACE " "
+          RECORD_EXPR_FIELD_LIST
+            L_CURLY "{"
+            WHITESPACE " "
+            DOT2 ".."
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "x"
+            COMMA ","
+            WHITESPACE " "
+            RECORD_EXPR_FIELD
+              NAME_REF
+                IDENT "a"
+              COLON ":"
+              WHITESPACE " "
+              LITERAL
+                INT_NUMBER "0"
+            WHITESPACE " "
+            R_CURLY "}"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 22: cannot use a comma after the base struct
+error 38: cannot use a comma after the base struct
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs
new file mode 100644
index 00000000000..14cf96719b4
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    S { ..x, };
+    S { ..x, a: 0 }
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast
new file mode 100644
index 00000000000..5ddef5f3f03
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast
@@ -0,0 +1,30 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      REF_KW "ref"
+      WHITESPACE " "
+      NAME
+        IDENT "foo"
+    COLON ":"
+    WHITESPACE " "
+    FN_PTR_TYPE
+      FN_KW "fn"
+      PARAM_LIST
+        L_PAREN "("
+        R_PAREN ")"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    BIN_EXPR
+      LITERAL
+        INT_NUMBER "1"
+      WHITESPACE " "
+      PLUS "+"
+      WHITESPACE " "
+      LITERAL
+        INT_NUMBER "3"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs
new file mode 100644
index 00000000000..3d3e7dd56c7
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs
@@ -0,0 +1 @@
+let ref foo: fn() = 1 + 3;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 0f6539f224d..b4debba38c9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -783,6 +783,7 @@ impl flags::AnalysisStats {
                     closure_return_type_hints: ide::ClosureReturnTypeHints::Always,
                     closure_capture_hints: true,
                     binding_mode_hints: true,
+                    implicit_drop_hints: true,
                     lifetime_elision_hints: ide::LifetimeElisionHints::Always,
                     param_names_for_lifetime_elision_hints: true,
                     hide_named_constructor_hints: false,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index f28f6ffb874..90d1d6b0555 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -381,6 +381,8 @@ config_data! {
         inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false",
         /// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
         inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = "\"prefix\"",
+        /// Whether to show implicit drop hints.
+        inlayHints_implicitDrops_enable: bool                      = "false",
         /// Whether to show inlay type hints for elided lifetimes in function signatures.
         inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
         /// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
@@ -1391,6 +1393,7 @@ impl Config {
             type_hints: self.data.inlayHints_typeHints_enable,
             parameter_hints: self.data.inlayHints_parameterHints_enable,
             chaining_hints: self.data.inlayHints_chainingHints_enable,
+            implicit_drop_hints: self.data.inlayHints_implicitDrops_enable,
             discriminant_hints: match self.data.inlayHints_discriminantHints_enable {
                 DiscriminantHintsDef::Always => ide::DiscriminantHints::Always,
                 DiscriminantHintsDef::Never => ide::DiscriminantHints::Never,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index 8dba83ed5ed..abe2191f400 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -22,6 +22,7 @@ use ide_db::{
     base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, ProcMacros},
     FxHashMap,
 };
+use itertools::Itertools;
 use load_cargo::{load_proc_macro, ProjectFolders};
 use proc_macro_api::ProcMacroServer;
 use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
@@ -227,16 +228,12 @@ impl GlobalState {
                 let mut i = 0;
                 while i < workspaces.len() {
                     if let Ok(w) = &workspaces[i] {
-                        let dupes: Vec<_> = workspaces
+                        let dupes: Vec<_> = workspaces[i + 1..]
                             .iter()
-                            .enumerate()
-                            .skip(i + 1)
-                            .filter_map(|(i, it)| {
-                                it.as_ref().ok().filter(|ws| ws.eq_ignore_build_data(w)).map(|_| i)
-                            })
+                            .positions(|it| it.as_ref().is_ok_and(|ws| ws.eq_ignore_build_data(w)))
                             .collect();
                         dupes.into_iter().rev().for_each(|d| {
-                            _ = workspaces.remove(d);
+                            _ = workspaces.remove(d + i + 1);
                         });
                     }
                     i += 1;
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index f2ca9d82ed0..ba5c86db0e2 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -1054,6 +1054,10 @@ pub mod option {
         Some(T),
     }
 
+    // region:copy
+    impl<T: Copy> Copy for Option<T> {}
+    // endregion:copy
+
     impl<T> Option<T> {
         pub const fn unwrap(self) -> T {
             match self {
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 7091ea1ce9a..8a2d0808443 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -564,6 +564,11 @@ Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
 --
 Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
 --
+[[rust-analyzer.inlayHints.implicitDrops.enable]]rust-analyzer.inlayHints.implicitDrops.enable (default: `false`)::
++
+--
+Whether to show implicit drop hints.
+--
 [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`)::
 +
 --
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index c43f2b964fd..cfaf4213277 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1264,6 +1264,11 @@
                         "Show prefix or postfix depending on which uses less parenthesis, preferring postfix."
                     ]
                 },
+                "rust-analyzer.inlayHints.implicitDrops.enable": {
+                    "markdownDescription": "Whether to show implicit drop hints.",
+                    "default": false,
+                    "type": "boolean"
+                },
                 "rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
                     "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",
                     "default": "never",
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index e817d680eae..06034e16480 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -3,7 +3,7 @@ import * as vscode from "vscode";
 import * as path from "path";
 import type * as ra from "./lsp_ext";
 
-import { Cargo, getRustcId, getSysroot } from "./toolchain";
+import { Cargo, type ExecutableInfo, getRustcId, getSysroot } from "./toolchain";
 import type { Ctx } from "./ctx";
 import { prepareEnv } from "./run";
 import { unwrapUndefinable } from "./undefinable";
@@ -12,6 +12,7 @@ const debugOutput = vscode.window.createOutputChannel("Debug");
 type DebugConfigProvider = (
     config: ra.Runnable,
     executable: string,
+    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ) => vscode.DebugConfiguration;
@@ -130,7 +131,7 @@ async function getDebugConfiguration(
     }
 
     const env = prepareEnv(runnable, ctx.config.runnablesExtraEnv);
-    const executable = await getDebugExecutable(runnable, env);
+    const { executable, workspace: cargoWorkspace } = await getDebugExecutableInfo(runnable, env);
     let sourceFileMap = debugOptions.sourceFileMap;
     if (sourceFileMap === "auto") {
         // let's try to use the default toolchain
@@ -142,7 +143,13 @@ async function getDebugConfiguration(
     }
 
     const provider = unwrapUndefinable(knownEngines[debugEngine.id]);
-    const debugConfig = provider(runnable, simplifyPath(executable), env, sourceFileMap);
+    const debugConfig = provider(
+        runnable,
+        simplifyPath(executable),
+        cargoWorkspace,
+        env,
+        sourceFileMap,
+    );
     if (debugConfig.type in debugOptions.engineSettings) {
         const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
         for (var key in settingsMap) {
@@ -164,20 +171,21 @@ async function getDebugConfiguration(
     return debugConfig;
 }
 
-async function getDebugExecutable(
+async function getDebugExecutableInfo(
     runnable: ra.Runnable,
     env: Record<string, string>,
-): Promise<string> {
+): Promise<ExecutableInfo> {
     const cargo = new Cargo(runnable.args.workspaceRoot || ".", debugOutput, env);
-    const executable = await cargo.executableFromArgs(runnable.args.cargoArgs);
+    const executableInfo = await cargo.executableInfoFromArgs(runnable.args.cargoArgs);
 
     // if we are here, there were no compilation errors.
-    return executable;
+    return executableInfo;
 }
 
 function getLldbDebugConfig(
     runnable: ra.Runnable,
     executable: string,
+    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
@@ -187,7 +195,7 @@ function getLldbDebugConfig(
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
-        cwd: runnable.args.workspaceRoot,
+        cwd: cargoWorkspace || runnable.args.workspaceRoot,
         sourceMap: sourceFileMap,
         sourceLanguages: ["rust"],
         env,
@@ -197,6 +205,7 @@ function getLldbDebugConfig(
 function getCppvsDebugConfig(
     runnable: ra.Runnable,
     executable: string,
+    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
@@ -206,7 +215,7 @@ function getCppvsDebugConfig(
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
-        cwd: runnable.args.workspaceRoot,
+        cwd: cargoWorkspace || runnable.args.workspaceRoot,
         sourceFileMap,
         env,
     };
diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
index 58e5fc747a1..1037e513aa1 100644
--- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts
+++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
@@ -9,11 +9,17 @@ import { unwrapUndefinable } from "./undefinable";
 
 interface CompilationArtifact {
     fileName: string;
+    workspace: string;
     name: string;
     kind: string;
     isTest: boolean;
 }
 
+export interface ExecutableInfo {
+    executable: string;
+    workspace: string;
+}
+
 export interface ArtifactSpec {
     cargoArgs: string[];
     filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[];
@@ -68,6 +74,7 @@ export class Cargo {
                             artifacts.push({
                                 fileName: message.executable,
                                 name: message.target.name,
+                                workspace: message.manifest_path.replace(/\/Cargo\.toml$/, ""),
                                 kind: message.target.kind[0],
                                 isTest: message.profile.test,
                             });
@@ -86,7 +93,7 @@ export class Cargo {
         return spec.filter?.(artifacts) ?? artifacts;
     }
 
-    async executableFromArgs(args: readonly string[]): Promise<string> {
+    async executableInfoFromArgs(args: readonly string[]): Promise<ExecutableInfo> {
         const artifacts = await this.getArtifacts(Cargo.artifactSpec(args));
 
         if (artifacts.length === 0) {
@@ -96,7 +103,10 @@ export class Cargo {
         }
 
         const artifact = unwrapUndefinable(artifacts[0]);
-        return artifact.fileName;
+        return {
+            executable: artifact.fileName,
+            workspace: artifact.workspace,
+        };
     }
 
     private async runCargo(
diff --git a/tests/codegen/issues/issue-116878.rs b/tests/codegen/issues/issue-116878.rs
new file mode 100644
index 00000000000..d5f679459f7
--- /dev/null
+++ b/tests/codegen/issues/issue-116878.rs
@@ -0,0 +1,13 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+/// Make sure no bounds checks are emitted after a `get_unchecked`.
+// CHECK-LABEL: @unchecked_slice_no_bounds_check
+#[no_mangle]
+pub unsafe fn unchecked_slice_no_bounds_check(s: &[u8]) -> u8 {
+    let a = *s.get_unchecked(1);
+    // CHECK-NOT: panic_bounds_check
+    a + s[0]
+}
diff --git a/tests/rustdoc/enum-variant-fields-heading.rs b/tests/rustdoc/enum-variant-fields-heading.rs
new file mode 100644
index 00000000000..8a7c99a8735
--- /dev/null
+++ b/tests/rustdoc/enum-variant-fields-heading.rs
@@ -0,0 +1,18 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/118195>.
+// It ensures that the "Fields" heading is not generated if no field is displayed.
+
+#![crate_name = "foo"]
+
+// @has 'foo/enum.Foo.html'
+// @has - '//*[@id="variant.A"]' 'A'
+// @count - '//*[@id="variant.A.fields"]' 0
+// @has - '//*[@id="variant.B"]' 'B'
+// @count - '//*[@id="variant.B.fields"]' 0
+// @snapshot variants - '//*[@id="main-content"]/*[@class="variants"]'
+
+pub enum Foo {
+    /// A variant with no fields
+    A {},
+    /// A variant with hidden fields
+    B { #[doc(hidden)] a: u8 },
+}
diff --git a/tests/rustdoc/enum-variant-fields-heading.variants.html b/tests/rustdoc/enum-variant-fields-heading.variants.html
new file mode 100644
index 00000000000..bcb36f7cf86
--- /dev/null
+++ b/tests/rustdoc/enum-variant-fields-heading.variants.html
@@ -0,0 +1,3 @@
+<div class="variants"><section id="variant.A" class="variant"><a href="#variant.A" class="anchor">&#167;</a><h3 class="code-header">A</h3></section><div class="docblock"><p>A variant with no fields</p>
+</div><section id="variant.B" class="variant"><a href="#variant.B" class="anchor">&#167;</a><h3 class="code-header">B</h3></section><div class="docblock"><p>A variant with hidden fields</p>
+</div></div>
\ No newline at end of file
diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr
new file mode 100644
index 00000000000..69f541cba05
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr
@@ -0,0 +1,25 @@
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
+  --> $DIR/associated-type.rs:31:1
+   |
+LL |   impl<T> Overlap<T> for T {
+   |   ------------------------ first implementation here
+...
+LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
+LL | |
+LL | | where
+LL | |     for<'a> *const T: ToUnit<'a>,
+   | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())`
+   |
+   = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr
new file mode 100644
index 00000000000..c2c951af0db
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr
@@ -0,0 +1,25 @@
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
+  --> $DIR/associated-type.rs:31:1
+   |
+LL |   impl<T> Overlap<T> for T {
+   |   ------------------------ first implementation here
+...
+LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
+LL | |
+LL | | where
+LL | |     for<'a> *const T: ToUnit<'a>,
+   | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)`
+   |
+   = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs
new file mode 100644
index 00000000000..909551f65be
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/associated-type.rs
@@ -0,0 +1,45 @@
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+
+// A regression test for #105787
+
+// Using the higher ranked projection hack to prevent us from replacing the projection
+// with an inference variable.
+trait ToUnit<'a> {
+    type Unit;
+}
+
+struct LocalTy;
+impl<'a> ToUnit<'a> for *const LocalTy {
+    type Unit = ();
+}
+
+impl<'a, T: Copy + ?Sized> ToUnit<'a> for *const T {
+    type Unit = ();
+}
+
+trait Overlap<T> {
+    type Assoc;
+}
+
+type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
+
+impl<T> Overlap<T> for T {
+    type Assoc = usize;
+}
+
+impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
+//~^ ERROR conflicting implementations of trait
+where
+    for<'a> *const T: ToUnit<'a>,
+{
+    type Assoc = Box<usize>;
+}
+
+fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
+    x
+}
+
+fn main() {
+    foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
+}
diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr
new file mode 100644
index 00000000000..428ee902ea5
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/opaques.next.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait<Alias<_>>` for type `Alias<_>`
+  --> $DIR/opaques.rs:29:1
+   |
+LL | impl<T> Trait<T> for T {
+   | ---------------------- first implementation here
+...
+LL | impl<T> Trait<T> for defining_scope::Alias<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs
new file mode 100644
index 00000000000..9d31a3dc82d
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/opaques.rs
@@ -0,0 +1,37 @@
+//revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+
+// A regression test for #105787
+
+//[old] known-bug: #105787
+//[old] check-pass
+#![feature(type_alias_impl_trait)]
+mod defining_scope {
+    use super::*;
+    pub type Alias<T> = impl Sized;
+
+    pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
+        x
+    }
+}
+
+struct Container<T: Trait<U>, U> {
+    x: <T as Trait<U>>::Assoc,
+}
+
+trait Trait<T> {
+    type Assoc;
+}
+
+impl<T> Trait<T> for T {
+    type Assoc = Box<u32>;
+}
+impl<T> Trait<T> for defining_scope::Alias<T> {
+    //[next]~^ ERROR conflicting implementations of trait
+    type Assoc = usize;
+}
+
+fn main() {
+    let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x;
+    println!("{}", *x);
+}
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
new file mode 100644
index 00000000000..eb985c062f3
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
@@ -0,0 +1,67 @@
+#![feature(diagnostic_namespace)]
+
+#[diagnostic::on_unimplemented(
+    on(_Self = "&str"),
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+    message = "trait has `{Self}` and `{T}` as params",
+    label = "trait has `{Self}` and `{T}` as params",
+    note  = "trait has `{Self}` and `{T}` as params",
+    parent_label = "in this scope",
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+    append_const_msg
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+)]
+trait Foo<T> {}
+
+#[diagnostic::on_unimplemented = "Message"]
+//~^WARN malformed `on_unimplemented` attribute
+//~|WARN malformed `on_unimplemented` attribute
+trait Bar {}
+
+#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
+//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions
+impl Bar for i32 {}
+
+// cannot use special rustc_on_unimplement symbols
+// in the format string
+#[diagnostic::on_unimplemented(
+    message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+    //~^WARN there is no parameter `from_desugaring` on trait `Baz`
+    //~|WARN there is no parameter `from_desugaring` on trait `Baz`
+    //~|WARN there is no parameter `direct` on trait `Baz`
+    //~|WARN there is no parameter `direct` on trait `Baz`
+    //~|WARN there is no parameter `cause` on trait `Baz`
+    //~|WARN there is no parameter `cause` on trait `Baz`
+    //~|WARN there is no parameter `integral` on trait `Baz`
+    //~|WARN there is no parameter `integral` on trait `Baz`
+    //~|WARN there is no parameter `integer` on trait `Baz`
+    //~|WARN there is no parameter `integer` on trait `Baz`
+    label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+    //~^WARN there is no parameter `float` on trait `Baz`
+    //~|WARN there is no parameter `float` on trait `Baz`
+    //~|WARN there is no parameter `_Self` on trait `Baz`
+    //~|WARN there is no parameter `_Self` on trait `Baz`
+    //~|WARN there is no parameter `crate_local` on trait `Baz`
+    //~|WARN there is no parameter `crate_local` on trait `Baz`
+    //~|WARN there is no parameter `Trait` on trait `Baz`
+    //~|WARN there is no parameter `Trait` on trait `Baz`
+    //~|WARN there is no parameter `ItemContext` on trait `Baz`
+    //~|WARN there is no parameter `ItemContext` on trait `Baz`
+)]
+trait Baz {}
+
+fn takes_foo(_: impl Foo<i32>) {}
+fn takes_bar(_: impl Bar) {}
+fn takes_baz(_: impl Baz) {}
+
+fn main() {
+    takes_foo(());
+    //~^ERROR trait has `()` and `i32` as params
+    takes_bar(());
+    //~^ERROR the trait bound `(): Bar` is not satisfied
+    takes_baz(());
+    //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer}
+}
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
new file mode 100644
index 00000000000..75a701f0b5f
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
@@ -0,0 +1,305 @@
+warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1
+   |
+LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+   |
+LL |     on(_Self = "&str"),
+   |     ^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+   |
+LL |     parent_label = "in this scope",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+   |
+LL |     append_const_msg
+   |     ^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+   |
+LL | #[diagnostic::on_unimplemented = "Message"]
+   |                                ^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: there is no parameter `from_desugaring` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `direct` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `cause` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `integral` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `integer` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `float` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `_Self` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `crate_local` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `Trait` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `ItemContext` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+   |
+LL |     on(_Self = "&str"),
+   |     ^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+   |
+LL |     parent_label = "in this scope",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+   |
+LL |     append_const_msg
+   |     ^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: trait has `()` and `i32` as params
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
+   |
+LL |     takes_foo(());
+   |     --------- ^^ trait has `()` and `i32` as params
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Foo<i32>` is not implemented for `()`
+   = note: trait has `()` and `i32` as params
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1
+   |
+LL | trait Foo<T> {}
+   | ^^^^^^^^^^^^
+note: required by a bound in `takes_foo`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
+   |
+LL | fn takes_foo(_: impl Foo<i32>) {}
+   |                      ^^^^^^^^ required by this bound in `takes_foo`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+   |
+LL | #[diagnostic::on_unimplemented = "Message"]
+   |                                ^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `(): Bar` is not satisfied
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
+   |
+LL |     takes_bar(());
+   |     --------- ^^ the trait `Bar` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Bar` is implemented for `i32`
+note: required by a bound in `takes_bar`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22
+   |
+LL | fn takes_bar(_: impl Bar) {}
+   |                      ^^^ required by this bound in `takes_bar`
+
+warning: there is no parameter `from_desugaring` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `direct` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `cause` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `integral` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `integer` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `float` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `_Self` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `crate_local` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `Trait` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `ItemContext` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
+   |
+LL |     takes_baz(());
+   |     --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Baz` is not implemented for `()`
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1
+   |
+LL | trait Baz {}
+   | ^^^^^^^^^
+note: required by a bound in `takes_baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
+   |
+LL | fn takes_baz(_: impl Baz) {}
+   |                      ^^^ required by this bound in `takes_baz`
+
+error: aborting due to 3 previous errors; 29 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
index 346d8373f73..12fe988170a 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
@@ -28,10 +28,16 @@ trait Doom {}
 //~|WARN missing options for `on_unimplemented` attribute
 trait Whatever {}
 
+#[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+//~^WARN there is no parameter `DoesNotExist` on trait `Test`
+//~|WARN there is no parameter `DoesNotExist` on trait `Test`
+trait Test {}
+
 fn take_foo(_: impl Foo) {}
 fn take_baz(_: impl Baz) {}
 fn take_boom(_: impl Boom) {}
 fn take_whatever(_: impl Whatever) {}
+fn take_test(_: impl Test) {}
 
 fn main() {
     take_foo(1_i32);
@@ -42,4 +48,6 @@ fn main() {
     //~^ERROR Boom
     take_whatever(1_i32);
     //~^ERROR the trait bound `i32: Whatever` is not satisfied
+    take_test(());
+    //~^ERROR {DoesNotExist}
 }
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
index 162ddd79fbb..11263580b15 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
@@ -46,6 +46,14 @@ LL | #[diagnostic::on_unimplemented]
    |
    = help: at least one of the `message`, `note` and `label` options are expected
 
+warning: there is no parameter `DoesNotExist` on trait `Test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
 warning: malformed `on_unimplemented` attribute
   --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
    |
@@ -56,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
    |
 LL |     take_foo(1_i32);
    |     -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -69,7 +77,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `take_foo`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
    |
 LL | fn take_foo(_: impl Foo) {}
    |                     ^^^ required by this bound in `take_foo`
@@ -84,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
    |
 LL |     take_baz(1_i32);
    |     -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -97,7 +105,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `take_baz`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
    |
 LL | fn take_baz(_: impl Baz) {}
    |                     ^^^ required by this bound in `take_baz`
@@ -112,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
    |
 LL |     take_boom(1_i32);
    |     --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -125,7 +133,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Boom {}
    | ^^^^^^^^^^
 note: required by a bound in `take_boom`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
    |
 LL | fn take_boom(_: impl Boom) {}
    |                      ^^^^ required by this bound in `take_boom`
@@ -140,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Whatever` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:19
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
    |
 LL |     take_whatever(1_i32);
    |     ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
@@ -153,11 +161,39 @@ help: this trait has no implementations, consider adding one
 LL | trait Whatever {}
    | ^^^^^^^^^^^^^^
 note: required by a bound in `take_whatever`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:26
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
    |
 LL | fn take_whatever(_: impl Whatever) {}
    |                          ^^^^^^^^ required by this bound in `take_whatever`
 
-error: aborting due to 4 previous errors; 10 warnings emitted
+warning: there is no parameter `DoesNotExist` on trait `Test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: {DoesNotExist}
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
+   |
+LL |     take_test(());
+   |     --------- ^^ the trait `Test` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
+   |
+LL | trait Test {}
+   | ^^^^^^^^^^
+note: required by a bound in `take_test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
+   |
+LL | fn take_test(_: impl Test) {}
+   |                      ^^^^ required by this bound in `take_test`
+
+error: aborting due to 5 previous errors; 12 warnings emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/packed/issue-118537-field-offset-ice.rs b/tests/ui/packed/issue-118537-field-offset-ice.rs
new file mode 100644
index 00000000000..657aec64003
--- /dev/null
+++ b/tests/ui/packed/issue-118537-field-offset-ice.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed(4))]
+struct Slice([u32]);
+
+#[repr(packed(2), C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed(2), C)]
+struct PackedUnsized {
+    f: u8,
+    d: Slice,
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation correctly adds exact 1 byte of padding
+    // in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }
diff --git a/tests/ui/packed/issue-118537-field-offset.rs b/tests/ui/packed/issue-118537-field-offset.rs
new file mode 100644
index 00000000000..cd17f767947
--- /dev/null
+++ b/tests/ui/packed/issue-118537-field-offset.rs
@@ -0,0 +1,36 @@
+// run-pass
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed, C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed, C)]
+struct PackedUnsized {
+    f: u8,
+    d: [u32],
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation does *not* think there is
+    // any padding in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }
diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.rs b/tests/ui/traits/new-solver/equating-projection-cyclically.rs
index 2668da1b745..845597e9ce1 100644
--- a/tests/ui/traits/new-solver/equating-projection-cyclically.rs
+++ b/tests/ui/traits/new-solver/equating-projection-cyclically.rs
@@ -1,3 +1,4 @@
+// check-pass
 // compile-flags: -Ztrait-solver=next
 
 trait Test {
@@ -22,7 +23,9 @@ fn main() {
     let mut x: Inv<_> = Inv(None);
     // This ends up equating `Inv<?x>` with `Inv<<?x as Test>::Assoc>`
     // which fails the occurs check when generalizing `?x`.
+    //
+    // We end up emitting a delayed obligation, causing this to still
+    // succeed.
     x = transform(x);
-    //~^ ERROR mismatched types
     x = Inv::<i32>(None);
 }
diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr
deleted file mode 100644
index 91dd3ebc31b..00000000000
--- a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/equating-projection-cyclically.rs:25:9
-   |
-LL |     x = transform(x);
-   |         ^^^^^^^^^^^^ cyclic type of infinite size
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr
new file mode 100644
index 00000000000..34c2f0438c7
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr
@@ -0,0 +1,9 @@
+error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
+  --> $DIR/occurs-check-nested-alias.rs:35:9
+   |
+LL |     x = y;
+   |         ^ types differ
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs
new file mode 100644
index 00000000000..a2113b2a8b3
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs
@@ -0,0 +1,37 @@
+// revisions: old next
+//[old] check-pass
+
+// Need to emit an alias-relate instead of a `Projection` goal here.
+//[next] compile-flags: -Ztrait-solver=next
+//[next] known-bug: trait-system-refactor-initiative#8
+#![crate_type = "lib"]
+#![allow(unused)]
+trait Unnormalizable {
+    type Assoc;
+}
+
+trait Id<T> {
+    type Id;
+}
+impl<T, U> Id<T> for U {
+    type Id = U;
+}
+
+struct Inv<T>(*mut T);
+
+fn unconstrained<T>() -> T {
+    todo!()
+}
+
+fn create<T, U: Unnormalizable>(
+    x: &U,
+) -> (Inv<T>, Inv<<<U as Id<T>>::Id as Unnormalizable>::Assoc>) {
+    todo!()
+}
+
+fn foo<T: Unnormalizable>() {
+    let q = unconstrained();
+    let (mut x, y) = create::<_, _>(&q);
+    x = y;
+    drop::<T>(q);
+}