summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/token.rs22
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs21
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs27
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/archive.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs242
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs202
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs6
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl68
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs13
-rw-r--r--compiler/rustc_errors/src/lib.rs8
-rw-r--r--compiler/rustc_hir/src/def.rs115
-rw-r--r--compiler/rustc_hir/src/hir.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/check/callee.rs274
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/mem_categorization.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs3
-rw-r--r--compiler/rustc_interface/src/queries.rs4
-rw-r--r--compiler/rustc_lint/src/internal.rs2
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs33
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs3
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs13
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs5
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs3
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs18
-rw-r--r--compiler/rustc_parse/src/parser/item.rs28
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/check_const.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs10
-rw-r--r--compiler/rustc_privacy/src/lib.rs4
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs4
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs3
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs15
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs25
-rw-r--r--compiler/rustc_resolve/src/ident.rs22
-rw-r--r--compiler/rustc_resolve/src/late.rs49
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs3
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs5
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs2
-rw-r--r--compiler/rustc_span/src/def_id.rs20
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs33
-rw-r--r--library/core/src/const_closure.rs64
-rw-r--r--library/core/src/ops/try_trait.rs2
-rw-r--r--library/core/src/time.rs39
-rw-r--r--library/core/tests/time.rs24
-rw-r--r--src/bootstrap/lib.rs2
-rw-r--r--src/librustdoc/clean/types.rs13
-rw-r--r--src/librustdoc/clean/utils.rs4
-rw-r--r--src/librustdoc/html/render/print_item.rs6
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css31
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css21
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css24
-rw-r--r--src/librustdoc/html/static/css/themes/light.css24
m---------src/llvm-project0
-rw-r--r--src/test/rustdoc-gui/anchor-navigable.goml2
-rw-r--r--src/test/rustdoc-gui/font-weight.goml4
-rw-r--r--src/test/rustdoc-gui/no-docblock.goml8
-rw-r--r--src/test/rustdoc-gui/sidebar-links-color.goml233
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile-scroll.goml6
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code-display.goml19
-rw-r--r--src/test/rustdoc-gui/src-font-size.goml8
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs12
-rw-r--r--src/test/rustdoc/anchors.no_const_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_trait_method_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_tymethod_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_type_anchor.html2
-rw-r--r--src/test/rustdoc/rfc-2632-const-trait-impl.rs8
-rw-r--r--src/test/rustdoc/toggle-trait-fn.rs12
-rw-r--r--src/test/ui/borrowck/issue-102209.rs28
-rw-r--r--src/test/ui/borrowck/issue-102209.stderr22
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-102057.rs19
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-102057.stderr45
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-1.stderr8
-rw-r--r--src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs11
-rw-r--r--src/test/ui/impl-trait/in-trait/foreign.rs9
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-captures.stderr8
-rw-r--r--src/test/ui/parser/fn-field-parse-error-ice.rs2
-rw-r--r--src/test/ui/parser/fn-field-parse-error-ice.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr19
-rw-r--r--src/test/ui/stats/hir-stats.rs1
-rw-r--r--src/test/ui/stats/hir-stats.stderr92
-rw-r--r--src/test/ui/structs/incomplete-fn-in-struct-definition.rs5
-rw-r--r--src/test/ui/structs/incomplete-fn-in-struct-definition.stderr15
-rw-r--r--src/test/ui/type/issue-101866.rs15
-rw-r--r--src/test/ui/type/issue-101866.stderr18
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/tidy/src/deps.rs33
112 files changed, 1640 insertions, 800 deletions
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index fa6162c5184..99034799b3c 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -256,10 +256,6 @@ pub enum TokenKind {
     Eof,
 }
 
-// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenKind, 16);
-
 #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct Token {
     pub kind: TokenKind,
@@ -728,6 +724,7 @@ impl Token {
 }
 
 impl PartialEq<TokenKind> for Token {
+    #[inline]
     fn eq(&self, rhs: &TokenKind) -> bool {
         self.kind == *rhs
     }
@@ -751,10 +748,6 @@ pub enum Nonterminal {
     NtVis(P<ast::Visibility>),
 }
 
-// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Nonterminal, 16);
-
 #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
 pub enum NonterminalKind {
     Item,
@@ -893,3 +886,16 @@ where
         panic!("interpolated tokens should not be present in the HIR")
     }
 }
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    use rustc_data_structures::static_assert_size;
+    // These are in alphabetical order, which is easy to maintain.
+    static_assert_size!(Lit, 12);
+    static_assert_size!(LitKind, 2);
+    static_assert_size!(Nonterminal, 16);
+    static_assert_size!(Token, 24);
+    static_assert_size!(TokenKind, 16);
+}
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 875cd620dfc..824206a99d8 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -47,10 +47,6 @@ pub enum TokenTree {
     Delimited(DelimSpan, Delimiter, TokenStream),
 }
 
-// This type is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenTree, 32);
-
 // Ensure all fields of `TokenTree` is `Send` and `Sync`.
 #[cfg(parallel_compiler)]
 fn _dummy()
@@ -308,10 +304,6 @@ pub struct AttributesData {
 #[derive(Clone, Debug, Default, Encodable, Decodable)]
 pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
 
-// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenStream, 8);
-
 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum Spacing {
     Alone,
@@ -664,3 +656,16 @@ impl DelimSpan {
         self.open.with_hi(self.close.hi())
     }
 }
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    use rustc_data_structures::static_assert_size;
+    // These are in alphabetical order, which is easy to maintain.
+    static_assert_size!(AttrTokenStream, 8);
+    static_assert_size!(AttrTokenTree, 32);
+    static_assert_size!(LazyAttrTokenStream, 8);
+    static_assert_size!(TokenStream, 8);
+    static_assert_size!(TokenTree, 32);
+}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 275ceed30d7..8281164ab12 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -61,8 +61,8 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::DesugaringKind;
@@ -1060,13 +1060,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
                     // constructing the HIR for `impl bounds...` and then lowering that.
 
-                    let parent_def_id = self.current_hir_id_owner;
                     let impl_trait_node_id = self.next_node_id();
-                    self.create_def(
-                        parent_def_id.def_id,
-                        impl_trait_node_id,
-                        DefPathData::ImplTrait,
-                    );
 
                     self.with_dyn_type_scope(false, |this| {
                         let node_id = this.next_node_id();
@@ -1357,9 +1351,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         def_node_id,
                         bounds,
                         false,
-                        &ImplTraitContext::TypeAliasesOpaqueTy,
+                        itctx,
                     ),
                     ImplTraitContext::Universal => {
+                        self.create_def(
+                            self.current_hir_id_owner.def_id,
+                            def_node_id,
+                            DefPathData::ImplTrait,
+                        );
                         let span = t.span;
                         let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         let (param, bounds, path) =
@@ -1453,7 +1452,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
+        let opaque_ty_def_id = match origin {
+            hir::OpaqueTyOrigin::TyAlias => self.create_def(
+                self.current_hir_id_owner.def_id,
+                opaque_ty_node_id,
+                DefPathData::ImplTrait,
+            ),
+            hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
+                self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
+            }
+            hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
+        };
         debug!(?opaque_ty_def_id);
 
         // Contains the new lifetime definitions created for the TAIT (if any).
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 419e6c81791..4d251cf7ac7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -864,15 +864,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         };
 
         let tcx = self.infcx.tcx;
-        let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?;
-        if tcx.parent(region.def_id) != body_parent_did
-            || tcx.def_kind(body_parent_did) != DefKind::Impl
-        {
+        let region_parent = tcx.parent(region.def_id);
+        if tcx.def_kind(region_parent) != DefKind::Impl {
             return None;
         }
 
         let mut found = false;
-        tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| {
+        tcx.fold_regions(tcx.type_of(region_parent), |r: ty::Region<'tcx>, _| {
             if *r == ty::ReEarlyBound(region) {
                 found = true;
             }
diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs
index f863abdcc97..ac0342f6b80 100644
--- a/compiler/rustc_codegen_gcc/src/archive.rs
+++ b/compiler/rustc_codegen_gcc/src/archive.rs
@@ -1,6 +1,8 @@
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
+use crate::errors::RanlibFailure;
+
 use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
 use rustc_session::Session;
 
@@ -181,7 +183,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
             std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
 
         if !status.success() {
-            self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
+            self.config.sess.emit_fatal(RanlibFailure::new(status.code()));
         }
 
         any_members
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 52fd66af065..007b001f213 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -12,6 +12,7 @@ use std::borrow::Cow;
 
 use crate::builder::Builder;
 use crate::context::CodegenCx;
+use crate::errors::UnwindingInlineAsm;
 use crate::type_of::LayoutGccExt;
 use crate::callee::get_fn;
 
@@ -109,7 +110,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) {
         if options.contains(InlineAsmOptions::MAY_UNWIND) {
             self.sess()
-                .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
+                .create_err(UnwindingInlineAsm { span: span[0] })
                 .emit();
             return;
         }
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 356c03ee3c1..81f53328867 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -14,6 +14,7 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan
 
 use crate::base;
 use crate::context::CodegenCx;
+use crate::errors::LinkageConstOrMutType;
 use crate::type_of::LayoutGccExt;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -368,10 +369,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
                 cx.layout_of(mt.ty).gcc_type(cx, true)
             }
             else {
-                cx.sess().span_fatal(
-                    span,
-                    "must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
-                )
+                cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
             };
         // Declare a symbol `foo` with the desired linkage.
         let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 478f6d893dd..46ade33eb01 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
 use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
 use rustc_session::Session;
-use rustc_span::Span;
+use rustc_span::{Span, source_map::respan};
 use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
 
@@ -293,7 +293,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type)
     }
 
-    pub fn sess(&self) -> &Session {
+    pub fn sess(&self) -> &'tcx Session {
         &self.tcx.sess
     }
 
@@ -477,7 +477,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) = err {
-            self.sess().span_fatal(span, &err.to_string())
+            self.sess().emit_fatal(respan(span, err))
         } else {
             span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
         }
@@ -495,7 +495,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
         fn_abi_request: FnAbiRequest<'tcx>,
     ) -> ! {
         if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
-            self.sess().span_fatal(span, &err.to_string())
+            self.sess().emit_fatal(respan(span, err))
         } else {
             match fn_abi_request {
                 FnAbiRequest::OfFnPtr { sig, extra_args } => {
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
new file mode 100644
index 00000000000..d7816e395c8
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -0,0 +1,242 @@
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_macros::Diagnostic;
+use rustc_middle::ty::Ty;
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
+
+struct ExitCode(Option<i32>);
+
+impl IntoDiagnosticArg for ExitCode {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        let ExitCode(exit_code) = self;
+        match exit_code {
+            Some(t) => t.into_diagnostic_arg(),
+            None => DiagnosticArgValue::Str(Cow::Borrowed("<signal>")),
+        }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::ranlib_failure)]
+pub(crate) struct RanlibFailure {
+    exit_code: ExitCode,
+}
+
+impl RanlibFailure {
+    pub fn new(exit_code: Option<i32>) -> Self {
+        RanlibFailure { exit_code: ExitCode(exit_code) }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub elem_ty: &'a str,
+    pub vec_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnrecognized {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub elem_ty: Ty<'a>,
+    pub vec_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_ty: Ty<'a>,
+    pub elem_ty: Ty<'a>,
+    pub ret_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ty: Ty<'a>,
+    pub expected_int_bits: u64,
+    pub expected_bytes: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub position: &'a str,
+    pub found_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationMaskType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_len: u64,
+    pub ret_ty: Ty<'a>,
+    pub out_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_len: u64,
+    pub in_ty: Ty<'a>,
+    pub ret_ty: Ty<'a>,
+    pub out_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_elem: Ty<'a>,
+    pub in_ty: Ty<'a>,
+    pub ret_ty: Ty<'a>,
+    pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_elem: Ty<'a>,
+    pub in_ty: Ty<'a>,
+    pub ret_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_elem: Ty<'a>,
+    pub in_ty: Ty<'a>,
+    pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub ret_ty: Ty<'a>,
+    pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationMismatchedLengths {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub m_len: u64,
+    pub v_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_ty: Ty<'a>,
+    pub in_elem: Ty<'a>,
+    pub ret_ty: Ty<'a>,
+    pub out_elem: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub in_ty: Ty<'a>,
+    pub in_elem: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::linkage_const_or_mut_type)]
+pub(crate) struct LinkageConstOrMutType {
+    #[primary_span]
+    pub span: Span
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::lto_not_supported)]
+pub(crate) struct LTONotSupported;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc::unwinding_inline_asm)]
+pub(crate) struct UnwindingInlineAsm {
+    #[primary_span]
+    pub span: Span
+}
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 02cedd4646b..cc9c90c2427 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -4,7 +4,7 @@ mod simd;
 use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
-use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error};
+use rustc_codegen_ssa::common::IntPredicate;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
@@ -20,6 +20,7 @@ use crate::abi::GccType;
 use crate::builder::Builder;
 use crate::common::{SignType, TypeReflection};
 use crate::context::CodegenCx;
+use crate::errors::InvalidMonomorphizationBasicInteger;
 use crate::type_of::LayoutGccExt;
 use crate::intrinsic::simd::generic_simd_intrinsic;
 
@@ -242,15 +243,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                                 _ => bug!(),
                             },
                             None => {
-                                span_invalid_monomorphization_error(
-                                    tcx.sess,
-                                    span,
-                                    &format!(
-                                        "invalid monomorphization of `{}` intrinsic: \
-                                      expected basic integer type, found `{}`",
-                                      name, ty
-                                    ),
-                                );
+                                tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty });
                                 return;
                             }
                         }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 2401f335018..ffc85b773a2 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -2,7 +2,7 @@ use std::cmp::Ordering;
 
 use gccjit::{BinaryOp, RValue, Type, ToRValue};
 use rustc_codegen_ssa::base::compare_simd_types;
-use rustc_codegen_ssa::common::{TypeKind, span_invalid_monomorphization_error};
+use rustc_codegen_ssa::common::TypeKind;
 use rustc_codegen_ssa::mir::operand::OperandRef;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
@@ -14,43 +14,48 @@ use rustc_span::{Span, Symbol, sym};
 use rustc_target::abi::Align;
 
 use crate::builder::Builder;
+use crate::errors::{
+    InvalidMonomorphizationInvalidFloatVector,
+    InvalidMonomorphizationNotFloat,
+    InvalidMonomorphizationUnrecognized,
+    InvalidMonomorphizationExpectedSignedUnsigned,
+    InvalidMonomorphizationUnsupportedElement,
+    InvalidMonomorphizationInvalidBitmask,
+    InvalidMonomorphizationSimdShuffle,
+    InvalidMonomorphizationExpectedSimd,
+    InvalidMonomorphizationMaskType,
+    InvalidMonomorphizationReturnLength,
+    InvalidMonomorphizationReturnLengthInputType,
+    InvalidMonomorphizationReturnElement,
+    InvalidMonomorphizationReturnType,
+    InvalidMonomorphizationInsertedType,
+    InvalidMonomorphizationReturnIntegerType,
+    InvalidMonomorphizationMismatchedLengths,
+    InvalidMonomorphizationUnsupportedCast,
+    InvalidMonomorphizationUnsupportedOperation
+};
 use crate::intrinsic;
 
 pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> {
     // macros for error handling:
-    #[allow(unused_macro_rules)]
-    macro_rules! emit_error {
-        ($msg: tt) => {
-            emit_error!($msg, )
-        };
-        ($msg: tt, $($fmt: tt)*) => {
-            span_invalid_monomorphization_error(
-                bx.sess(), span,
-                &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
-                         name, $($fmt)*));
-        }
-    }
-
     macro_rules! return_error {
-        ($($fmt: tt)*) => {
+        ($err:expr) => {
             {
-                emit_error!($($fmt)*);
+                bx.sess().emit_err($err);
                 return Err(());
             }
         }
     }
-
     macro_rules! require {
-        ($cond: expr, $($fmt: tt)*) => {
+        ($cond:expr, $err:expr) => {
             if !$cond {
-                return_error!($($fmt)*);
+                return_error!($err);
             }
-        };
+        }
     }
-
     macro_rules! require_simd {
         ($ty: expr, $position: expr) => {
-            require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
+            require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty })
         };
     }
 
@@ -82,10 +87,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                 bx.load(int_ty, ptr, Align::ONE)
             }
             _ => return_error!(
-                "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
-                mask_ty,
-                expected_int_bits,
-                expected_bytes
+                InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes }
             ),
         };
 
@@ -127,18 +129,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-             found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
         );
         require!(
             bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
-            "expected return type with integer elements, found `{}` with non-integer `{}`",
-            ret_ty,
-            out_ty
+            InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty}
         );
 
         return Ok(compare_simd_types(
@@ -163,8 +158,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                         })
                     }
                     _ => return_error!(
-                        "simd_shuffle index must be an array of `u32`, got `{}`",
-                        args[2].layout.ty
+                        InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty }
                     ),
                 }
             }
@@ -179,19 +173,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             out_len == n,
-            "expected return type of length {}, found `{}` with length {}",
-            n,
-            ret_ty,
-            out_len
+            InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len }
         );
         require!(
             in_elem == out_ty,
-            "expected return element type `{}` (element of input `{}`), \
-             found `{}` with element type `{}`",
-            in_elem,
-            in_ty,
-            ret_ty,
-            out_ty
+            InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
         );
 
         let vector = args[2].immediate();
@@ -207,10 +193,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
     if name == sym::simd_insert {
         require!(
             in_elem == arg_tys[2],
-            "expected inserted type `{}` (element of input `{}`), found `{}`",
-            in_elem,
-            in_ty,
-            arg_tys[2]
+            InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
         );
         let vector = args[0].immediate();
         let index = args[1].immediate();
@@ -263,10 +246,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
     if name == sym::simd_extract {
         require!(
             ret_ty == in_elem,
-            "expected return type `{}` (element of input `{}`), found `{}`",
-            in_elem,
-            in_ty,
-            ret_ty
+            InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
         );
         let vector = args[0].immediate();
         return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
@@ -279,13 +259,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
         require!(
             m_len == v_len,
-            "mismatched lengths: mask length `{}` != other vector length `{}`",
-            m_len,
-            v_len
+            InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len }
         );
         match m_elem_ty.kind() {
             ty::Int(_) => {}
-            _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty),
+            _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }),
         }
         return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
     }
@@ -295,12 +273,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-                  found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
         );
         // casting cares about nominal type, not just structural type
         if in_elem == out_elem {
@@ -412,13 +385,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
             }
             _ => { /* Unsupported. Fallthrough. */ }
         }
-        require!(
-            false,
-            "unsupported cast from `{}` with element `{}` to `{}` with element `{}`",
-            in_ty,
-            in_elem,
-            ret_ty,
-            out_elem
+        return_error!(
+            InvalidMonomorphizationUnsupportedCast { span, name, in_ty, in_elem, ret_ty, out_elem }
         );
     }
 
@@ -431,10 +399,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                     })*
                     _ => {},
                 }
-                require!(false,
-                         "unsupported operation on `{}` with element `{}`",
-                         in_ty,
-                         in_elem)
+                return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
             })*
         }
     }
@@ -448,23 +413,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         span: Span,
         args: &[OperandRef<'tcx, RValue<'gcc>>],
     ) -> Result<RValue<'gcc>, ()> {
-        macro_rules! emit_error {
-            ($msg: tt, $($fmt: tt)*) => {
-                span_invalid_monomorphization_error(
-                    bx.sess(), span,
-                    &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
-                             name, $($fmt)*));
-            }
-        }
         macro_rules! return_error {
-            ($($fmt: tt)*) => {
+            ($err:expr) => {
                 {
-                    emit_error!($($fmt)*);
+                    bx.sess().emit_err($err);
                     return Err(());
                 }
             }
         }
-
         let (elem_ty_str, elem_ty) =
             if let ty::Float(f) = in_elem.kind() {
                 let elem_ty = bx.cx.type_float_from_ty(*f);
@@ -472,16 +428,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                     32 => ("f32", elem_ty),
                     64 => ("f64", elem_ty),
                     _ => {
-                        return_error!(
-                            "unsupported element type `{}` of floating-point vector `{}`",
-                            f.name_str(),
-                            in_ty
-                        );
+                        return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
                     }
                 }
             }
             else {
-                return_error!("`{}` is not a floating-point type", in_ty);
+                return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
             };
 
         let vec_ty = bx.cx.type_vector(elem_ty, in_len);
@@ -504,7 +456,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                 sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
                 sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
                 sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
-                _ => return_error!("unrecognized intrinsic `{}`", name),
+                _ => return_error!(InvalidMonomorphizationUnrecognized { span, name })
             };
         let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
         let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx);
@@ -557,10 +509,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                     })*
                     _ => {},
                 }
-                require!(false,
-                         "unsupported operation on `{}` with element `{}`",
-                         in_ty,
-                         in_elem)
+                return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
             })*
         }
     }
@@ -579,12 +528,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
             ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)),
             ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)),
             _ => {
-                return_error!(
-                    "expected element type `{}` of vector type `{}` \
-                     to be a signed or unsigned integer type",
-                    arg_tys[0].simd_size_and_type(bx.tcx()).1,
-                    arg_tys[0]
-                );
+                return_error!(InvalidMonomorphizationExpectedSignedUnsigned {
+                    span,
+                    name,
+                    elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1,
+                    vec_ty: arg_tys[0],
+                });
             }
         };
         let builtin_name =
@@ -617,10 +566,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    "expected return type `{}` (element of input `{}`), found `{}`",
-                    in_elem,
-                    in_ty,
-                    ret_ty
+                    InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_) | ty::Uint(_) => {
@@ -644,13 +590,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                             Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
                         }
                     }
-                    _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
-                        in_ty,
-                        in_elem,
-                        ret_ty
-                    ),
+                    _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
                 };
             }
         };
@@ -676,20 +616,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    "expected return type `{}` (element of input `{}`), found `{}`",
-                    in_elem,
-                    in_ty,
-                    ret_ty
+                    InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_) | ty::Uint(_) | ty::Float(_) => Ok(bx.$reduction(args[0].immediate())),
-                    _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
-                        in_ty,
-                        in_elem,
-                        ret_ty
-                    ),
+                    _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
                 };
             }
         };
@@ -704,22 +635,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                 let input = if !$boolean {
                     require!(
                         ret_ty == in_elem,
-                        "expected return type `{}` (element of input `{}`), found `{}`",
-                        in_elem,
-                        in_ty,
-                        ret_ty
+                        InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
                     );
                     args[0].immediate()
                 } else {
                     match in_elem.kind() {
                         ty::Int(_) | ty::Uint(_) => {}
-                        _ => return_error!(
-                            "unsupported {} from `{}` with element `{}` to `{}`",
-                            sym::$name,
-                            in_ty,
-                            in_elem,
-                            ret_ty
-                        ),
+                        _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
                     }
 
                     // boolean reductions operate on vectors of i1s:
@@ -733,11 +655,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                         Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
                     }
                     _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
-                        in_ty,
-                        in_elem,
-                        ret_ty
+                        InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }
                     ),
                 };
             }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 223466fb9b5..007d61ed51d 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -18,6 +18,8 @@
 #![recursion_limit="256"]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 extern crate rustc_apfloat;
 extern crate rustc_ast;
@@ -25,6 +27,7 @@ extern crate rustc_codegen_ssa;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
+extern crate rustc_macros;
 extern crate rustc_metadata;
 extern crate rustc_middle;
 extern crate rustc_session;
@@ -50,6 +53,7 @@ mod context;
 mod coverageinfo;
 mod debuginfo;
 mod declare;
+mod errors;
 mod int;
 mod intrinsic;
 mod mono_item;
@@ -59,6 +63,7 @@ mod type_of;
 use std::any::Any;
 use std::sync::{Arc, Mutex};
 
+use crate::errors::LTONotSupported;
 use gccjit::{Context, OptimizationLevel, CType};
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
@@ -97,7 +102,7 @@ pub struct GccCodegenBackend {
 impl CodegenBackend for GccCodegenBackend {
     fn init(&self, sess: &Session) {
         if sess.lto() != Lto::No {
-            sess.warn("LTO is not supported. You may get a linker error.");
+            sess.emit_warning(LTONotSupported {});
         }
 
         let temp_dir = TempDir::new().expect("cannot create temporary directory");
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 67ffc7cb951..2ab69d25411 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -154,6 +154,11 @@ pub unsafe fn create_module<'ll>(
             target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
         }
     }
+    if llvm_version < (16, 0, 0) {
+        if sess.target.arch == "s390x" {
+            target_data_layout = target_data_layout.replace("-v128:64", "");
+        }
+    }
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.is_builtin {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 061053ef2ac..f59a753a5ce 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1180,18 +1180,12 @@ impl<'a> WasmLd<'a> {
         //   sharing memory and instantiating the module multiple times. As a
         //   result if it were exported then we'd just have no sharing.
         //
-        // * `--export=__wasm_init_memory` - when using `--passive-segments` the
-        //   linker will synthesize this function, and so we need to make sure
-        //   that our usage of `--export` below won't accidentally cause this
-        //   function to get deleted.
-        //
         // * `--export=*tls*` - when `#[thread_local]` symbols are used these
         //   symbols are how the TLS segments are initialized and configured.
         if sess.target_features.contains(&sym::atomics) {
             cmd.arg("--shared-memory");
             cmd.arg("--max-memory=1073741824");
             cmd.arg("--import-memory");
-            cmd.arg("--export=__wasm_init_memory");
             cmd.arg("--export=__wasm_init_tls");
             cmd.arg("--export=__tls_size");
             cmd.arg("--export=__tls_align");
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
new file mode 100644
index 00000000000..178e1a67cce
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
@@ -0,0 +1,68 @@
+codegen_gcc_ranlib_failure =
+    Ranlib exited with code {$exit_code}
+
+codegen_gcc_linkage_const_or_mut_type =
+    must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+
+codegen_gcc_unwinding_inline_asm =
+    GCC backend does not support unwinding from inline asm
+
+codegen_gcc_lto_not_supported =
+    LTO is not supported. You may get a linker error.
+
+codegen_gcc_invalid_monomorphization_basic_integer =
+    invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+
+codegen_gcc_invalid_monomorphization_invalid_float_vector =
+    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
+
+codegen_gcc_invalid_monomorphization_not_float =
+    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
+
+codegen_gcc_invalid_monomorphization_unrecognized =
+    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+
+codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
+    invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
+
+codegen_gcc_invalid_monomorphization_unsupported_element =
+    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
+
+codegen_gcc_invalid_monomorphization_invalid_bitmask =
+    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_gcc_invalid_monomorphization_simd_shuffle =
+    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+
+codegen_gcc_invalid_monomorphization_expected_simd =
+    invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
+
+codegen_gcc_invalid_monomorphization_mask_type =
+    invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+
+codegen_gcc_invalid_monomorphization_return_length =
+    invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+
+codegen_gcc_invalid_monomorphization_return_length_input_type =
+    invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+
+codegen_gcc_invalid_monomorphization_return_element =
+    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_type =
+    invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+
+codegen_gcc_invalid_monomorphization_inserted_type =
+    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_integer_type =
+    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_mismatched_lengths =
+    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_gcc_invalid_monomorphization_unsupported_cast =
+    invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+
+codegen_gcc_invalid_monomorphization_unsupported_operation =
+    invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index fb7f89d7a28..bf9248f99b6 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -41,6 +41,7 @@ fluent_messages! {
     borrowck => "../locales/en-US/borrowck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
     const_eval => "../locales/en-US/const_eval.ftl",
+    codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
     driver => "../locales/en-US/driver.ftl",
     expand => "../locales/en-US/expand.ftl",
     session => "../locales/en-US/session.ftl",
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 4f26ecb1bdd..bbe6435be59 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -5,6 +5,7 @@ use crate::{
 };
 use crate::{Handler, Level, MultiSpan, StashKey};
 use rustc_lint_defs::Applicability;
+use rustc_span::source_map::Spanned;
 
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -23,6 +24,18 @@ pub trait IntoDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
     fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>;
 }
 
+impl<'a, T, E> IntoDiagnostic<'a, E> for Spanned<T>
+where
+    T: IntoDiagnostic<'a, E>,
+    E: EmissionGuarantee,
+{
+    fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, E> {
+        let mut diag = self.node.into_diagnostic(handler);
+        diag.set_span(self.span);
+        diag
+    }
+}
+
 /// Used for emitting structured error messages and other diagnostic information.
 ///
 /// If there is some state in a downstream crate you would like to
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 646af7e1c6c..c8711ec6e25 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -66,7 +66,7 @@ pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
 pub type PResult<'a, T> = Result<T, PErr<'a>>;
 
 // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
-// (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.)
+// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -1134,6 +1134,12 @@ impl Handler {
         );
         std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
     }
+
+    pub fn flush_delayed(&self) {
+        let mut inner = self.inner.lock();
+        let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new());
+        inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
+    }
 }
 
 impl HandlerInner {
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index e7c26bd726f..f1f0c224bbd 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -314,74 +314,75 @@ pub enum Res<Id = hir::HirId> {
     /// **Belongs to the type namespace.**
     PrimTy(hir::PrimTy),
 
-    /// The `Self` type, optionally with the [`DefId`] of the trait it belongs to and
-    /// optionally with the [`DefId`] of the item introducing the `Self` type alias.
+    /// The `Self` type, as used within a trait.
+    ///
+    /// **Belongs to the type namespace.**
+    ///
+    /// See the examples on [`Res::SelfTyAlias`] for details.
+    SelfTyParam {
+        /// The trait this `Self` is a generic parameter for.
+        trait_: DefId,
+    },
+
+    /// The `Self` type, as used somewhere other than within a trait.
     ///
     /// **Belongs to the type namespace.**
     ///
     /// Examples:
     /// ```
-    /// struct Bar(Box<Self>);
-    /// // `Res::SelfTy { trait_: None, alias_of: Some(Bar) }`
+    /// struct Bar(Box<Self>); // SelfTyAlias
     ///
     /// trait Foo {
-    ///     fn foo() -> Box<Self>;
-    ///     // `Res::SelfTy { trait_: Some(Foo), alias_of: None }`
+    ///     fn foo() -> Box<Self>; // SelfTyParam
     /// }
     ///
     /// impl Bar {
     ///     fn blah() {
-    ///         let _: Self;
-    ///         // `Res::SelfTy { trait_: None, alias_of: Some(::{impl#0}) }`
+    ///         let _: Self; // SelfTyAlias
     ///     }
     /// }
     ///
     /// impl Foo for Bar {
-    ///     fn foo() -> Box<Self> {
-    ///     // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
-    ///         let _: Self;
-    ///         // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
+    ///     fn foo() -> Box<Self> { // SelfTyAlias
+    ///         let _: Self;        // SelfTyAlias
     ///
     ///         todo!()
     ///     }
     /// }
     /// ```
-    ///
     /// *See also [`Res::SelfCtor`].*
     ///
-    /// -----
-    ///
-    /// HACK(min_const_generics): self types also have an optional requirement to **not** mention
-    /// any generic parameters to allow the following with `min_const_generics`:
-    /// ```
-    /// # struct Foo;
-    /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
-    ///
-    /// struct Bar([u8; baz::<Self>()]);
-    /// const fn baz<T>() -> usize { 10 }
-    /// ```
-    /// We do however allow `Self` in repeat expression even if it is generic to not break code
-    /// which already works on stable while causing the `const_evaluatable_unchecked` future compat
-    /// lint:
-    /// ```
-    /// fn foo<T>() {
-    ///     let _bar = [1_u8; std::mem::size_of::<*mut T>()];
-    /// }
-    /// ```
-    // FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
-    SelfTy {
-        /// The trait this `Self` is a generic arg for.
-        trait_: Option<DefId>,
+    SelfTyAlias {
         /// The item introducing the `Self` type alias. Can be used in the `type_of` query
-        /// to get the underlying type. Additionally whether the `Self` type is disallowed
-        /// from mentioning generics (i.e. when used in an anonymous constant).
-        alias_to: Option<(DefId, bool)>,
-    },
+        /// to get the underlying type.
+        alias_to: DefId,
 
-    /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
-    ///
-    /// **Belongs to the type namespace.**
-    ToolMod,
+        /// Whether the `Self` type is disallowed from mentioning generics (i.e. when used in an
+        /// anonymous constant).
+        ///
+        /// HACK(min_const_generics): self types also have an optional requirement to **not**
+        /// mention any generic parameters to allow the following with `min_const_generics`:
+        /// ```
+        /// # struct Foo;
+        /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
+        ///
+        /// struct Bar([u8; baz::<Self>()]);
+        /// const fn baz<T>() -> usize { 10 }
+        /// ```
+        /// We do however allow `Self` in repeat expression even if it is generic to not break code
+        /// which already works on stable while causing the `const_evaluatable_unchecked` future
+        /// compat lint:
+        /// ```
+        /// fn foo<T>() {
+        ///     let _bar = [1_u8; std::mem::size_of::<*mut T>()];
+        /// }
+        /// ```
+        // FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
+        forbid_generic: bool,
+
+        /// Is this within an `impl Foo for bar`?
+        is_trait_impl: bool,
+    },
 
     // Value namespace
     /// The `Self` constructor, along with the [`DefId`]
@@ -389,7 +390,7 @@ pub enum Res<Id = hir::HirId> {
     ///
     /// **Belongs to the value namespace.**
     ///
-    /// *See also [`Res::SelfTy`].*
+    /// *See also [`Res::SelfTyParam`] and [`Res::SelfTyAlias`].*
     SelfCtor(DefId),
 
     /// A local variable or function parameter.
@@ -397,6 +398,11 @@ pub enum Res<Id = hir::HirId> {
     /// **Belongs to the value namespace.**
     Local(Id),
 
+    /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
+    ///
+    /// **Belongs to the type namespace.**
+    ToolMod,
+
     // Macro namespace
     /// An attribute that is *not* implemented via macro.
     /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,
@@ -606,7 +612,8 @@ impl<Id> Res<Id> {
 
             Res::Local(..)
             | Res::PrimTy(..)
-            | Res::SelfTy { .. }
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..)
             | Res::ToolMod
             | Res::NonMacroAttr(..)
@@ -629,7 +636,7 @@ impl<Id> Res<Id> {
             Res::SelfCtor(..) => "self constructor",
             Res::PrimTy(..) => "builtin type",
             Res::Local(..) => "local variable",
-            Res::SelfTy { .. } => "self type",
+            Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
             Res::ToolMod => "tool module",
             Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
             Res::Err => "unresolved item",
@@ -652,7 +659,10 @@ impl<Id> Res<Id> {
             Res::SelfCtor(id) => Res::SelfCtor(id),
             Res::PrimTy(id) => Res::PrimTy(id),
             Res::Local(id) => Res::Local(map(id)),
-            Res::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+            Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
+            Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
+                Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
+            }
             Res::ToolMod => Res::ToolMod,
             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
             Res::Err => Res::Err,
@@ -665,7 +675,10 @@ impl<Id> Res<Id> {
             Res::SelfCtor(id) => Res::SelfCtor(id),
             Res::PrimTy(id) => Res::PrimTy(id),
             Res::Local(id) => Res::Local(map(id)?),
-            Res::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+            Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
+            Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
+                Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
+            }
             Res::ToolMod => Res::ToolMod,
             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
             Res::Err => Res::Err,
@@ -692,7 +705,9 @@ impl<Id> Res<Id> {
     pub fn ns(&self) -> Option<Namespace> {
         match self {
             Res::Def(kind, ..) => kind.ns(),
-            Res::PrimTy(..) | Res::SelfTy { .. } | Res::ToolMod => Some(Namespace::TypeNS),
+            Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
+                Some(Namespace::TypeNS)
+            }
             Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
             Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
             Res::Err => None,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index cde8ec73701..922ce738dbb 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2404,8 +2404,9 @@ impl<'hir> Ty<'hir> {
             return None;
         };
         match path.res {
-            Res::Def(DefKind::TyParam, def_id)
-            | Res::SelfTy { trait_: Some(def_id), alias_to: None } => Some((def_id, segment.ident)),
+            Res::Def(DefKind::TyParam, def_id) | Res::SelfTyParam { trait_: def_id } => {
+                Some((def_id, segment.ident))
+            }
             _ => None,
         }
     }
@@ -3533,9 +3534,10 @@ mod size_asserts {
     static_assert_size!(Param<'_>, 32);
     static_assert_size!(Pat<'_>, 72);
     static_assert_size!(PatKind<'_>, 48);
-    static_assert_size!(Path<'_>, 48);
-    static_assert_size!(PathSegment<'_>, 56);
+    static_assert_size!(Path<'_>, 40);
+    static_assert_size!(PathSegment<'_>, 48);
     static_assert_size!(QPath<'_>, 24);
+    static_assert_size!(Res, 12);
     static_assert_size!(Stmt<'_>, 32);
     static_assert_size!(StmtKind<'_>, 16);
     static_assert_size!(TraitItem<'_>, 88);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 5752b6a356d..b66e59d8ac6 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -448,8 +448,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let infer_lifetimes =
             (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
 
-        if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
-            Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
+        if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
+            Self::prohibit_assoc_ty_binding(tcx, b.span);
         }
 
         let explicit_late_bound =
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index cf65bc19a5c..6e373e41b4c 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -276,9 +276,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             item_segment.infer_args,
             None,
         );
-        let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
-
-        if let Some(b) = assoc_bindings.first() {
+        if let Some(b) = item_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
 
@@ -605,8 +603,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             None,
         );
 
-        let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
-        if let Some(b) = assoc_bindings.first() {
+        if let Some(b) = item_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
 
@@ -794,8 +791,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             trait_segment,
             is_impl,
         );
-        let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args());
-        if let Some(b) = assoc_bindings.first() {
+        if let Some(b) = trait_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
         ty::TraitRef::new(trait_def_id, substs)
@@ -1902,7 +1898,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // Find the type of the associated item, and the trait where the associated
         // item is declared.
         let bound = match (&qself_ty.kind(), qself_res) {
-            (_, Res::SelfTy { trait_: Some(_), alias_to: Some((impl_def_id, _)) }) => {
+            (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
                 // `Self` in an impl of a trait -- we have a concrete self type and a
                 // trait reference.
                 let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
@@ -1921,8 +1917,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             (
                 &ty::Param(_),
-                Res::SelfTy { trait_: Some(param_did), alias_to: None }
-                | Res::Def(DefKind::TyParam, param_did),
+                Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
             ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
             _ => {
                 let reported = if variant_resolution.is_some() {
@@ -2213,8 +2208,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
-            if let [binding, ..] = segment.args().bindings {
-                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+            if let Some(b) = segment.args().bindings.first() {
+                Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
                 return true;
             }
         }
@@ -2422,7 +2417,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let index = generics.param_def_id_to_index[&def_id.to_def_id()];
                 tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
             }
-            Res::SelfTy { trait_: Some(_), alias_to: None } => {
+            Res::SelfTyParam { .. } => {
                 // `Self` in trait or type alias.
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments.iter(), |err| {
@@ -2437,7 +2432,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 });
                 tcx.types.self_param
             }
-            Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
+            Res::SelfTyAlias { alias_to: def_id, forbid_generic, .. } => {
                 // `Self` in impl (we know the concrete type).
                 assert_eq!(opt_self_ty, None);
                 // Try to evaluate any array length constants.
diff --git a/compiler/rustc_hir_analysis/src/check/callee.rs b/compiler/rustc_hir_analysis/src/check/callee.rs
index c82a31e65cf..080771844a4 100644
--- a/compiler/rustc_hir_analysis/src/check/callee.rs
+++ b/compiler/rustc_hir_analysis/src/check/callee.rs
@@ -394,140 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ty::FnPtr(sig) => (sig, None),
             _ => {
-                let mut unit_variant = None;
-                if let hir::ExprKind::Path(qpath) = &callee_expr.kind
-                    && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
-                        = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
-                    // Only suggest removing parens if there are no arguments
-                    && arg_exprs.is_empty()
-                {
-                    let descr = match kind {
-                        def::CtorOf::Struct => "struct",
-                        def::CtorOf::Variant => "enum variant",
-                    };
-                    let removal_span =
-                        callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
-                    unit_variant =
-                        Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
-                }
-
-                let callee_ty = self.resolve_vars_if_possible(callee_ty);
-                let mut err = type_error_struct!(
-                    self.tcx.sess,
-                    callee_expr.span,
-                    callee_ty,
-                    E0618,
-                    "expected function, found {}",
-                    match &unit_variant {
-                        Some((_, kind, path)) => format!("{kind} `{path}`"),
-                        None => format!("`{callee_ty}`"),
-                    }
-                );
-
-                self.identify_bad_closure_def_and_call(
-                    &mut err,
-                    call_expr.hir_id,
-                    &callee_expr.kind,
-                    callee_expr.span,
-                );
-
-                if let Some((removal_span, kind, path)) = &unit_variant {
-                    err.span_suggestion_verbose(
-                        *removal_span,
-                        &format!(
-                            "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
-                        ),
-                        "",
-                        Applicability::MachineApplicable,
-                    );
-                }
-
-                let mut inner_callee_path = None;
-                let def = match callee_expr.kind {
-                    hir::ExprKind::Path(ref qpath) => {
-                        self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
-                    }
-                    hir::ExprKind::Call(ref inner_callee, _) => {
-                        // If the call spans more than one line and the callee kind is
-                        // itself another `ExprCall`, that's a clue that we might just be
-                        // missing a semicolon (Issue #51055)
-                        let call_is_multiline =
-                            self.tcx.sess.source_map().is_multiline(call_expr.span);
-                        if call_is_multiline {
-                            err.span_suggestion(
-                                callee_expr.span.shrink_to_hi(),
-                                "consider using a semicolon here",
-                                ";",
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                        if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
-                            inner_callee_path = Some(inner_qpath);
-                            self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
-                        } else {
-                            Res::Err
-                        }
-                    }
-                    _ => Res::Err,
-                };
-
-                if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
-                    if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
-                        && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
-                    {
-                        let descr = match maybe_def {
-                            DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
-                            DefIdOrName::Name(name) => name,
-                        };
-                        err.span_label(
-                            callee_expr.span,
-                            format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
-                        );
-                        if let DefIdOrName::DefId(def_id) = maybe_def
-                            && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
-                        {
-                            err.span_label(def_span, "the callable type is defined here");
-                        }
-                    } else {
-                        err.span_label(call_expr.span, "call expression requires function");
-                    }
-                }
-
-                if let Some(span) = self.tcx.hir().res_span(def) {
-                    let callee_ty = callee_ty.to_string();
-                    let label = match (unit_variant, inner_callee_path) {
-                        (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
-                        (_, Some(hir::QPath::Resolved(_, path))) => self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(path.span)
-                            .ok()
-                            .map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
-                        _ => {
-                            match def {
-                                // Emit a different diagnostic for local variables, as they are not
-                                // type definitions themselves, but rather variables *of* that type.
-                                Res::Local(hir_id) => Some(format!(
-                                    "`{}` has type `{}`",
-                                    self.tcx.hir().name(hir_id),
-                                    callee_ty
-                                )),
-                                Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
-                                    Some(format!(
-                                        "`{}` defined here",
-                                        self.tcx.def_path_str(def_id),
-                                    ))
-                                }
-                                _ => Some(format!("`{callee_ty}` defined here")),
-                            }
-                        }
-                    };
-                    if let Some(label) = label {
-                        err.span_label(span, label);
-                    }
-                }
-                err.emit();
+                self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
 
                 // This is the "default" function signature, used in case of error.
                 // In that case, we check each argument against "error" in order to
@@ -574,6 +441,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fn_sig.output()
     }
 
+    fn report_invalid_callee(
+        &self,
+        call_expr: &'tcx hir::Expr<'tcx>,
+        callee_expr: &'tcx hir::Expr<'tcx>,
+        callee_ty: Ty<'tcx>,
+        arg_exprs: &'tcx [hir::Expr<'tcx>],
+    ) {
+        let mut unit_variant = None;
+        if let hir::ExprKind::Path(qpath) = &callee_expr.kind
+            && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
+                = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
+            // Only suggest removing parens if there are no arguments
+            && arg_exprs.is_empty()
+        {
+            let descr = match kind {
+                def::CtorOf::Struct => "struct",
+                def::CtorOf::Variant => "enum variant",
+            };
+            let removal_span =
+                callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
+            unit_variant =
+                Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
+        }
+
+        let callee_ty = self.resolve_vars_if_possible(callee_ty);
+        let mut err = type_error_struct!(
+            self.tcx.sess,
+            callee_expr.span,
+            callee_ty,
+            E0618,
+            "expected function, found {}",
+            match &unit_variant {
+                Some((_, kind, path)) => format!("{kind} `{path}`"),
+                None => format!("`{callee_ty}`"),
+            }
+        );
+
+        self.identify_bad_closure_def_and_call(
+            &mut err,
+            call_expr.hir_id,
+            &callee_expr.kind,
+            callee_expr.span,
+        );
+
+        if let Some((removal_span, kind, path)) = &unit_variant {
+            err.span_suggestion_verbose(
+                *removal_span,
+                &format!(
+                    "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
+                ),
+                "",
+                Applicability::MachineApplicable,
+            );
+        }
+
+        let mut inner_callee_path = None;
+        let def = match callee_expr.kind {
+            hir::ExprKind::Path(ref qpath) => {
+                self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
+            }
+            hir::ExprKind::Call(ref inner_callee, _) => {
+                // If the call spans more than one line and the callee kind is
+                // itself another `ExprCall`, that's a clue that we might just be
+                // missing a semicolon (Issue #51055)
+                let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span);
+                if call_is_multiline {
+                    err.span_suggestion(
+                        callee_expr.span.shrink_to_hi(),
+                        "consider using a semicolon here",
+                        ";",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
+                    inner_callee_path = Some(inner_qpath);
+                    self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
+                } else {
+                    Res::Err
+                }
+            }
+            _ => Res::Err,
+        };
+
+        if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
+            if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
+                && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
+            {
+                let descr = match maybe_def {
+                    DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
+                    DefIdOrName::Name(name) => name,
+                };
+                err.span_label(
+                    callee_expr.span,
+                    format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
+                );
+                if let DefIdOrName::DefId(def_id) = maybe_def
+                    && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
+                {
+                    err.span_label(def_span, "the callable type is defined here");
+                }
+            } else {
+                err.span_label(call_expr.span, "call expression requires function");
+            }
+        }
+
+        if let Some(span) = self.tcx.hir().res_span(def) {
+            let callee_ty = callee_ty.to_string();
+            let label = match (unit_variant, inner_callee_path) {
+                (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
+                (_, Some(hir::QPath::Resolved(_, path))) => self
+                    .tcx
+                    .sess
+                    .source_map()
+                    .span_to_snippet(path.span)
+                    .ok()
+                    .map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
+                _ => {
+                    match def {
+                        // Emit a different diagnostic for local variables, as they are not
+                        // type definitions themselves, but rather variables *of* that type.
+                        Res::Local(hir_id) => Some(format!(
+                            "`{}` has type `{}`",
+                            self.tcx.hir().name(hir_id),
+                            callee_ty
+                        )),
+                        Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
+                            Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),))
+                        }
+                        _ => Some(format!("`{callee_ty}` defined here")),
+                    }
+                }
+            };
+            if let Some(label) = label {
+                err.span_label(span, label);
+            }
+        }
+        err.emit();
+    }
+
     fn confirm_deferred_closure_call(
         &self,
         call_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 60a4904373e..824144aeac0 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -613,9 +613,12 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
         fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
             match arg.kind {
                 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
-                    [PathSegment { res: Res::SelfTy { trait_: _, alias_to: impl_ref }, .. }] => {
-                        let impl_ty_name =
-                            impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id));
+                    [PathSegment { res: Res::SelfTyParam { .. }, .. }] => {
+                        let impl_ty_name = None;
+                        self.selftys.push((path.span, impl_ty_name));
+                    }
+                    [PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => {
+                        let impl_ty_name = Some(self.tcx.def_path_str(*def_id));
                         self.selftys.push((path.span, impl_ty_name));
                     }
                     _ => {}
diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
index 64e7fa1a42b..55902aafb35 100644
--- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
@@ -1199,7 +1199,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => bug!("unexpected type: {:?}", ty),
             },
             Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
-            | Res::SelfTy { .. } => match ty.kind() {
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. } => match ty.kind() {
                 ty::Adt(adt, substs) if !adt.is_enum() => {
                     Some((adt.non_enum_variant(), adt.did(), substs))
                 }
diff --git a/compiler/rustc_hir_analysis/src/mem_categorization.rs b/compiler/rustc_hir_analysis/src/mem_categorization.rs
index 39610e3ae38..46b49647836 100644
--- a/compiler/rustc_hir_analysis/src/mem_categorization.rs
+++ b/compiler/rustc_hir_analysis/src/mem_categorization.rs
@@ -560,7 +560,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
             | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
             | Res::SelfCtor(..)
-            | Res::SelfTy { .. } => {
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. } => {
                 // Structs and Unions have only have one variant.
                 Ok(VariantIdx::new(0))
             }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index baa97d72a4b..03116d59bf4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                                     }
                                     // There cannot be inference variables in the self type,
                                     // so there's nothing for us to do here.
-                                    Res::SelfTy { .. } => {}
+                                    Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
                                     _ => warn!(
                                         "unexpected path: def={:?} substs={:?} path={:?}",
                                         def, substs, path,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index a6a39d062d5..778c4fc01c8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -156,7 +156,8 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
                 [segment]
                     if matches!(
                         segment.res,
-                        Res::SelfTy { trait_: _, alias_to: _ }
+                        Res::SelfTyParam { .. }
+                            | Res::SelfTyAlias { .. }
                             | Res::Def(hir::def::DefKind::TyParam, _)
                     ) =>
                 {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6c725a01b53..91d180e1eb7 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -246,6 +246,10 @@ impl<'tcx> Queries<'tcx> {
                 // Don't do code generation if there were any errors
                 self.session().compile_status()?;
 
+                // If we have any delayed bugs, for example because we created TyKind::Error earlier,
+                // it's likely that codegen will only cause more ICEs, obscuring the original problem
+                self.session().diagnostic().flush_delayed();
+
                 // Hook for UI tests.
                 Self::check_for_rustc_errors_attr(tcx);
 
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index ed28620fc36..8f5e38fdbcc 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -246,7 +246,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
             }
         }
         // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
-        Res::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
+        Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
             if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
                 if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
                 {
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 7e5a20a3bc1..349399b5964 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -58,7 +58,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
                 let path_segment = path.segments.last().unwrap();
                 return Some(format!("{}{}", name, gen_args(cx, path_segment)));
             }
-            Res::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
+            Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
                 if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
                     if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
                         return Some(cx.tcx.def_path_str_with_substs(adt.did(), substs));
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index dede1b2122a..466da175810 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -223,6 +223,15 @@ provide! { tcx, def_id, other, cdata,
     fn_arg_names => { table }
     generator_kind => { table }
     trait_def => { table }
+    collect_trait_impl_trait_tys => {
+        Ok(cdata
+            .root
+            .tables
+            .trait_impl_trait_tys
+            .get(cdata, def_id.index)
+            .map(|lazy| lazy.decode((cdata, tcx)))
+            .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id)))
+     }
 
     visibility => { cdata.get_visibility(def_id.index) }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7cf00ca41fe..1a7a3c65c3b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1059,6 +1059,34 @@ fn should_encode_const(def_kind: DefKind) -> bool {
     }
 }
 
+fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+    if tcx.def_kind(def_id) != DefKind::AssocFn {
+        return false;
+    }
+
+    let Some(item) = tcx.opt_associated_item(def_id) else { return false; };
+    if item.container != ty::AssocItemContainer::ImplContainer {
+        return false;
+    }
+
+    let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+
+    // FIXME(RPITIT): This does a somewhat manual walk through the signature
+    // of the trait fn to look for any RPITITs, but that's kinda doing a lot
+    // of work. We can probably remove this when we refactor RPITITs to be
+    // associated types.
+    tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
+        if let ty::GenericArgKind::Type(ty) = arg.unpack()
+            && let ty::Projection(data) = ty.kind()
+            && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+        {
+            true
+        } else {
+            false
+        }
+    })
+}
+
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_attrs(&mut self, def_id: LocalDefId) {
         let mut attrs = self
@@ -1128,6 +1156,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if let DefKind::Trait | DefKind::TraitAlias = def_kind {
                 record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
             }
+            if should_encode_trait_impl_trait_tys(tcx, def_id)
+                && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id)
+            {
+                record!(self.tables.trait_impl_trait_tys[def_id] <- table);
+            }
         }
         let inherent_impls = tcx.crate_inherent_impls(());
         for (def_id, implementations) in inherent_impls.inherent_impls.iter() {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 748b3afec37..6d7345570af 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -1,6 +1,7 @@
 use crate::creader::CrateMetadataRef;
 use decoder::Metadata;
 use def_path_hash_map::DefPathHashMapRef;
+use rustc_data_structures::fx::FxHashMap;
 use table::TableBuilder;
 
 use rustc_ast as ast;
@@ -399,6 +400,8 @@ define_tables! {
     macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>,
     proc_macro: Table<DefIndex, MacroKind>,
     module_reexports: Table<DefIndex, LazyArray<ModChild>>,
+
+    trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
 }
 
 #[derive(TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index b5f7b26ea7a..8523b5ca0ec 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -14,7 +14,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 
 #[inline]
@@ -1131,7 +1131,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
                 .filter_map(|(def_id, info)| {
                     let _ = info.as_owner()?;
                     let def_path_hash = definitions.def_path_hash(def_id);
-                    let span = resolutions.source_span[def_id];
+                    let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
                     debug_assert_eq!(span.parent(), None);
                     Some((def_path_hash, span))
                 })
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 2e596b27527..74ce0b38ed2 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -438,7 +438,8 @@ impl<'tcx> AdtDef<'tcx> {
             | Res::Def(DefKind::Union, _)
             | Res::Def(DefKind::TyAlias, _)
             | Res::Def(DefKind::AssocTy, _)
-            | Res::SelfTy { .. }
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..) => self.non_enum_variant(),
             _ => bug!("unexpected res {:?} in variant_of_res", res),
         }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cc820d9eb2d..3c523659df7 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -7,6 +7,7 @@ use crate::ty::{
 };
 use rustc_ast as ast;
 use rustc_attr as attr;
+use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -206,6 +207,12 @@ pub enum LayoutError<'tcx> {
     NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
 }
 
+impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
+    fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
+        handler.struct_fatal(self.to_string())
+    }
+}
+
 impl<'tcx> fmt::Display for LayoutError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
@@ -3065,6 +3072,12 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
     }
 }
 
+impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> {
+    fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> {
+        handler.struct_fatal(self.to_string())
+    }
+}
+
 // FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
 // just for error handling.
 #[derive(Debug)]
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 9c8dc30e2db..0257ca7b29c 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_index::vec::{Idx, IndexVec};
 
@@ -29,6 +30,10 @@ impl<I: Idx + 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for IndexVe
     type Value<'tcx> = IndexVec<I, T::Value<'tcx>>;
 }
 
+impl<I: 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for FxHashMap<I, T> {
+    type Value<'tcx> = FxHashMap<I, T::Value<'tcx>>;
+}
+
 impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> {
     type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>;
 }
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a939be32fff..36eb2ab5157 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -492,6 +492,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
 }
 
 impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
+    #[inline]
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.iter().try_for_each(|t| t.visit_with(visitor))
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index cd186421bb1..895af80bd7f 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -433,7 +433,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 | DefKind::AssocTy,
                 _,
             )
-            | Res::SelfTy { .. }
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
             _ => {
                 let pattern_error = match res {
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 86c386b94c8..0dc05475ce9 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -32,11 +32,6 @@ pub struct AttrWrapper {
     start_pos: usize,
 }
 
-// This struct is passed around very frequently,
-// so make sure it doesn't accidentally get larger
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(AttrWrapper, 16);
-
 impl AttrWrapper {
     pub(super) fn new(attrs: AttrVec, start_pos: usize) -> AttrWrapper {
         AttrWrapper { attrs, start_pos }
@@ -96,9 +91,6 @@ struct LazyAttrTokenStreamImpl {
     replace_ranges: Box<[ReplaceRange]>,
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(LazyAttrTokenStreamImpl, 144);
-
 impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
     fn to_attr_token_stream(&self) -> AttrTokenStream {
         // The token produced by the final call to `{,inlined_}next` was not
@@ -461,3 +453,13 @@ fn make_token_stream(
     }
     AttrTokenStream::new(final_buf.inner)
 }
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    use rustc_data_structures::static_assert_size;
+    // These are in alphabetical order, which is easy to maintain.
+    static_assert_size!(AttrWrapper, 16);
+    static_assert_size!(LazyAttrTokenStreamImpl, 144);
+}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c8a8e00b1fa..25425fbb2c6 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1753,18 +1753,24 @@ impl<'a> Parser<'a> {
                 };
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
-                if let Err(mut db) =
-                    self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
-                {
-                    db.delay_as_bug();
+                match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
+                    Ok(_) => {
+                        let mut err = self.struct_span_err(
+                            lo.to(self.prev_token.span),
+                            &format!("functions are not allowed in {adt_ty} definitions"),
+                        );
+                        err.help(
+                            "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
+                        );
+                        err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+                        err
+                    }
+                    Err(err) => {
+                        err.cancel();
+                        self.restore_snapshot(snapshot);
+                        self.expected_ident_found()
+                    }
                 }
-                let mut err = self.struct_span_err(
-                    lo.to(self.prev_token.span),
-                    &format!("functions are not allowed in {adt_ty} definitions"),
-                );
-                err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
-                err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                err
             } else if self.eat_keyword(kw::Struct) {
                 match self.parse_item_struct() {
                     Ok((ident, _)) => {
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index a9e502016aa..df22d79f82e 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -224,7 +224,7 @@ impl<'a> Iterator for Parser<'a> {
                 '{' => {
                     let curr_last_brace = self.last_opening_brace;
                     let byte_pos = self.to_span_index(pos);
-                    let lbrace_end = InnerOffset(byte_pos.0 + 1);
+                    let lbrace_end = self.to_span_index(pos + 1);
                     self.last_opening_brace = Some(byte_pos.to(lbrace_end));
                     self.cur.next();
                     if self.consume('{') {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 4062862ad74..116aaf48349 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -198,8 +198,8 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
             of_trait: Some(trait_ref),
             ..
         }) = item.kind
+            && let Some(def_id) = trait_ref.trait_def_id()
         {
-            let def_id = trait_ref.trait_def_id().unwrap();
             let source_map = tcx.sess.source_map();
             if !tcx.has_attr(def_id, sym::const_trait) {
                 tcx.sess
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 5e28a900e55..08f704da62c 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -102,14 +102,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                 }
             }
             Res::Def(_, def_id) => self.check_def_id(def_id),
-            Res::SelfTy { trait_: t, alias_to: i } => {
-                if let Some(t) = t {
-                    self.check_def_id(t);
-                }
-                if let Some((i, _)) = i {
-                    self.check_def_id(i);
-                }
-            }
+            Res::SelfTyParam { trait_: t } => self.check_def_id(t),
+            Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
             Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
         }
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 7ab07a671c4..841e3ebb2a1 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1422,7 +1422,9 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
 impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path: &hir::Path<'_>) -> bool {
         let did = match path.res {
-            Res::PrimTy(..) | Res::SelfTy { .. } | Res::Err => return false,
+            Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
+                return false;
+            }
             res => res.def_id(),
         };
 
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index 8140c243453..148eabb38e2 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -12,7 +12,7 @@ use rustc_session::cstore::CrateStore;
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData, DUMMY_SP};
 
 /// This is the context state available during incr. comp. hashing. It contains
 /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
@@ -185,7 +185,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
 
     #[inline]
     fn def_span(&self, def_id: LocalDefId) -> Span {
-        self.source_span[def_id]
+        *self.source_span.get(def_id).unwrap_or(&DUMMY_SP)
     }
 
     #[inline]
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 81b67b758f7..29aab416ae9 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1010,7 +1010,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 _,
             )
             | Res::Local(..)
-            | Res::SelfTy { .. }
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..)
             | Res::Err => bug!("unexpected resolution: {:?}", res),
         }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 7e83f2a7221..38a3c9dd71a 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -285,21 +285,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.kind {
             TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
-            TyKind::ImplTrait(node_id, _) => {
-                let parent_def = match self.impl_trait_context {
-                    ImplTraitContext::Universal(item_def) => self.resolver.create_def(
-                        item_def,
-                        node_id,
-                        DefPathData::ImplTrait,
-                        self.expansion.to_expn_id(),
-                        ty.span,
-                    ),
-                    ImplTraitContext::Existential => {
-                        self.create_def(node_id, DefPathData::ImplTrait, ty.span)
-                    }
-                };
-                self.with_parent(parent_def, |this| visit::walk_ty(this, ty))
-            }
             _ => visit::walk_ty(self, ty),
         }
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index ab71fa0bc1d..b6778804a99 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -511,24 +511,18 @@ impl<'a> Resolver<'a> {
 
                 let sm = self.session.source_map();
                 let def_id = match outer_res {
-                    Res::SelfTy { trait_: maybe_trait_defid, alias_to: maybe_impl_defid } => {
-                        if let Some(impl_span) =
-                            maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id))
-                        {
+                    Res::SelfTyParam { .. } => {
+                        err.span_label(span, "can't use `Self` here");
+                        return err;
+                    }
+                    Res::SelfTyAlias { alias_to: def_id, .. } => {
+                        if let Some(impl_span) = self.opt_span(def_id) {
                             err.span_label(
                                 reduce_impl_span_to_impl_keyword(sm, impl_span),
                                 "`Self` type implicitly declared here, by this `impl`",
                             );
                         }
-                        match (maybe_trait_defid, maybe_impl_defid) {
-                            (Some(_), None) => {
-                                err.span_label(span, "can't use `Self` here");
-                            }
-                            (_, Some(_)) => {
-                                err.span_label(span, "use a type here instead");
-                            }
-                            (None, None) => bug!("`impl` without trait nor type?"),
-                        }
+                        err.span_label(span, "use a type here instead");
                         return err;
                     }
                     Res::Def(DefKind::TyParam, def_id) => {
@@ -545,8 +539,9 @@ impl<'a> Resolver<'a> {
                     }
                     _ => {
                         bug!(
-                            "GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
-                            DefKind::TyParam or DefKind::ConstParam"
+                            "GenericParamsFromOuterFunction should only be used with \
+                            Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
+                            DefKind::ConstParam"
                         );
                     }
                 };
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 2287aa1eb25..e0542d5479f 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1162,7 +1162,7 @@ impl<'a> Resolver<'a> {
                     return Res::Err;
                 }
             }
-            Res::Def(DefKind::TyParam, _) | Res::SelfTy { .. } => {
+            Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
                 for rib in ribs {
                     let has_generic_params: HasGenericParams = match rib.kind {
                         NormalRibKind
@@ -1182,11 +1182,21 @@ impl<'a> Resolver<'a> {
                             if !(trivial == ConstantHasGenerics::Yes
                                 || features.generic_const_exprs)
                             {
-                                // HACK(min_const_generics): If we encounter `Self` in an anonymous constant
-                                // we can't easily tell if it's generic at this stage, so we instead remember
-                                // this and then enforce the self type to be concrete later on.
-                                if let Res::SelfTy { trait_, alias_to: Some((def, _)) } = res {
-                                    res = Res::SelfTy { trait_, alias_to: Some((def, true)) }
+                                // HACK(min_const_generics): If we encounter `Self` in an anonymous
+                                // constant we can't easily tell if it's generic at this stage, so
+                                // we instead remember this and then enforce the self type to be
+                                // concrete later on.
+                                if let Res::SelfTyAlias {
+                                    alias_to: def,
+                                    forbid_generic: _,
+                                    is_trait_impl,
+                                } = res
+                                {
+                                    res = Res::SelfTyAlias {
+                                        alias_to: def,
+                                        forbid_generic: true,
+                                        is_trait_impl,
+                                    }
                                 } else {
                                     if let Some(span) = finalize {
                                         self.report_error(
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 558db003867..72029488cb1 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -19,7 +19,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::DiagnosticId;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_lifetime::Set1;
 use rustc_middle::ty::DefIdTree;
@@ -414,7 +414,8 @@ impl<'a> PathSource<'a> {
                         | DefKind::ForeignTy,
                     _,
                 ) | Res::PrimTy(..)
-                    | Res::SelfTy { .. }
+                    | Res::SelfTyParam { .. }
+                    | Res::SelfTyAlias { .. }
             ),
             PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
             PathSource::Trait(AliasPossibility::Maybe) => {
@@ -448,7 +449,8 @@ impl<'a> PathSource<'a> {
                         | DefKind::TyAlias
                         | DefKind::AssocTy,
                     _,
-                ) | Res::SelfTy { .. }
+                ) | Res::SelfTyParam { .. }
+                    | Res::SelfTyAlias { .. }
             ),
             PathSource::TraitItem(ns) => match res {
                 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
@@ -1929,7 +1931,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     TyKind::ImplicitSelf => true,
                     TyKind::Path(None, _) => {
                         let path_res = self.r.partial_res_map[&ty.id].base_res();
-                        if let Res::SelfTy { .. } = path_res {
+                        if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path_res {
                             return true;
                         }
                         Some(path_res) == self.impl_self
@@ -2050,7 +2052,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 |this| {
                     let item_def_id = this.r.local_def_id(item.id).to_def_id();
                     this.with_self_rib(
-                        Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
+                        Res::SelfTyAlias {
+                            alias_to: item_def_id,
+                            forbid_generic: false,
+                            is_trait_impl: false,
+                        },
                         |this| {
                             visit::walk_item(this, item);
                         },
@@ -2164,14 +2170,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     },
                     |this| {
                         let local_def_id = this.r.local_def_id(item.id).to_def_id();
-                        this.with_self_rib(
-                            Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
-                            |this| {
-                                this.visit_generics(generics);
-                                walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
-                                this.resolve_trait_items(items);
-                            },
-                        );
+                        this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+                            this.visit_generics(generics);
+                            walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
+                            this.resolve_trait_items(items);
+                        });
                     },
                 );
             }
@@ -2188,13 +2191,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     },
                     |this| {
                         let local_def_id = this.r.local_def_id(item.id).to_def_id();
-                        this.with_self_rib(
-                            Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
-                            |this| {
-                                this.visit_generics(generics);
-                                walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
-                            },
-                        );
+                        this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+                            this.visit_generics(generics);
+                            walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
+                        });
                     },
                 );
             }
@@ -2576,7 +2576,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             },
             |this| {
                 // Dummy self type for better errors if `Self` is used in the trait path.
-                this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
+                this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
                     this.with_lifetime_rib(
                         LifetimeRibKind::AnonymousCreateParameter {
                             binder: item_id,
@@ -2600,9 +2600,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                     }
 
                                     let item_def_id = item_def_id.to_def_id();
-                                    let res = Res::SelfTy {
-                                        trait_: trait_id,
-                                        alias_to: Some((item_def_id, false)),
+                                    let res = Res::SelfTyAlias {
+                                        alias_to: item_def_id,
+                                        forbid_generic: false,
+                                        is_trait_impl: trait_id.is_some()
                                     };
                                     this.with_self_rib(res, |this| {
                                         if let Some(trait_ref) = opt_trait_reference.as_ref() {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 824cebd7e0a..2d339a4d070 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1449,7 +1449,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     Applicability::HasPlaceholders,
                 );
             }
-            (Res::SelfTy { .. }, _) if ns == ValueNS => {
+            (Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
                 err.span_label(span, fallback_label);
                 err.note("can't use `Self` as a constructor, you must use the implemented struct");
             }
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index adbc119387d..ecb09f0c4b7 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -913,7 +913,8 @@ impl<'tcx> DumpVisitor<'tcx> {
                     | HirDefKind::AssocTy,
                     _,
                 )
-                | Res::SelfTy { .. } => {
+                | Res::SelfTyParam { .. }
+                | Res::SelfTyAlias { .. } => {
                     self.dump_path_segment_ref(
                         id,
                         &hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index ad7aca3cb94..aa000b7067b 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -740,7 +740,8 @@ impl<'tcx> SaveContext<'tcx> {
                 _,
             )
             | Res::PrimTy(..)
-            | Res::SelfTy { .. }
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
             | Res::ToolMod
             | Res::NonMacroAttr(..)
             | Res::SelfCtor(..)
@@ -805,7 +806,7 @@ impl<'tcx> SaveContext<'tcx> {
 
     fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
         match self.get_path_res(ref_id) {
-            Res::PrimTy(_) | Res::SelfTy { .. } | Res::Err => None,
+            Res::PrimTy(_) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => None,
             def => def.opt_def_id(),
         }
     }
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index bae1828cd18..62e9f6520fb 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -579,7 +579,7 @@ impl<'hir> Sig for hir::Path<'hir> {
         let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
 
         let (name, start, end) = match res {
-            Res::PrimTy(..) | Res::SelfTy { .. } | Res::Err => {
+            Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
                 return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
             }
             Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 37b8371a8fe..bbeabdb55a7 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -218,7 +218,9 @@ impl<D: Decoder> Decodable<D> for DefIndex {
 /// index and a def index.
 ///
 /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)]
+#[derive(Clone, PartialEq, Eq, Copy)]
+// Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order.
+#[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))]
 // On below-64 bit systems we can simply use the derived `Hash` impl
 #[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
 #[repr(C)]
@@ -260,6 +262,22 @@ impl Hash for DefId {
     }
 }
 
+// Implement the same comparison as derived with the other field order.
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl Ord for DefId {
+    #[inline]
+    fn cmp(&self, other: &DefId) -> std::cmp::Ordering {
+        Ord::cmp(&(self.index, self.krate), &(other.index, other.krate))
+    }
+}
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl PartialOrd for DefId {
+    #[inline]
+    fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
+        Some(Ord::cmp(self, other))
+    }
+}
+
 impl DefId {
     /// Makes a local `DefId` from the given `DefIndex`.
     #[inline]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 09727b433b3..8cb7d147d02 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1704,6 +1704,7 @@ impl Ident {
     /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
     /// non-transparent macros.
     /// Technically, this operation strips all transparent marks from ident's syntactic context.
+    #[inline]
     pub fn normalize_to_macro_rules(self) -> Ident {
         Ident::new(self.name, self.span.normalize_to_macro_rules())
     }
@@ -1719,6 +1720,7 @@ impl Ident {
 }
 
 impl PartialEq for Ident {
+    #[inline]
     fn eq(&self, rhs: &Self) -> bool {
         self.name == rhs.name && self.span.eq_ctxt(rhs.span)
     }
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index 9bb9c931f5c..cda88de0ea4 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -6,9 +6,9 @@ pub fn target() -> Target {
     base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
     base.cpu = "z10".into();
-    // FIXME: The data_layout string below and the ABI implementation in
-    // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
-    // Pass the -vector feature string to LLVM to respect this assumption.
+    // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
+    // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
+    // also strip v128 from the data_layout below to match the older LLVM's expectation.
     base.features = "-vector".into();
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
@@ -17,7 +17,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "s390x-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
index f877279781d..91e63aee5e4 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -6,9 +6,9 @@ pub fn target() -> Target {
     base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
     base.cpu = "z10".into();
-    // FIXME: The data_layout string below and the ABI implementation in
-    // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
-    // Pass the -vector feature string to LLVM to respect this assumption.
+    // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
+    // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
+    // also strip v128 from the data_layout below to match the older LLVM's expectation.
     base.features = "-vector".into();
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
@@ -18,7 +18,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
         options: base,
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index b0cabc6275f..5fdadd0b4b4 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2263,13 +2263,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                                     trait_impls.non_blanket_impls().len()
                                 )
                             };
-
+                            let mut suggestions = vec![(
+                                trait_path_segment.ident.span.shrink_to_lo(),
+                                format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())
+                            )];
+                            if let Some(generic_arg) = trait_path_segment.args {
+                                let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
+                                // get rid of :: between Trait and <type>
+                                // must be '::' between them, otherwise the parser won't accept the code
+                                suggestions.push((between_span, "".to_string(),));
+                                suggestions.push((generic_arg.span_ext.shrink_to_hi(), format!(">")));
+                            } else {
+                                suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), format!(">")));
+                            }
                             err.multipart_suggestion(
                                 message,
-                                vec![
-                                    (trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
-                                    (trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
-                                ],
+                                suggestions,
                                 Applicability::MaybeIncorrect
                             );
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fff26547be0..698fc81c587 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1425,7 +1425,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let mut spans_and_needs_box = vec![];
 
         match liberated_sig.output().kind() {
-            ty::Dynamic(predicates, _, _) => {
+            ty::Dynamic(predicates, _, ty::Dyn) => {
                 let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
                 let param_env = ty::ParamEnv::empty();
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0ed59223337..bac34985237 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -35,7 +35,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
@@ -914,38 +913,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let unbound_input_types =
             stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
 
-        if stack.obligation.polarity() != ty::ImplPolarity::Negative {
-            // This check was an imperfect workaround for a bug in the old
-            // intercrate mode; it should be removed when that goes away.
-            if unbound_input_types && self.intercrate {
-                debug!("evaluate_stack --> unbound argument, intercrate -->  ambiguous",);
-                // Heuristics: show the diagnostics when there are no candidates in crate.
-                if self.intercrate_ambiguity_causes.is_some() {
-                    debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                    if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                        if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
-                            let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                            let self_ty = trait_ref.self_ty();
-                            let cause = with_no_trimmed_paths!({
-                                IntercrateAmbiguityCause::DownstreamCrate {
-                                    trait_desc: trait_ref.print_only_trait_path().to_string(),
-                                    self_desc: if self_ty.has_concrete_skeleton() {
-                                        Some(self_ty.to_string())
-                                    } else {
-                                        None
-                                    },
-                                }
-                            });
-
-                            debug!(?cause, "evaluate_stack: pushing cause");
-                            self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
-                        }
-                    }
-                }
-                return Ok(EvaluatedToAmbig);
-            }
-        }
-
         if unbound_input_types
             && stack.iter().skip(1).any(|prev| {
                 stack.obligation.param_env == prev.obligation.param_env
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
index d2e80e8e7e5..9e9c02093be 100644
--- a/library/core/src/const_closure.rs
+++ b/library/core/src/const_closure.rs
@@ -16,15 +16,18 @@ use crate::marker::Destruct;
 /// assert!(7 == cl(2));
 /// assert!(8 == cl(1));
 /// ```
-pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> {
-    data: &'a mut CapturedData,
-    func: Function,
+pub(crate) struct ConstFnMutClosure<CapturedData, Function> {
+    /// The Data captured by the Closure.
+    /// Must be either a (mutable) reference or a tuple of (mutable) references.
+    pub data: CapturedData,
+    /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn
+    pub func: Function,
 }
-
-impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> {
+impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> {
     /// Function for creating a new closure.
     ///
     /// `data` is the a mutable borrow of data that is captured from the environment.
+    /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually.
     ///
     /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
     ///   and return the return value of the closure.
@@ -39,25 +42,36 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Fun
     }
 }
 
-impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
-    FnOnce<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
-where
-    Function:
-        ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct,
-{
-    type Output = ClosureReturnValue;
+macro_rules! impl_fn_mut_tuple {
+    ($($var:ident)*) => {
+        #[allow(unused_parens)]
+        impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
+            FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+        where
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
+        {
+            type Output = ClosureReturnValue;
 
-    extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
-        self.call_mut(args)
-    }
-}
-
-impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
-    FnMut<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
-where
-    Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
-{
-    extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
-        (self.func)(self.data, args)
-    }
+            extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
+            self.call_mut(args)
+            }
+        }
+        #[allow(unused_parens)]
+        impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
+            FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+        where
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
+        {
+            extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
+                #[allow(non_snake_case)]
+                let ($($var),*) = &mut self.data;
+                (self.func)(($($var),*), args)
+            }
+        }
+    };
 }
+impl_fn_mut_tuple!(A);
+impl_fn_mut_tuple!(A B);
+impl_fn_mut_tuple!(A B C);
+impl_fn_mut_tuple!(A B C D);
+impl_fn_mut_tuple!(A B C D E);
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 33df9e6c5cd..84a69046807 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -379,7 +379,7 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
 pub(crate) struct NeverShortCircuit<T>(pub T);
 
 impl<T> NeverShortCircuit<T> {
-    /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
+    /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
     #[inline]
     pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
         f: &mut F,
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 2b85d6e2225..1d0c51c3c83 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1043,7 +1043,7 @@ impl fmt::Debug for Duration {
         /// to the formatter's `width`, if specified.
         fn fmt_decimal(
             f: &mut fmt::Formatter<'_>,
-            mut integer_part: u64,
+            integer_part: u64,
             mut fractional_part: u32,
             mut divisor: u32,
             prefix: &str,
@@ -1075,7 +1075,7 @@ impl fmt::Debug for Duration {
             // normal floating point numbers. However, we only need to do work
             // when rounding up. This happens if the first digit of the
             // remaining ones is >= 5.
-            if fractional_part > 0 && fractional_part >= divisor * 5 {
+            let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
                 // Round up the number contained in the buffer. We go through
                 // the buffer backwards and keep track of the carry.
                 let mut rev_pos = pos;
@@ -1099,9 +1099,18 @@ impl fmt::Debug for Duration {
                 // the whole buffer to '0's and need to increment the integer
                 // part.
                 if carry {
-                    integer_part += 1;
+                    // If `integer_part == u64::MAX` and precision < 9, any
+                    // carry of the overflow during rounding of the
+                    // `fractional_part` into the `integer_part` will cause the
+                    // `integer_part` itself to overflow. Avoid this by using an
+                    // `Option<u64>`, with `None` representing `u64::MAX + 1`.
+                    integer_part.checked_add(1)
+                } else {
+                    Some(integer_part)
                 }
-            }
+            } else {
+                Some(integer_part)
+            };
 
             // Determine the end of the buffer: if precision is set, we just
             // use as many digits from the buffer (capped to 9). If it isn't
@@ -1111,7 +1120,12 @@ impl fmt::Debug for Duration {
             // This closure emits the formatted duration without emitting any
             // padding (padding is calculated below).
             let emit_without_padding = |f: &mut fmt::Formatter<'_>| {
-                write!(f, "{}{}", prefix, integer_part)?;
+                if let Some(integer_part) = integer_part {
+                    write!(f, "{}{}", prefix, integer_part)?;
+                } else {
+                    // u64::MAX + 1 == 18446744073709551616
+                    write!(f, "{}18446744073709551616", prefix)?;
+                }
 
                 // Write the decimal point and the fractional part (if any).
                 if end > 0 {
@@ -1141,12 +1155,17 @@ impl fmt::Debug for Duration {
                     // 2. The postfix: can be "µs" so we have to count UTF8 characters.
                     let mut actual_w = prefix.len() + postfix.chars().count();
                     // 3. The integer part:
-                    if let Some(log) = integer_part.checked_ilog10() {
-                        // integer_part is > 0, so has length log10(x)+1
-                        actual_w += 1 + log as usize;
+                    if let Some(integer_part) = integer_part {
+                        if let Some(log) = integer_part.checked_ilog10() {
+                            // integer_part is > 0, so has length log10(x)+1
+                            actual_w += 1 + log as usize;
+                        } else {
+                            // integer_part is 0, so has length 1.
+                            actual_w += 1;
+                        }
                     } else {
-                        // integer_part is 0, so has length 1.
-                        actual_w += 1;
+                        // integer_part is u64::MAX + 1, so has length 20
+                        actual_w += 20;
                     }
                     // 4. The fractional part (if any):
                     if end > 0 {
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index fe2d2f2412d..697bf33a8b0 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -197,9 +197,31 @@ fn correct_sum() {
 #[test]
 fn debug_formatting_extreme_values() {
     assert_eq!(
-        format!("{:?}", Duration::new(18_446_744_073_709_551_615, 123_456_789)),
+        format!("{:?}", Duration::new(u64::MAX, 123_456_789)),
         "18446744073709551615.123456789s"
     );
+    assert_eq!(format!("{:.0?}", Duration::MAX), "18446744073709551616s");
+    assert_eq!(format!("{:.0?}", Duration::new(u64::MAX, 500_000_000)), "18446744073709551616s");
+    assert_eq!(format!("{:.0?}", Duration::new(u64::MAX, 499_999_999)), "18446744073709551615s");
+    assert_eq!(
+        format!("{:.3?}", Duration::new(u64::MAX, 999_500_000)),
+        "18446744073709551616.000s"
+    );
+    assert_eq!(
+        format!("{:.3?}", Duration::new(u64::MAX, 999_499_999)),
+        "18446744073709551615.999s"
+    );
+    assert_eq!(
+        format!("{:.8?}", Duration::new(u64::MAX, 999_999_995)),
+        "18446744073709551616.00000000s"
+    );
+    assert_eq!(
+        format!("{:.8?}", Duration::new(u64::MAX, 999_999_994)),
+        "18446744073709551615.99999999s"
+    );
+    assert_eq!(format!("{:21.0?}", Duration::MAX), "18446744073709551616s");
+    assert_eq!(format!("{:22.0?}", Duration::MAX), "18446744073709551616s ");
+    assert_eq!(format!("{:24.0?}", Duration::MAX), "18446744073709551616s   ");
 }
 
 #[test]
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c83490316b6..cb18e14fa36 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -654,6 +654,8 @@ impl Build {
             job::setup(self);
         }
 
+        // Download rustfmt early so that it can be used in rust-analyzer configs.
+        let _ = &builder::Builder::new(&self).initial_rustfmt();
         self.maybe_update_submodules();
 
         if let Subcommand::Format { check, paths } = &self.config.cmd {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index a68b55e26b6..5a4fa05e261 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2197,8 +2197,11 @@ impl Path {
     /// Checks if this is a `T::Name` path for an associated type.
     pub(crate) fn is_assoc_ty(&self) -> bool {
         match self.res {
-            Res::SelfTy { .. } if self.segments.len() != 1 => true,
-            Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
+            Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
+                if self.segments.len() != 1 =>
+            {
+                true
+            }
             Res::Def(DefKind::AssocTy, _) => true,
             _ => false,
         }
@@ -2531,11 +2534,11 @@ mod size_asserts {
     // These are in alphabetical order, which is easy to maintain.
     static_assert_size!(Crate, 72); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
-    static_assert_size!(GenericArg, 56);
+    static_assert_size!(GenericArg, 48);
     static_assert_size!(GenericArgs, 32);
     static_assert_size!(GenericParamDef, 56);
     static_assert_size!(Item, 56);
-    static_assert_size!(ItemKind, 96);
+    static_assert_size!(ItemKind, 88);
     static_assert_size!(PathSegment, 40);
-    static_assert_size!(Type, 56);
+    static_assert_size!(Type, 48);
 }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index edcd81061f8..6b844710514 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -454,7 +454,9 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
 
     match path.res {
         Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
-        Res::SelfTy { .. } if path.segments.len() == 1 => Generic(kw::SelfUpper),
+        Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
+            Generic(kw::SelfUpper)
+        }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
         _ => {
             let _ = register_res(cx, path.res);
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 3e324bbb069..7bd0dbf9325 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -716,9 +716,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         document(&mut content, cx, m, Some(t), HeadingOffset::H5);
         let toggled = !content.is_empty();
         if toggled {
-            write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
+            write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
         }
-        write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
+        write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
         render_rightside(w, cx, m, t, RenderMode::Normal);
         write!(w, "<h4 class=\"code-header\">");
         render_assoc_item(
@@ -730,7 +730,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             RenderMode::Normal,
         );
         w.write_str("</h4>");
-        w.write_str("</div>");
+        w.write_str("</section>");
         if toggled {
             write!(w, "</summary>");
             w.push_buffer(content);
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 7bc8fbb1ea7..84e6df59f57 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -138,6 +138,13 @@ h1, h2, h3, h4 {
 .docblock h3, .docblock h4, h5, h6 {
 	margin: 15px 0 5px 0;
 }
+.docblock > h2:first-child,
+.docblock > h3:first-child,
+.docblock > h4:first-child,
+.docblock > h5:first-child,
+.docblock > h6:first-child {
+	margin-top: 0;
+}
 h1.fqn {
 	margin: 0;
 	padding: 0;
@@ -187,7 +194,6 @@ h4.code-header {
 .impl-items .associatedtype,
 .methods .associatedtype {
 	flex-basis: 100%;
-	font-weight: 600;
 	position: relative;
 }
 
@@ -442,7 +448,6 @@ img {
 }
 
 .source .sidebar > *:not(#sidebar-toggle) {
-	opacity: 0;
 	visibility: hidden;
 }
 
@@ -451,7 +456,6 @@ img {
 }
 
 .source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) {
-	opacity: 1;
 	visibility: visible;
 }
 
@@ -541,6 +545,14 @@ h2.location a {
 	margin: 0;
 }
 
+.sidebar a, .sidebar .current {
+	color: var(--sidebar-link-color);
+}
+.sidebar .current,
+.sidebar a:hover {
+	background-color: var(--sidebar-current-link-background-color);
+}
+
 .sidebar-elems .block {
 	margin-bottom: 2em;
 }
@@ -1241,13 +1253,11 @@ h3.variant {
 	font-weight: 600;
 	font-size: 1.125rem;
 	margin-bottom: 10px;
-	border-bottom: none;
 }
 
 .sub-variant h4 {
 	font-size: 1rem;
 	font-weight: 400;
-	border-bottom: none;
 	margin-top: 0;
 	margin-bottom: 0;
 }
@@ -1316,11 +1326,6 @@ h3.variant {
 	font-size: 1.25rem;
 }
 
-/* Example code has the "Run" button that needs to be positioned relative to the pre */
-pre.rust.rust-example-rendered {
-	position: relative;
-}
-
 pre.rust {
 	tab-size: 4;
 	-moz-tab-size: 4;
@@ -2008,7 +2013,11 @@ in storage.js plus the media query with (min-width: 701px)
 
 .method-toggle summary,
 .implementors-toggle summary,
-.impl {
+.impl,
+#implementors-list > .docblock,
+.impl-items > section,
+.methods > section
+{
 	margin-bottom: 0.75em;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 44238ca573d..1c317aa7cfe 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -35,6 +35,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--keyword-link-color: #39afd7;
 	--mod-link-color: #39afd7;
 	--link-color: #39afd7;
+	--sidebar-link-color: #53b1db;
+	--sidebar-current-link-background-color: transparent;
 }
 
 .slider {
@@ -85,7 +87,6 @@ pre, .rustdoc.source .example-wrap {
 
 .sidebar .current,
 .sidebar a:hover {
-	background-color: transparent;
 	color: #ffb44c;
 }
 
@@ -119,9 +120,6 @@ pre, .rustdoc.source .example-wrap {
 
 .content .item-info::before { color: #ccc; }
 
-.sidebar a { color: #53b1db; }
-.sidebar a.current.type { color: #53b1db; }
-
 pre.rust .comment { color: #788797; }
 pre.rust .doccomment { color: #a1ac88; }
 
@@ -284,21 +282,6 @@ a.result-static:focus {}
 a.result-primitive:focus {}
 a.result-keyword:focus {}
 
-.sidebar a.current.enum {}
-.sidebar a.current.struct {}
-.sidebar a.current.foreigntype {}
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro {}
-.sidebar a.current.union {}
-.sidebar a.current.constant
-.sidebar a.current.static {}
-.sidebar a.current.primitive {}
-.sidebar a.current.trait {}
-.sidebar a.current.traitalias {}
-.sidebar a.current.fn {}
-.sidebar a.current.keyword {}
-
 kbd {
 	color: #c5c5c5;
 	background-color: #314559;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 858d836c03d..a8204eebe54 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -30,6 +30,8 @@
 	--keyword-link-color: #d2991d;
 	--mod-link-color:  #d2991d;
 	--link-color: #d2991d;
+	--sidebar-link-color: #fdbf35;
+	--sidebar-current-link-background-color: #444;
 }
 
 .slider {
@@ -49,11 +51,6 @@ input:focus + .slider {
 		drop-shadow(0 -1px 0 #fff)
 }
 
-.sidebar .current,
-.sidebar a:hover {
-	background: #444;
-}
-
 .src-line-numbers span { color: #3B91E2; }
 .src-line-numbers .line-highlighted {
 	background-color: #0a042f !important;
@@ -91,23 +88,6 @@ a.result-keyword:focus { background-color: #884719; }
 
 .content .item-info::before { color: #ccc; }
 
-.sidebar a { color: #fdbf35; }
-.sidebar a.current.enum { color: #12ece2; }
-.sidebar a.current.struct { color: #12ece2; }
-.sidebar a.current.type { color: #12ece2; }
-.sidebar a.current.foreigntype { color: #12ece2; }
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro { color: #0be900; }
-.sidebar a.current.union { color: #12ece2; }
-.sidebar a.current.constant
-.sidebar a.current.static { color: #fdbf35; }
-.sidebar a.current.primitive { color: #12ece2; }
-.sidebar a.current.trait { color: #cca7ff; }
-.sidebar a.current.traitalias { color: #cca7ff; }
-.sidebar a.current.fn { color: #32d479; }
-.sidebar a.current.keyword { color: #fdbf35; }
-
 pre.rust .comment { color: #8d8d8b; }
 pre.rust .doccomment { color: #8ca375; }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 6fbea6f6c7a..8fb60b6f887 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -30,6 +30,8 @@
 	--keyword-link-color: #3873ad;
 	--mod-link-color: #3873ad;
 	--link-color: #3873ad;
+	--sidebar-link-color: #356da4;
+	--sidebar-current-link-background-color: #fff;
 }
 
 .slider {
@@ -48,11 +50,6 @@ input:focus + .slider {
 	 */
 }
 
-.sidebar .current,
-.sidebar a:hover {
-	background-color: #fff;
-}
-
 .src-line-numbers span { color: #c67e2d; }
 .src-line-numbers .line-highlighted {
 	background-color: #FDFFD3 !important;
@@ -90,23 +87,6 @@ a.result-keyword:focus { background-color: #afc6e4; }
 
 .content .item-info::before { color: #ccc; }
 
-.sidebar a { color: #356da4; }
-.sidebar a.current.enum { color: #a63283; }
-.sidebar a.current.struct { color: #a63283; }
-.sidebar a.current.type { color: #a63283; }
-.sidebar a.current.foreigntype { color: #356da4; }
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro { color: #067901; }
-.sidebar a.current.union { color: #a63283; }
-.sidebar a.current.constant
-.sidebar a.current.static { color: #356da4; }
-.sidebar a.current.primitive { color: #a63283; }
-.sidebar a.current.trait { color: #6849c3; }
-.sidebar a.current.traitalias { color: #4b349e; }
-.sidebar a.current.fn { color: #a67736; }
-.sidebar a.current.keyword { color: #356da4; }
-
 body.source .example-wrap pre.rust a {
 	background: #eee;
 }
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 670e5f673acb736acbfce65e0ffe2c8cd115b93
+Subproject 9567f08afc94332d59025744f3a8198104949d3
diff --git a/src/test/rustdoc-gui/anchor-navigable.goml b/src/test/rustdoc-gui/anchor-navigable.goml
index 424c312233b..14653f0bfc7 100644
--- a/src/test/rustdoc-gui/anchor-navigable.goml
+++ b/src/test/rustdoc-gui/anchor-navigable.goml
@@ -7,5 +7,5 @@
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 // We check that ".item-info" is bigger than its content.
 move-cursor-to: ".impl"
-assert-property: (".impl > a.anchor", {"offsetWidth": "9"})
+assert-property: (".impl > a.anchor", {"offsetWidth": "8"})
 assert-css: (".impl > a.anchor", {"left": "-8px"})
diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml
index 13e8ec9fb16..d5c934551a5 100644
--- a/src/test/rustdoc-gui/font-weight.goml
+++ b/src/test/rustdoc-gui/font-weight.goml
@@ -13,7 +13,7 @@ goto: file://|DOC_PATH|/test_docs/type.SomeType.html
 assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
 
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert-css: (".impl-items .method", {"font-weight": "600"}, ALL)
+assert-css: (".impl-items .method > .code-header", {"font-weight": "600"}, ALL)
 
 goto: file://|DOC_PATH|/lib2/trait.Trait.html
 
@@ -41,4 +41,4 @@ assert-count: (".methods .associatedtype", 1)
 assert-css: (".methods .associatedtype", {"font-weight": "600"})
 assert-count: (".methods .constant", 1)
 assert-css: (".methods .constant", {"font-weight": "600"})
-assert-css: (".methods .method", {"font-weight": "600"})
+assert-css: (".methods .method > .code-header", {"font-weight": "600"})
diff --git a/src/test/rustdoc-gui/no-docblock.goml b/src/test/rustdoc-gui/no-docblock.goml
new file mode 100644
index 00000000000..2408be4534b
--- /dev/null
+++ b/src/test/rustdoc-gui/no-docblock.goml
@@ -0,0 +1,8 @@
+// This test checks that there are margins applied to methods with no docblocks.
+goto: file://|DOC_PATH|/test_docs/trait.TraitWithNoDocblocks.html
+// Check that the two methods are more than 24px apart.
+compare-elements-position-near-false: ("//*[@id='tymethod.first_fn']", "//*[@id='tymethod.second_fn']", {"y": 24})
+
+goto: file://|DOC_PATH|/test_docs/struct.TypeWithNoDocblocks.html
+// Check that the two methods are more than 24px apart.
+compare-elements-position-near-false: ("//*[@id='method.first_fn']", "//*[@id='method.second_fn']", {"y": 24})
diff --git a/src/test/rustdoc-gui/sidebar-links-color.goml b/src/test/rustdoc-gui/sidebar-links-color.goml
new file mode 100644
index 00000000000..d2a1688080c
--- /dev/null
+++ b/src/test/rustdoc-gui/sidebar-links-color.goml
@@ -0,0 +1,233 @@
+// This test checks links colors in sidebar before and after hover.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {
+    "rustdoc-theme": "ayu",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+// Struct
+assert-css: (
+    ".sidebar a.struct:not(.current)",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.struct:not(.current)"
+assert-css: (
+    ".sidebar a.struct:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Enum
+assert-css: (
+    ".sidebar a.enum",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.enum"
+assert-css: (
+    ".sidebar a.enum:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Union
+assert-css: (
+    ".sidebar a.union",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.union"
+assert-css: (
+    ".sidebar a.union:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Trait
+assert-css: (
+    ".sidebar a.trait",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.trait"
+assert-css: (
+    ".sidebar a.trait:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Function
+assert-css: (
+    ".sidebar a.fn",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.fn"
+assert-css: (
+    ".sidebar a.fn:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Type definition
+assert-css: (
+    ".sidebar a.type",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.type"
+assert-css: (
+    ".sidebar a.type:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Keyword
+assert-css: (
+    ".sidebar a.keyword",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.keyword"
+assert-css: (
+    ".sidebar a.keyword:hover",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark"}
+reload:
+
+// Struct
+assert-css: (
+    ".sidebar a.struct:not(.current)",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.struct:not(.current)"
+assert-css: (
+    ".sidebar a.struct:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Enum
+assert-css: (
+    ".sidebar a.enum",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.enum"
+assert-css: (
+    ".sidebar a.enum:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Union
+assert-css: (
+    ".sidebar a.union",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.union"
+assert-css: (
+    ".sidebar a.union:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Trait
+assert-css: (
+    ".sidebar a.trait",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.trait"
+assert-css: (
+    ".sidebar a.trait:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Function
+assert-css: (
+    ".sidebar a.fn",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.fn"
+assert-css: (
+    ".sidebar a.fn:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Type definition
+assert-css: (
+    ".sidebar a.type",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.type"
+assert-css: (
+    ".sidebar a.type:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Keyword
+assert-css: (
+    ".sidebar a.keyword",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.keyword"
+assert-css: (
+    ".sidebar a.keyword:hover",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+
+// Light theme
+local-storage: {"rustdoc-theme": "light"}
+reload:
+
+// Struct
+assert-css: (
+    ".sidebar a.struct:not(.current)",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.struct:not(.current)"
+assert-css: (
+    ".sidebar a.struct:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Enum
+assert-css: (
+    ".sidebar a.enum",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.enum"
+assert-css: (
+    ".sidebar a.enum:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Union
+assert-css: (
+    ".sidebar a.union",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.union"
+assert-css: (
+    ".sidebar a.union:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Trait
+assert-css: (
+    ".sidebar a.trait",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.trait"
+assert-css: (
+    ".sidebar a.trait:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Function
+assert-css: (
+    ".sidebar a.fn",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.fn"
+assert-css: (
+    ".sidebar a.fn:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Type definition
+assert-css: (
+    ".sidebar a.type",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.type"
+assert-css: (
+    ".sidebar a.type:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Keyword
+assert-css: (
+    ".sidebar a.keyword",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar a.keyword"
+assert-css: (
+    ".sidebar a.keyword:hover",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
diff --git a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
index 9af7c636a0c..6cb492cfc64 100644
--- a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
@@ -6,7 +6,7 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
 // Scroll down.
 scroll-to: "//h2[@id='blanket-implementations']"
-assert-window-property: {"pageYOffset": "639"}
+assert-window-property: {"pageYOffset": "651"}
 
 // Open the sidebar menu.
 click: ".sidebar-menu-toggle"
@@ -21,11 +21,11 @@ assert-window-property: {"pageYOffset": "0"}
 // Close the sidebar menu. Make sure the scroll position gets restored.
 click: ".sidebar-menu-toggle"
 wait-for-css: (".sidebar", {"left": "-1000px"})
-assert-window-property: {"pageYOffset": "639"}
+assert-window-property: {"pageYOffset": "651"}
 
 // Now test that scrollability returns when the browser window is just resized.
 click: ".sidebar-menu-toggle"
 wait-for-css: (".sidebar", {"left": "0px"})
 assert-window-property: {"pageYOffset": "0"}
 size: (900, 600)
-assert-window-property: {"pageYOffset": "639"}
+assert-window-property: {"pageYOffset": "651"}
diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml
index 4321efcdb17..24d1820ff27 100644
--- a/src/test/rustdoc-gui/sidebar-source-code-display.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml
@@ -3,20 +3,17 @@ javascript: false
 goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
 // Since the javascript is disabled, there shouldn't be a toggle.
 assert-false: "#sidebar-toggle"
-// For some reason, we need to wait a bit here because it seems like the transition on opacity
-// is being applied whereas it can't be reproduced in a browser...
-wait-for-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0})
+wait-for-css: (".sidebar > *", {"visibility": "hidden"})
 
 // Let's retry with javascript enabled.
 javascript: true
 reload:
 wait-for: "#sidebar-toggle"
-assert-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
-assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden", "opacity": 0})
+assert-css: ("#sidebar-toggle", {"visibility": "visible"})
+assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden"})
 // Let's expand the sidebar now.
 click: "#sidebar-toggle"
-// Because of the transition CSS, we check by using `wait-for-css` instead of `assert-css`.
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
 
 // We now check that opening the sidebar and clicking a link will leave it open.
 // The behavior here on desktop is different than the behavior on mobile,
@@ -36,7 +33,7 @@ show-text: true
 local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
 // Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
 assert-css: (
     "#source-sidebar details[open] > .files a.selected",
     {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"},
@@ -91,7 +88,7 @@ assert-css: (
 local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
 reload:
 // Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
 assert-css: (
     "#source-sidebar details[open] > .files > a.selected",
     {"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"},
@@ -146,7 +143,7 @@ assert-css: (
 local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"}
 reload:
 // Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
 assert-css: (
     "#source-sidebar details[open] > .files a.selected",
     {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"},
@@ -201,7 +198,7 @@ assert-css: (
 size: (500, 700)
 reload:
 // Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
 
 // We now check it takes the full size of the display.
 assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"})
diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml
index 9797f196c55..ebb413b8c41 100644
--- a/src/test/rustdoc-gui/src-font-size.goml
+++ b/src/test/rustdoc-gui/src-font-size.goml
@@ -4,8 +4,8 @@
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 show-text: true
 // Check the impl headers.
-assert-css: (".impl.has-srclink .srclink", {"font-size": "16px"}, ALL)
-assert-css: (".impl.has-srclink .code-header", {"font-size": "18px"}, ALL)
+assert-css: (".impl.has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
+assert-css: (".impl.has-srclink .code-header", {"font-size": "18px", "font-weight": 600}, ALL)
 // Check the impl items.
-assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL)
-assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL)
+assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
+assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px", "font-weight": 600}, ALL)
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 1c066206c1f..0281973c1ba 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -355,3 +355,15 @@ impl<R: std::io::Read> std::iter::Iterator for NotableStructWithLongName<R> {
 
     fn next(&mut self) -> Option<Self::Item> { () }
 }
+
+pub trait TraitWithNoDocblocks {
+    fn first_fn(&self);
+    fn second_fn(&self);
+}
+
+pub struct TypeWithNoDocblocks;
+
+impl TypeWithNoDocblocks {
+    pub fn first_fn(&self) {}
+    pub fn second_fn(&self) {}
+}
diff --git a/src/test/rustdoc/anchors.no_const_anchor.html b/src/test/rustdoc/anchors.no_const_anchor.html
index 4da1ffead2a..75e67330a3e 100644
--- a/src/test/rustdoc/anchors.no_const_anchor.html
+++ b/src/test/rustdoc/anchors.no_const_anchor.html
@@ -1 +1 @@
-<div id="associatedconstant.YOLO" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></div>
\ No newline at end of file
+<section id="associatedconstant.YOLO" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section>
\ No newline at end of file
diff --git a/src/test/rustdoc/anchors.no_trait_method_anchor.html b/src/test/rustdoc/anchors.no_trait_method_anchor.html
index 6b78c7c811a..d7bd525ff0f 100644
--- a/src/test/rustdoc/anchors.no_trait_method_anchor.html
+++ b/src/test/rustdoc/anchors.no_trait_method_anchor.html
@@ -1 +1 @@
-<div id="method.bar" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fnname">bar</a>()</h4></div>
\ No newline at end of file
+<section id="method.bar" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fnname">bar</a>()</h4></section>
\ No newline at end of file
diff --git a/src/test/rustdoc/anchors.no_tymethod_anchor.html b/src/test/rustdoc/anchors.no_tymethod_anchor.html
index c08f4427cf6..e668e5e4db1 100644
--- a/src/test/rustdoc/anchors.no_tymethod_anchor.html
+++ b/src/test/rustdoc/anchors.no_tymethod_anchor.html
@@ -1 +1 @@
-<div id="tymethod.foo" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fnname">foo</a>()</h4></div>
\ No newline at end of file
+<section id="tymethod.foo" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fnname">foo</a>()</h4></section>
\ No newline at end of file
diff --git a/src/test/rustdoc/anchors.no_type_anchor.html b/src/test/rustdoc/anchors.no_type_anchor.html
index ba8e65443ec..2c66d5aa315 100644
--- a/src/test/rustdoc/anchors.no_type_anchor.html
+++ b/src/test/rustdoc/anchors.no_type_anchor.html
@@ -1 +1 @@
-<div id="associatedtype.T" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></div>
\ No newline at end of file
+<section id="associatedtype.T" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section>
\ No newline at end of file
diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
index 8bd402291aa..602ee1b1b1f 100644
--- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs
+++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
@@ -18,10 +18,10 @@ pub struct S<T>(T);
 // @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone'
 #[const_trait]
 pub trait Tr<T> {
-    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]' '~const'
-    // @has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
-    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
-    // @has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+    // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
+    // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+    // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+    // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
     fn a<A: ~const Clone + ~const Destruct>()
     where
         Option<A>: ~const Clone + ~const Destruct,
diff --git a/src/test/rustdoc/toggle-trait-fn.rs b/src/test/rustdoc/toggle-trait-fn.rs
index 65e8daeb066..e41422ce7c5 100644
--- a/src/test/rustdoc/toggle-trait-fn.rs
+++ b/src/test/rustdoc/toggle-trait-fn.rs
@@ -4,12 +4,12 @@
 // summary. Trait methods with no documentation should not be wrapped.
 //
 // @has foo/trait.Foo.html
-// @has -  '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
-// @has -  '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @has -  '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
-// @has -  '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
+// @has -  '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+// @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @has -  '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
+// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
+// @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
 pub trait Foo {
     fn not_documented();
 
diff --git a/src/test/ui/borrowck/issue-102209.rs b/src/test/ui/borrowck/issue-102209.rs
new file mode 100644
index 00000000000..37628bff7df
--- /dev/null
+++ b/src/test/ui/borrowck/issue-102209.rs
@@ -0,0 +1,28 @@
+use std::marker::PhantomData;
+
+pub struct NfaBuilder<'brand> {
+    brand: PhantomData<&'brand mut &'brand mut ()>,
+}
+
+impl NfaBuilder<'_> {
+    pub fn with<R, F: FnOnce(NfaBuilder<'_>) -> R>(f: F) -> R {
+        Brand::with(|brand| {
+            f(Self { brand: brand.lt })
+            //~^ ERROR lifetime may not live long enough
+            //~| ERROR lifetime may not live long enough
+        })
+    }
+}
+
+#[derive(Clone, Copy)]
+pub struct Brand<'brand> {
+    lt: PhantomData<&'brand mut &'brand mut ()>,
+}
+
+impl Brand<'_> {
+    pub fn with<R, F: FnOnce(Brand<'_>) -> R>(f: F) -> R {
+        f(Self { lt: PhantomData })
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-102209.stderr b/src/test/ui/borrowck/issue-102209.stderr
new file mode 100644
index 00000000000..351de8217b2
--- /dev/null
+++ b/src/test/ui/borrowck/issue-102209.stderr
@@ -0,0 +1,22 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-102209.rs:10:29
+   |
+LL | impl NfaBuilder<'_> {
+   |                 -- lifetime `'2` appears in the `impl`'s self type
+LL |     pub fn with<R, F: FnOnce(NfaBuilder<'_>) -> R>(f: F) -> R {
+LL |         Brand::with(|brand| {
+   |                      ----- has type `Brand<'1>`
+LL |             f(Self { brand: brand.lt })
+   |                             ^^^^^^^^ this usage requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-102209.rs:10:29
+   |
+LL | impl NfaBuilder<'_> {
+   |                 -- lifetime `'1` appears in the `impl`'s self type
+...
+LL |             f(Self { brand: brand.lt })
+   |                             ^^^^^^^^ this usage requires that `'1` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.rs b/src/test/ui/fmt/format-args-capture-issue-102057.rs
new file mode 100644
index 00000000000..b8089d49bcb
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-issue-102057.rs
@@ -0,0 +1,19 @@
+fn main() {
+    format!("\x7Ba}");
+    //~^ ERROR cannot find value `a` in this scope
+    format!("\x7Ba\x7D");
+    //~^ ERROR cannot find value `a` in this scope
+
+    let a = 0;
+
+    format!("\x7Ba} {b}");
+    //~^ ERROR cannot find value `b` in this scope
+    format!("\x7Ba\x7D {b}");
+    //~^ ERROR cannot find value `b` in this scope
+    format!("\x7Ba} \x7Bb}");
+    //~^ ERROR cannot find value `b` in this scope
+    format!("\x7Ba\x7D \x7Bb}");
+    //~^ ERROR cannot find value `b` in this scope
+    format!("\x7Ba\x7D \x7Bb\x7D");
+    //~^ ERROR cannot find value `b` in this scope
+}
diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.stderr b/src/test/ui/fmt/format-args-capture-issue-102057.stderr
new file mode 100644
index 00000000000..f2d625e7f8d
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-issue-102057.stderr
@@ -0,0 +1,45 @@
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:2:18
+   |
+LL |     format!("\x7Ba}");
+   |                  ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:4:18
+   |
+LL |     format!("\x7Ba\x7D");
+   |                  ^ not found in this scope
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:9:22
+   |
+LL |     format!("\x7Ba} {b}");
+   |                      ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:11:25
+   |
+LL |     format!("\x7Ba\x7D {b}");
+   |                         ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:13:25
+   |
+LL |     format!("\x7Ba} \x7Bb}");
+   |                         ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:15:28
+   |
+LL |     format!("\x7Ba\x7D \x7Bb}");
+   |                            ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/format-args-capture-issue-102057.rs:17:28
+   |
+LL |     format!("\x7Ba\x7D \x7Bb\x7D");
+   |                            ^ help: a local variable with a similar name exists: `a`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr
index 3a83021dd99..2e020780480 100644
--- a/src/test/ui/generator/print/generator-print-verbose-1.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr
@@ -9,7 +9,7 @@ note: generator is not `Send` as this value is used across a yield
   --> $DIR/generator-print-verbose-1.rs:35:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+   |             ------------- has type `Opaque(DefId(0:44 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 LL |     };
@@ -35,17 +35,17 @@ note: required because it's used within this generator
    |
 LL |     || {
    |     ^^
-note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+note: required because it appears within the type `Opaque(DefId(0:45 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
   --> $DIR/generator-print-verbose-1.rs:41:30
    |
 LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+note: required because it appears within the type `Opaque(DefId(0:46 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
   --> $DIR/generator-print-verbose-1.rs:47:34
    |
 LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: required because it captures the following types: `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
+   = note: required because it captures the following types: `Opaque(DefId(0:46 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
 note: required because it's used within this generator
   --> $DIR/generator-print-verbose-1.rs:52:20
    |
diff --git a/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs
new file mode 100644
index 00000000000..74df300f85a
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs
@@ -0,0 +1,11 @@
+#![feature(return_position_impl_trait_in_trait)]
+
+pub trait Foo {
+    fn bar() -> impl Sized;
+}
+
+pub struct Foreign;
+
+impl Foo for Foreign {
+    fn bar() {}
+}
diff --git a/src/test/ui/impl-trait/in-trait/foreign.rs b/src/test/ui/impl-trait/in-trait/foreign.rs
new file mode 100644
index 00000000000..6341f5b4284
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/foreign.rs
@@ -0,0 +1,9 @@
+// check-pass
+// aux-build: rpitit.rs
+
+extern crate rpitit;
+
+fn main() {
+    // Witness an RPITIT from another crate
+    let () = <rpitit::Foreign as rpitit::Foo>::bar();
+}
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
index 330c6fafa2d..6a8a1ad1caa 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -1,14 +1,14 @@
-error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
   --> $DIR/impl-trait-captures.rs:11:5
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-   |                  -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
+   |                  -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
 LL |     x
    |     ^
    |
-help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
+help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
    |
-LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
+LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
    |                                      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.rs b/src/test/ui/parser/fn-field-parse-error-ice.rs
index 4ea55062fc4..188257ea53a 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.rs
+++ b/src/test/ui/parser/fn-field-parse-error-ice.rs
@@ -3,7 +3,7 @@
 struct Baz {
     inner : dyn fn ()
     //~^ ERROR expected `,`, or `}`, found keyword `fn`
-    //~| ERROR functions are not allowed in struct definitions
+    //~| ERROR expected identifier, found keyword `fn`
     //~| ERROR cannot find type `dyn` in this scope
 }
 
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.stderr b/src/test/ui/parser/fn-field-parse-error-ice.stderr
index e9583f55b8e..3bf68e8cc04 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.stderr
+++ b/src/test/ui/parser/fn-field-parse-error-ice.stderr
@@ -4,16 +4,18 @@ error: expected `,`, or `}`, found keyword `fn`
 LL |     inner : dyn fn ()
    |                ^ help: try adding a comma: `,`
 
-error: functions are not allowed in struct definitions
+error: expected identifier, found keyword `fn`
   --> $DIR/fn-field-parse-error-ice.rs:4:17
    |
 LL | struct Baz {
    |        --- while parsing this struct
 LL |     inner : dyn fn ()
-   |                 ^^
+   |                 ^^ expected identifier, found keyword
    |
-   = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
-   = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+help: escape `fn` to use it as an identifier
+   |
+LL |     inner : dyn r#fn ()
+   |                 ++
 
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/fn-field-parse-error-ice.rs:4:13
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
new file mode 100644
index 00000000000..fe4e9108130
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
@@ -0,0 +1,15 @@
+#![feature(allocator_api)]
+#![feature(const_trait_impl)]
+
+use core::convert::{From, TryFrom};
+//~^ ERROR
+//~| ERROR
+
+use std::pin::Pin;
+use std::alloc::Allocator;
+impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
+where
+    A: 'static,
+{}
+
+pub fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
new file mode 100644
index 00000000000..8bf00eaff1f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,19 @@
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs
index 5102574d4be..a24b3ada57e 100644
--- a/src/test/ui/stats/hir-stats.rs
+++ b/src/test/ui/stats/hir-stats.rs
@@ -1,7 +1,6 @@
 // check-pass
 // compile-flags: -Zhir-stats
 // only-x86_64
-// ignore-stage1
 
 // The aim here is to include at least one of every different type of top-level
 // AST/HIR node reported by `-Zhir-stats`.
diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 8fe84bf776f..350b140aada 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -118,61 +118,61 @@ ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
 hir-stats ----------------------------------------------------------------
-hir-stats ForeignItemRef            24 ( 0.2%)             1            24
-hir-stats Lifetime                  32 ( 0.3%)             1            32
-hir-stats Mod                       32 ( 0.3%)             1            32
+hir-stats ForeignItemRef            24 ( 0.3%)             1            24
+hir-stats Lifetime                  32 ( 0.4%)             1            32
+hir-stats Mod                       32 ( 0.4%)             1            32
 hir-stats ExprField                 40 ( 0.4%)             1            40
 hir-stats TraitItemRef              56 ( 0.6%)             2            28
 hir-stats Local                     64 ( 0.7%)             1            64
 hir-stats Param                     64 ( 0.7%)             2            32
-hir-stats InlineAsm                 72 ( 0.7%)             1            72
-hir-stats ImplItemRef               72 ( 0.7%)             2            36
-hir-stats Body                      96 ( 1.0%)             3            32
-hir-stats GenericArg                96 ( 1.0%)             4            24
-hir-stats - Type                      24 ( 0.2%)             1
-hir-stats - Lifetime                  72 ( 0.7%)             3
-hir-stats FieldDef                  96 ( 1.0%)             2            48
-hir-stats Arm                       96 ( 1.0%)             2            48
-hir-stats Stmt                      96 ( 1.0%)             3            32
-hir-stats - Local                     32 ( 0.3%)             1
-hir-stats - Semi                      32 ( 0.3%)             1
-hir-stats - Expr                      32 ( 0.3%)             1
-hir-stats FnDecl                   120 ( 1.2%)             3            40
-hir-stats Attribute                128 ( 1.3%)             4            32
-hir-stats GenericArgs              144 ( 1.5%)             3            48
-hir-stats Variant                  160 ( 1.6%)             2            80
-hir-stats GenericBound             192 ( 2.0%)             4            48
-hir-stats - Trait                    192 ( 2.0%)             4
-hir-stats WherePredicate           192 ( 2.0%)             3            64
-hir-stats - BoundPredicate           192 ( 2.0%)             3
-hir-stats Block                    288 ( 3.0%)             6            48
-hir-stats Pat                      360 ( 3.7%)             5            72
-hir-stats - Wild                      72 ( 0.7%)             1
-hir-stats - Struct                    72 ( 0.7%)             1
-hir-stats - Binding                  216 ( 2.2%)             3
-hir-stats GenericParam             400 ( 4.1%)             5            80
-hir-stats Generics                 560 ( 5.8%)            10            56
-hir-stats Ty                       720 ( 7.4%)            15            48
+hir-stats InlineAsm                 72 ( 0.8%)             1            72
+hir-stats ImplItemRef               72 ( 0.8%)             2            36
+hir-stats Body                      96 ( 1.1%)             3            32
+hir-stats GenericArg                96 ( 1.1%)             4            24
+hir-stats - Type                      24 ( 0.3%)             1
+hir-stats - Lifetime                  72 ( 0.8%)             3
+hir-stats FieldDef                  96 ( 1.1%)             2            48
+hir-stats Arm                       96 ( 1.1%)             2            48
+hir-stats Stmt                      96 ( 1.1%)             3            32
+hir-stats - Local                     32 ( 0.4%)             1
+hir-stats - Semi                      32 ( 0.4%)             1
+hir-stats - Expr                      32 ( 0.4%)             1
+hir-stats FnDecl                   120 ( 1.3%)             3            40
+hir-stats Attribute                128 ( 1.4%)             4            32
+hir-stats GenericArgs              144 ( 1.6%)             3            48
+hir-stats Variant                  160 ( 1.8%)             2            80
+hir-stats GenericBound             192 ( 2.1%)             4            48
+hir-stats - Trait                    192 ( 2.1%)             4
+hir-stats WherePredicate           192 ( 2.1%)             3            64
+hir-stats - BoundPredicate           192 ( 2.1%)             3
+hir-stats Block                    288 ( 3.2%)             6            48
+hir-stats Pat                      360 ( 3.9%)             5            72
+hir-stats - Wild                      72 ( 0.8%)             1
+hir-stats - Struct                    72 ( 0.8%)             1
+hir-stats - Binding                  216 ( 2.4%)             3
+hir-stats GenericParam             400 ( 4.4%)             5            80
+hir-stats Generics                 560 ( 6.1%)            10            56
+hir-stats Ty                       720 ( 7.9%)            15            48
 hir-stats - Ptr                       48 ( 0.5%)             1
 hir-stats - Rptr                      48 ( 0.5%)             1
-hir-stats - Path                     624 ( 6.4%)            13
-hir-stats Expr                     768 ( 7.9%)            12            64
+hir-stats - Path                     624 ( 6.8%)            13
+hir-stats Expr                     768 ( 8.4%)            12            64
 hir-stats - Path                      64 ( 0.7%)             1
 hir-stats - Struct                    64 ( 0.7%)             1
 hir-stats - Match                     64 ( 0.7%)             1
 hir-stats - InlineAsm                 64 ( 0.7%)             1
-hir-stats - Lit                      128 ( 1.3%)             2
-hir-stats - Block                    384 ( 4.0%)             6
-hir-stats Item                     960 ( 9.9%)            12            80
-hir-stats - Trait                     80 ( 0.8%)             1
-hir-stats - Enum                      80 ( 0.8%)             1
-hir-stats - ExternCrate               80 ( 0.8%)             1
-hir-stats - ForeignMod                80 ( 0.8%)             1
-hir-stats - Impl                      80 ( 0.8%)             1
-hir-stats - Fn                       160 ( 1.6%)             2
-hir-stats - Use                      400 ( 4.1%)             5
-hir-stats Path                   1_536 (15.8%)            32            48
-hir-stats PathSegment            2_240 (23.1%)            40            56
+hir-stats - Lit                      128 ( 1.4%)             2
+hir-stats - Block                    384 ( 4.2%)             6
+hir-stats Item                     960 (10.5%)            12            80
+hir-stats - Trait                     80 ( 0.9%)             1
+hir-stats - Enum                      80 ( 0.9%)             1
+hir-stats - ExternCrate               80 ( 0.9%)             1
+hir-stats - ForeignMod                80 ( 0.9%)             1
+hir-stats - Impl                      80 ( 0.9%)             1
+hir-stats - Fn                       160 ( 1.8%)             2
+hir-stats - Use                      400 ( 4.4%)             5
+hir-stats Path                   1_280 (14.0%)            32            40
+hir-stats PathSegment            1_920 (21.0%)            40            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  9_704
+hir-stats Total                  9_128
 hir-stats
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
new file mode 100644
index 00000000000..cd8a79ba687
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
@@ -0,0 +1,5 @@
+fn main() {}
+
+struct S {
+    fn: u8 //~ ERROR expected identifier, found keyword `fn`
+}
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
new file mode 100644
index 00000000000..0d12ba9c916
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
@@ -0,0 +1,15 @@
+error: expected identifier, found keyword `fn`
+  --> $DIR/incomplete-fn-in-struct-definition.rs:4:5
+   |
+LL | struct S {
+   |        - while parsing this struct
+LL |     fn: u8
+   |     ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL |     r#fn: u8
+   |     ++
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type/issue-101866.rs b/src/test/ui/type/issue-101866.rs
new file mode 100644
index 00000000000..d332c4adb00
--- /dev/null
+++ b/src/test/ui/type/issue-101866.rs
@@ -0,0 +1,15 @@
+trait TraitA<T> {
+    fn func();
+}
+
+struct StructA {}
+
+impl TraitA<i32> for StructA {
+    fn func() {}
+}
+
+fn main() {
+    TraitA::<i32>::func();
+    //~^ ERROR: cannot call associated function on trait without specifying the corresponding `impl` type [E0790]
+    //~| help: use the fully-qualified path to the only available implementation
+}
diff --git a/src/test/ui/type/issue-101866.stderr b/src/test/ui/type/issue-101866.stderr
new file mode 100644
index 00000000000..788e54b9381
--- /dev/null
+++ b/src/test/ui/type/issue-101866.stderr
@@ -0,0 +1,18 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/issue-101866.rs:12:5
+   |
+LL |     fn func();
+   |     ---------- `TraitA::func` defined here
+...
+LL |     TraitA::<i32>::func();
+   |     ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL -     TraitA::<i32>::func();
+LL +     <::StructA as TraitA<i32>>::func();
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index a25be93b8d6..2be22884027 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
                 if !bound_predicate.span.from_expansion();
                 if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
                 if let Some(PathSegment {
-                    res: Res::SelfTy{ trait_: Some(def_id), alias_to: _ }, ..
+                    res: Res::SelfTyParam { trait_: def_id }, ..
                 }) = segments.first();
                 if let Some(
                     Node::Item(
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 6a767967ef4..2c4f5075e98 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -206,7 +206,12 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                 ref types_to_skip,
             }) = self.stack.last();
             if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
-            if !matches!(path.res, Res::SelfTy { .. } | Res::Def(DefKind::TyParam, _));
+            if !matches!(
+                path.res,
+                Res::SelfTyParam { .. }
+                | Res::SelfTyAlias { .. }
+                | Res::Def(DefKind::TyParam, _)
+            );
             if !types_to_skip.contains(&hir_ty.hir_id);
             let ty = if in_body > 0 {
                 cx.typeck_results().node_type(hir_ty.hir_id)
@@ -230,7 +235,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         }
         match expr.kind {
             ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
-                Res::SelfTy { .. } => (),
+                Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => (),
                 Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
                 _ => span_lint(cx, path.span),
             },
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 627d6b51944..8f79c07c977 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1535,7 +1535,7 @@ pub fn is_self(slf: &Param<'_>) -> bool {
 
 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
     if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
-        if let Res::SelfTy { .. } = path.res {
+        if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
             return true;
         }
     }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 9aab66b1d21..d4733107e79 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -73,14 +73,11 @@ const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
 /// these and all their dependencies *must not* be in the exception list.
 const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
 
-/// Crates whose dependencies must be explicitly permitted.
-const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_driver", "rustc_codegen_llvm"];
-
 /// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
 ///
 /// This list is here to provide a speed-bump to adding a new dependency to
 /// rustc. Please check with the compiler team before adding an entry.
-const PERMITTED_DEPENDENCIES: &[&str] = &[
+const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "addr2line",
     "adler",
     "ahash",
@@ -307,7 +304,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
 ];
 
 const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
-    // These two crates take quite a long time to build, so don't allow two versions of them
+    // This crate takes quite a long time to build, so don't allow two versions of them
     // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
     // under control.
     "cargo",
@@ -324,12 +321,12 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
         .features(cargo_metadata::CargoOpt::AllFeatures);
     let metadata = t!(cmd.exec());
     let runtime_ids = compute_runtime_crates(&metadata);
-    check_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
-    check_dependencies(
+    check_license_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
+    check_permitted_dependencies(
         &metadata,
-        "main workspace",
-        PERMITTED_DEPENDENCIES,
-        RESTRICTED_DEPENDENCY_CRATES,
+        "rustc",
+        PERMITTED_RUSTC_DEPENDENCIES,
+        &["rustc_driver", "rustc_codegen_llvm"],
         bad,
     );
     check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad);
@@ -342,8 +339,8 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
         .features(cargo_metadata::CargoOpt::AllFeatures);
     let metadata = t!(cmd.exec());
     let runtime_ids = HashSet::new();
-    check_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
-    check_dependencies(
+    check_license_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
+    check_permitted_dependencies(
         &metadata,
         "cranelift",
         PERMITTED_CRANELIFT_DEPENDENCIES,
@@ -358,13 +355,13 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
         .features(cargo_metadata::CargoOpt::AllFeatures);
     let metadata = t!(cmd.exec());
     let runtime_ids = HashSet::new();
-    check_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
+    check_license_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
 }
 
 /// Check that all licenses are in the valid list in `LICENSES`.
 ///
-/// Packages listed in `EXCEPTIONS` are allowed for tools.
-fn check_exceptions(
+/// Packages listed in `exceptions` are allowed for tools.
+fn check_license_exceptions(
     metadata: &Metadata,
     exceptions: &[(&str, &str)],
     runtime_ids: HashSet<&PackageId>,
@@ -434,11 +431,11 @@ fn check_exceptions(
     }
 }
 
-/// Checks the dependency of `RESTRICTED_DEPENDENCY_CRATES` at the given path. Changes `bad` to
+/// Checks the dependency of `restricted_dependency_crates` at the given path. Changes `bad` to
 /// `true` if a check failed.
 ///
-/// Specifically, this checks that the dependencies are on the `PERMITTED_DEPENDENCIES`.
-fn check_dependencies(
+/// Specifically, this checks that the dependencies are on the `permitted_dependencies`.
+fn check_permitted_dependencies(
     metadata: &Metadata,
     descr: &str,
     permitted_dependencies: &[&'static str],