about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs18
-rw-r--r--compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/mod.rs10
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs4
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl3
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs43
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs24
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_const_eval/messages.ftl3
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs30
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/messages.ftl4
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs80
-rw-r--r--compiler/rustc_driver_impl/src/session_diagnostics.rs23
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0391.md3
-rw-r--r--compiler/rustc_error_messages/src/lib.rs7
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/json/tests.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs45
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_expand/src/tests.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs24
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_interface/src/interface.rs11
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_interface/src/util.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs8
-rw-r--r--compiler/rustc_lint/src/levels.rs4
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs2
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs6
-rw-r--r--compiler/rustc_llvm/build.rs5
-rw-r--r--compiler/rustc_metadata/src/foreign_modules.rs17
-rw-r--r--compiler/rustc_metadata/src/locator.rs49
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs80
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs21
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs36
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs8
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs53
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs8
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs115
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs30
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs5
-rw-r--r--compiler/rustc_middle/src/ty/util.rs18
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs40
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs204
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs10
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs3
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs49
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs2
-rw-r--r--compiler/rustc_parse_format/src/lib.rs103
-rw-r--r--compiler/rustc_parse_format/src/tests.rs15
-rw-r--r--compiler/rustc_query_system/messages.ftl1
-rw-r--r--compiler/rustc_query_system/src/error.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs46
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs10
-rw-r--r--compiler/rustc_resolve/src/ident.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_session/src/cstore.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs22
-rw-r--r--compiler/rustc_session/src/session.rs20
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs32
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs75
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs35
-rw-r--r--compiler/rustc_span/src/edition.rs6
-rw-r--r--compiler/rustc_span/src/lib.rs16
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs4
-rw-r--r--compiler/rustc_target/src/asm/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs6
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs6
-rw-r--r--compiler/rustc_target/src/spec/linux_ohos_base.rs12
-rw-r--r--compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs27
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs26
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs286
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/inherent_projection.rs44
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs30
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/weak_types.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs13
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs30
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs21
142 files changed, 1570 insertions, 759 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 429e62c4a1c..9e193402feb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1619,13 +1619,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 debug!(?hir_bounds);
 
                 let lifetime_mapping = if in_trait {
-                    self.arena.alloc_from_iter(
-                        collected_lifetime_mapping
-                            .iter()
-                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    Some(
+                        &*self.arena.alloc_from_iter(
+                            collected_lifetime_mapping
+                                .iter()
+                                .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                        ),
                     )
                 } else {
-                    &mut []
+                    None
                 };
 
                 let opaque_ty_item = hir::OpaqueTy {
@@ -2090,13 +2092,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
 
                 let lifetime_mapping = if in_trait {
-                    self.arena.alloc_from_iter(
-                        collected_lifetime_mapping
-                            .iter()
-                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    Some(
+                        &*self.arena.alloc_from_iter(
+                            collected_lifetime_mapping
+                                .iter()
+                                .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                        ),
                     )
                 } else {
-                    &mut []
+                    None
                 };
 
                 let opaque_ty_item = hir::OpaqueTy {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 278e450c6b5..97c3e0b879a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -695,7 +695,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 .find_map(find_fn_kind_from_did),
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
                 .explicit_item_bounds(def_id)
-                .arg_iter_copied(tcx, args)
+                .iter_instantiated_copied(tcx, args)
                 .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
             ty::Closure(_, args) => match args.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 4ba09335cb7..9865b6a72ee 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1134,9 +1134,14 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'b>,
         enum_def: &'b EnumDef,
         type_ident: Ident,
-        selflike_args: ThinVec<P<Expr>>,
+        mut selflike_args: ThinVec<P<Expr>>,
         nonselflike_args: &[P<Expr>],
     ) -> BlockOrExpr {
+        assert!(
+            !selflike_args.is_empty(),
+            "static methods must use `expand_static_enum_method_body`",
+        );
+
         let span = trait_.span;
         let variants = &enum_def.variants;
 
@@ -1144,10 +1149,15 @@ impl<'a> MethodDef<'a> {
         let unify_fieldless_variants =
             self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
 
-        // There is no sensible code to be generated for *any* deriving on a
-        // zero-variant enum. So we just generate a failing expression.
+        // For zero-variant enum, this function body is unreachable. Generate
+        // `match *self {}`. This produces machine code identical to `unsafe {
+        // core::intrinsics::unreachable() }` while being safe and stable.
         if variants.is_empty() {
-            return BlockOrExpr(ThinVec::new(), Some(deriving::call_unreachable(cx, span)));
+            selflike_args.truncate(1);
+            let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap());
+            let match_arms = ThinVec::new();
+            let expr = cx.expr_match(span, match_arg, match_arms);
+            return BlockOrExpr(ThinVec::new(), Some(expr));
         }
 
         let prefixes = iter::once("__self".to_string())
diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
index b8f901d1ba1..80a2776ca1e 100644
--- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
+++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
@@ -22,7 +22,7 @@ fn main() {
 
     #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
     let nan = f32::NAN;
-    // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
+    // MIPS hardware except MIPS R6 treats f32::NAN as SNAN. Clear the signaling bit.
     // See https://github.com/rust-lang/rust/issues/52746.
     #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
     let nan = f32::from_bits(f32::NAN.to_bits() - 1);
diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
index 5c52c9c18ad..12e90b58410 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
@@ -5,7 +5,7 @@
 //! [`codegen_static`]: crate::constant::codegen_static
 
 use rustc_data_structures::profiling::SelfProfilerRef;
-use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
+use rustc_middle::mir::mono::{MonoItem, MonoItemData};
 
 use crate::prelude::*;
 
@@ -16,11 +16,11 @@ pub(crate) mod jit;
 fn predefine_mono_items<'tcx>(
     tcx: TyCtxt<'tcx>,
     module: &mut dyn Module,
-    mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
+    mono_items: &[(MonoItem<'tcx>, MonoItemData)],
 ) {
     tcx.prof.generic_activity("predefine functions").run(|| {
         let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
-        for &(mono_item, (linkage, visibility)) in mono_items {
+        for &(mono_item, data) in mono_items {
             match mono_item {
                 MonoItem::Fn(instance) => {
                     let name = tcx.symbol_name(instance).name;
@@ -29,8 +29,8 @@ fn predefine_mono_items<'tcx>(
                         get_function_sig(tcx, module.target_config().default_call_conv, instance);
                     let linkage = crate::linkage::get_clif_linkage(
                         mono_item,
-                        linkage,
-                        visibility,
+                        data.linkage,
+                        data.visibility,
                         is_compiler_builtins,
                     );
                     module.declare_function(name, linkage, &sig).unwrap();
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 046903fe5ac..e756b347e89 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -10,6 +10,7 @@
 #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
+              target_arch = "mips32r6",
               target_arch = "powerpc",
               target_arch = "powerpc64"))]
 const MIN_ALIGN: usize = 8;
@@ -17,6 +18,7 @@ const MIN_ALIGN: usize = 8;
               target_arch = "aarch64",
               target_arch = "loongarch64",
               target_arch = "mips64",
+              target_arch = "mips64r6",
               target_arch = "s390x",
               target_arch = "sparc64"))]
 const MIN_ALIGN: usize = 16;
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index dcd560b3dcd..9e614ca4ace 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -159,8 +159,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
             let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers);
 
             let mono_items = cgu.items_in_deterministic_order(tcx);
-            for &(mono_item, (linkage, visibility)) in &mono_items {
-                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
+            for &(mono_item, data) in &mono_items {
+                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, data.linkage, data.visibility);
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index de1622951fe..aed4a8f3c85 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,7 +1,8 @@
 codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
 
 codegen_llvm_dlltool_fail_import_library =
-    Dlltool could not create import library: {$stdout}
+    Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
+    {$stdout}
     {$stderr}
 
 codegen_llvm_dynamic_linking_with_lto =
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 39275272e42..4c69b9503a2 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -335,6 +335,10 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     to_add.extend(probestack_attr(cx));
     to_add.extend(stackprotector_attr(cx));
 
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_BUILTINS) {
+        to_add.push(llvm::CreateAttrString(cx.llcx, "no-builtins"));
+    }
+
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
         to_add.push(AttributeKind::Cold.create_attr(cx.llcx));
     }
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index a6416e9540c..10bf954d242 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -198,25 +198,24 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                 "arm" => ("arm", "--32"),
                 _ => panic!("unsupported arch {}", sess.target.arch),
             };
-            let result = std::process::Command::new(&dlltool)
-                .args([
-                    "-d",
-                    def_file_path.to_str().unwrap(),
-                    "-D",
-                    lib_name,
-                    "-l",
-                    output_path.to_str().unwrap(),
-                    "-m",
-                    dlltool_target_arch,
-                    "-f",
-                    dlltool_target_bitness,
-                    "--no-leading-underscore",
-                    "--temp-prefix",
-                    temp_prefix.to_str().unwrap(),
-                ])
-                .output();
-
-            match result {
+            let mut dlltool_cmd = std::process::Command::new(&dlltool);
+            dlltool_cmd.args([
+                "-d",
+                def_file_path.to_str().unwrap(),
+                "-D",
+                lib_name,
+                "-l",
+                output_path.to_str().unwrap(),
+                "-m",
+                dlltool_target_arch,
+                "-f",
+                dlltool_target_bitness,
+                "--no-leading-underscore",
+                "--temp-prefix",
+                temp_prefix.to_str().unwrap(),
+            ]);
+
+            match dlltool_cmd.output() {
                 Err(e) => {
                     sess.emit_fatal(ErrorCallingDllTool {
                         dlltool_path: dlltool.to_string_lossy(),
@@ -226,6 +225,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                 // dlltool returns '0' on failure, so check for error output instead.
                 Ok(output) if !output.stderr.is_empty() => {
                     sess.emit_fatal(DlltoolFailImportLibrary {
+                        dlltool_path: dlltool.to_string_lossy(),
+                        dlltool_args: dlltool_cmd
+                            .get_args()
+                            .map(|arg| arg.to_string_lossy())
+                            .collect::<Vec<_>>()
+                            .join(" "),
                         stdout: String::from_utf8_lossy(&output.stdout),
                         stderr: String::from_utf8_lossy(&output.stderr),
                     })
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 5b2bbdb4bde..5b5f81c0329 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -86,8 +86,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
         {
             let cx = CodegenCx::new(tcx, cgu, &llvm_module);
             let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx);
-            for &(mono_item, (linkage, visibility)) in &mono_items {
-                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
+            for &(mono_item, data) in &mono_items {
+                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, data.linkage, data.visibility);
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 44869ced1ae..fced6d504d2 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -81,6 +81,8 @@ pub(crate) struct ErrorCallingDllTool<'a> {
 #[derive(Diagnostic)]
 #[diag(codegen_llvm_dlltool_fail_import_library)]
 pub(crate) struct DlltoolFailImportLibrary<'a> {
+    pub dlltool_path: Cow<'a, str>,
+    pub dlltool_args: String,
     pub stdout: Cow<'a, str>,
     pub stderr: Cow<'a, str>,
 }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 984efa21044..6582fd62387 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -17,7 +17,6 @@ tempfile = "3.2"
 thorin-dwp = "0.6"
 pathdiff = "0.2.0"
 serde_json = "1.0.59"
-snap = "1"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 regex = "1.4"
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 1f827a2375d..c4bb51edade 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -10,8 +10,6 @@ use object::{
     ObjectSymbol, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
 };
 
-use snap::write::FrameEncoder;
-
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
 use rustc_metadata::fs::METADATA_FILENAME;
@@ -193,8 +191,8 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         }
         "x86" => Architecture::I386,
         "s390x" => Architecture::S390x,
-        "mips" => Architecture::Mips,
-        "mips64" => Architecture::Mips64,
+        "mips" | "mips32r6" => Architecture::Mips,
+        "mips64" | "mips64r6" => Architecture::Mips64,
         "x86_64" => {
             if sess.target.pointer_width == 32 {
                 Architecture::X86_64_X32
@@ -481,19 +479,15 @@ pub fn create_compressed_metadata_file(
     metadata: &EncodedMetadata,
     symbol_name: &str,
 ) -> Vec<u8> {
-    let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
-    // Our length will be backfilled once we're done writing
-    compressed.write_all(&[0; 4]).unwrap();
-    FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap();
-    let meta_len = rustc_metadata::METADATA_HEADER.len();
-    let data_len = (compressed.len() - meta_len - 4) as u32;
-    compressed[meta_len..meta_len + 4].copy_from_slice(&data_len.to_be_bytes());
+    let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
+    packed_metadata.write_all(&(metadata.raw_data().len() as u32).to_be_bytes()).unwrap();
+    packed_metadata.extend(metadata.raw_data());
 
     let Some(mut file) = create_object_file(sess) else {
-        return compressed.to_vec();
+        return packed_metadata.to_vec();
     };
     if file.format() == BinaryFormat::Xcoff {
-        return create_compressed_metadata_file_for_xcoff(file, &compressed, symbol_name);
+        return create_compressed_metadata_file_for_xcoff(file, &packed_metadata, symbol_name);
     }
     let section = file.add_section(
         file.segment_name(StandardSegment::Data).to_vec(),
@@ -507,14 +501,14 @@ pub fn create_compressed_metadata_file(
         }
         _ => {}
     };
-    let offset = file.append_section_data(section, &compressed, 1);
+    let offset = file.append_section_data(section, &packed_metadata, 1);
 
     // For MachO and probably PE this is necessary to prevent the linker from throwing away the
     // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
     file.add_symbol(Symbol {
         name: symbol_name.as_bytes().to_vec(),
         value: offset,
-        size: compressed.len() as u64,
+        size: packed_metadata.len() as u64,
         kind: SymbolKind::Data,
         scope: SymbolScope::Dynamic,
         weak: false,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 406048bfe05..cbe7e519079 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -328,14 +328,14 @@ fn exported_symbols_provider_local(
 
         let (_, cgus) = tcx.collect_and_partition_mono_items(());
 
-        for (mono_item, &(linkage, visibility)) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
-            if linkage != Linkage::External {
+        for (mono_item, data) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
+            if data.linkage != Linkage::External {
                 // We can only re-use things with external linkage, otherwise
                 // we'll get a linker error
                 continue;
             }
 
-            if need_visibility && visibility == Visibility::Hidden {
+            if need_visibility && data.visibility == Visibility::Hidden {
                 // If we potentially share things from Rust dylibs, they must
                 // not be hidden
                 continue;
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index ececa29b231..1c5d7a7c68e 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -362,7 +362,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
 
 impl<B: WriteBackendMethods> CodegenContext<B> {
     pub fn create_diag_handler(&self) -> Handler {
-        Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()))
+        Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()), None)
     }
 
     pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index d6c23012762..0c7b8a79612 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,4 +1,4 @@
-use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
+use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
@@ -60,6 +60,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
+    // When `no_builtins` is applied at the crate level, we should add the
+    // `no-builtins` attribute to each function to ensure it takes effect in LTO.
+    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+    let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
+    if no_builtins {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
+    }
+
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 1c5031dfc4b..babcf9bee24 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -65,8 +65,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         constant: &mir::Constant<'tcx>,
     ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
-        let uv = match constant.literal {
+        let uv = match self.monomorphize(constant.literal) {
             mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
+            mir::ConstantKind::Ty(c) => match c.kind() {
+                // A constant that came from a const generic but was then used as an argument to old-style
+                // simd_shuffle (passing as argument instead of as a generic param).
+                rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
+                other => span_bug!(constant.span, "{other:#?}"),
+            },
+            // We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate
+            // a constant and write that value back into `Operand`s. This could happen, but is unlikely.
+            // Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care
+            // around intrinsics. For an issue to happen here, it would require a macro expanding to a
+            // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
+            // the user pass through arbitrary expressions.
+            // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
+            // const generic.
             other => span_bug!(constant.span, "{other:#?}"),
         };
         let uv = self.monomorphize(uv);
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 7b5d83c612a..48c6c75bb1a 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -321,7 +321,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
         "aarch64" => AARCH64_ALLOWED_FEATURES,
         "x86" | "x86_64" => X86_ALLOWED_FEATURES,
         "hexagon" => HEXAGON_ALLOWED_FEATURES,
-        "mips" | "mips64" => MIPS_ALLOWED_FEATURES,
+        "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES,
         "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
         "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
         "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index e99005316b3..d8eade5bd2a 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -399,6 +399,9 @@ const_eval_unallowed_mutable_refs_raw =
 const_eval_unallowed_op_in_const_context =
     {$msg}
 
+const_eval_unavailable_target_features_for_fn =
+    calling a function that requires unavailable target features: {$unavailable_feats}
+
 const_eval_undefined_behavior =
     it is undefined behavior to use this value
 
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index c944782b487..7964c6be008 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -503,6 +503,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
 
+                // Check that all target features required by the callee (i.e., from
+                // the attribute `#[target_feature(enable = ...)]`) are enabled at
+                // compile time.
+                self.check_fn_target_features(instance)?;
+
                 if !callee_fn_abi.can_unwind {
                     // The callee cannot unwind, so force the `Unreachable` unwind handling.
                     unwind = mir::UnwindAction::Unreachable;
@@ -786,6 +791,31 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
+    fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> {
+        let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
+        if attrs
+            .target_features
+            .iter()
+            .any(|feature| !self.tcx.sess.target_features.contains(feature))
+        {
+            throw_ub_custom!(
+                fluent::const_eval_unavailable_target_features_for_fn,
+                unavailable_feats = attrs
+                    .target_features
+                    .iter()
+                    .filter(|&feature| !self.tcx.sess.target_features.contains(feature))
+                    .fold(String::new(), |mut s, feature| {
+                        if !s.is_empty() {
+                            s.push_str(", ");
+                        }
+                        s.push_str(feature.as_str());
+                        s
+                    }),
+            );
+        }
+        Ok(())
+    }
+
     fn drop_in_place(
         &mut self,
         place: &PlaceTy<'tcx, M::Provenance>,
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 67352c55c90..a7b01618ade 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [lib]
 
 [dependencies]
+time = { version = "0.3", default-features = false, features = ["formatting", ] }
 tracing = { version = "0.1.35" }
 serde_json = "1.0.59"
 rustc_log = { path = "../rustc_log" }
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index 22b4ec6b0d1..9b2f2c33860 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -3,7 +3,11 @@ driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
 
 driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_path = please attach the file at `{$path}` to your bug report
+driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error}
+driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}`
 driver_impl_ice_version = rustc {$version} running on {$triple}
+
 driver_impl_rlink_empty_version_number = The input does not contain version number
 
 driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 25c043149e8..11303e7d09e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -7,6 +7,8 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(lazy_cell)]
 #![feature(decl_macro)]
+#![feature(ice_to_disk)]
+#![feature(let_chains)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
@@ -57,8 +59,11 @@ use std::panic::{self, catch_unwind};
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
 use std::str;
+use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::OnceLock;
-use std::time::Instant;
+use std::time::{Instant, SystemTime};
+use time::format_description::well_known::Rfc3339;
+use time::OffsetDateTime;
 
 #[allow(unused_macros)]
 macro do_not_use_print($($t:tt)*) {
@@ -294,6 +299,7 @@ fn run_compiler(
         input: Input::File(PathBuf::new()),
         output_file: ofile,
         output_dir: odir,
+        ice_file: ice_path().clone(),
         file_loader,
         locale_resources: DEFAULT_LOCALE_RESOURCES,
         lint_caps: Default::default(),
@@ -1292,9 +1298,29 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
     }
 }
 
-/// Stores the default panic hook, from before [`install_ice_hook`] was called.
-static DEFAULT_HOOK: OnceLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
-    OnceLock::new();
+pub static ICE_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
+
+pub fn ice_path() -> &'static Option<PathBuf> {
+    ICE_PATH.get_or_init(|| {
+        if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() {
+            return None;
+        }
+        if let Ok("0") = std::env::var("RUST_BACKTRACE").as_deref() {
+            return None;
+        }
+        let mut path = match std::env::var("RUSTC_ICE").as_deref() {
+            // Explicitly opting out of writing ICEs to disk.
+            Ok("0") => return None,
+            Ok(s) => PathBuf::from(s),
+            Err(_) => std::env::current_dir().unwrap_or_default(),
+        };
+        let now: OffsetDateTime = SystemTime::now().into();
+        let file_now = now.format(&Rfc3339).unwrap_or(String::new());
+        let pid = std::process::id();
+        path.push(format!("rustc-ice-{file_now}-{pid}.txt"));
+        Some(path)
+    })
+}
 
 /// Installs a panic hook that will print the ICE message on unexpected panics.
 ///
@@ -1318,8 +1344,6 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         std::env::set_var("RUST_BACKTRACE", "full");
     }
 
-    let default_hook = DEFAULT_HOOK.get_or_init(panic::take_hook);
-
     panic::set_hook(Box::new(move |info| {
         // If the error was caused by a broken pipe then this is not a bug.
         // Write the error and return immediately. See #98700.
@@ -1336,7 +1360,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         // Invoke the default handler, which prints the actual panic message and optionally a backtrace
         // Don't do this for delayed bugs, which already emit their own more useful backtrace.
         if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
-            (*default_hook)(info);
+            std::panic_hook_with_disk_dump(info, ice_path().as_deref());
 
             // Separate the output with an empty line
             eprintln!();
@@ -1368,7 +1392,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
         false,
         TerminalUrl::No,
     ));
-    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
+    let handler = rustc_errors::Handler::with_emitter(true, None, emitter, None);
 
     // a .span_bug or .bug call has already printed what
     // it wants to print.
@@ -1379,10 +1403,40 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
     }
 
     handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
-    handler.emit_note(session_diagnostics::IceVersion {
-        version: util::version_str!().unwrap_or("unknown_version"),
-        triple: config::host_triple(),
-    });
+
+    let version = util::version_str!().unwrap_or("unknown_version");
+    let triple = config::host_triple();
+
+    static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
+
+    let file = if let Some(path) = ice_path().as_ref() {
+        // Create the ICE dump target file.
+        match crate::fs::File::options().create(true).append(true).open(&path) {
+            Ok(mut file) => {
+                handler
+                    .emit_note(session_diagnostics::IcePath { path: path.display().to_string() });
+                if FIRST_PANIC.swap(false, Ordering::SeqCst) {
+                    let _ = write!(file, "\n\nrustc version: {version}\nplatform: {triple}");
+                }
+                Some(file)
+            }
+            Err(err) => {
+                // The path ICE couldn't be written to disk, provide feedback to the user as to why.
+                handler.emit_warning(session_diagnostics::IcePathError {
+                    path: path.display().to_string(),
+                    error: err.to_string(),
+                    env_var: std::env::var("RUSTC_ICE")
+                        .ok()
+                        .map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }),
+                });
+                handler.emit_note(session_diagnostics::IceVersion { version, triple });
+                None
+            }
+        }
+    } else {
+        handler.emit_note(session_diagnostics::IceVersion { version, triple });
+        None
+    };
 
     if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
         handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
@@ -1396,7 +1450,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
 
     let num_frames = if backtrace { None } else { Some(2) };
 
-    interface::try_print_query_stack(&handler, num_frames);
+    interface::try_print_query_stack(&handler, num_frames, file);
 
     // We don't trust this callback not to panic itself, so run it at the end after we're sure we've
     // printed all the relevant info.
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
index 638b368f702..f7f06b7d0f2 100644
--- a/compiler/rustc_driver_impl/src/session_diagnostics.rs
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -1,4 +1,4 @@
-use rustc_macros::Diagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
 
 #[derive(Diagnostic)]
 #[diag(driver_impl_rlink_unable_to_read)]
@@ -57,6 +57,27 @@ pub(crate) struct IceVersion<'a> {
 }
 
 #[derive(Diagnostic)]
+#[diag(driver_impl_ice_path)]
+pub(crate) struct IcePath {
+    pub path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_path_error)]
+pub(crate) struct IcePathError {
+    pub path: String,
+    pub error: String,
+    #[subdiagnostic]
+    pub env_var: Option<IcePathErrorEnv>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(driver_impl_ice_path_error_env)]
+pub(crate) struct IcePathErrorEnv {
+    pub env_var: String,
+}
+
+#[derive(Diagnostic)]
 #[diag(driver_impl_ice_flags)]
 pub(crate) struct IceFlags {
     pub flags: String,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0391.md b/compiler/rustc_error_codes/src/error_codes/E0391.md
index dff50ccaa0b..457fbd002a1 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0391.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0391.md
@@ -14,3 +14,6 @@ trait SecondTrait : FirstTrait {
 
 The previous example contains a circular dependency between two traits:
 `FirstTrait` depends on `SecondTrait` which itself depends on `FirstTrait`.
+
+See https://rustc-dev-guide.rust-lang.org/overview.html#queries and
+https://rustc-dev-guide.rust-lang.org/query.html for more information.
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 51e1fe531dd..1879ece59e3 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -354,6 +354,13 @@ impl DiagnosticMessage {
             }
         }
     }
+
+    pub fn as_str(&self) -> Option<&str> {
+        match self {
+            DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
+            DiagnosticMessage::FluentIdentifier(_, _) => None,
+        }
+    }
 }
 
 impl From<String> for DiagnosticMessage {
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 9d4d159fd96..a0fa4115c3e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1982,7 +1982,7 @@ impl EmitterWriter {
                 // We special case `#[derive(_)]\n` and other attribute suggestions, because those
                 // are the ones where context is most useful.
                 let file_lines = sm
-                    .span_to_lines(span.primary_span().unwrap().shrink_to_hi())
+                    .span_to_lines(parts[0].span.shrink_to_hi())
                     .expect("span_to_lines failed when emitting suggestion");
                 let line_num = sm.lookup_char_pos(parts[0].span.lo()).line;
                 if let Some(line) = file_lines.file.get_line(line_num - 1) {
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index 671dc449eaa..db0dd4ffe8e 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -64,7 +64,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
         );
 
         let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
-        let handler = Handler::with_emitter(true, None, Box::new(je));
+        let handler = Handler::with_emitter(true, None, Box::new(je), None);
         handler.span_err(span, "foo");
 
         let bytes = output.lock().unwrap();
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b9db25103a3..1da02e1bb01 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -47,9 +47,10 @@ use std::borrow::Cow;
 use std::error::Report;
 use std::fmt;
 use std::hash::Hash;
+use std::io::Write;
 use std::num::NonZeroUsize;
 use std::panic;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use termcolor::{Color, ColorSpec};
 
@@ -461,6 +462,10 @@ struct HandlerInner {
     ///
     /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
     fulfilled_expectations: FxHashSet<LintExpectationId>,
+
+    /// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be
+    /// stored along side the main panic backtrace.
+    ice_file: Option<PathBuf>,
 }
 
 /// A key denoting where from a diagnostic was stashed.
@@ -550,6 +555,7 @@ impl Handler {
         sm: Option<Lrc<SourceMap>>,
         fluent_bundle: Option<Lrc<FluentBundle>>,
         fallback_bundle: LazyFallbackBundle,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Self::with_tty_emitter_and_flags(
             color_config,
@@ -557,6 +563,7 @@ impl Handler {
             fluent_bundle,
             fallback_bundle,
             HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
+            ice_file,
         )
     }
 
@@ -566,6 +573,7 @@ impl Handler {
         fluent_bundle: Option<Lrc<FluentBundle>>,
         fallback_bundle: LazyFallbackBundle,
         flags: HandlerFlags,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         let emitter = Box::new(EmitterWriter::stderr(
             color_config,
@@ -579,23 +587,26 @@ impl Handler {
             flags.track_diagnostics,
             TerminalUrl::No,
         ));
-        Self::with_emitter_and_flags(emitter, flags)
+        Self::with_emitter_and_flags(emitter, flags, ice_file)
     }
 
     pub fn with_emitter(
         can_emit_warnings: bool,
         treat_err_as_bug: Option<NonZeroUsize>,
         emitter: Box<dyn Emitter + sync::Send>,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Handler::with_emitter_and_flags(
             emitter,
             HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
+            ice_file,
         )
     }
 
     pub fn with_emitter_and_flags(
         emitter: Box<dyn Emitter + sync::Send>,
         flags: HandlerFlags,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Self {
             flags,
@@ -618,6 +629,7 @@ impl Handler {
                 check_unstable_expect_diagnostics: false,
                 unstable_expect_diagnostics: Vec::new(),
                 fulfilled_expectations: Default::default(),
+                ice_file,
             }),
         }
     }
@@ -991,7 +1003,7 @@ impl Handler {
         self.emit_diag_at_span(Diagnostic::new_with_code(Warning(None), Some(code), msg), span);
     }
 
-    pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
         self.inner.borrow_mut().span_bug(span, msg)
     }
 
@@ -1000,7 +1012,7 @@ impl Handler {
     pub fn delay_span_bug(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<String>,
     ) -> ErrorGuaranteed {
         self.inner.borrow_mut().delay_span_bug(span, msg)
     }
@@ -1584,8 +1596,8 @@ impl HandlerInner {
     }
 
     #[track_caller]
-    fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
-        self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp);
+    fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
+        self.emit_diag_at_span(Diagnostic::new(Bug, msg.into()), sp);
         panic::panic_any(ExplicitBug);
     }
 
@@ -1598,7 +1610,7 @@ impl HandlerInner {
     fn delay_span_bug(
         &mut self,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<String>,
     ) -> ErrorGuaranteed {
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
@@ -1607,9 +1619,9 @@ impl HandlerInner {
             self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
         }) {
             // FIXME: don't abort here if report_delayed_bugs is off
-            self.span_bug(sp, msg);
+            self.span_bug(sp, msg.into());
         }
-        let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
+        let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into());
         diagnostic.set_span(sp.into());
         self.emit_diagnostic(&mut diagnostic).unwrap()
     }
@@ -1657,8 +1669,21 @@ impl HandlerInner {
         explanation: impl Into<DiagnosticMessage> + Copy,
     ) {
         let mut no_bugs = true;
+        // If backtraces are enabled, also print the query stack
+        let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
         for bug in bugs {
-            let mut bug = bug.decorate();
+            if let Some(file) = self.ice_file.as_ref()
+                && let Ok(mut out) = std::fs::File::options().append(true).open(file)
+            {
+                let _ = write!(
+                    &mut out,
+                    "\n\ndelayed span bug: {}\n{}",
+                    bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
+                    &bug.note
+                );
+            }
+            let mut bug =
+                if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
 
             if no_bugs {
                 // Put the overall explanation before the `DelayedBug`s, to
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 4b0907cf15a..12473a2bb0b 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1147,7 +1147,7 @@ impl<'a> ExtCtxt<'a> {
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<String>) -> ! {
         self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
     pub fn trace_macros_diag(&mut self) {
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 42cc0a6b143..102bae2a744 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1200,7 +1200,7 @@ fn check_matcher_core<'tt>(
                             err.span_label(sp, format!("not allowed after `{}` fragments", kind));
 
                             if kind == NonterminalKind::PatWithOr
-                                && sess.edition.rust_2021()
+                                && sess.edition.at_least_rust_2021()
                                 && next_token.is_token(&BinOp(token::BinOpToken::Or))
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 8a5e09475ff..6490e52955d 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -161,7 +161,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
             false,
             TerminalUrl::No,
         );
-        let handler = Handler::with_emitter(true, None, Box::new(emitter));
+        let handler = Handler::with_emitter(true, None, Box::new(emitter), None);
         #[allow(rustc::untranslatable_diagnostic)]
         handler.span_err(msp, "foo");
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 35ef30114b7..68f1559ea22 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2664,10 +2664,19 @@ pub struct OpaqueTy<'hir> {
     pub generics: &'hir Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
     pub origin: OpaqueTyOrigin,
-    // Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy
-    // so we can later generate bidirectional outlives predicates to enforce that these lifetimes
-    // stay in sync.
-    pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)],
+    /// Return-position impl traits (and async futures) must "reify" any late-bound
+    /// lifetimes that are captured from the function signature they originate from.
+    ///
+    /// This is done by generating a new early-bound lifetime parameter local to the
+    /// opaque which is substituted in the function signature with the late-bound
+    /// lifetime.
+    ///
+    /// This mapping associated a captured lifetime (first parameter) with the new
+    /// early-bound lifetime that was generated for the opaque.
+    pub lifetime_mapping: Option<&'hir [(Lifetime, LocalDefId)]>,
+    /// Whether the opaque is a return-position impl trait (or async future)
+    /// originating from a trait method. This makes it so that the opaque is
+    /// lowered as an associated type.
     pub in_trait: bool,
 }
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index 05a3ab63d5c..ff55174f97a 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 ));
             }
 
-            if self_ty.span.edition().rust_2021() {
+            if self_ty.span.edition().at_least_rust_2021() {
                 let msg = "trait objects must include the `dyn` keyword";
                 let label = "add `dyn` keyword before this trait";
                 let mut diag =
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 07f8dd948e2..89877280a73 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -867,7 +867,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
             });
             self.types.insert(proj.def_id, (infer_ty, proj.args));
             // Recurse into bounds
-            for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).arg_iter_copied(self.interner(), proj.args) {
+            for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).iter_instantiated_copied(self.interner(), proj.args) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     &ObligationCause::misc(self.span, self.body_id),
@@ -2149,7 +2149,7 @@ pub(super) fn check_type_bounds<'tcx>(
 
     let obligations: Vec<_> = tcx
         .explicit_item_bounds(trait_ty.def_id)
-        .arg_iter_copied(tcx, rebased_args)
+        .iter_instantiated_copied(tcx, rebased_args)
         .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
             traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 5ff33763e13..def7a3a9d88 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -409,7 +409,7 @@ fn fn_sig_suggestion<'tcx>(
     let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
         output = if let ty::Alias(_, alias_ty) = *output.kind() {
             tcx.explicit_item_bounds(alias_ty.def_id)
-                .arg_iter_copied(tcx, alias_ty.args)
+                .iter_instantiated_copied(tcx, alias_ty.args)
                 .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
                 .unwrap_or_else(|| {
                     span_bug!(
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 443d072f992..4e194f1c381 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1567,7 +1567,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             });
             for (bound, bound_span) in tcx
                 .explicit_item_bounds(opaque_ty.def_id)
-                .arg_iter_copied(tcx, opaque_ty.args)
+                .iter_instantiated_copied(tcx, opaque_ty.args)
             {
                 let bound = self.wfcx.normalize(bound_span, None, bound);
                 self.wfcx.register_obligations(traits::wf::predicate_obligations(
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 05c78f57088..21ffbefcd08 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -568,10 +568,10 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
 
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for DisableAutoTraitVisitor<'tcx> {
         type BreakTy = ();
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             let tcx = self.tcx;
-            if t != self.self_ty_root {
-                for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) {
+            if ty != self.self_ty_root {
+                for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, ty) {
                     match tcx.impl_polarity(impl_def_id) {
                         ImplPolarity::Negative => return ControlFlow::Break(()),
                         ImplPolarity::Reservation => {}
@@ -584,7 +584,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
                 }
             }
 
-            match t.kind() {
+            match ty.kind() {
                 ty::Adt(def, args) if def.is_phantom_data() => args.visit_with(self),
                 ty::Adt(def, args) => {
                     // @lcnr: This is the only place where cycles can happen. We avoid this
@@ -599,7 +599,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
 
                     ControlFlow::Continue(())
                 }
-                _ => t.super_visit_with(self),
+                _ => ty.super_visit_with(self),
             }
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 1c9070600db..979b101e7fe 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -66,7 +66,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
             let opaque_ty_node = tcx.hir().get(opaque_ty_id);
             let Node::Item(&Item {
-                kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }),
+                kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping: Some(lifetime_mapping), .. }),
                 ..
             }) = opaque_ty_node
             else {
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 199cdabb7e9..1ef257e87d6 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -145,7 +145,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
     let mut collector =
         OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
     let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
-    for (pred, _) in tcx.explicit_item_bounds(item_def_id).arg_iter_copied(tcx, id_args) {
+    for (pred, _) in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) {
         debug!(?pred);
 
         // We only ignore opaque type args if the opaque type is the outermost type.
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index f2a43cc414d..119ed2fa408 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -551,8 +551,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 for ty in [first_ty, second_ty] {
-                    for (clause, _) in
-                        self.tcx.explicit_item_bounds(rpit_def_id).arg_iter_copied(self.tcx, args)
+                    for (clause, _) in self
+                        .tcx
+                        .explicit_item_bounds(rpit_def_id)
+                        .iter_instantiated_copied(self.tcx, args)
                     {
                         let pred = clause.kind().rebind(match clause.kind().skip_binder() {
                             ty::ClauseKind::Trait(trait_pred) => {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index e7df9ecf383..affeee55e79 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     expected_ty,
                     self.tcx
                         .explicit_item_bounds(def_id)
-                        .arg_iter_copied(self.tcx, args)
+                        .iter_instantiated_copied(self.tcx, args)
                         .map(|(c, s)| (c.as_predicate(), s)),
                 ),
             ty::Dynamic(ref object_type, ..) => {
@@ -720,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
                 .tcx
                 .explicit_item_bounds(def_id)
-                .arg_iter_copied(self.tcx, args)
+                .iter_instantiated_copied(self.tcx, args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return None,
             ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
                 .tcx
                 .explicit_item_bounds(proj.def_id)
-                .arg_iter_copied(self.tcx, proj.args)
+                .iter_instantiated_copied(self.tcx, proj.args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index bd7e7a671e6..94f64a1ffdb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -860,7 +860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
             .and_then(|r| {
                 // lint bare trait if the method is found in the trait
-                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
                     diag.emit();
                 }
                 Ok(r)
@@ -890,7 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 // emit or cancel the diagnostic for bare traits
-                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
                     if trait_missing_method {
                         // cancel the diag for bare traits when meeting `MyTrait::missing_method`
                         diag.cancel();
@@ -908,7 +908,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         error,
                         None,
                         Expectation::NoExpectation,
-                        trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
+                        trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
                         e.emit();
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 15ca5808a93..c44d12e61e3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -2,7 +2,7 @@ use crate::FnCtxt;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
-use rustc_infer::traits::ObligationCauseCode;
+use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::{self, symbol::kw, Span};
 use rustc_trait_selection::traits;
@@ -267,8 +267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             type BreakTy = ty::GenericArg<'tcx>;
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
                 if let Some(origin) = self.0.type_var_origin(ty)
-                    && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, def_id) =
-                        origin.kind
+                    && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
                     && let generics = self.0.tcx.generics_of(self.1)
                     && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
                     && let Some(subst) = ty::GenericArgs::identity_for_item(self.0.tcx, self.1)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 1e8af6c6ed7..6a82b00211e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -302,7 +302,9 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         match ty.kind() {
             ty::Adt(adt_def, _) => Some(*adt_def),
             // FIXME(#104767): Should we handle bound regions here?
-            ty::Alias(ty::Projection | ty::Inherent, _) if !ty.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _)
+                if !ty.has_escaping_bound_vars() =>
+            {
                 self.normalize(span, ty).ty_adt_def()
             }
             _ => None,
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index ec4e7f7f88a..4efe95c4dc5 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         // Rust 2021 and later is already using the new prelude
-        if span.rust_2021() {
+        if span.at_least_rust_2021() {
             return;
         }
 
@@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pick: &Pick<'tcx>,
     ) {
         // Rust 2021 and later is already using the new prelude
-        if span.rust_2021() {
+        if span.at_least_rust_2021() {
             return;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 9ef97243c5e..05eed1923d1 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -437,7 +437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // this case used to be allowed by the compiler,
                 // so we do a future-compat lint here for the 2015 edition
                 // (see https://github.com/rust-lang/rust/issues/46906)
-                if self.tcx.sess.rust_2018() {
+                if self.tcx.sess.at_least_rust_2018() {
                     self.tcx.sess.emit_err(MethodCallOnUnknownRawPointee { span });
                 } else {
                     self.tcx.struct_span_lint_hir(
@@ -1592,7 +1592,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     if let Some(method_name) = self.method_name {
                         // Some trait methods are excluded for arrays before 2021.
                         // (`array.into_iter()` wants a slice iterator for compatibility.)
-                        if self_ty.is_array() && !method_name.span.rust_2021() {
+                        if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
                             let trait_def = self.tcx.trait_def(trait_ref.def_id);
                             if trait_def.skip_array_during_method_dispatch {
                                 return ProbeResult::NoMatch;
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index f77a4d16b5f..fb81a8395d7 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -2001,7 +2001,7 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
     tcx: TyCtxt<'_>,
     closure_id: hir::HirId,
 ) -> bool {
-    if tcx.sess.rust_2021() {
+    if tcx.sess.at_least_rust_2021() {
         return false;
     }
 
@@ -2247,5 +2247,5 @@ fn truncate_capture_for_optimization(
 fn enable_precise_capture(span: Span) -> bool {
     // We use span here to ensure that if the closure was generated by a macro with a different
     // edition.
-    span.rust_2021()
+    span.at_least_rust_2021()
 }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index cf6c7f70de3..2329a1f63ce 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -3,7 +3,6 @@
 // substitutions.
 
 use crate::FnCtxt;
-use hir::def_id::LocalDefId;
 use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
@@ -11,13 +10,12 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
 use std::mem;
-use std::ops::ControlFlow;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point
@@ -565,23 +563,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
             let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
 
-            struct RecursionChecker {
-                def_id: LocalDefId,
-            }
-            impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RecursionChecker {
-                type BreakTy = ();
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
-                        if def_id == self.def_id.to_def_id() {
-                            return ControlFlow::Break(());
-                        }
-                    }
-                    t.super_visit_with(self)
-                }
-            }
-            if hidden_type
-                .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
-                .is_break()
+            if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
+                && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
+                && alias_ty.args == opaque_type_key.args
             {
                 continue;
             }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index bf46f9881d4..8e3c76d6a4b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -403,7 +403,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
         let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
 
-        self.tcx.explicit_item_bounds(def_id).arg_iter_copied(self.tcx, args).find_map(
+        self.tcx.explicit_item_bounds(def_id).iter_instantiated_copied(self.tcx, args).find_map(
             |(predicate, _)| {
                 predicate
                     .kind()
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 b4d8205fd6d..36b56fe782c 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
@@ -163,7 +163,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
         let ty_vars = infcx_inner.type_variables();
         let var_origin = ty_vars.var_origin(ty_vid);
         if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind
-            && !var_origin.span.from_expansion()
+            && name != kw::SelfUpper && !var_origin.span.from_expansion()
         {
             let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
             let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 90f0b4ce401..945136fbff2 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -591,7 +591,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let tcx = self.tcx;
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
-        for (predicate, _) in item_bounds.arg_iter_copied(tcx, args) {
+        for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
                 ty_op: |ty| match *ty.kind() {
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 1e1ecd3fb94..2bc6546ba28 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -295,7 +295,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         let bounds = tcx.item_bounds(alias_ty.def_id);
         trace!("{:#?}", bounds.skip_binder());
         bounds
-            .arg_iter(tcx, alias_ty.args)
+            .iter_instantiated(tcx, alias_ty.args)
             .filter_map(|p| p.as_type_outlives_clause())
             .filter_map(|p| p.no_bound_vars())
             .map(|OutlivesPredicate(_, r)| r)
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 3f420f19efe..5b417e008cf 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -251,6 +251,7 @@ pub struct Config {
     pub input: Input,
     pub output_dir: Option<PathBuf>,
     pub output_file: Option<OutFileName>,
+    pub ice_file: Option<PathBuf>,
     pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
     pub locale_resources: &'static [&'static str],
 
@@ -315,6 +316,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.lint_caps,
                 config.make_codegen_backend,
                 registry.clone(),
+                config.ice_file,
             );
 
             if let Some(parse_sess_created) = config.parse_sess_created {
@@ -346,7 +348,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
     )
 }
 
-pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
+pub fn try_print_query_stack(
+    handler: &Handler,
+    num_frames: Option<usize>,
+    file: Option<std::fs::File>,
+) {
     eprintln!("query stack during panic:");
 
     // Be careful relying on global state here: this code is called from
@@ -358,7 +364,8 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
                 QueryCtxt::new(icx.tcx),
                 icx.query,
                 handler,
-                num_frames
+                num_frames,
+                file,
             ))
         } else {
             0
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 09141afd137..5c6c3491b38 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -67,6 +67,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
         None,
         None,
         "",
+        None,
     );
     (sess, cfg)
 }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 035ea2414f7..12d33f06309 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -70,6 +70,7 @@ pub fn create_session(
         Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
     >,
     descriptions: Registry,
+    ice_file: Option<PathBuf>,
 ) -> (Session, Box<dyn CodegenBackend>) {
     let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
         make_codegen_backend(&sopts)
@@ -111,6 +112,7 @@ pub fn create_session(
         file_loader,
         target_override,
         rustc_version_str().unwrap_or("unknown"),
+        ice_file,
     );
 
     codegen_backend.init(&sess);
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 6522e449386..7c701fd4fe1 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -956,11 +956,11 @@ pub trait LintContext: Sized {
                     db.span_note(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace));
                     db.span_note(private_item_span, "but the private item here shadows it".to_owned());
                 }
-                BuiltinLintDiagnostics::UnusedQualifications { path_span, unqualified_path } => {
+                BuiltinLintDiagnostics::UnusedQualifications { removal_span } => {
                     db.span_suggestion_verbose(
-                        path_span,
-                        "replace it with the unqualified path",
-                        unqualified_path,
+                        removal_span,
+                        "remove the unnecessary path segments",
+                        "",
                         Applicability::MachineApplicable
                     );
                 }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index c9ee2da6fdf..0c80141a756 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -978,6 +978,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     /// Returns `true` if the lint's feature is enabled.
     // FIXME only emit this once for each attribute, instead of repeating it 4 times for
     // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
+    #[track_caller]
     fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
         if let Some(feature) = lint_id.lint.feature_gate {
             if !self.sess.features_untracked().enabled(feature) {
@@ -1015,6 +1016,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub(crate) fn struct_lint(
         &self,
         lint: &'static Lint,
@@ -1028,6 +1030,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
     }
 
+    #[track_caller]
     pub fn emit_spanned_lint(
         &self,
         lint: &'static Lint,
@@ -1040,6 +1043,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         });
     }
 
+    #[track_caller]
     pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) {
         let (level, src) = self.lint_level(lint);
         struct_lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index d5f0290767a..79b0b32bef2 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             for (assoc_pred, assoc_pred_span) in cx
                 .tcx
                 .explicit_item_bounds(proj.projection_ty.def_id)
-                .arg_iter_copied(cx.tcx, &proj.projection_ty.args)
+                .iter_instantiated_copied(cx.tcx, &proj.projection_ty.args)
             {
                 let assoc_pred = assoc_pred.fold_with(proj_replacer);
                 let Ok(assoc_pred) = traits::fully_normalize(
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index f6ffd46b1fe..10ebe29dfce 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -551,10 +551,8 @@ pub enum BuiltinLintDiagnostics {
         private_item_span: Span,
     },
     UnusedQualifications {
-        /// The span of the unnecessarily-qualified path.
-        path_span: Span,
-        /// The replacement unqualified path.
-        unqualified_path: Ident,
+        /// The span of the unnecessarily-qualified path to remove.
+        removal_span: Span,
     },
 }
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index b0783d75d47..aa1121d6bb3 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -251,8 +251,11 @@ fn main() {
     } else if target.contains("windows-gnu") {
         println!("cargo:rustc-link-lib=shell32");
         println!("cargo:rustc-link-lib=uuid");
-    } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
+    } else if target.contains("haiku") || target.contains("darwin") {
         println!("cargo:rustc-link-lib=z");
+    } else if target.contains("netbsd") {
+        println!("cargo:rustc-link-lib=z");
+        println!("cargo:rustc-link-lib=execinfo");
     }
     cmd.args(&components);
 
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index d1c2f3104d0..154eb684f11 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -1,19 +1,28 @@
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::cstore::ForeignModule;
 
-pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
-    let mut modules = Vec::new();
+pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> FxIndexMap<DefId, ForeignModule> {
+    let mut modules = FxIndexMap::default();
+
+    // We need to collect all the `ForeignMod`, even if they are empty.
     for id in tcx.hir().items() {
         if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
             continue;
         }
+
+        let def_id = id.owner_id.to_def_id();
         let item = tcx.hir().item(id);
-        if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
+
+        if let hir::ItemKind::ForeignMod { abi, items } = item.kind {
             let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect();
-            modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() });
+            modules.insert(def_id, ForeignModule { def_id, abi, foreign_items });
         }
     }
+
     modules
 }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index a1511c4b570..44195996762 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -511,7 +511,7 @@ impl<'a> CrateLocator<'a> {
             rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?,
             dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?,
         };
-        Ok(slot.map(|(svh, metadata)| (svh, Library { source, metadata })))
+        Ok(slot.map(|(svh, metadata, _)| (svh, Library { source, metadata })))
     }
 
     fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool {
@@ -535,11 +535,13 @@ impl<'a> CrateLocator<'a> {
     // read the metadata from it if `*slot` is `None`. If the metadata couldn't
     // be read, it is assumed that the file isn't a valid rust library (no
     // errors are emitted).
+    //
+    // The `PathBuf` in `slot` will only be used for diagnostic purposes.
     fn extract_one(
         &mut self,
         m: FxHashMap<PathBuf, PathKind>,
         flavor: CrateFlavor,
-        slot: &mut Option<(Svh, MetadataBlob)>,
+        slot: &mut Option<(Svh, MetadataBlob, PathBuf)>,
     ) -> Result<Option<(PathBuf, PathKind)>, CrateError> {
         // If we are producing an rlib, and we've already loaded metadata, then
         // we should not attempt to discover further crate sources (unless we're
@@ -550,16 +552,9 @@ impl<'a> CrateLocator<'a> {
         //
         // See also #68149 which provides more detail on why emitting the
         // dependency on the rlib is a bad thing.
-        //
-        // We currently do not verify that these other sources are even in sync,
-        // and this is arguably a bug (see #10786), but because reading metadata
-        // is quite slow (especially from dylibs) we currently do not read it
-        // from the other crate sources.
         if slot.is_some() {
             if m.is_empty() || !self.needs_crate_flavor(flavor) {
                 return Ok(None);
-            } else if m.len() == 1 {
-                return Ok(Some(m.into_iter().next().unwrap()));
             }
         }
 
@@ -610,8 +605,7 @@ impl<'a> CrateLocator<'a> {
                         candidates,
                     ));
                 }
-                err_data = Some(vec![ret.as_ref().unwrap().0.clone()]);
-                *slot = None;
+                err_data = Some(vec![slot.take().unwrap().2]);
             }
             if let Some(candidates) = &mut err_data {
                 candidates.push(lib);
@@ -644,7 +638,7 @@ impl<'a> CrateLocator<'a> {
                     continue;
                 }
             }
-            *slot = Some((hash, metadata));
+            *slot = Some((hash, metadata, lib.clone()));
             ret = Some((lib, kind));
         }
 
@@ -814,19 +808,26 @@ fn get_metadata_section<'p>(
             let compressed_len = u32::from_be_bytes(len_bytes) as usize;
 
             // Header is okay -> inflate the actual metadata
-            let compressed_bytes = &buf[data_start..(data_start + compressed_len)];
-            debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
-            // Assume the decompressed data will be at least the size of the compressed data, so we
-            // don't have to grow the buffer as much.
-            let mut inflated = Vec::with_capacity(compressed_bytes.len());
-            FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated).map_err(|_| {
-                MetadataError::LoadFailure(format!(
-                    "failed to decompress metadata: {}",
-                    filename.display()
-                ))
-            })?;
+            let compressed_bytes = buf.slice(|buf| &buf[data_start..(data_start + compressed_len)]);
+            if &compressed_bytes[..cmp::min(METADATA_HEADER.len(), compressed_bytes.len())]
+                == METADATA_HEADER
+            {
+                // The metadata was not actually compressed.
+                compressed_bytes
+            } else {
+                debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
+                // Assume the decompressed data will be at least the size of the compressed data, so we
+                // don't have to grow the buffer as much.
+                let mut inflated = Vec::with_capacity(compressed_bytes.len());
+                FrameDecoder::new(&*compressed_bytes).read_to_end(&mut inflated).map_err(|_| {
+                    MetadataError::LoadFailure(format!(
+                        "failed to decompress metadata: {}",
+                        filename.display()
+                    ))
+                })?;
 
-            slice_owned(inflated, Deref::deref)
+                slice_owned(inflated, Deref::deref)
+            }
         }
         CrateFlavor::Rmeta => {
             // mmap the file, because only a small fraction of it is read.
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 9e0bf81d58d..ca5043cc263 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -1,15 +1,17 @@
 use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_session::config::CrateType;
-use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType};
+use rustc_session::cstore::{
+    DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
+};
 use rustc_session::parse::feature_err;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
 use rustc_session::Session;
+use rustc_span::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::spec::abi::Abi;
 
@@ -66,10 +68,12 @@ fn find_bundled_library(
     None
 }
 
-pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
+pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> {
     let mut collector = Collector { tcx, libs: Vec::new() };
-    for id in tcx.hir().items() {
-        collector.process_item(id);
+    if tcx.sess.opts.unstable_opts.link_directives {
+        for module in tcx.foreign_modules(LOCAL_CRATE).values() {
+            collector.process_module(module);
+        }
     }
     collector.process_command_line();
     collector.libs
@@ -88,29 +92,20 @@ struct Collector<'tcx> {
 }
 
 impl<'tcx> Collector<'tcx> {
-    fn process_item(&mut self, id: rustc_hir::ItemId) {
-        if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
-            return;
-        }
+    fn process_module(&mut self, module: &ForeignModule) {
+        let ForeignModule { def_id, abi, ref foreign_items } = *module;
+        let def_id = def_id.expect_local();
 
-        let it = self.tcx.hir().item(id);
-        let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
-            return;
-        };
+        let sess = self.tcx.sess;
 
         if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
             return;
         }
 
         // Process all of the #[link(..)]-style arguments
-        let sess = self.tcx.sess;
         let features = self.tcx.features();
 
-        if !sess.opts.unstable_opts.link_directives {
-            return;
-        }
-
-        for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
+        for m in self.tcx.get_attrs(def_id, sym::link) {
             let Some(items) = m.meta_item_list() else {
                 continue;
             };
@@ -340,9 +335,9 @@ impl<'tcx> Collector<'tcx> {
                     if name.as_str().contains('\0') {
                         sess.emit_err(errors::RawDylibNoNul { span: name_span });
                     }
-                    foreign_mod_items
+                    foreign_items
                         .iter()
-                        .map(|child_item| {
+                        .map(|&child_item| {
                             self.build_dll_import(
                                 abi,
                                 import_name_type.map(|(import_name_type, _)| import_name_type),
@@ -352,21 +347,12 @@ impl<'tcx> Collector<'tcx> {
                         .collect()
                 }
                 _ => {
-                    for child_item in foreign_mod_items {
-                        if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs()
-                            && self
-                                .tcx
-                                .codegen_fn_attrs(child_item.id.owner_id)
-                                .link_ordinal
-                                .is_some()
+                    for &child_item in foreign_items {
+                        if self.tcx.def_kind(child_item).has_codegen_attrs()
+                            && self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some()
                         {
-                            let link_ordinal_attr = self
-                                .tcx
-                                .hir()
-                                .attrs(child_item.id.owner_id.into())
-                                .iter()
-                                .find(|a| a.has_name(sym::link_ordinal))
-                                .unwrap();
+                            let link_ordinal_attr =
+                                self.tcx.get_attr(child_item, sym::link_ordinal).unwrap();
                             sess.emit_err(errors::LinkOrdinalRawDylib {
                                 span: link_ordinal_attr.span,
                             });
@@ -384,7 +370,7 @@ impl<'tcx> Collector<'tcx> {
                 filename,
                 kind,
                 cfg,
-                foreign_module: Some(it.owner_id.to_def_id()),
+                foreign_module: Some(def_id.to_def_id()),
                 verbatim,
                 dll_imports,
             });
@@ -476,10 +462,10 @@ impl<'tcx> Collector<'tcx> {
         }
     }
 
-    fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
+    fn i686_arg_list_size(&self, item: DefId) -> usize {
         let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
             self.tcx
-                .type_of(item.id.owner_id)
+                .type_of(item)
                 .instantiate_identity()
                 .fn_sig(self.tcx)
                 .inputs()
@@ -505,8 +491,10 @@ impl<'tcx> Collector<'tcx> {
         &self,
         abi: Abi,
         import_name_type: Option<PeImportNameType>,
-        item: &hir::ForeignItemRef,
+        item: DefId,
     ) -> DllImport {
+        let span = self.tcx.def_span(item);
+
         let calling_convention = if self.tcx.sess.target.arch == "x86" {
             match abi {
                 Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
@@ -520,29 +508,29 @@ impl<'tcx> Collector<'tcx> {
                     DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
                 }
                 _ => {
-                    self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
+                    self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span });
                 }
             }
         } else {
             match abi {
                 Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
                 _ => {
-                    self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
+                    self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span });
                 }
             }
         };
 
-        let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id);
+        let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item);
         let import_name_type = codegen_fn_attrs
             .link_ordinal
             .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord)));
 
         DllImport {
-            name: codegen_fn_attrs.link_name.unwrap_or(item.ident.name),
+            name: codegen_fn_attrs.link_name.unwrap_or(self.tcx.item_name(item)),
             import_name_type,
             calling_convention,
-            span: item.span,
-            is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(),
+            span,
+            is_fn: self.tcx.def_kind(item).is_fn_like(),
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 8fa1d365728..9e67bb655d4 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -34,7 +34,7 @@ use rustc_session::cstore::{
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnIndex;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{self, BytePos, ExpnId, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
 
 use proc_macro::bridge::client::ProcMacro;
 use std::iter::TrustedLen;
@@ -513,11 +513,26 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
+        let mode = SpanEncodingMode::decode(decoder);
+        let data = match mode {
+            SpanEncodingMode::Direct => SpanData::decode(decoder),
+            SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| {
+                let mode = SpanEncodingMode::decode(decoder);
+                debug_assert!(matches!(mode, SpanEncodingMode::Direct));
+                SpanData::decode(decoder)
+            }),
+        };
+        Span::new(data.lo, data.hi, data.ctxt, data.parent)
+    }
+}
+
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData {
         let ctxt = SyntaxContext::decode(decoder);
         let tag = u8::decode(decoder);
 
         if tag == TAG_PARTIAL_SPAN {
-            return DUMMY_SP.with_ctxt(ctxt);
+            return DUMMY_SP.with_ctxt(ctxt).data();
         }
 
         debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
@@ -612,7 +627,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
         let hi = hi + source_file.translated_source_file.start_pos;
 
         // Do not try to decode parent for foreign spans.
-        Span::new(lo, hi, ctxt, None)
+        SpanData { lo, hi, ctxt, parent: None }
     }
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 848535fb395..a8815ee0908 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -403,10 +403,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
                         .contains(&id)
                 })
         },
-        native_libraries: |tcx, LocalCrate| native_libs::collect(tcx),
-        foreign_modules: |tcx, LocalCrate| {
-            foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect()
-        },
+        native_libraries: native_libs::collect,
+        foreign_modules: foreign_modules::collect,
 
         // Returns a map from a sufficiently visible external item (i.e., an
         // external item that is visible from at least one local module) to a
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b5f955d14fb..ac86110f2bd 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -37,7 +37,7 @@ use rustc_session::config::{CrateType, OptLevel};
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
@@ -53,6 +53,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
     tables: TableBuilders,
 
     lazy_state: LazyState,
+    span_shorthands: FxHashMap<Span, usize>,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
 
@@ -177,8 +178,20 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        let span = self.data();
+        match s.span_shorthands.entry(*self) {
+            Entry::Occupied(o) => SpanEncodingMode::Shorthand(*o.get()).encode(s),
+            Entry::Vacant(v) => {
+                let position = s.opaque.position();
+                v.insert(position);
+                SpanEncodingMode::Direct.encode(s);
+                self.data().encode(s);
+            }
+        }
+    }
+}
 
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
         // Don't serialize any `SyntaxContext`s from a proc-macro crate,
         // since we don't load proc-macro dependencies during serialization.
         // This means that any hygiene information from macros used *within*
@@ -213,7 +226,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         if s.is_proc_macro {
             SyntaxContext::root().encode(s);
         } else {
-            span.ctxt.encode(s);
+            self.ctxt.encode(s);
         }
 
         if self.is_dummy() {
@@ -221,18 +234,18 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         }
 
         // The Span infrastructure should make sure that this invariant holds:
-        debug_assert!(span.lo <= span.hi);
+        debug_assert!(self.lo <= self.hi);
 
-        if !s.source_file_cache.0.contains(span.lo) {
+        if !s.source_file_cache.0.contains(self.lo) {
             let source_map = s.tcx.sess.source_map();
-            let source_file_index = source_map.lookup_source_file_idx(span.lo);
+            let source_file_index = source_map.lookup_source_file_idx(self.lo);
             s.source_file_cache =
                 (source_map.files()[source_file_index].clone(), source_file_index);
         }
         let (ref source_file, source_file_index) = s.source_file_cache;
-        debug_assert!(source_file.contains(span.lo));
+        debug_assert!(source_file.contains(self.lo));
 
-        if !source_file.contains(span.hi) {
+        if !source_file.contains(self.hi) {
             // Unfortunately, macro expansion still sometimes generates Spans
             // that malformed in this way.
             return TAG_PARTIAL_SPAN.encode(s);
@@ -286,11 +299,11 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
 
         // Encode the start position relative to the file start, so we profit more from the
         // variable-length integer encoding.
-        let lo = span.lo - source_file.start_pos;
+        let lo = self.lo - source_file.start_pos;
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
-        let len = span.hi - span.lo;
+        let len = self.hi - self.lo;
 
         tag.encode(s);
         lo.encode(s);
@@ -608,7 +621,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 trace!("encoding {} further alloc ids", new_n - n);
                 for idx in n..new_n {
                     let id = self.interpret_allocs[idx];
-                    let pos = self.position() as u32;
+                    let pos = self.position() as u64;
                     interpret_alloc_index.push(pos);
                     interpret::specialized_encode_alloc_id(self, tcx, id);
                 }
@@ -2182,6 +2195,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
         feat: tcx.features(),
         tables: Default::default(),
         lazy_state: LazyState::NoNode,
+        span_shorthands: Default::default(),
         type_shorthands: Default::default(),
         predicate_shorthands: Default::default(),
         source_file_cache,
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9cffd96f4a3..0bc16fc64ff 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -66,6 +66,12 @@ const METADATA_VERSION: u8 = 8;
 /// unsigned integer, and further followed by the rustc version string.
 pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
+#[derive(Encodable, Decodable)]
+enum SpanEncodingMode {
+    Shorthand(usize),
+    Direct,
+}
+
 /// A value of type T referred to by its absolute position
 /// in the metadata, and which can be decoded lazily.
 ///
@@ -264,7 +270,7 @@ pub(crate) struct CrateRoot {
     traits: LazyArray<DefIndex>,
     impls: LazyArray<TraitImpls>,
     incoherent_impls: LazyArray<IncoherentImpls>,
-    interpret_alloc_index: LazyArray<u32>,
+    interpret_alloc_index: LazyArray<u64>,
     proc_macro_data: Option<ProcMacroData>,
 
     tables: LazyTables,
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 20230217afc..6ce1ad8f43e 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -278,6 +278,7 @@ pub fn explain_lint_level_source(
 ///     //          ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default
 /// )
 /// ```
+#[track_caller]
 pub fn struct_lint_level(
     sess: &Session,
     lint: &'static Lint,
@@ -291,6 +292,7 @@ pub fn struct_lint_level(
 ) {
     // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
     // the "real" work.
+    #[track_caller]
     fn struct_lint_level_impl(
         sess: &Session,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index c4601a1fb41..02fd6ed7ba6 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -100,6 +100,8 @@ bitflags! {
         const REALLOCATOR               = 1 << 18;
         /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
         const ALLOCATOR_ZEROED          = 1 << 19;
+        /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
+        const NO_BUILTINS               = 1 << 20;
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index fbd667a87fe..69c15e9cc06 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -274,7 +274,7 @@ pub struct AllocDecodingState {
     // For each `AllocId`, we keep track of which decoding state it's currently in.
     decoding_state: Vec<Lock<State>>,
     // The offsets of each allocation in the data stream.
-    data_offsets: Vec<u32>,
+    data_offsets: Vec<u64>,
 }
 
 impl AllocDecodingState {
@@ -289,7 +289,7 @@ impl AllocDecodingState {
         AllocDecodingSession { state: self, session_id }
     }
 
-    pub fn new(data_offsets: Vec<u32>) -> Self {
+    pub fn new(data_offsets: Vec<u64>) -> Self {
         let decoding_state =
             std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect();
 
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ca3cd943d3d..f4133dfbc95 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -56,15 +56,24 @@ impl<'tcx> MonoItem<'tcx> {
         }
     }
 
+    // Note: if you change how item size estimates work, you might need to
+    // change NON_INCR_MIN_CGU_SIZE as well.
     pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
         match *self {
             MonoItem::Fn(instance) => {
-                // Estimate the size of a function based on how many statements
-                // it contains.
-                tcx.instance_def_size_estimate(instance.def)
+                match instance.def {
+                    // "Normal" functions size estimate: the number of
+                    // statements, plus one for the terminator.
+                    InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
+                        let mir = tcx.instance_mir(instance.def);
+                        mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
+                    }
+                    // Other compiler-generated shims size estimate: 1
+                    _ => 1,
+                }
             }
-            // Conservatively estimate the size of a static declaration
-            // or assembly to be 1.
+            // Conservatively estimate the size of a static declaration or
+            // assembly item to be 1.
             MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
         }
     }
@@ -230,7 +239,7 @@ pub struct CodegenUnit<'tcx> {
     /// contain something unique to this crate (e.g., a module path)
     /// as well as the crate name and disambiguator.
     name: Symbol,
-    items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
+    items: FxHashMap<MonoItem<'tcx>, MonoItemData>,
     size_estimate: usize,
     primary: bool,
     /// True if this is CGU is used to hold code coverage information for dead code,
@@ -238,6 +247,20 @@ pub struct CodegenUnit<'tcx> {
     is_code_coverage_dead_code_cgu: bool,
 }
 
+/// Auxiliary info about a `MonoItem`.
+#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+pub struct MonoItemData {
+    /// A cached copy of the result of `MonoItem::instantiation_mode`, where
+    /// `GloballyShared` maps to `false` and `LocalCopy` maps to `true`.
+    pub inlined: bool,
+
+    pub linkage: Linkage,
+    pub visibility: Visibility,
+
+    /// A cached copy of the result of `MonoItem::size_estimate`.
+    pub size_estimate: usize,
+}
+
 /// Specifies the linkage type for a `MonoItem`.
 ///
 /// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
@@ -292,12 +315,12 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 
     /// The order of these items is non-determinstic.
-    pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
+    pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, MonoItemData> {
         &self.items
     }
 
     /// The order of these items is non-determinstic.
-    pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
+    pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, MonoItemData> {
         &mut self.items
     }
 
@@ -320,16 +343,16 @@ impl<'tcx> CodegenUnit<'tcx> {
         base_n::encode(hash, base_n::CASE_INSENSITIVE)
     }
 
-    pub fn compute_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
-        // Estimate the size of a codegen unit as (approximately) the number of MIR
-        // statements it corresponds to.
-        self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum();
+    pub fn compute_size_estimate(&mut self) {
+        // The size of a codegen unit as the sum of the sizes of the items
+        // within it.
+        self.size_estimate = self.items.values().map(|data| data.size_estimate).sum();
     }
 
-    #[inline]
     /// Should only be called if [`compute_size_estimate`] has previously been called.
     ///
     /// [`compute_size_estimate`]: Self::compute_size_estimate
+    #[inline]
     pub fn size_estimate(&self) -> usize {
         // Items are never zero-sized, so if we have items the estimate must be
         // non-zero, unless we forgot to call `compute_size_estimate` first.
@@ -355,7 +378,7 @@ impl<'tcx> CodegenUnit<'tcx> {
     pub fn items_in_deterministic_order(
         &self,
         tcx: TyCtxt<'tcx>,
-    ) -> Vec<(MonoItem<'tcx>, (Linkage, Visibility))> {
+    ) -> Vec<(MonoItem<'tcx>, MonoItemData)> {
         // The codegen tests rely on items being process in the same order as
         // they appear in the file, so for local items, we sort by node_id first
         #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -390,7 +413,7 @@ impl<'tcx> CodegenUnit<'tcx> {
             )
         }
 
-        let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
+        let mut items: Vec<_> = self.items().iter().map(|(&i, &data)| (i, data)).collect();
         items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
         items
     }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 8f5f92f80d8..b36f0df78f1 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1583,7 +1583,7 @@ rustc_queries! {
     }
 
     /// Returns a list of all `extern` blocks of a crate.
-    query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> {
+    query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap<DefId, ForeignModule> {
         arena_cache
         desc { "looking up the foreign modules of a linked crate" }
         separate_provide_extern
@@ -2084,12 +2084,6 @@ rustc_queries! {
         desc { "looking up supported target features" }
     }
 
-    /// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
-    query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
-        -> usize {
-        desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
-    }
-
     query features_query(_: ()) -> &'tcx rustc_feature::Features {
         feedable
         desc { "looking up enabled feature gates" }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 8751d3b7890..995b2140f61 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -104,7 +104,9 @@ struct Footer {
     query_result_index: EncodedDepNodeIndex,
     side_effects_index: EncodedDepNodeIndex,
     // The location of all allocations.
-    interpret_alloc_index: Vec<u32>,
+    // Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64
+    // without measurable overhead. This permits larger const allocations without ICEing.
+    interpret_alloc_index: Vec<u64>,
     // See `OnDiskCache.syntax_contexts`
     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
     // See `OnDiskCache.expn_data`
@@ -301,7 +303,7 @@ impl<'sess> OnDiskCache<'sess> {
                     interpret_alloc_index.reserve(new_n - n);
                     for idx in n..new_n {
                         let id = encoder.interpret_allocs[idx];
-                        let pos: u32 = encoder.position().try_into().unwrap();
+                        let pos: u64 = encoder.position().try_into().unwrap();
                         interpret_alloc_index.push(pos);
                         interpret::specialized_encode_alloc_id(&mut encoder, tcx, id);
                     }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index bf9f5846ed9..4ef70107f19 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -294,6 +294,14 @@ impl<'tcx> Const<'tcx> {
         Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
     }
 
+    /// Attempts to convert to a `ValTree`
+    pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
+        match self.kind() {
+            ty::ConstKind::Value(valtree) => Some(valtree),
+            _ => None,
+        }
+    }
+
     #[inline]
     /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
     /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 8b96864ddd7..fb7bf78bafe 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -24,7 +24,7 @@ pub enum ValTree<'tcx> {
     Leaf(ScalarInt),
 
     //SliceOrStr(ValSlice<'tcx>),
-    // dont use SliceOrStr for now
+    // don't use SliceOrStr for now
     /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
     /// listing their fields' values in order.
     ///
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8bb13edbe95..1a23fa80210 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1860,6 +1860,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
     /// typically generated by `#[derive(LintDiagnostic)]`).
+    #[track_caller]
     pub fn emit_spanned_lint(
         self,
         lint: &'static Lint,
@@ -1880,6 +1881,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_lint_hir(
         self,
         lint: &'static Lint,
@@ -1896,6 +1898,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
     /// generated by `#[derive(LintDiagnostic)]`).
+    #[track_caller]
     pub fn emit_lint(
         self,
         lint: &'static Lint,
@@ -1911,6 +1914,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_lint_node(
         self,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index e86ff4d26aa..668aa4521c1 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -6,35 +6,33 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::iter;
 
-use self::SimplifiedType::*;
-
 /// See `simplify_type`.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub enum SimplifiedType {
-    BoolSimplifiedType,
-    CharSimplifiedType,
-    IntSimplifiedType(ty::IntTy),
-    UintSimplifiedType(ty::UintTy),
-    FloatSimplifiedType(ty::FloatTy),
-    AdtSimplifiedType(DefId),
-    ForeignSimplifiedType(DefId),
-    StrSimplifiedType,
-    ArraySimplifiedType,
-    SliceSimplifiedType,
-    RefSimplifiedType(Mutability),
-    PtrSimplifiedType(Mutability),
-    NeverSimplifiedType,
-    TupleSimplifiedType(usize),
+    Bool,
+    Char,
+    Int(ty::IntTy),
+    Uint(ty::UintTy),
+    Float(ty::FloatTy),
+    Adt(DefId),
+    Foreign(DefId),
+    Str,
+    Array,
+    Slice,
+    Ref(Mutability),
+    Ptr(Mutability),
+    Never,
+    Tuple(usize),
     /// A trait object, all of whose components are markers
     /// (e.g., `dyn Send + Sync`).
-    MarkerTraitObjectSimplifiedType,
-    TraitSimplifiedType(DefId),
-    ClosureSimplifiedType(DefId),
-    GeneratorSimplifiedType(DefId),
-    GeneratorWitnessSimplifiedType(usize),
-    GeneratorWitnessMIRSimplifiedType(DefId),
-    FunctionSimplifiedType(usize),
-    PlaceholderSimplifiedType,
+    MarkerTraitObject,
+    Trait(DefId),
+    Closure(DefId),
+    Generator(DefId),
+    GeneratorWitness(usize),
+    GeneratorWitnessMIR(DefId),
+    Function(usize),
+    Placeholder,
 }
 
 /// Generic parameters are pretty much just bound variables, e.g.
@@ -64,6 +62,9 @@ pub enum TreatParams {
     /// correct mode for *lookup*, as during candidate selection.
     ///
     /// N.B. during deep rejection, this acts identically to `ForLookup`.
+    ///
+    /// FIXME(-Ztrait-solver=next): Remove this variant and cleanup
+    /// the code.
     NextSolverLookup,
 }
 
@@ -110,34 +111,36 @@ pub fn simplify_type<'tcx>(
     treat_params: TreatParams,
 ) -> Option<SimplifiedType> {
     match *ty.kind() {
-        ty::Bool => Some(BoolSimplifiedType),
-        ty::Char => Some(CharSimplifiedType),
-        ty::Int(int_type) => Some(IntSimplifiedType(int_type)),
-        ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)),
-        ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
-        ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())),
-        ty::Str => Some(StrSimplifiedType),
-        ty::Array(..) => Some(ArraySimplifiedType),
-        ty::Slice(..) => Some(SliceSimplifiedType),
-        ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)),
+        ty::Bool => Some(SimplifiedType::Bool),
+        ty::Char => Some(SimplifiedType::Char),
+        ty::Int(int_type) => Some(SimplifiedType::Int(int_type)),
+        ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)),
+        ty::Float(float_type) => Some(SimplifiedType::Float(float_type)),
+        ty::Adt(def, _) => Some(SimplifiedType::Adt(def.did())),
+        ty::Str => Some(SimplifiedType::Str),
+        ty::Array(..) => Some(SimplifiedType::Array),
+        ty::Slice(..) => Some(SimplifiedType::Slice),
+        ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)),
         ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
             Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
-                Some(TraitSimplifiedType(principal_def_id))
+                Some(SimplifiedType::Trait(principal_def_id))
             }
-            _ => Some(MarkerTraitObjectSimplifiedType),
+            _ => Some(SimplifiedType::MarkerTraitObject),
         },
-        ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)),
-        ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
-        ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
-        ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())),
-        ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)),
-        ty::Never => Some(NeverSimplifiedType),
-        ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
-        ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
-        ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
+        ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)),
+        ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)),
+        ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)),
+        ty::GeneratorWitness(tys) => {
+            Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len()))
+        }
+        ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)),
+        ty::Never => Some(SimplifiedType::Never),
+        ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
+        ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())),
+        ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
         ty::Param(_) => match treat_params {
             TreatParams::ForLookup | TreatParams::NextSolverLookup => {
-                Some(PlaceholderSimplifiedType)
+                Some(SimplifiedType::Placeholder)
             }
             TreatParams::AsCandidateKey => None,
         },
@@ -147,11 +150,13 @@ pub fn simplify_type<'tcx>(
             //
             // We will have to be careful with lazy normalization here.
             // FIXME(lazy_normalization): This is probably not right...
-            TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType),
-            TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType),
+            TreatParams::ForLookup if !ty.has_non_region_infer() => {
+                Some(SimplifiedType::Placeholder)
+            }
+            TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder),
             TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
         },
-        ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
+        ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
         ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
     }
 }
@@ -159,12 +164,12 @@ pub fn simplify_type<'tcx>(
 impl SimplifiedType {
     pub fn def(self) -> Option<DefId> {
         match self {
-            AdtSimplifiedType(d)
-            | ForeignSimplifiedType(d)
-            | TraitSimplifiedType(d)
-            | ClosureSimplifiedType(d)
-            | GeneratorSimplifiedType(d)
-            | GeneratorWitnessMIRSimplifiedType(d) => Some(d),
+            SimplifiedType::Adt(d)
+            | SimplifiedType::Foreign(d)
+            | SimplifiedType::Trait(d)
+            | SimplifiedType::Closure(d)
+            | SimplifiedType::Generator(d)
+            | SimplifiedType::GeneratorWitnessMIR(d) => Some(d),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 12af8456494..97dab5cb47e 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -610,8 +610,12 @@ impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
 where
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
 {
-    pub fn arg_iter(self, tcx: TyCtxt<'tcx>, args: &'s [GenericArg<'tcx>]) -> ArgIter<'s, 'tcx, I> {
-        ArgIter { it: self.value.into_iter(), tcx, args }
+    pub fn iter_instantiated(
+        self,
+        tcx: TyCtxt<'tcx>,
+        args: &'s [GenericArg<'tcx>],
+    ) -> IterInstantiated<'s, 'tcx, I> {
+        IterInstantiated { it: self.value.into_iter(), tcx, args }
     }
 
     /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
@@ -621,13 +625,13 @@ where
     }
 }
 
-pub struct ArgIter<'s, 'tcx, I: IntoIterator> {
+pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> {
     it: I::IntoIter,
     tcx: TyCtxt<'tcx>,
     args: &'s [GenericArg<'tcx>],
 }
 
-impl<'tcx, I: IntoIterator> Iterator for ArgIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I>
 where
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
 {
@@ -642,7 +646,7 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I>
 where
     I::IntoIter: DoubleEndedIterator,
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
@@ -652,7 +656,7 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I>
 where
     I::IntoIter: ExactSizeIterator,
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
@@ -664,12 +668,12 @@ where
     I::Item: Deref,
     <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
 {
-    pub fn arg_iter_copied(
+    pub fn iter_instantiated_copied(
         self,
         tcx: TyCtxt<'tcx>,
         args: &'s [GenericArg<'tcx>],
-    ) -> ArgIterCopied<'s, 'tcx, I> {
-        ArgIterCopied { it: self.value.into_iter(), tcx, args }
+    ) -> IterInstantiatedCopied<'s, 'tcx, I> {
+        IterInstantiatedCopied { it: self.value.into_iter(), tcx, args }
     }
 
     /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
@@ -681,13 +685,13 @@ where
     }
 }
 
-pub struct ArgIterCopied<'a, 'tcx, I: IntoIterator> {
+pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> {
     it: I::IntoIter,
     tcx: TyCtxt<'tcx>,
     args: &'a [GenericArg<'tcx>],
 }
 
-impl<'tcx, I: IntoIterator> Iterator for ArgIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I>
 where
     I::Item: Deref,
     <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
@@ -703,7 +707,7 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I>
 where
     I::IntoIter: DoubleEndedIterator,
     I::Item: Deref,
@@ -716,7 +720,7 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I>
 where
     I::IntoIter: ExactSizeIterator,
     I::Item: Deref,
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 338590717d0..70a35f137d8 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -347,7 +347,7 @@ impl<'tcx> GenericPredicates<'tcx> {
         tcx: TyCtxt<'tcx>,
         args: GenericArgsRef<'tcx>,
     ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
-        EarlyBinder::bind(self.predicates).arg_iter_copied(tcx, args)
+        EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
     }
 
     #[instrument(level = "debug", skip(self, tcx))]
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index cc2b26a5e14..f1c38984296 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -52,6 +52,7 @@ trivially_parameterized_over_tcx! {
     usize,
     (),
     u32,
+    u64,
     bool,
     std::string::String,
     crate::metadata::ModChild,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3591acdea56..e5633223464 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>:
         let mut is_sized = false;
         let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
 
-        for (predicate, _) in bounds.arg_iter_copied(tcx, args) {
+        for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
@@ -1932,7 +1932,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
         self.empty_path = true;
         if cnum == LOCAL_CRATE {
-            if self.tcx.sess.rust_2018() {
+            if self.tcx.sess.at_least_rust_2018() {
                 // We add the `crate::` keyword on Rust 2018, only when desired.
                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
                     write!(self, "{}", kw::Crate)?;
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 66d8a79de42..f9c1ca9a8b1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -15,7 +15,6 @@ use hir::def::DefKind;
 use polonius_engine::Atom;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
-use rustc_error_messages::DiagnosticMessage;
 use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -1313,7 +1312,7 @@ impl<'tcx> AliasTy<'tcx> {
     ///     I_i impl subst
     ///     P_j GAT subst
     /// ```
-    pub fn rebase_args_onto_impl(
+    pub fn rebase_inherent_args_onto_impl(
         self,
         impl_args: ty::GenericArgsRef<'tcx>,
         tcx: TyCtxt<'tcx>,
@@ -1991,7 +1990,7 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_error_with_message<S: Into<MultiSpan>>(
         tcx: TyCtxt<'tcx>,
         span: S,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<String>,
     ) -> Ty<'tcx> {
         let reported = tcx.sess.delay_span_bug(span, msg);
         Ty::new(tcx, Error(reported))
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b4852ab8881..553b76cad4e 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -19,7 +19,7 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_macros::HashStable;
 use rustc_session::Limit;
 use rustc_span::sym;
-use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
+use rustc_target::abi::{Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::{fmt, iter};
@@ -1085,7 +1085,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
-        match needs_drop_components(self, &tcx.data_layout) {
+        match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
             Ok(components) => {
                 let query_ty = match *components {
@@ -1118,7 +1118,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
-        match needs_drop_components(self, &tcx.data_layout) {
+        match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
             Ok(components) => {
                 let query_ty = match *components {
@@ -1278,10 +1278,10 @@ impl<'tcx> ExplicitSelf<'tcx> {
 /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
 /// this type always needs drop.
 pub fn needs_drop_components<'tcx>(
+    tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
-    target_layout: &TargetDataLayout,
 ) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
-    match ty.kind() {
+    match *ty.kind() {
         ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
         | ty::Bool
@@ -1303,11 +1303,11 @@ pub fn needs_drop_components<'tcx>(
 
         ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
 
-        ty::Slice(ty) => needs_drop_components(*ty, target_layout),
+        ty::Slice(ty) => needs_drop_components(tcx, ty),
         ty::Array(elem_ty, size) => {
-            match needs_drop_components(*elem_ty, target_layout) {
+            match needs_drop_components(tcx, elem_ty) {
                 Ok(v) if v.is_empty() => Ok(v),
-                res => match size.try_to_bits(target_layout.pointer_size) {
+                res => match size.try_to_target_usize(tcx) {
                     // Arrays of size zero don't need drop, even if their element
                     // type does.
                     Some(0) => Ok(SmallVec::new()),
@@ -1321,7 +1321,7 @@ pub fn needs_drop_components<'tcx>(
         }
         // If any field needs drop, then the whole tuple does.
         ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| {
-            acc.extend(needs_drop_components(elem, target_layout)?);
+            acc.extend(needs_drop_components(tcx, elem)?);
             Ok(acc)
         }),
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index c122230b841..7756d5d4879 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -730,5 +730,5 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
 /// Precise capture is enabled if user is using Rust Edition 2021 or higher.
 fn enable_precise_capture(closure_span: Span) -> bool {
-    closure_span.rust_2021()
+    closure_span.at_least_rust_2021()
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 9662c19777f..34e0834a68b 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -88,7 +88,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
     }
 }
 
-struct TransferFunction<'a, T>(&'a mut T);
+pub struct TransferFunction<'a, T>(pub &'a mut T);
 
 impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T>
 where
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 633b99a332b..7ddd01e34aa 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -26,6 +26,7 @@ pub use self::borrowed_locals::borrowed_locals;
 pub use self::borrowed_locals::MaybeBorrowedLocals;
 pub use self::liveness::MaybeLiveLocals;
 pub use self::liveness::MaybeTransitiveLiveLocals;
+pub use self::liveness::TransferFunction as LivenessTransferFunction;
 pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
 
 /// `MaybeInitializedPlaces` tracks all places that might be
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 7bc5183a00a..3f988930b5e 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -13,9 +13,12 @@
 //!
 
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
-use rustc_mir_dataflow::impls::{borrowed_locals, MaybeTransitiveLiveLocals};
+use rustc_mir_dataflow::impls::{
+    borrowed_locals, LivenessTransferFunction, MaybeTransitiveLiveLocals,
+};
 use rustc_mir_dataflow::Analysis;
 
 /// Performs the optimization on the body
@@ -28,8 +31,33 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
         .iterate_to_fixpoint()
         .into_results_cursor(body);
 
+    // For blocks with a call terminator, if an argument copy can be turned into a move,
+    // record it as (block, argument index).
+    let mut call_operands_to_move = Vec::new();
     let mut patch = Vec::new();
+
     for (bb, bb_data) in traversal::preorder(body) {
+        if let TerminatorKind::Call { ref args, .. } = bb_data.terminator().kind {
+            let loc = Location { block: bb, statement_index: bb_data.statements.len() };
+
+            // Position ourselves between the evaluation of `args` and the write to `destination`.
+            live.seek_to_block_end(bb);
+            let mut state = live.get().clone();
+
+            for (index, arg) in args.iter().enumerate().rev() {
+                if let Operand::Copy(place) = *arg
+                    && !place.is_indirect()
+                    && !borrowed.contains(place.local)
+                    && !state.contains(place.local)
+                {
+                    call_operands_to_move.push((bb, index));
+                }
+
+                // Account that `arg` is read from, so we don't promote another argument to a move.
+                LivenessTransferFunction(&mut state).visit_operand(arg, loc);
+            }
+        }
+
         for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
             let loc = Location { block: bb, statement_index };
             if let StatementKind::Assign(assign) = &statement.kind {
@@ -64,7 +92,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
         }
     }
 
-    if patch.is_empty() {
+    if patch.is_empty() && call_operands_to_move.is_empty() {
         return;
     }
 
@@ -72,6 +100,14 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
     for Location { block, statement_index } in patch {
         bbs[block].statements[statement_index].make_nop();
     }
+    for (block, argument_index) in call_operands_to_move {
+        let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else {
+            bug!()
+        };
+        let arg = &mut args[argument_index];
+        let Operand::Copy(place) = *arg else { bug!() };
+        *arg = Operand::Move(place);
+    }
 
     crate::simplify::simplify_locals(body, tcx)
 }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 391666554bb..71aef53192f 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -107,7 +107,8 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
 use rustc_middle::mir;
 use rustc_middle::mir::mono::{
-    CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, Visibility,
+    CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
+    Visibility,
 };
 use rustc_middle::query::Providers;
 use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
@@ -130,11 +131,6 @@ struct PlacedMonoItems<'tcx> {
     codegen_units: Vec<CodegenUnit<'tcx>>,
 
     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-
-    /// These must be obtained when the iterator in `partition` runs. They
-    /// can't be obtained later because some inlined functions might not be
-    /// reachable.
-    unique_inlined_stats: (usize, usize),
 }
 
 // The output CGUs are sorted by name.
@@ -152,11 +148,11 @@ where
 
     // Place all mono items into a codegen unit. `place_mono_items` is
     // responsible for initializing the CGU size estimates.
-    let PlacedMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = {
+    let PlacedMonoItems { mut codegen_units, internalization_candidates } = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_items");
         let placed = place_mono_items(cx, mono_items);
 
-        debug_dump(tcx, "PLACE", &placed.codegen_units, placed.unique_inlined_stats);
+        debug_dump(tcx, "PLACE", &placed.codegen_units);
 
         placed
     };
@@ -167,7 +163,7 @@ where
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
         merge_codegen_units(cx, &mut codegen_units);
-        debug_dump(tcx, "MERGE", &codegen_units, unique_inlined_stats);
+        debug_dump(tcx, "MERGE", &codegen_units);
     }
 
     // Make as many symbols "internal" as possible, so LLVM has more freedom to
@@ -176,7 +172,7 @@ where
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
         internalize_symbols(cx, &mut codegen_units, internalization_candidates);
 
-        debug_dump(tcx, "INTERNALIZE", &codegen_units, unique_inlined_stats);
+        debug_dump(tcx, "INTERNALIZE", &codegen_units);
     }
 
     // Mark one CGU for dead code, if necessary.
@@ -216,18 +212,12 @@ where
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
     let cgu_name_cache = &mut FxHashMap::default();
 
-    let mut num_unique_inlined_items = 0;
-    let mut unique_inlined_items_size = 0;
     for mono_item in mono_items {
         // Handle only root items directly here. Inlined items are handled at
         // the bottom of the loop based on reachability.
         match mono_item.instantiation_mode(cx.tcx) {
             InstantiationMode::GloballyShared { .. } => {}
-            InstantiationMode::LocalCopy => {
-                num_unique_inlined_items += 1;
-                unique_inlined_items_size += mono_item.size_estimate(cx.tcx);
-                continue;
-            }
+            InstantiationMode::LocalCopy => continue,
         }
 
         let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
@@ -256,8 +246,10 @@ where
         if visibility == Visibility::Hidden && can_be_internalized {
             internalization_candidates.insert(mono_item);
         }
+        let size_estimate = mono_item.size_estimate(cx.tcx);
 
-        cgu.items_mut().insert(mono_item, (linkage, visibility));
+        cgu.items_mut()
+            .insert(mono_item, MonoItemData { inlined: false, linkage, visibility, size_estimate });
 
         // Get all inlined items that are reachable from `mono_item` without
         // going via another root item. This includes drop-glue, functions from
@@ -271,7 +263,12 @@ where
         // the `insert` will be a no-op.
         for inlined_item in reachable_inlined_items {
             // This is a CGU-private copy.
-            cgu.items_mut().insert(inlined_item, (Linkage::Internal, Visibility::Default));
+            cgu.items_mut().entry(inlined_item).or_insert_with(|| MonoItemData {
+                inlined: true,
+                linkage: Linkage::Internal,
+                visibility: Visibility::Default,
+                size_estimate: inlined_item.size_estimate(cx.tcx),
+            });
         }
     }
 
@@ -286,14 +283,10 @@ where
     codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
     for cgu in codegen_units.iter_mut() {
-        cgu.compute_size_estimate(cx.tcx);
+        cgu.compute_size_estimate();
     }
 
-    return PlacedMonoItems {
-        codegen_units,
-        internalization_candidates,
-        unique_inlined_stats: (num_unique_inlined_items, unique_inlined_items_size),
-    };
+    return PlacedMonoItems { codegen_units, internalization_candidates };
 
     fn get_reachable_inlined_items<'tcx>(
         tcx: TyCtxt<'tcx>,
@@ -325,6 +318,60 @@ fn merge_codegen_units<'tcx>(
     let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
         codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
 
+    // If N is the maximum number of CGUs, and the CGUs are sorted from largest
+    // to smallest, we repeatedly find which CGU in codegen_units[N..] has the
+    // greatest overlap of inlined items with codegen_units[N-1], merge that
+    // CGU into codegen_units[N-1], then re-sort by size and repeat.
+    //
+    // We use inlined item overlap to guide this merging because it minimizes
+    // duplication of inlined items, which makes LLVM be faster and generate
+    // better and smaller machine code.
+    //
+    // Why merge into codegen_units[N-1]? We want CGUs to have similar sizes,
+    // which means we don't want codegen_units[0..N] (the already big ones)
+    // getting any bigger, if we can avoid it. When we have more than N CGUs
+    // then at least one of the biggest N will have to grow. codegen_units[N-1]
+    // is the smallest of those, and so has the most room to grow.
+    let max_codegen_units = cx.tcx.sess.codegen_units().as_usize();
+    while codegen_units.len() > max_codegen_units {
+        // Sort small CGUs to the back.
+        codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+
+        let cgu_dst = &codegen_units[max_codegen_units - 1];
+
+        // Find the CGU that overlaps the most with `cgu_dst`. In the case of a
+        // tie, favour the earlier (bigger) CGU.
+        let mut max_overlap = 0;
+        let mut max_overlap_i = max_codegen_units;
+        for (i, cgu_src) in codegen_units.iter().enumerate().skip(max_codegen_units) {
+            if cgu_src.size_estimate() <= max_overlap {
+                // None of the remaining overlaps can exceed `max_overlap`, so
+                // stop looking.
+                break;
+            }
+
+            let overlap = compute_inlined_overlap(cgu_dst, cgu_src);
+            if overlap > max_overlap {
+                max_overlap = overlap;
+                max_overlap_i = i;
+            }
+        }
+
+        let mut cgu_src = codegen_units.swap_remove(max_overlap_i);
+        let cgu_dst = &mut codegen_units[max_codegen_units - 1];
+
+        // Move the items from `cgu_src` to `cgu_dst`. Some of them may be
+        // duplicate inlined items, in which case the destination CGU is
+        // unaffected. Recalculate size estimates afterwards.
+        cgu_dst.items_mut().extend(cgu_src.items_mut().drain());
+        cgu_dst.compute_size_estimate();
+
+        // Record that `cgu_dst` now contains all the stuff that was in
+        // `cgu_src` before.
+        let mut consumed_cgu_names = cgu_contents.remove(&cgu_src.name()).unwrap();
+        cgu_contents.get_mut(&cgu_dst.name()).unwrap().append(&mut consumed_cgu_names);
+    }
+
     // Having multiple CGUs can drastically speed up compilation. But for
     // non-incremental builds, tiny CGUs slow down compilation *and* result in
     // worse generated code. So we don't allow CGUs smaller than this (unless
@@ -332,21 +379,19 @@ fn merge_codegen_units<'tcx>(
     // common in larger programs, so this isn't all that large.
     const NON_INCR_MIN_CGU_SIZE: usize = 1800;
 
-    // Repeatedly merge the two smallest codegen units as long as:
-    // - we have more CGUs than the upper limit, or
-    // - (Non-incremental builds only) the user didn't specify a CGU count, and
-    //   there are multiple CGUs, and some are below the minimum size.
+    // Repeatedly merge the two smallest codegen units as long as: it's a
+    // non-incremental build, and the user didn't specify a CGU count, and
+    // there are multiple CGUs, and some are below the minimum size.
     //
     // The "didn't specify a CGU count" condition is because when an explicit
     // count is requested we observe it as closely as possible. For example,
     // the `compiler_builtins` crate sets `codegen-units = 10000` and it's
     // critical they aren't merged. Also, some tests use explicit small values
     // and likewise won't work if small CGUs are merged.
-    while codegen_units.len() > cx.tcx.sess.codegen_units().as_usize()
-        || (cx.tcx.sess.opts.incremental.is_none()
-            && matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
-            && codegen_units.len() > 1
-            && codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE))
+    while cx.tcx.sess.opts.incremental.is_none()
+        && matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
+        && codegen_units.len() > 1
+        && codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE)
     {
         // Sort small cgus to the back.
         codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
@@ -358,18 +403,9 @@ fn merge_codegen_units<'tcx>(
         // may be duplicate inlined items, in which case the destination CGU is
         // unaffected. Recalculate size estimates afterwards.
         second_smallest.items_mut().extend(smallest.items_mut().drain());
-        second_smallest.compute_size_estimate(cx.tcx);
+        second_smallest.compute_size_estimate();
 
-        // Record that `second_smallest` now contains all the stuff that was
-        // in `smallest` before.
-        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
-        cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
-
-        debug!(
-            "CodegenUnit {} merged into CodegenUnit {}",
-            smallest.name(),
-            second_smallest.name()
-        );
+        // Don't update `cgu_contents`, that's only for incremental builds.
     }
 
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
@@ -448,6 +484,25 @@ fn merge_codegen_units<'tcx>(
     }
 }
 
+/// Compute the combined size of all inlined items that appear in both `cgu1`
+/// and `cgu2`.
+fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'tcx>) -> usize {
+    // Either order works. We pick the one that involves iterating over fewer
+    // items.
+    let (src_cgu, dst_cgu) =
+        if cgu1.items().len() <= cgu2.items().len() { (cgu1, cgu2) } else { (cgu2, cgu1) };
+
+    let mut overlap = 0;
+    for (item, data) in src_cgu.items().iter() {
+        if data.inlined {
+            if dst_cgu.items().contains_key(item) {
+                overlap += data.size_estimate;
+            }
+        }
+    }
+    overlap
+}
+
 fn internalize_symbols<'tcx>(
     cx: &PartitioningCx<'_, 'tcx>,
     codegen_units: &mut [CodegenUnit<'tcx>],
@@ -492,7 +547,7 @@ fn internalize_symbols<'tcx>(
     for cgu in codegen_units {
         let home_cgu = MonoItemPlacement::SingleCgu(cgu.name());
 
-        for (item, linkage_and_visibility) in cgu.items_mut() {
+        for (item, data) in cgu.items_mut() {
             if !internalization_candidates.contains(item) {
                 // This item is no candidate for internalizing, so skip it.
                 continue;
@@ -520,7 +575,8 @@ fn internalize_symbols<'tcx>(
 
             // If we got here, we did not find any uses from other CGUs, so
             // it's fine to make this monomorphization internal.
-            *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
+            data.linkage = Linkage::Internal;
+            data.visibility = Visibility::Default;
         }
     }
 }
@@ -537,7 +593,7 @@ fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>
     // function symbols to be included via `-u` or `/include` linker args.
     let dead_code_cgu = codegen_units
         .iter_mut()
-        .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External))
+        .filter(|cgu| cgu.items().iter().any(|(_, data)| data.linkage == Linkage::External))
         .min_by_key(|cgu| cgu.size_estimate());
 
     // If there are no CGUs that have externally linked items, then we just
@@ -851,12 +907,7 @@ fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibilit
     }
 }
 
-fn debug_dump<'a, 'tcx: 'a>(
-    tcx: TyCtxt<'tcx>,
-    label: &str,
-    cgus: &[CodegenUnit<'tcx>],
-    (unique_inlined_items, unique_inlined_size): (usize, usize),
-) {
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
     let dump = move || {
         use std::fmt::Write;
 
@@ -865,29 +916,34 @@ fn debug_dump<'a, 'tcx: 'a>(
 
         // Note: every unique root item is placed exactly once, so the number
         // of unique root items always equals the number of placed root items.
+        //
+        // Also, unreached inlined items won't be counted here. This is fine.
+
+        let mut inlined_items = FxHashSet::default();
 
         let mut root_items = 0;
-        // unique_inlined_items is passed in above.
+        let mut unique_inlined_items = 0;
         let mut placed_inlined_items = 0;
 
         let mut root_size = 0;
-        // unique_inlined_size is passed in above.
+        let mut unique_inlined_size = 0;
         let mut placed_inlined_size = 0;
 
         for cgu in cgus.iter() {
             num_cgus += 1;
             all_cgu_sizes.push(cgu.size_estimate());
 
-            for (item, _) in cgu.items() {
-                match item.instantiation_mode(tcx) {
-                    InstantiationMode::GloballyShared { .. } => {
-                        root_items += 1;
-                        root_size += item.size_estimate(tcx);
-                    }
-                    InstantiationMode::LocalCopy => {
-                        placed_inlined_items += 1;
-                        placed_inlined_size += item.size_estimate(tcx);
+            for (item, data) in cgu.items() {
+                if !data.inlined {
+                    root_items += 1;
+                    root_size += data.size_estimate;
+                } else {
+                    if inlined_items.insert(item) {
+                        unique_inlined_items += 1;
+                        unique_inlined_size += data.size_estimate;
                     }
+                    placed_inlined_items += 1;
+                    placed_inlined_size += data.size_estimate;
                 }
             }
         }
@@ -928,7 +984,7 @@ fn debug_dump<'a, 'tcx: 'a>(
             let mean_size = size as f64 / num_items as f64;
 
             let mut placed_item_sizes: Vec<_> =
-                cgu.items().iter().map(|(item, _)| item.size_estimate(tcx)).collect();
+                cgu.items().values().map(|data| data.size_estimate).collect();
             placed_item_sizes.sort_unstable_by_key(|&n| cmp::Reverse(n));
             let sizes = list(&placed_item_sizes);
 
@@ -937,15 +993,13 @@ fn debug_dump<'a, 'tcx: 'a>(
             let _ =
                 writeln!(s, "  - items: {num_items}, mean size: {mean_size:.1}, sizes: {sizes}",);
 
-            for (item, linkage) in cgu.items_in_deterministic_order(tcx) {
+            for (item, data) in cgu.items_in_deterministic_order(tcx) {
+                let linkage = data.linkage;
                 let symbol_name = item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
-                let size = item.size_estimate(tcx);
-                let kind = match item.instantiation_mode(tcx) {
-                    InstantiationMode::GloballyShared { .. } => "root",
-                    InstantiationMode::LocalCopy => "inlined",
-                };
+                let kind = if !data.inlined { "root" } else { "inlined" };
+                let size = data.size_estimate;
                 let _ = with_no_trimmed_paths!(writeln!(
                     s,
                     "  - {item} [{linkage:?}] [{symbol_hash}] ({kind}, size: {size})"
@@ -1100,8 +1154,8 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
         let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
 
         for cgu in codegen_units {
-            for (&mono_item, &linkage) in cgu.items() {
-                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), linkage));
+            for (&mono_item, &data) in cgu.items() {
+                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), data.linkage));
             }
         }
 
@@ -1114,7 +1168,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
                 let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
                 cgus.sort_by_key(|(name, _)| *name);
                 cgus.dedup();
-                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
+                for &(ref cgu_name, linkage) in cgus.iter() {
                     output.push(' ');
                     output.push_str(cgu_name.as_str());
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 8455803ad0c..c3cf6437afa 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
         self.sess.span_diagnostic.struct_span_err(sp, m)
     }
 
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<String>) -> ! {
         self.sess.span_diagnostic.span_bug(sp, m)
     }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 7ede4fbc3d9..3ecdbc36248 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1309,7 +1309,7 @@ impl<'a> Parser<'a> {
 
     /// Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
+        if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await) {
             return Ok(self.mk_await_expr(self_arg, lo));
         }
 
@@ -1442,8 +1442,8 @@ impl<'a> Parser<'a> {
             self.parse_expr_let()
         } else if self.eat_keyword(kw::Underscore) {
             Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
-        } else if self.token.uninterpolated_span().rust_2018() {
-            // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
+        } else if self.token.uninterpolated_span().at_least_rust_2018() {
+            // `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
             if self.check_keyword(kw::Async) {
                 if self.is_async_block() {
                     // Check for `async {` and `async move {`.
@@ -2230,7 +2230,7 @@ impl<'a> Parser<'a> {
         let movability =
             if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
 
-        let asyncness = if self.token.uninterpolated_span().rust_2018() {
+        let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() {
             self.parse_asyncness(Case::Sensitive)
         } else {
             Async::No
@@ -3014,7 +3014,7 @@ impl<'a> Parser<'a> {
     fn is_try_block(&self) -> bool {
         self.token.is_keyword(kw::Try)
             && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
-            && self.token.uninterpolated_span().rust_2018()
+            && self.token.uninterpolated_span().at_least_rust_2018()
     }
 
     /// Parses an `async move? {...}` expression.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index e4d843b7c8b..2e1a61e634e 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1210,7 +1210,8 @@ impl<'a> Parser<'a> {
     fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
         // Avoid const blocks and const closures to be parsed as const items
         if (self.check_const_closure() == is_closure)
-            && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
+            && !self
+                .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
             && self.eat_keyword_case(kw::Const, case)
         {
             Const::Yes(self.prev_token.uninterpolated_span())
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index fdf36517847..14891c45d81 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -8,7 +8,6 @@ use crate::errors::{
     TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
     UnexpectedVertVertInPattern,
 };
-use crate::fluent_generated as fluent;
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
@@ -214,41 +213,25 @@ impl<'a> Parser<'a> {
 
         if let PatKind::Or(pats) = &pat.kind {
             let span = pat.span;
-
-            if trailing_vert {
-                // We already emitted an error and suggestion to remove the trailing vert. Don't
-                // emit again.
-
-                // FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to
-                // `delay_span_bug()` instead of fluent message
-                self.sess.span_diagnostic.delay_span_bug(
-                    span,
-                    match syntax_loc {
-                        PatternLocation::LetBinding => {
-                            fluent::parse_or_pattern_not_allowed_in_let_binding
-                        }
-                        PatternLocation::FunctionParameter => {
-                            fluent::parse_or_pattern_not_allowed_in_fn_parameters
-                        }
-                    },
-                );
+            let pat = pprust::pat_to_string(&pat);
+            let sub = if pats.len() == 1 {
+                Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
             } else {
-                let pat = pprust::pat_to_string(&pat);
-                let sub = if pats.len() == 1 {
-                    Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
-                } else {
-                    Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
-                };
+                Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
+            };
 
-                self.sess.emit_err(match syntax_loc {
-                    PatternLocation::LetBinding => {
-                        TopLevelOrPatternNotAllowed::LetBinding { span, sub }
-                    }
-                    PatternLocation::FunctionParameter => {
-                        TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
-                    }
-                });
+            let mut err = self.sess.create_err(match syntax_loc {
+                PatternLocation::LetBinding => {
+                    TopLevelOrPatternNotAllowed::LetBinding { span, sub }
+                }
+                PatternLocation::FunctionParameter => {
+                    TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
+                }
+            });
+            if trailing_vert {
+                err.delay_as_bug();
             }
+            err.emit();
         }
 
         Ok((pat, colon))
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a29b696aea8..3bb50b05aa3 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -608,7 +608,7 @@ impl<'a> Parser<'a> {
     /// Is a `dyn B0 + ... + Bn` type allowed here?
     fn is_explicit_dyn_type(&mut self) -> bool {
         self.check_keyword(kw::Dyn)
-            && (self.token.uninterpolated_span().rust_2018()
+            && (self.token.uninterpolated_span().at_least_rust_2018()
                 || self.look_ahead(1, |t| {
                     (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
                         && !can_continue_type_after_non_fn_ident(t)
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 7de84db211e..88452ccdf05 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -109,6 +109,8 @@ pub struct Argument<'a> {
 pub struct FormatSpec<'a> {
     /// Optionally specified character to fill alignment with.
     pub fill: Option<char>,
+    /// Span of the optionally specified fill character.
+    pub fill_span: Option<InnerSpan>,
     /// Optionally specified alignment.
     pub align: Alignment,
     /// The `+` or `-` flag.
@@ -264,7 +266,7 @@ impl<'a> Iterator for Parser<'a> {
                         Some(String(self.string(pos + 1)))
                     } else {
                         let arg = self.argument(lbrace_end);
-                        if let Some(rbrace_pos) = self.must_consume('}') {
+                        if let Some(rbrace_pos) = self.consume_closing_brace(&arg) {
                             if self.is_source_literal {
                                 let lbrace_byte_pos = self.to_span_index(pos);
                                 let rbrace_byte_pos = self.to_span_index(rbrace_pos);
@@ -450,69 +452,51 @@ impl<'a> Parser<'a> {
 
     /// Forces consumption of the specified character. If the character is not
     /// found, an error is emitted.
-    fn must_consume(&mut self, c: char) -> Option<usize> {
+    fn consume_closing_brace(&mut self, arg: &Argument<'_>) -> Option<usize> {
         self.ws();
 
-        if let Some(&(pos, maybe)) = self.cur.peek() {
-            if c == maybe {
+        let pos;
+        let description;
+
+        if let Some(&(peek_pos, maybe)) = self.cur.peek() {
+            if maybe == '}' {
                 self.cur.next();
-                Some(pos)
-            } else {
-                let pos = self.to_span_index(pos);
-                let description = format!("expected `'}}'`, found `{maybe:?}`");
-                let label = "expected `}`".to_owned();
-                let (note, secondary_label) = if c == '}' {
-                    (
-                        Some(
-                            "if you intended to print `{`, you can escape it using `{{`".to_owned(),
-                        ),
-                        self.last_opening_brace
-                            .map(|sp| ("because of this opening brace".to_owned(), sp)),
-                    )
-                } else {
-                    (None, None)
-                };
-                self.errors.push(ParseError {
-                    description,
-                    note,
-                    label,
-                    span: pos.to(pos),
-                    secondary_label,
-                    should_be_replaced_with_positional_argument: false,
-                });
-                None
+                return Some(peek_pos);
             }
+
+            pos = peek_pos;
+            description = format!("expected `'}}'`, found `{maybe:?}`");
         } else {
-            let description = format!("expected `{c:?}` but string was terminated");
+            description = "expected `'}'` but string was terminated".to_owned();
             // point at closing `"`
-            let pos = self.input.len() - if self.append_newline { 1 } else { 0 };
-            let pos = self.to_span_index(pos);
-            if c == '}' {
-                let label = format!("expected `{c:?}`");
-                let (note, secondary_label) = if c == '}' {
-                    (
-                        Some(
-                            "if you intended to print `{`, you can escape it using `{{`".to_owned(),
-                        ),
-                        self.last_opening_brace
-                            .map(|sp| ("because of this opening brace".to_owned(), sp)),
-                    )
-                } else {
-                    (None, None)
-                };
-                self.errors.push(ParseError {
-                    description,
-                    note,
-                    label,
-                    span: pos.to(pos),
-                    secondary_label,
-                    should_be_replaced_with_positional_argument: false,
-                });
-            } else {
-                self.err(description, format!("expected `{c:?}`"), pos.to(pos));
-            }
-            None
+            pos = self.input.len() - if self.append_newline { 1 } else { 0 };
         }
+
+        let pos = self.to_span_index(pos);
+
+        let label = "expected `'}'`".to_owned();
+        let (note, secondary_label) = if arg.format.fill == Some('}') {
+            (
+                Some("the character `'}'` is interpreted as a fill character because of the `:` that precedes it".to_owned()),
+                arg.format.fill_span.map(|sp| ("this is not interpreted as a formatting closing brace".to_owned(), sp)),
+            )
+        } else {
+            (
+                Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
+                self.last_opening_brace.map(|sp| ("because of this opening brace".to_owned(), sp)),
+            )
+        };
+
+        self.errors.push(ParseError {
+            description,
+            note,
+            label,
+            span: pos.to(pos),
+            secondary_label,
+            should_be_replaced_with_positional_argument: false,
+        });
+
+        None
     }
 
     /// Consumes all whitespace characters until the first non-whitespace character
@@ -608,6 +592,7 @@ impl<'a> Parser<'a> {
     fn format(&mut self) -> FormatSpec<'a> {
         let mut spec = FormatSpec {
             fill: None,
+            fill_span: None,
             align: AlignUnknown,
             sign: None,
             alternate: false,
@@ -625,9 +610,10 @@ impl<'a> Parser<'a> {
         }
 
         // fill character
-        if let Some(&(_, c)) = self.cur.peek() {
+        if let Some(&(idx, c)) = self.cur.peek() {
             if let Some((_, '>' | '<' | '^')) = self.cur.clone().nth(1) {
                 spec.fill = Some(c);
+                spec.fill_span = Some(self.span(idx, idx + 1));
                 self.cur.next();
             }
         }
@@ -722,6 +708,7 @@ impl<'a> Parser<'a> {
     fn inline_asm(&mut self) -> FormatSpec<'a> {
         let mut spec = FormatSpec {
             fill: None,
+            fill_span: None,
             align: AlignUnknown,
             sign: None,
             alternate: false,
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 45314e2fb55..0c594f9104c 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -9,6 +9,7 @@ fn same(fmt: &'static str, p: &[Piece<'static>]) {
 fn fmtdflt() -> FormatSpec<'static> {
     return FormatSpec {
         fill: None,
+        fill_span: None,
         align: AlignUnknown,
         sign: None,
         alternate: false,
@@ -128,6 +129,7 @@ fn format_type() {
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -152,6 +154,7 @@ fn format_align_fill() {
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignRight,
                 sign: None,
                 alternate: false,
@@ -173,6 +176,7 @@ fn format_align_fill() {
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
                 fill: Some('0'),
+                fill_span: Some(InnerSpan::new(4, 5)),
                 align: AlignLeft,
                 sign: None,
                 alternate: false,
@@ -194,6 +198,7 @@ fn format_align_fill() {
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
                 fill: Some('*'),
+                fill_span: Some(InnerSpan::new(4, 5)),
                 align: AlignLeft,
                 sign: None,
                 alternate: false,
@@ -218,6 +223,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -239,6 +245,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -260,6 +267,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -281,6 +289,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -302,6 +311,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -323,6 +333,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -344,6 +355,7 @@ fn format_counts() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: None,
                 alternate: false,
@@ -368,6 +380,7 @@ fn format_flags() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: Some(Sign::Minus),
                 alternate: false,
@@ -389,6 +402,7 @@ fn format_flags() {
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
                 fill: None,
+                fill_span: None,
                 align: AlignUnknown,
                 sign: Some(Sign::Plus),
                 alternate: true,
@@ -415,6 +429,7 @@ fn format_mixture() {
                 position_span: InnerSpan { start: 7, end: 8 },
                 format: FormatSpec {
                     fill: None,
+                    fill_span: None,
                     align: AlignUnknown,
                     sign: None,
                     alternate: false,
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 49b423d1ade..d5fed8fe179 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,4 +1,5 @@
 query_system_cycle = cycle detected when {$stack_bottom}
+    .note = see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
 
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index cf2f04c7486..e49e78cc7c4 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -57,6 +57,8 @@ pub struct Cycle {
     pub alias: Option<Alias>,
     #[subdiagnostic]
     pub cycle_usage: Option<CycleUsage>,
+    #[note]
+    pub note_span: (),
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index f45f7ca5da6..d2140161f1d 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -13,6 +13,7 @@ use rustc_session::Session;
 use rustc_span::Span;
 
 use std::hash::Hash;
+use std::io::Write;
 use std::num::NonZeroU64;
 
 #[cfg(parallel_compiler)]
@@ -607,6 +608,7 @@ pub(crate) fn report_cycle<'a, D: DepKind>(
         alias,
         cycle_usage: cycle_usage,
         stack_count,
+        note_span: (),
     };
 
     cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic)
@@ -617,30 +619,50 @@ pub fn print_query_stack<Qcx: QueryContext>(
     mut current_query: Option<QueryJobId>,
     handler: &Handler,
     num_frames: Option<usize>,
+    mut file: Option<std::fs::File>,
 ) -> usize {
     // Be careful relying on global state here: this code is called from
     // a panic hook, which means that the global `Handler` may be in a weird
     // state if it was responsible for triggering the panic.
-    let mut i = 0;
+    let mut count_printed = 0;
+    let mut count_total = 0;
     let query_map = qcx.try_collect_active_jobs();
 
+    if let Some(ref mut file) = file {
+        let _ = writeln!(file, "\n\nquery stack during panic:");
+    }
     while let Some(query) = current_query {
-        if Some(i) == num_frames {
-            break;
-        }
         let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
             break;
         };
-        let mut diag = Diagnostic::new(
-            Level::FailureNote,
-            format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description),
-        );
-        diag.span = query_info.job.span.into();
-        handler.force_print_diagnostic(diag);
+        if Some(count_printed) < num_frames || num_frames.is_none() {
+            // Only print to stderr as many stack frames as `num_frames` when present.
+            let mut diag = Diagnostic::new(
+                Level::FailureNote,
+                format!(
+                    "#{} [{:?}] {}",
+                    count_printed, query_info.query.dep_kind, query_info.query.description
+                ),
+            );
+            diag.span = query_info.job.span.into();
+            handler.force_print_diagnostic(diag);
+            count_printed += 1;
+        }
+
+        if let Some(ref mut file) = file {
+            let _ = writeln!(
+                file,
+                "#{} [{:?}] {}",
+                count_total, query_info.query.dep_kind, query_info.query.description
+            );
+        }
 
         current_query = query_info.job.parent;
-        i += 1;
+        count_total += 1;
     }
 
-    i
+    if let Some(ref mut file) = file {
+        let _ = writeln!(file, "end of query stack");
+    }
+    count_printed
 }
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index dc35c8b176f..3228e8d52f0 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -440,7 +440,7 @@ impl Resolver<'_, '_> {
 
             // If we are not in Rust 2018 edition, then we don't make any further
             // suggestions.
-            if !tcx.sess.rust_2018() {
+            if !tcx.sess.at_least_rust_2018() {
                 continue;
             }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d3dcdfa4275..2cfde2f62d8 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1203,7 +1203,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     if filter_fn(res) {
                         // create the path
                         let mut segms = path_segments.clone();
-                        if lookup_ident.span.rust_2018() {
+                        if lookup_ident.span.at_least_rust_2018() {
                             // crate-local absolute paths start with `crate::` in edition 2018
                             // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
                             segms.insert(0, ast::PathSegment::from_ident(crate_name));
@@ -1268,7 +1268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     path_segments.push(ast::PathSegment::from_ident(ident));
 
                     let is_extern_crate_that_also_appears_in_prelude =
-                        name_binding.is_extern_crate() && lookup_ident.span.rust_2018();
+                        name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
 
                     if !is_extern_crate_that_also_appears_in_prelude {
                         // add the module to the lookup
@@ -1315,7 +1315,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             &filter_fn,
         );
 
-        if lookup_ident.span.rust_2018() {
+        if lookup_ident.span.at_least_rust_2018() {
             let extern_prelude_names = self.extern_prelude.clone();
             for (ident, _) in extern_prelude_names.into_iter() {
                 if ident.span.from_expansion() {
@@ -1568,7 +1568,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     "consider adding an explicit import of `{ident}` to disambiguate"
                 ))
             }
-            if b.is_extern_crate() && ident.span.rust_2018() {
+            if b.is_extern_crate() && ident.span.at_least_rust_2018() {
                 help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
             }
             match misc {
@@ -1973,7 +1973,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {}
             // `ident::...` on 2018.
             (Some(fst), _)
-                if fst.ident.span.rust_2018() && !fst.ident.is_path_segment_keyword() =>
+                if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() =>
             {
                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
                 path.insert(0, Segment::from_ident(Ident::empty()));
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 520fab1f0c8..de431444769 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1417,13 +1417,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         ));
                         continue;
                     }
-                    if name == kw::PathRoot && ident.span.rust_2018() {
+                    if name == kw::PathRoot && ident.span.at_least_rust_2018() {
                         module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
                     if name == kw::PathRoot
                         && ident.span.is_rust_2015()
-                        && self.tcx.sess.rust_2018()
+                        && self.tcx.sess.at_least_rust_2018()
                     {
                         // `::a::b` from 2015 macro on 2018 global edition
                         module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 846a1ffe09b..05128a51016 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -3911,8 +3911,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             && path[0].ident.name != kw::PathRoot
             && path[0].ident.name != kw::DollarCrate
         {
+            let last_segment = *path.last().unwrap();
             let unqualified_result = {
-                match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
+                match self.resolve_path(&[last_segment], Some(ns), None) {
                     PathResult::NonModule(path_res) => path_res.expect_full_res(),
                     PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
                         module.res().unwrap()
@@ -3928,8 +3929,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     finalize.path_span,
                     "unnecessary qualification",
                     lint::BuiltinLintDiagnostics::UnusedQualifications {
-                        path_span: finalize.path_span,
-                        unqualified_path: path.last().unwrap().ident
+                        removal_span: finalize.path_span.until(last_segment.ident.span),
                     }
                 )
             }
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index dc475e8c6d5..c53a355b533 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -13,6 +13,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
 use rustc_span::hygiene::{ExpnHash, ExpnId};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
 use rustc_target::spec::Target;
 
 use std::any::Any;
@@ -147,6 +148,7 @@ pub enum DllCallingConvention {
 pub struct ForeignModule {
     pub foreign_items: Vec<DefId>,
     pub def_id: DefId,
+    pub abi: Abi,
 }
 
 #[derive(Copy, Clone, Debug, HashStable_Generic)]
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 194f7201ff3..b0a67c564ce 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -117,6 +117,7 @@ pub fn feature_err_issue(
 /// Construct a future incompatibility diagnostic for a feature gate.
 ///
 /// This diagnostic is only a warning and *does not cause compilation to fail*.
+#[track_caller]
 pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
     feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
 }
@@ -129,6 +130,7 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st
 /// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
 #[allow(rustc::diagnostic_outside_of_impl)]
 #[allow(rustc::untranslatable_diagnostic)]
+#[track_caller]
 pub fn feature_warn_issue(
     sess: &ParseSess,
     feature: Symbol,
@@ -229,6 +231,7 @@ impl ParseSess {
             Some(sm.clone()),
             None,
             fallback_bundle,
+            None,
         );
         ParseSess::with_span_handler(handler, sm)
     }
@@ -259,12 +262,20 @@ impl ParseSess {
     pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
         let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-        let fatal_handler =
-            Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
+        let fatal_handler = Handler::with_tty_emitter(
+            ColorConfig::Auto,
+            false,
+            None,
+            None,
+            None,
+            fallback_bundle,
+            None,
+        );
         let handler = Handler::with_emitter(
             false,
             None,
             Box::new(SilentEmitter { fatal_handler, fatal_note }),
+            None,
         );
         ParseSess::with_span_handler(handler, sm)
     }
@@ -351,6 +362,7 @@ impl ParseSess {
         self.create_warning(warning).emit()
     }
 
+    #[track_caller]
     pub fn create_note<'a>(
         &'a self,
         note: impl IntoDiagnostic<'a, Noted>,
@@ -358,10 +370,12 @@ impl ParseSess {
         note.into_diagnostic(&self.span_diagnostic)
     }
 
+    #[track_caller]
     pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
         self.create_note(note).emit()
     }
 
+    #[track_caller]
     pub fn create_fatal<'a>(
         &'a self,
         fatal: impl IntoDiagnostic<'a, !>,
@@ -369,6 +383,7 @@ impl ParseSess {
         fatal.into_diagnostic(&self.span_diagnostic)
     }
 
+    #[track_caller]
     pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
         self.create_fatal(fatal).emit()
     }
@@ -383,16 +398,19 @@ impl ParseSess {
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.span_diagnostic.struct_warn(msg)
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
         self.span_diagnostic.struct_fatal(msg)
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_diagnostic<G: EmissionGuarantee>(
         &self,
         msg: impl Into<DiagnosticMessage>,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 5be122ffbde..146bb11bd3a 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -677,7 +677,7 @@ impl Session {
     pub fn delay_span_bug<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<String>,
     ) -> ErrorGuaranteed {
         self.diagnostic().delay_span_bug(sp, msg)
     }
@@ -995,18 +995,18 @@ impl Session {
     }
 
     /// Are we allowed to use features from the Rust 2018 edition?
-    pub fn rust_2018(&self) -> bool {
-        self.edition().rust_2018()
+    pub fn at_least_rust_2018(&self) -> bool {
+        self.edition().at_least_rust_2018()
     }
 
     /// Are we allowed to use features from the Rust 2021 edition?
-    pub fn rust_2021(&self) -> bool {
-        self.edition().rust_2021()
+    pub fn at_least_rust_2021(&self) -> bool {
+        self.edition().at_least_rust_2021()
     }
 
     /// Are we allowed to use features from the Rust 2024 edition?
-    pub fn rust_2024(&self) -> bool {
-        self.edition().rust_2024()
+    pub fn at_least_rust_2024(&self) -> bool {
+        self.edition().at_least_rust_2024()
     }
 
     /// Returns `true` if we should use the PLT for shared library calls.
@@ -1392,6 +1392,7 @@ pub fn build_session(
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target_override: Option<Target>,
     cfg_version: &'static str,
+    ice_file: Option<PathBuf>,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1440,6 +1441,7 @@ pub fn build_session(
     let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
         emitter,
         sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings),
+        ice_file,
     );
 
     let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
@@ -1731,7 +1733,7 @@ pub struct EarlyErrorHandler {
 impl EarlyErrorHandler {
     pub fn new(output: ErrorOutputType) -> Self {
         let emitter = mk_emitter(output);
-        Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter) }
+        Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter, None) }
     }
 
     pub fn abort_if_errors(&self) {
@@ -1745,7 +1747,7 @@ impl EarlyErrorHandler {
         self.handler.abort_if_errors();
 
         let emitter = mk_emitter(output);
-        self.handler = Handler::with_emitter(true, None, emitter);
+        self.handler = Handler::with_emitter(true, None, emitter, None);
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 527d5220564..ccb12c27107 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -31,6 +31,22 @@ pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef {
     with_tables(|t| t.adt_def(did))
 }
 
+pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef {
+    with_tables(|t| t.foreign_def(did))
+}
+
+pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef {
+    with_tables(|t| t.fn_def(did))
+}
+
+pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef {
+    with_tables(|t| t.closure_def(did))
+}
+
+pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef {
+    with_tables(|t| t.generator_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
@@ -44,6 +60,22 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::AdtDef(self.create_def_id(did))
     }
 
+    pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
+        stable_mir::ty::ForeignDef(self.create_def_id(did))
+    }
+
+    pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef {
+        stable_mir::ty::FnDef(self.create_def_id(did))
+    }
+
+    pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef {
+        stable_mir::ty::ClosureDef(self.create_def_id(did))
+    }
+
+    pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
+        stable_mir::ty::GeneratorDef(self.create_def_id(did))
+    }
+
     fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 6af6cfe58f1..f512a98f41a 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -8,8 +8,11 @@
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
 use crate::rustc_internal::{self, opaque};
-use crate::stable_mir::ty::{AdtSubsts, FloatTy, GenericArgKind, IntTy, RigidTy, TyKind, UintTy};
+use crate::stable_mir::ty::{
+    FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy,
+};
 use crate::stable_mir::{self, Context};
+use rustc_hir as hir;
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -94,39 +97,43 @@ impl<'tcx> Tables<'tcx> {
                 ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
                 ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
             },
-            ty::Adt(adt_def, substs) => TyKind::RigidTy(RigidTy::Adt(
+            ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
                 rustc_internal::adt_def(adt_def.did()),
-                AdtSubsts(
-                    substs
-                        .iter()
-                        .map(|arg| match arg.unpack() {
-                            ty::GenericArgKind::Lifetime(region) => {
-                                GenericArgKind::Lifetime(opaque(&region))
-                            }
-                            ty::GenericArgKind::Type(ty) => {
-                                GenericArgKind::Type(self.intern_ty(ty))
-                            }
-                            ty::GenericArgKind::Const(const_) => {
-                                GenericArgKind::Const(opaque(&const_))
-                            }
-                        })
-                        .collect(),
-                ),
+                self.generic_args(generic_args),
             )),
-            ty::Foreign(_) => todo!(),
+            ty::Foreign(def_id) => {
+                TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
+            }
             ty::Str => TyKind::RigidTy(RigidTy::Str),
             ty::Array(ty, constant) => {
                 TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
             }
             ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
-            ty::RawPtr(_) => todo!(),
-            ty::Ref(_, _, _) => todo!(),
-            ty::FnDef(_, _) => todo!(),
+            ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
+                TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable()))
+            }
+            ty::Ref(region, ty, mutbl) => {
+                TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable()))
+            }
+            ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
+                rustc_internal::fn_def(*def_id),
+                self.generic_args(generic_args),
+            )),
             ty::FnPtr(_) => todo!(),
             ty::Dynamic(_, _, _) => todo!(),
-            ty::Closure(_, _) => todo!(),
-            ty::Generator(_, _, _) => todo!(),
-            ty::Never => todo!(),
+            ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
+                rustc_internal::closure_def(*def_id),
+                self.generic_args(generic_args),
+            )),
+            ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
+                rustc_internal::generator_def(*def_id),
+                self.generic_args(generic_args),
+                match movability {
+                    hir::Movability::Static => Movability::Static,
+                    hir::Movability::Movable => Movability::Movable,
+                },
+            )),
+            ty::Never => TyKind::RigidTy(RigidTy::Never),
             ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
                 fields.iter().map(|ty| self.intern_ty(ty)).collect(),
             )),
@@ -151,6 +158,24 @@ impl<'tcx> Tables<'tcx> {
         self.types.push(ty);
         stable_mir::ty::Ty(id)
     }
+
+    fn generic_args(
+        &mut self,
+        generic_args: &ty::GenericArgs<'tcx>,
+    ) -> stable_mir::ty::GenericArgs {
+        GenericArgs(
+            generic_args
+                .iter()
+                .map(|arg| match arg.unpack() {
+                    ty::GenericArgKind::Lifetime(region) => {
+                        GenericArgKind::Lifetime(opaque(&region))
+                    }
+                    ty::GenericArgKind::Type(ty) => GenericArgKind::Type(self.intern_ty(ty)),
+                    ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
+                })
+                .collect(),
+        )
+    }
 }
 
 /// Build a stable mir crate from a given crate number.
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index 02ac907f09a..831eb6589e4 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -1,4 +1,4 @@
-use crate::rustc_internal::Opaque;
+use crate::stable_mir::ty::Region;
 use crate::stable_mir::{self, ty::Ty};
 
 #[derive(Clone, Debug)]
@@ -137,8 +137,6 @@ pub enum Statement {
     Nop,
 }
 
-type Region = Opaque;
-
 // FIXME this is incomplete
 #[derive(Clone, Debug)]
 pub enum Rvalue {
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index e9f17f92c04..ba120be04b2 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,4 +1,4 @@
-use super::{with, DefId};
+use super::{mir::Mutability, with, DefId};
 use crate::rustc_internal::Opaque;
 
 #[derive(Copy, Clone, Debug)]
@@ -11,7 +11,7 @@ impl Ty {
 }
 
 type Const = Opaque;
-type Region = Opaque;
+pub(crate) type Region = Opaque;
 
 #[derive(Clone, Debug)]
 pub enum TyKind {
@@ -25,10 +25,17 @@ pub enum RigidTy {
     Int(IntTy),
     Uint(UintTy),
     Float(FloatTy),
-    Adt(AdtDef, AdtSubsts),
+    Adt(AdtDef, GenericArgs),
+    Foreign(ForeignDef),
     Str,
     Array(Ty, Const),
     Slice(Ty),
+    RawPtr(Ty, Mutability),
+    Ref(Region, Ty, Mutability),
+    FnDef(FnDef, GenericArgs),
+    Closure(ClosureDef, GenericArgs),
+    Generator(GeneratorDef, GenericArgs, Movability),
+    Never,
     Tuple(Vec<Ty>),
 }
 
@@ -58,17 +65,33 @@ pub enum FloatTy {
     F64,
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Movability {
+    Static,
+    Movable,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ForeignDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FnDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ClosureDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct GeneratorDef(pub(crate) DefId);
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct AdtDef(pub(crate) DefId);
 
 #[derive(Clone, Debug)]
-pub struct AdtSubsts(pub Vec<GenericArgKind>);
+pub struct GenericArgs(pub Vec<GenericArgKind>);
 
 #[derive(Clone, Debug)]
 pub enum GenericArgKind {
-    // FIXME add proper region
     Lifetime(Region),
     Type(Ty),
-    // FIXME add proper const
     Const(Const),
 }
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index f16db69aae2..608b8c24bde 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -82,17 +82,17 @@ impl Edition {
     }
 
     /// Are we allowed to use features from the Rust 2018 edition?
-    pub fn rust_2018(self) -> bool {
+    pub fn at_least_rust_2018(self) -> bool {
         self >= Edition::Edition2018
     }
 
     /// Are we allowed to use features from the Rust 2021 edition?
-    pub fn rust_2021(self) -> bool {
+    pub fn at_least_rust_2021(self) -> bool {
         self >= Edition::Edition2021
     }
 
     /// Are we allowed to use features from the Rust 2024 edition?
-    pub fn rust_2024(self) -> bool {
+    pub fn at_least_rust_2024(self) -> bool {
         self >= Edition::Edition2024
     }
 }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 5c56337d1e0..ecaa82874a3 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -707,24 +707,28 @@ impl Span {
         self.ctxt().edition()
     }
 
+    /// Is this edition 2015?
     #[inline]
     pub fn is_rust_2015(self) -> bool {
         self.edition().is_rust_2015()
     }
 
+    /// Are we allowed to use features from the Rust 2018 edition?
     #[inline]
-    pub fn rust_2018(self) -> bool {
-        self.edition().rust_2018()
+    pub fn at_least_rust_2018(self) -> bool {
+        self.edition().at_least_rust_2018()
     }
 
+    /// Are we allowed to use features from the Rust 2021 edition?
     #[inline]
-    pub fn rust_2021(self) -> bool {
-        self.edition().rust_2021()
+    pub fn at_least_rust_2021(self) -> bool {
+        self.edition().at_least_rust_2021()
     }
 
+    /// Are we allowed to use features from the Rust 2024 edition?
     #[inline]
-    pub fn rust_2024(self) -> bool {
-        self.edition().rust_2024()
+    pub fn at_least_rust_2024(self) -> bool {
+        self.edition().at_least_rust_2024()
     }
 
     /// Returns the source callee.
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 03e7b3e7b40..3d2ea017d8f 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -693,8 +693,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "avr" => avr::compute_abi_info(self),
             "loongarch64" => loongarch::compute_abi_info(cx, self),
             "m68k" => m68k::compute_abi_info(self),
-            "mips" => mips::compute_abi_info(cx, self),
-            "mips64" => mips64::compute_abi_info(cx, self),
+            "mips" | "mips32r6" => mips::compute_abi_info(cx, self),
+            "mips64" | "mips64r6" => mips64::compute_abi_info(cx, self),
             "powerpc" => powerpc::compute_abi_info(self),
             "powerpc64" => powerpc64::compute_abi_info(cx, self),
             "s390x" => s390x::compute_abi_info(cx, self),
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index e60b8e78e5d..7c27732079b 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -238,8 +238,8 @@ impl FromStr for InlineAsmArch {
             "powerpc64" => Ok(Self::PowerPC64),
             "hexagon" => Ok(Self::Hexagon),
             "loongarch64" => Ok(Self::LoongArch64),
-            "mips" => Ok(Self::Mips),
-            "mips64" => Ok(Self::Mips64),
+            "mips" | "mips32r6" => Ok(Self::Mips),
+            "mips64" | "mips64r6" => Ok(Self::Mips64),
             "s390x" => Ok(Self::S390x),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs
index bf1b089f657..c8f3db00e01 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs
@@ -3,9 +3,7 @@ use crate::spec::{Target, TargetOptions};
 use super::SanitizerSet;
 
 pub fn target() -> Target {
-    let mut base = super::linux_musl_base::opts();
-    base.env = "ohos".into();
-    base.crt_static_default = false;
+    let mut base = super::linux_ohos_base::opts();
     base.max_atomic_width = Some(128);
 
     Target {
@@ -17,8 +15,6 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+reserve-x18".into(),
             mcount: "\u{1}_mcount".into(),
-            force_emulated_tls: true,
-            has_thread_local: false,
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
                 | SanitizerSet::LEAK
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs
index 16da2453367..e9b0bda68ef 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs
@@ -17,12 +17,8 @@ pub fn target() -> Target {
             abi: "eabi".into(),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
-            env: "ohos".into(),
-            crt_static_default: false,
             mcount: "\u{1}mcount".into(),
-            force_emulated_tls: true,
-            has_thread_local: false,
-            ..super::linux_musl_base::opts()
+            ..super::linux_ohos_base::opts()
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/linux_ohos_base.rs b/compiler/rustc_target/src/spec/linux_ohos_base.rs
new file mode 100644
index 00000000000..4ad4c837336
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_ohos_base.rs
@@ -0,0 +1,12 @@
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+    let mut base = super::linux_base::opts();
+
+    base.env = "ohos".into();
+    base.crt_static_default = false;
+    base.force_emulated_tls = true;
+    base.has_thread_local = false;
+
+    base
+}
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
index 1e066b271e2..983a449b006 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
         llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
-        arch: "mips".into(),
+        arch: "mips32r6".into(),
         options: TargetOptions {
             endian: Endian::Big,
             cpu: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
index 4785929c100..ec0facdfb7b 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
         llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
-        arch: "mips".into(),
+        arch: "mips32r6".into(),
 
         options: TargetOptions {
             cpu: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
index 766ac768064..16dd1c416f4 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
         llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
-        arch: "mips64".into(),
+        arch: "mips64r6".into(),
         options: TargetOptions {
             abi: "abi64".into(),
             endian: Endian::Big,
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
index d2b07c654dc..8d0a6aa8f51 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
         llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
-        arch: "mips64".into(),
+        arch: "mips64r6".into(),
         options: TargetOptions {
             abi: "abi64".into(),
             // NOTE(mips64r6) matches C toolchain
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 2365dfaf1af..6ae07f45f4a 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -74,6 +74,7 @@ mod l4re_base;
 mod linux_base;
 mod linux_gnu_base;
 mod linux_musl_base;
+mod linux_ohos_base;
 mod linux_uclibc_base;
 mod msvc_base;
 mod netbsd_base;
@@ -1433,6 +1434,8 @@ supported_targets! {
     ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
     ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
 
+    ("sparc-unknown-none-elf", sparc_unknown_none_elf),
+
     ("loongarch64-unknown-none", loongarch64_unknown_none),
     ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
 
@@ -1493,6 +1496,7 @@ supported_targets! {
 
     ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
     ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
+    ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
 }
 
 /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs
new file mode 100644
index 00000000000..7e908a0f365
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs
@@ -0,0 +1,27 @@
+use crate::abi::Endian;
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let options = TargetOptions {
+        linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+        linker: Some("sparc-elf-gcc".into()),
+        endian: Endian::Big,
+        cpu: "v7".into(),
+        abi: "elf".into(),
+        max_atomic_width: Some(32),
+        atomic_cas: true,
+        panic_strategy: PanicStrategy::Abort,
+        relocation_model: RelocModel::Static,
+        no_default_libraries: false,
+        emit_debug_gdb_scripts: false,
+        eh_frame_header: false,
+        ..Default::default()
+    };
+    Target {
+        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
+        llvm_target: "sparc-unknown-none-elf".into(),
+        pointer_width: 32,
+        arch: "sparc".into(),
+        options,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs
new file mode 100644
index 00000000000..a96be8cd554
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs
@@ -0,0 +1,26 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+    let mut base = super::linux_ohos_base::opts();
+    base.cpu = "x86-64".into();
+    base.max_atomic_width = Some(64);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+    base.stack_probes = StackProbeType::X86;
+    base.static_position_independent_executables = true;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
+    base.supports_xray = true;
+
+    Target {
+        // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
+        llvm_target: "x86_64-unknown-linux-musl".into(),
+        pointer_width: 64,
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
+        arch: "x86_64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 312bd38178f..6efc1e7302c 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,5 +1,5 @@
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, ObligationCtxt};
+use crate::traits::{self, DefiningAnchor, ObligationCtxt};
 
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -80,7 +80,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
 
 pub trait InferCtxtBuilderExt<'tcx> {
     fn enter_canonical_trait_query<K, R>(
-        &mut self,
+        self,
         canonical_key: &Canonical<'tcx, K>,
         operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
     ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
@@ -108,7 +108,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
     /// have `'tcx` be free on this function so that we can talk about
     /// `K: TypeFoldable<TyCtxt<'tcx>>`.)
     fn enter_canonical_trait_query<K, R>(
-        &mut self,
+        self,
         canonical_key: &Canonical<'tcx, K>,
         operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
     ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
@@ -117,8 +117,9 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
     {
-        let (infcx, key, canonical_inference_vars) =
-            self.build_with_canonical(DUMMY_SP, canonical_key);
+        let (infcx, key, canonical_inference_vars) = self
+            .with_opaque_type_inference(DefiningAnchor::Bubble)
+            .build_with_canonical(DUMMY_SP, canonical_key);
         let ocx = ObligationCtxt::new(&infcx);
         let value = operation(&ocx, key)?;
         ocx.make_canonicalized_query_response(canonical_inference_vars, value)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 1e798998895..6920e790e71 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -10,9 +10,11 @@ use rustc_infer::traits::util::elaborate;
 use rustc_infer::traits::Reveal;
 use rustc_middle::traits::solve::inspect::CandidateKind;
 use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
-use rustc_middle::ty::fast_reject::TreatProjections;
-use rustc_middle::ty::TypeFoldable;
+use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{fast_reject, TypeFoldable};
+use rustc_span::ErrorGuaranteed;
 use std::fmt::Debug;
 
 pub(super) mod structural_traits;
@@ -109,10 +111,10 @@ pub(super) trait GoalKind<'tcx>:
 
     fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
 
-    // Try equating an assumption predicate against a goal's predicate. If it
-    // holds, then execute the `then` callback, which should do any additional
-    // work, then produce a response (typically by executing
-    // [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
+    /// Try equating an assumption predicate against a goal's predicate. If it
+    /// holds, then execute the `then` callback, which should do any additional
+    /// work, then produce a response (typically by executing
+    /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
     fn probe_and_match_goal_against_assumption(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -120,9 +122,9 @@ pub(super) trait GoalKind<'tcx>:
         then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
     ) -> QueryResult<'tcx>;
 
-    // Consider a clause, which consists of a "assumption" and some "requirements",
-    // to satisfy a goal. If the requirements hold, then attempt to satisfy our
-    // goal by equating it with the assumption.
+    /// Consider a clause, which consists of a "assumption" and some "requirements",
+    /// to satisfy a goal. If the requirements hold, then attempt to satisfy our
+    /// goal by equating it with the assumption.
     fn consider_implied_clause(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -149,9 +151,9 @@ pub(super) trait GoalKind<'tcx>:
         })
     }
 
-    // Consider a clause specifically for a `dyn Trait` self type. This requires
-    // additionally checking all of the supertraits and object bounds to hold,
-    // since they're not implied by the well-formedness of the object type.
+    /// Consider a clause specifically for a `dyn Trait` self type. This requires
+    /// additionally checking all of the supertraits and object bounds to hold,
+    /// since they're not implied by the well-formedness of the object type.
     fn consider_object_bound_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -182,96 +184,113 @@ pub(super) trait GoalKind<'tcx>:
         impl_def_id: DefId,
     ) -> QueryResult<'tcx>;
 
-    // A type implements an `auto trait` if its components do as well. These components
-    // are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`].
+    /// If the predicate contained an error, we want to avoid emitting unnecessary trait
+    /// errors but still want to emit errors for other trait goals. We have some special
+    /// handling for this case.
+    ///
+    /// Trait goals always hold while projection goals never do. This is a bit arbitrary
+    /// but prevents incorrect normalization while hiding any trait errors.
+    fn consider_error_guaranteed_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        guar: ErrorGuaranteed,
+    ) -> QueryResult<'tcx>;
+
+    /// A type implements an `auto trait` if its components do as well.
+    ///
+    /// These components are given by built-in rules from
+    /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
     fn consider_auto_trait_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A trait alias holds if the RHS traits and `where` clauses hold.
+    /// A trait alias holds if the RHS traits and `where` clauses hold.
     fn consider_trait_alias_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A type is `Copy` or `Clone` if its components are `Sized`. These components
-    // are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`].
+    /// A type is `Copy` or `Clone` if its components are `Sized`.
+    ///
+    /// These components are given by built-in rules from
+    /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
     fn consider_builtin_sized_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These
-    // components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`].
+    /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
+    ///
+    /// These components are given by built-in rules from
+    /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
     fn consider_builtin_copy_clone_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A type is `PointerLike` if we can compute its layout, and that layout
-    // matches the layout of `usize`.
+    /// A type is `PointerLike` if we can compute its layout, and that layout
+    /// matches the layout of `usize`.
     fn consider_builtin_pointer_like_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A type is a `FnPtr` if it is of `FnPtr` type.
+    /// A type is a `FnPtr` if it is of `FnPtr` type.
     fn consider_builtin_fn_ptr_trait_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
-    // family of traits where `A` is given by the signature of the type.
+    /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
+    /// family of traits where `A` is given by the signature of the type.
     fn consider_builtin_fn_trait_candidates(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
         kind: ty::ClosureKind,
     ) -> QueryResult<'tcx>;
 
-    // `Tuple` is implemented if the `Self` type is a tuple.
+    /// `Tuple` is implemented if the `Self` type is a tuple.
     fn consider_builtin_tuple_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // `Pointee` is always implemented.
-    //
-    // See the projection implementation for the `Metadata` types for all of
-    // the built-in types. For structs, the metadata type is given by the struct
-    // tail.
+    /// `Pointee` is always implemented.
+    ///
+    /// See the projection implementation for the `Metadata` types for all of
+    /// the built-in types. For structs, the metadata type is given by the struct
+    /// tail.
     fn consider_builtin_pointee_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A generator (that comes from an `async` desugaring) is known to implement
-    // `Future<Output = O>`, where `O` is given by the generator's return type
-    // that was computed during type-checking.
+    /// A generator (that comes from an `async` desugaring) is known to implement
+    /// `Future<Output = O>`, where `O` is given by the generator's return type
+    /// that was computed during type-checking.
     fn consider_builtin_future_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // A generator (that doesn't come from an `async` desugaring) is known to
-    // implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
-    // and return types of the generator computed during type-checking.
+    /// A generator (that doesn't come from an `async` desugaring) is known to
+    /// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
+    /// and return types of the generator computed during type-checking.
     fn consider_builtin_generator_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // The most common forms of unsizing are array to slice, and concrete (Sized)
-    // type into a `dyn Trait`. ADTs and Tuples can also have their final field
-    // unsized if it's generic.
+    /// The most common forms of unsizing are array to slice, and concrete (Sized)
+    /// type into a `dyn Trait`. ADTs and Tuples can also have their final field
+    /// unsized if it's generic.
     fn consider_builtin_unsize_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
-    // if `Trait2` is a (transitive) supertrait of `Trait2`.
+    /// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
+    /// if `Trait2` is a (transitive) supertrait of `Trait2`.
     fn consider_builtin_dyn_upcast_candidates(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -299,35 +318,66 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         goal: Goal<'tcx, G>,
     ) -> Vec<Candidate<'tcx>> {
         debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
+        if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
+            return ambig;
+        }
+
+        let mut candidates = self.assemble_candidates_via_self_ty(goal);
+
+        self.assemble_blanket_impl_candidates(goal, &mut candidates);
 
-        // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
-        // object bound, alias bound, etc. We are unable to determine this until we can at
-        // least structurally resolve the type one layer.
-        if goal.predicate.self_ty().is_ty_var() {
-            return vec![Candidate {
+        self.assemble_param_env_candidates(goal, &mut candidates);
+
+        candidates
+    }
+
+    /// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule,
+    /// object bound, alias bound, etc. We are unable to determine this until we can at
+    /// least structurally resolve the type one layer.
+    ///
+    /// It would also require us to consider all impls of the trait, which is both pretty
+    /// bad for perf and would also constrain the self type if there is just a single impl.
+    fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
+        &mut self,
+        goal: Goal<'tcx, G>,
+    ) -> Option<Vec<Candidate<'tcx>>> {
+        goal.predicate.self_ty().is_ty_var().then(|| {
+            vec![Candidate {
                 source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity),
                 result: self
                     .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
                     .unwrap(),
-            }];
+            }]
+        })
+    }
+
+    /// Assemble candidates which apply to the self type. This only looks at candidate which
+    /// apply to the specific self type and ignores all others.
+    ///
+    /// Returns `None` if the self type is still ambiguous.
+    fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
+        &mut self,
+        goal: Goal<'tcx, G>,
+    ) -> Vec<Candidate<'tcx>> {
+        debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
+        if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
+            return ambig;
         }
 
         let mut candidates = Vec::new();
 
-        self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
-
-        self.assemble_impl_candidates(goal, &mut candidates);
+        self.assemble_non_blanket_impl_candidates(goal, &mut candidates);
 
         self.assemble_builtin_impl_candidates(goal, &mut candidates);
 
-        self.assemble_param_env_candidates(goal, &mut candidates);
-
         self.assemble_alias_bound_candidates(goal, &mut candidates);
 
         self.assemble_object_bound_candidates(goal, &mut candidates);
 
         self.assemble_coherence_unknowable_candidates(goal, &mut candidates);
 
+        self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
+
         candidates
     }
 
@@ -385,7 +435,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                         // have a `Normalized` candidate. This doesn't work as long as we
                         // use `CandidateSource` in winnowing.
                         let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
-                        Ok(ecx.assemble_and_evaluate_candidates(goal))
+                        Ok(ecx.assemble_candidates_via_self_ty(goal))
                     },
                 )
             });
@@ -396,22 +446,125 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 
     #[instrument(level = "debug", skip_all)]
-    fn assemble_impl_candidates<G: GoalKind<'tcx>>(
+    fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
         let tcx = self.tcx();
-        tcx.for_each_relevant_impl_treating_projections(
-            goal.predicate.trait_def_id(tcx),
-            goal.predicate.self_ty(),
-            TreatProjections::NextSolverLookup,
-            |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
+        let self_ty = goal.predicate.self_ty();
+        let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
+        let mut consider_impls_for_simplified_type = |simp| {
+            if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
+                for &impl_def_id in impls_for_type {
+                    match G::consider_impl_candidate(self, goal, impl_def_id) {
+                        Ok(result) => candidates
+                            .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
+                        Err(NoSolution) => (),
+                    }
+                }
+            }
+        };
+
+        match self_ty.kind() {
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(_, _)
+            | ty::Foreign(_)
+            | ty::Str
+            | ty::Array(_, _)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_)
+            | ty::Dynamic(_, _, _)
+            | ty::Closure(_, _)
+            | ty::Generator(_, _, _)
+            | ty::Never
+            | ty::Tuple(_) => {
+                let simp =
+                    fast_reject::simplify_type(tcx, self_ty, TreatParams::ForLookup).unwrap();
+                consider_impls_for_simplified_type(simp);
+            }
+
+            // HACK: For integer and float variables we have to manually look at all impls
+            // which have some integer or float as a self type.
+            ty::Infer(ty::IntVar(_)) => {
+                use ty::IntTy::*;
+                use ty::UintTy::*;
+                // This causes a compiler error if any new integer kinds are added.
+                let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy;
+                let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy;
+                let possible_integers = [
+                    // signed integers
+                    SimplifiedType::Int(I8),
+                    SimplifiedType::Int(I16),
+                    SimplifiedType::Int(I32),
+                    SimplifiedType::Int(I64),
+                    SimplifiedType::Int(I128),
+                    SimplifiedType::Int(Isize),
+                    // unsigned integers
+                    SimplifiedType::Uint(U8),
+                    SimplifiedType::Uint(U16),
+                    SimplifiedType::Uint(U32),
+                    SimplifiedType::Uint(U64),
+                    SimplifiedType::Uint(U128),
+                    SimplifiedType::Uint(Usize),
+                ];
+                for simp in possible_integers {
+                    consider_impls_for_simplified_type(simp);
+                }
+            }
+
+            ty::Infer(ty::FloatVar(_)) => {
+                // This causes a compiler error if any new float kinds are added.
+                let (ty::FloatTy::F32 | ty::FloatTy::F64);
+                let possible_floats = [
+                    SimplifiedType::Float(ty::FloatTy::F32),
+                    SimplifiedType::Float(ty::FloatTy::F64),
+                ];
+
+                for simp in possible_floats {
+                    consider_impls_for_simplified_type(simp);
+                }
+            }
+
+            // The only traits applying to aliases and placeholders are blanket impls.
+            //
+            // Impls which apply to an alias after normalization are handled by
+            // `assemble_candidates_after_normalizing_self_ty`.
+            ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),
+
+            // FIXME: These should ideally not exist as a self type. It would be nice for
+            // the builtin auto trait impls of generators should instead directly recurse
+            // into the witness.
+            ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(_, _) => (),
+
+            // These variants should not exist as a self type.
+            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
+            | ty::Param(_)
+            | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"),
+        }
+    }
+
+    fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
+        &mut self,
+        goal: Goal<'tcx, G>,
+        candidates: &mut Vec<Candidate<'tcx>>,
+    ) {
+        let tcx = self.tcx();
+        let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
+        for &impl_def_id in trait_impls.blanket_impls() {
+            match G::consider_impl_candidate(self, goal, impl_def_id) {
                 Ok(result) => candidates
                     .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
                 Err(NoSolution) => (),
-            },
-        );
+            }
+        }
     }
 
     #[instrument(level = "debug", skip_all)]
@@ -420,8 +573,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         goal: Goal<'tcx, G>,
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
-        let lang_items = self.tcx().lang_items();
-        let trait_def_id = goal.predicate.trait_def_id(self.tcx());
+        let tcx = self.tcx();
+        let lang_items = tcx.lang_items();
+        let trait_def_id = goal.predicate.trait_def_id(tcx);
 
         // N.B. When assembling built-in candidates for lang items that are also
         // `auto` traits, then the auto trait candidate that is assembled in
@@ -430,9 +584,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // Instead of adding the logic here, it's a better idea to add it in
         // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
         // `solve::trait_goals` instead.
-        let result = if self.tcx().trait_is_auto(trait_def_id) {
+        let result = if let Err(guar) = goal.predicate.error_reported() {
+            G::consider_error_guaranteed_candidate(self, guar)
+        } else if tcx.trait_is_auto(trait_def_id) {
             G::consider_auto_trait_candidate(self, goal)
-        } else if self.tcx().trait_is_alias(trait_def_id) {
+        } else if tcx.trait_is_alias(trait_def_id) {
             G::consider_trait_alias_candidate(self, goal)
         } else if lang_items.sized_trait() == Some(trait_def_id) {
             G::consider_builtin_sized_candidate(self, goal)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 3a1302e46ba..a8ba98bef6d 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -148,7 +148,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
 
         ty::Adt(def, args) => {
             let sized_crit = def.sized_constraint(ecx.tcx());
-            Ok(sized_crit.arg_iter_copied(ecx.tcx(), args).collect())
+            Ok(sized_crit.iter_instantiated_copied(ecx.tcx(), args).collect())
         }
     }
 }
@@ -353,7 +353,8 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
         // FIXME(associated_const_equality): Also add associated consts to
         // the requirements here.
         if item.kind == ty::AssocKind::Type {
-            requirements.extend(tcx.item_bounds(item.def_id).arg_iter(tcx, trait_ref.args));
+            requirements
+                .extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args));
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
new file mode 100644
index 00000000000..d10a14ff742
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
@@ -0,0 +1,44 @@
+use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
+use rustc_middle::ty;
+
+use super::EvalCtxt;
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    pub(super) fn normalize_inherent_associated_type(
+        &mut self,
+        goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        let tcx = self.tcx();
+        let inherent = goal.predicate.projection_ty;
+        let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
+
+        let impl_def_id = tcx.parent(inherent.def_id);
+        let impl_substs = self.fresh_args_for_item(impl_def_id);
+
+        // Equate impl header and add impl where clauses
+        self.eq(
+            goal.param_env,
+            inherent.self_ty(),
+            tcx.type_of(impl_def_id).instantiate(tcx, impl_substs),
+        )?;
+
+        // Equate IAT with the RHS of the project goal
+        let inherent_substs = inherent.rebase_inherent_args_onto_impl(impl_substs, tcx);
+        self.eq(
+            goal.param_env,
+            expected,
+            tcx.type_of(inherent.def_id).instantiate(tcx, inherent_substs),
+        )
+        .expect("expected goal term to be fully unconstrained");
+
+        // Check both where clauses on the impl and IAT
+        self.add_goals(
+            tcx.predicates_of(inherent.def_id)
+                .instantiate(tcx, inherent_substs)
+                .into_iter()
+                .map(|(pred, _)| goal.with(tcx, pred)),
+        );
+
+        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 1d9c975a97a..7c15c3c0e8b 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -25,6 +25,7 @@ mod assembly;
 mod canonicalize;
 mod eval_ctxt;
 mod fulfill;
+mod inherent_projection;
 pub mod inspect;
 mod normalize;
 mod opaques;
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 564451a31ed..222ed9939ba 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -2,7 +2,6 @@ use crate::traits::specialization_graph;
 
 use super::assembly::{self, structural_traits};
 use super::EvalCtxt;
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
@@ -15,7 +14,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::ProjectionPredicate;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
@@ -48,7 +47,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                             self.merge_candidates(candidates)
                         }
                         ty::AssocItemContainer::ImplContainer => {
-                            bug!("IATs not supported here yet")
+                            self.normalize_inherent_associated_type(goal)
                         }
                     }
                 } else {
@@ -112,6 +111,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
     ) -> QueryResult<'tcx> {
         if let Some(projection_pred) = assumption.as_projection_clause() {
             if projection_pred.projection_def_id() == goal.predicate.def_id() {
+                let tcx = ecx.tcx();
                 ecx.probe_candidate("assumption").enter(|ecx| {
                     let assumption_projection_pred =
                         ecx.instantiate_binder_with_infer(projection_pred);
@@ -122,6 +122,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                     )?;
                     ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
                         .expect("expected goal term to be fully unconstrained");
+
+                    // Add GAT where clauses from the trait's definition
+                    ecx.add_goals(
+                        tcx.predicates_of(goal.predicate.def_id())
+                            .instantiate_own(tcx, goal.predicate.projection_ty.args)
+                            .map(|(pred, _)| goal.with(tcx, pred)),
+                    );
+
                     then(ecx)
                 })
             } else {
@@ -160,6 +168,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 .map(|pred| goal.with(tcx, pred));
             ecx.add_goals(where_clause_bounds);
 
+            // Add GAT where clauses from the trait's definition
+            ecx.add_goals(
+                tcx.predicates_of(goal.predicate.def_id())
+                    .instantiate_own(tcx, goal.predicate.projection_ty.args)
+                    .map(|(pred, _)| goal.with(tcx, pred)),
+            );
+
             // In case the associated item is hidden due to specialization, we have to
             // return ambiguity this would otherwise be incomplete, resulting in
             // unsoundness during coherence (#105782).
@@ -230,6 +245,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         })
     }
 
+    /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error`
+    /// and succeed. Can experiment with this to figure out what results in better error messages.
+    fn consider_error_guaranteed_candidate(
+        _ecx: &mut EvalCtxt<'_, 'tcx>,
+        _guar: ErrorGuaranteed,
+    ) -> QueryResult<'tcx> {
+        Err(NoSolution)
+    }
+
     fn consider_auto_trait_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index e7867eead15..930e62d6388 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -11,7 +11,7 @@ use rustc_middle::traits::Reveal;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
-use rustc_span::DUMMY_SP;
+use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 
 impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn self_ty(self) -> Ty<'tcx> {
@@ -78,6 +78,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         })
     }
 
+    fn consider_error_guaranteed_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        _guar: ErrorGuaranteed,
+    ) -> QueryResult<'tcx> {
+        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+    }
+
     fn probe_and_match_goal_against_assumption(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -686,7 +693,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::Tuple(_)
             | ty::Adt(_, _)
             // FIXME: Handling opaques here is kinda sus. Especially because we
-            // simplify them to PlaceholderSimplifiedType.
+            // simplify them to SimplifiedType::Placeholder.
             | ty::Alias(ty::Opaque, _) => {
                 let mut disqualifying_impl = None;
                 self.tcx().for_each_relevant_impl_treating_projections(
diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs
index 2c176d4cfd6..c7717879a4a 100644
--- a/compiler/rustc_trait_selection/src/solve/weak_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs
@@ -14,6 +14,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
         let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
         self.eq(goal.param_env, expected, actual)?;
+
+        // Check where clauses
+        self.add_goals(
+            tcx.predicates_of(weak_ty.def_id)
+                .instantiate(tcx, weak_ty.args)
+                .predicates
+                .into_iter()
+                .map(|pred| goal.with(tcx, pred)),
+        );
+
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 }
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 a821d1be64b..c14839fe9be 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2388,14 +2388,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // If there is only one implementation of the trait, suggest using it.
                             // Otherwise, use a placeholder comment for the implementation.
                             let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
-                                "use the fully-qualified path to the only available implementation".to_string(),
+                                "use the fully-qualified path to the only available implementation",
                                 format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
-                            )} else {(
-                                format!(
-                                    "use a fully-qualified path to a specific available implementation ({} found)",
-                                    non_blanket_impl_count
-                                ),
-                                "</* self type */ as ".to_string()
+                            )} else {
+                                ("use a fully-qualified path to a specific available implementation",
+                                                                "</* self type */ as ".to_string()
                             )};
                             let mut suggestions = vec![(
                                 path.span.shrink_to_lo(),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 9ddf8a09b58..3ebf1246a41 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -670,7 +670,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx;
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             if infcx.predicate_must_hold_considering_regions(obligation) {
@@ -724,7 +724,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
 
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index e137ed9cda8..a39fc1f1771 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1402,9 +1402,17 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
     let impl_def_id = tcx.parent(alias_ty.def_id);
     let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
 
-    let impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
-    let impl_ty =
-        normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
+    let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
+    if !selcx.infcx.next_trait_solver() {
+        impl_ty = normalize_with_depth_to(
+            selcx,
+            param_env,
+            cause.clone(),
+            depth + 1,
+            impl_ty,
+            obligations,
+        );
+    }
 
     // Infer the generic parameters of the impl by unifying the
     // impl type with the self type of the projection.
@@ -1421,7 +1429,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
         }
     }
 
-    alias_ty.rebase_args_onto_impl(impl_args, tcx)
+    alias_ty.rebase_inherent_args_onto_impl(impl_args, tcx)
 }
 
 enum Projected<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 56d5d698d90..e086489b1bc 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2133,7 +2133,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 Where(
                     obligation
                         .predicate
-                        .rebind(sized_crit.arg_iter_copied(self.tcx(), args).collect()),
+                        .rebind(sized_crit.iter_instantiated_copied(self.tcx(), args).collect()),
                 )
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index b327dd2e150..5f6bb04fda4 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -570,7 +570,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                             ));
                         }
                         ty::ConstKind::Expr(_) => {
-                            // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the
+                            // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
                             // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
                             // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
                             // which means that the `DefId` would have been typeck'd elsewhere. However in
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 34ad6bd8c69..05ad4a4a12a 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -78,6 +78,7 @@ mod rustc {
     use rustc_middle::ty::ParamEnv;
     use rustc_middle::ty::Ty;
     use rustc_middle::ty::TyCtxt;
+    use rustc_middle::ty::ValTree;
 
     /// The source and destination types of a transmutation.
     #[derive(TypeVisitable, Debug, Clone, Copy)]
@@ -148,7 +149,17 @@ mod rustc {
             );
 
             let variant = adt_def.non_enum_variant();
-            let fields = c.to_valtree().unwrap_branch();
+            let fields = match c.try_to_valtree() {
+                Some(ValTree::Branch(branch)) => branch,
+                _ => {
+                    return Some(Self {
+                        alignment: true,
+                        lifetimes: true,
+                        safety: true,
+                        validity: true,
+                    });
+                }
+            };
 
             let get_field = |name| {
                 let (field_idx, _) = variant
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 5f754d90b6d..383cc996b9e 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -174,7 +174,7 @@ fn recurse_build<'tcx>(
         }
         // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
         // "coercion cast" i.e. using a coercion or is a no-op.
-        // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
+        // This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested)
         &ExprKind::Use { source } => {
             let arg = recurse_build(tcx, body, source, root_span)?;
             ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty)
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 3e6dfc1304f..e173bba49be 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -96,7 +96,7 @@ where
                 return Some(Err(AlwaysRequiresDrop));
             }
 
-            let components = match needs_drop_components(ty, &tcx.data_layout) {
+            let components = match needs_drop_components(tcx, ty) {
                 Err(e) => return Some(Err(e)),
                 Ok(components) => components,
             };
@@ -160,7 +160,7 @@ where
                             queue_type(self, required);
                         }
                     }
-                    ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
+                    ty::Alias(..) | ty::Array(..) | ty::Placeholder(_) | ty::Param(_) => {
                         if ty == component {
                             // Return the type to the caller: they may be able
                             // to normalize further than we can.
@@ -172,7 +172,31 @@ where
                             queue_type(self, component);
                         }
                     }
-                    _ => return Some(Err(AlwaysRequiresDrop)),
+
+                    ty::Foreign(_) | ty::Dynamic(..) => {
+                        return Some(Err(AlwaysRequiresDrop));
+                    }
+
+                    ty::Bool
+                    | ty::Char
+                    | ty::Int(_)
+                    | ty::Uint(_)
+                    | ty::Float(_)
+                    | ty::Str
+                    | ty::Slice(_)
+                    | ty::Ref(..)
+                    | ty::RawPtr(..)
+                    | ty::FnDef(..)
+                    | ty::FnPtr(..)
+                    | ty::Tuple(_)
+                    | ty::Bound(..)
+                    | ty::GeneratorWitness(..)
+                    | ty::GeneratorWitnessMIR(..)
+                    | ty::Never
+                    | ty::Infer(_)
+                    | ty::Error(_) => {
+                        bug!("unexpected type returned by `needs_drop_components`: {component}")
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index c228938126e..505f78d0e5f 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -42,7 +42,7 @@ fn sized_constraint_for_ty<'tcx>(
             let adt_tys = adt.sized_constraint(tcx);
             debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
             adt_tys
-                .arg_iter_copied(tcx, args)
+                .iter_instantiated_copied(tcx, args)
                 .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
                 .collect()
         }
@@ -297,7 +297,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             for bound in self
                 .tcx
                 .item_bounds(unshifted_alias_ty.def_id)
-                .arg_iter(self.tcx, unshifted_alias_ty.args)
+                .iter_instantiated(self.tcx, unshifted_alias_ty.args)
             {
                 bound.visit_with(self);
             }
@@ -311,22 +311,6 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
     tcx.param_env(def_id).with_reveal_all_normalized(tcx)
 }
 
-fn instance_def_size_estimate<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    instance_def: ty::InstanceDef<'tcx>,
-) -> usize {
-    use ty::InstanceDef;
-
-    match instance_def {
-        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
-            let mir = tcx.instance_mir(instance_def);
-            mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
-        }
-        // Estimate the size of other compiler-generated shims to be 1.
-        _ => 1,
-    }
-}
-
 /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
 ///
 /// See [`ty::ImplOverlapKind::Issue33140`] for more details.
@@ -432,7 +416,6 @@ pub fn provide(providers: &mut Providers) {
         adt_sized_constraint,
         param_env,
         param_env_reveal_all_normalized,
-        instance_def_size_estimate,
         issue33140_self_ty,
         defaultness,
         unsizing_params_for_adt,