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/src/ast.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs96
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs105
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs13
-rw-r--r--compiler/rustc_ast_passes/messages.ftl7
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs99
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs30
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/audit.yml19
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/bench.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs35
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/main.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/path.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/shared_utils.rs26
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs36
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/usage.txt2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs19
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch24
-rw-r--r--compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml4
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs63
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh8
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs43
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_const_eval/messages.ftl2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs140
-rw-r--r--compiler/rustc_const_eval/src/errors.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs10
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs11
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs7
-rw-r--r--compiler/rustc_data_structures/src/base_n.rs5
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs18
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs7
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs152
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs94
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs3
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs66
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs81
-rw-r--r--compiler/rustc_interface/src/passes.rs58
-rw-r--r--compiler/rustc_interface/src/queries.rs165
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp19
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp17
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp19
-rw-r--r--compiler/rustc_metadata/src/creader.rs12
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs3
-rw-r--r--compiler/rustc_metadata/src/fs.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs13
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs4
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs4
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs19
-rw-r--r--compiler/rustc_middle/src/ty/context.rs143
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs11
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs6
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs8
-rw-r--r--compiler/rustc_passes/src/stability.rs10
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs6
-rw-r--r--compiler/rustc_session/messages.ftl4
-rw-r--r--compiler/rustc_session/src/errors.rs4
-rw-r--r--compiler/rustc_session/src/session.rs66
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs16
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs97
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs9
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs170
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs7
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs25
-rw-r--r--compiler/rustc_target/src/abi/mod.rs7
-rw-r--r--compiler/rustc_target/src/json.rs5
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs16
-rw-r--r--compiler/rustc_target/src/spec/abi.rs30
-rw-r--r--compiler/rustc_target/src/spec/abi/tests.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs6
-rw-r--r--compiler/rustc_target/src/spec/teeos_base.rs29
-rw-r--r--compiler/rustc_trait_selection/messages.ftl9
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs36
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/cache.rs32
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs65
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs71
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs3
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs35
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs65
-rw-r--r--compiler/rustc_type_ir/src/sty.rs4
137 files changed, 1903 insertions, 1196 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index f2e90fd8eed..58725a08c7c 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -313,6 +313,16 @@ pub enum TraitBoundModifier {
     MaybeConstMaybe,
 }
 
+impl TraitBoundModifier {
+    pub fn to_constness(self) -> Const {
+        match self {
+            // FIXME(effects) span
+            Self::MaybeConst => Const::Yes(DUMMY_SP),
+            _ => Const::No,
+        }
+    }
+}
+
 /// The AST represents all type param bounds as types.
 /// `typeck::collect::compute_bounds` matches these against
 /// the "special" built-in traits (see `middle::lang_items`) and
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index ab55c09465b..a1e62699680 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -207,6 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 &sym.path,
                                 ParamMode::Optional,
                                 &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                                None,
                             );
                             hir::InlineAsmOperand::SymStatic { path, def_id }
                         } else {
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 72dc52a6329..a63bd4f8a02 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -31,9 +31,26 @@ pub struct InvalidAbi {
     pub abi: Symbol,
     pub command: String,
     #[subdiagnostic]
+    pub explain: Option<InvalidAbiReason>,
+    #[subdiagnostic]
     pub suggestion: Option<InvalidAbiSuggestion>,
 }
 
+pub struct InvalidAbiReason(pub &'static str);
+
+impl rustc_errors::AddToDiagnostic for InvalidAbiReason {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        #[allow(rustc::untranslatable_diagnostic)]
+        diag.note(self.0);
+    }
+}
+
 #[derive(Subdiagnostic)]
 #[suggestion(
     ast_lowering_invalid_abi_suggestion,
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 42d0998d162..b23cee14f75 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -100,6 +100,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         ParamMode::Optional,
                         ParenthesizedGenericArgs::Err,
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                        None,
                     ));
                     let receiver = self.lower_expr(receiver);
                     let args =
@@ -260,6 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         path,
                         ParamMode::Optional,
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                        None,
                     );
                     hir::ExprKind::Path(qpath)
                 }
@@ -307,6 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             &se.path,
                             ParamMode::Optional,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            None,
                         )),
                         self.arena
                             .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
@@ -1179,6 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         path,
                         ParamMode::Optional,
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                        None,
                     );
                     // Destructure like a tuple struct.
                     let tuple_struct_pat = hir::PatKind::TupleStruct(
@@ -1198,6 +1202,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         path,
                         ParamMode::Optional,
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                        None,
                     );
                     // Destructure like a unit struct.
                     let unit_struct_pat = hir::PatKind::Path(qpath);
@@ -1222,6 +1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     &se.path,
                     ParamMode::Optional,
                     &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                    None,
                 );
                 let fields_omitted = match &se.rest {
                     StructRest::Base(e) => {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index df73c721ade..a59c83de0f4 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,4 +1,4 @@
-use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
+use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
 use super::ResolverAstLoweringExt;
 use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
 use super::{FnDeclKind, LoweringContext, ParamMode};
@@ -90,6 +90,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
             allow_gen_future,
             generics_def_id_map: Default::default(),
+            host_param_id: None,
         };
         lctx.with_hir_id_owner(owner, |lctx| f(lctx));
 
@@ -144,8 +145,24 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             // This is used to track which lifetimes have already been defined,
             // and which need to be replicated when lowering an async fn.
 
-            if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
-                lctx.is_in_trait_impl = impl_.of_trait.is_some();
+            match parent_hir.node().expect_item().kind {
+                hir::ItemKind::Impl(impl_) => {
+                    lctx.is_in_trait_impl = impl_.of_trait.is_some();
+                }
+                hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => {
+                    lctx.host_param_id = generics
+                        .params
+                        .iter()
+                        .find(|param| {
+                            parent_hir
+                                .attrs
+                                .get(param.hir_id.local_id)
+                                .iter()
+                                .any(|attr| attr.has_name(sym::rustc_host))
+                        })
+                        .map(|param| param.def_id);
+                }
+                _ => {}
             }
 
             match ctxt {
@@ -389,6 +406,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
                         let trait_ref = trait_ref.as_ref().map(|trait_ref| {
                             this.lower_trait_ref(
+                                *constness,
                                 trait_ref,
                                 &ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
                             )
@@ -419,7 +437,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     polarity,
                     defaultness,
                     defaultness_span,
-                    constness: self.lower_constness(*constness),
                     generics,
                     of_trait: trait_ref,
                     self_ty: lowered_ty,
@@ -1254,8 +1271,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
-        abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
-            self.error_on_invalid_abi(abi);
+        abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|err| {
+            self.error_on_invalid_abi(abi, err);
             abi::Abi::Rust
         })
     }
@@ -1268,7 +1285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn error_on_invalid_abi(&self, abi: StrLit) {
+    fn error_on_invalid_abi(&self, abi: StrLit, err: abi::AbiUnsupported) {
         let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
             .iter()
             .map(|s| Symbol::intern(s))
@@ -1277,6 +1294,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.tcx.sess.emit_err(InvalidAbi {
             abi: abi.symbol_unescaped,
             span: abi.span,
+            explain: match err {
+                abi::AbiUnsupported::Reason { explain } => Some(InvalidAbiReason(explain)),
+                _ => None,
+            },
             suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
                 span: abi.span,
                 suggestion: format!("\"{suggested_name}\""),
@@ -1363,6 +1384,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
         }
 
+        // Desugar `~const` bound in generics into an additional `const host: bool` param
+        // if the effects feature is enabled. This needs to be done before we lower where
+        // clauses since where clauses need to bind to the DefId of the host param
+        let host_param_parts = if let Const::Yes(span) = constness && self.tcx.features().effects {
+            if let Some(param) = generics.params.iter().find(|x| {
+                x.attrs.iter().any(|x| x.has_name(sym::rustc_host))
+            }) {
+                // user has manually specified a `rustc_host` param, in this case, we set
+                // the param id so that lowering logic can use that. But we don't create
+                // another host param, so this gives `None`.
+                self.host_param_id = Some(self.local_def_id(param.id));
+                None
+            } else {
+                let param_node_id = self.next_node_id();
+                let hir_id = self.next_id();
+                let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
+                self.host_param_id = Some(def_id);
+                Some((span, hir_id, def_id))
+            }
+        } else {
+            None
+        };
+
         let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
         predicates.extend(generics.params.iter().filter_map(|param| {
             self.lower_generic_bound_predicate(
@@ -1410,22 +1454,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
         predicates.extend(impl_trait_bounds.into_iter());
 
-        // Desugar `~const` bound in generics into an additional `const host: bool` param
-        // if the effects feature is enabled.
-        if let Const::Yes(span) = constness && self.tcx.features().effects
-            // Do not add host param if it already has it (manually specified)
-            && !params.iter().any(|x| {
-                self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
-                    attrs.iter().any(|x| x.has_name(sym::rustc_host))
-                })
-            })
-        {
-            let param_node_id = self.next_node_id();
+        if let Some((span, hir_id, def_id)) = host_param_parts {
             let const_node_id = self.next_node_id();
-            let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
-            let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
+            let anon_const: LocalDefId =
+                self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
 
-            let hir_id = self.next_id();
             let const_id = self.next_id();
             let const_expr_id = self.next_id();
             let bool_id = self.next_id();
@@ -1435,14 +1468,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
 
-            let attrs = self.arena.alloc_from_iter([
-                Attribute {
-                    kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
+            let attrs = self.arena.alloc_from_iter([Attribute {
+                kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(
+                    sym::rustc_host,
                     span,
-                    id: attr_id,
-                    style: AttrStyle::Outer,
-                },
-            ]);
+                )))),
+                span,
+                id: attr_id,
+                style: AttrStyle::Outer,
+            }]);
             self.attrs.insert(hir_id.local_id, attrs);
 
             let const_body = self.lower_body(|this| {
@@ -1481,7 +1515,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             }),
                         )),
                     )),
-                    default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
+                    default: Some(hir::AnonConst {
+                        def_id: anon_const,
+                        hir_id: const_id,
+                        body: const_body,
+                    }),
                 },
                 colon_span: None,
                 pure_wrt_drop: false,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d29e9f9b3f6..89775bdee26 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -142,6 +142,8 @@ struct LoweringContext<'a, 'hir> {
     /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
     /// field from the original parameter 'a to the new parameter 'a1.
     generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
+
+    host_param_id: Option<LocalDefId>,
 }
 
 trait ResolverAstLoweringExt {
@@ -455,7 +457,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
 
     // Don't hash unless necessary, because it's expensive.
     let opt_hir_hash =
-        if tcx.sess.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
+        if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
     hir::Crate { owners, opt_hir_hash }
 }
 
@@ -646,7 +648,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let bodies = SortedMap::from_presorted_elements(bodies);
 
         // Don't hash unless necessary, because it's expensive.
-        let (opt_hash_including_bodies, attrs_hash) = if self.tcx.sess.needs_crate_hash() {
+        let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
             self.tcx.with_stable_hashing_context(|mut hcx| {
                 let mut stable_hasher = StableHasher::new();
                 hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
@@ -1262,6 +1264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: t.span
                     },
                     itctx,
+                    ast::Const::No,
                 );
                 let bounds = this.arena.alloc_from_iter([bound]);
                 let lifetime_bound = this.elided_dyn_bound(t.span);
@@ -1272,7 +1275,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let id = self.lower_node_id(t.id);
-        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
+        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
         self.ty_path(id, t.span, qpath)
     }
 
@@ -1356,10 +1359,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
                             GenericBound::Trait(
                                 ty,
-                                TraitBoundModifier::None
+                                modifier @ (TraitBoundModifier::None
                                 | TraitBoundModifier::MaybeConst
-                                | TraitBoundModifier::Negative,
-                            ) => Some(this.lower_poly_trait_ref(ty, itctx)),
+                                | TraitBoundModifier::Negative),
+                            ) => {
+                                Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
+                            }
                             // `~const ?Bound` will cause an error during AST validation
                             // anyways, so treat it like `?Bound` as compilation proceeds.
                             GenericBound::Trait(
@@ -1663,11 +1668,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             );
             debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
 
-            let lifetime_mapping = if in_trait {
-                Some(&*self.arena.alloc_slice(&synthesized_lifetime_args))
-            } else {
-                None
-            };
+            let lifetime_mapping = self.arena.alloc_slice(&synthesized_lifetime_args);
 
             let opaque_ty_item = hir::OpaqueTy {
                 generics: this.arena.alloc(hir::Generics {
@@ -1956,7 +1957,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::GenericBound<'hir> {
         match tpb {
             GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
-                self.lower_poly_trait_ref(p, itctx),
+                self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
                 self.lower_trait_bound_modifier(*modifier),
             ),
             GenericBound::Outlives(lifetime) => {
@@ -2099,8 +2100,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
-        let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
+    fn lower_trait_ref(
+        &mut self,
+        constness: ast::Const,
+        p: &TraitRef,
+        itctx: &ImplTraitContext,
+    ) -> hir::TraitRef<'hir> {
+        let path = match self.lower_qpath(
+            p.ref_id,
+            &None,
+            &p.path,
+            ParamMode::Explicit,
+            itctx,
+            Some(constness),
+        ) {
             hir::QPath::Resolved(None, path) => path,
             qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
         };
@@ -2112,10 +2125,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         p: &PolyTraitRef,
         itctx: &ImplTraitContext,
+        constness: ast::Const,
     ) -> hir::PolyTraitRef<'hir> {
         let bound_generic_params =
             self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
-        let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
+        let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
     }
 
@@ -2469,6 +2483,67 @@ struct GenericArgsCtor<'hir> {
 }
 
 impl<'hir> GenericArgsCtor<'hir> {
+    fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
+        if !lcx.tcx.features().effects {
+            return;
+        }
+
+        // if bound is non-const, don't add host effect param
+        let ast::Const::Yes(span) = constness else { return };
+
+        let span = lcx.lower_span(span);
+
+        let id = lcx.next_node_id();
+        let hir_id = lcx.next_id();
+        let body = lcx.lower_body(|lcx| {
+            (
+                &[],
+                match constness {
+                    ast::Const::Yes(_) => {
+                        let hir_id = lcx.next_id();
+                        let res =
+                            Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id());
+                        let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
+                            None,
+                            lcx.arena.alloc(hir::Path {
+                                span,
+                                res,
+                                segments: arena_vec![lcx; hir::PathSegment::new(Ident {
+                                    name: sym::host,
+                                    span,
+                                }, hir_id, res)],
+                            }),
+                        ));
+                        lcx.expr(span, expr_kind)
+                    }
+                    ast::Const::No => lcx.expr(
+                        span,
+                        hir::ExprKind::Lit(
+                            lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }),
+                        ),
+                    ),
+                },
+            )
+        });
+
+        let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
+        let attr = lcx.arena.alloc(Attribute {
+            kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
+            span,
+            id: attr_id,
+            style: AttrStyle::Outer,
+        });
+        lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr));
+
+        let def_id =
+            lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span);
+        lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
+        self.args.push(hir::GenericArg::Const(hir::ConstArg {
+            value: hir::AnonConst { def_id, hir_id, body },
+            span,
+        }))
+    }
+
     fn is_empty(&self) -> bool {
         self.args.is_empty()
             && self.bindings.is_empty()
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 2509b705639..a30f264bc7d 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             path,
                             ParamMode::Optional,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            None,
                         );
                         let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
                         break hir::PatKind::TupleStruct(qpath, pats, ddpos);
@@ -54,6 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             path,
                             ParamMode::Optional,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            None,
                         );
                         break hir::PatKind::Path(qpath);
                     }
@@ -64,6 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             path,
                             ParamMode::Optional,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            None,
                         );
 
                         let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 441282c05b4..899f92a9958 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -23,6 +23,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         p: &Path,
         param_mode: ParamMode,
         itctx: &ImplTraitContext,
+        // constness of the impl/bound if this is a trait path
+        constness: Option<ast::Const>,
     ) -> hir::QPath<'hir> {
         let qself_position = qself.as_ref().map(|q| q.position);
         let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
@@ -73,6 +75,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         param_mode,
                         parenthesized_generic_args,
                         itctx,
+                        // if this is the last segment, add constness to the trait path
+                        if i == proj_start - 1 { constness } else { None },
                     )
                 },
             )),
@@ -119,6 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 param_mode,
                 ParenthesizedGenericArgs::Err,
                 itctx,
+                None,
             ));
             let qpath = hir::QPath::TypeRelative(ty, hir_segment);
 
@@ -159,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     param_mode,
                     ParenthesizedGenericArgs::Err,
                     &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                    None,
                 )
             })),
             span: self.lower_span(p.span),
@@ -172,8 +178,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         param_mode: ParamMode,
         parenthesized_generic_args: ParenthesizedGenericArgs,
         itctx: &ImplTraitContext,
+        constness: Option<ast::Const>,
     ) -> hir::PathSegment<'hir> {
-        debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
+        debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
         let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
             match generic_args {
                 GenericArgs::AngleBracketed(data) => {
@@ -231,6 +238,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             )
         };
 
+        if let Some(constness) = constness {
+            generic_args.push_constness(self, constness);
+        }
+
         let has_lifetimes =
             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
 
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2f0ac0c2b19..f323bb4c254 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -239,5 +239,10 @@ ast_passes_visibility_not_permitted =
     .individual_impl_items = place qualifiers on individual impl items instead
     .individual_foreign_items = place qualifiers on individual foreign items instead
 
-ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases
+    .note = see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+    .help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable
+
+ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
     .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+    .suggestion = move it to the end of the type declaration
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index af594a00705..79fc9e4382f 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -136,40 +136,42 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_gat_where(
+    fn check_type_alias_where_clause_location(
         &mut self,
-        id: NodeId,
-        before_predicates: &[WherePredicate],
-        where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
-    ) {
-        if !before_predicates.is_empty() {
-            let mut state = State::new();
-            if !where_clauses.1.0 {
-                state.space();
-                state.word_space("where");
-            } else {
+        ty_alias: &TyAlias,
+    ) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
+        let before_predicates =
+            ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
+
+        if ty_alias.ty.is_none() || before_predicates.is_empty() {
+            return Ok(());
+        }
+
+        let mut state = State::new();
+        if !ty_alias.where_clauses.1.0 {
+            state.space();
+            state.word_space("where");
+        } else {
+            state.word_space(",");
+        }
+        let mut first = true;
+        for p in before_predicates {
+            if !first {
                 state.word_space(",");
             }
-            let mut first = true;
-            for p in before_predicates.iter() {
-                if !first {
-                    state.word_space(",");
-                }
-                first = false;
-                state.print_where_predicate(p);
-            }
-            let suggestion = state.s.eof();
-            self.lint_buffer.buffer_lint_with_diagnostic(
-                DEPRECATED_WHERE_CLAUSE_LOCATION,
-                id,
-                where_clauses.0.1,
-                fluent::ast_passes_deprecated_where_clause_location,
-                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
-                    where_clauses.1.1.shrink_to_hi(),
-                    suggestion,
-                ),
-            );
+            first = false;
+            state.print_where_predicate(p);
         }
+
+        let span = ty_alias.where_clauses.0.1;
+        Err(errors::WhereClauseBeforeTypeAlias {
+            span,
+            sugg: errors::WhereClauseBeforeTypeAliasSugg {
+                left: span,
+                snippet: state.s.eof(),
+                right: ty_alias.where_clauses.1.1.shrink_to_hi(),
+            },
+        })
     }
 
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
@@ -1009,7 +1011,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     replace_span: self.ending_semi_or_hi(item.span),
                 });
             }
-            ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
+            ItemKind::TyAlias(
+                ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
+            ) => {
                 self.check_defaultness(item.span, *defaultness);
                 if ty.is_none() {
                     self.session.emit_err(errors::TyAliasWithoutBody {
@@ -1018,9 +1022,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     });
                 }
                 self.check_type_no_bounds(bounds, "this context");
-                if where_clauses.1.0 {
-                    self.err_handler()
-                        .emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
+
+                if self.session.features_untracked().lazy_type_alias {
+                    if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
+                        self.err_handler().emit_err(err);
+                    }
+                } else if where_clauses.1.0 {
+                    self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias {
+                        span: where_clauses.1.1,
+                        help: self.session.is_nightly_build().then_some(()),
+                    });
                 }
             }
             _ => {}
@@ -1313,18 +1324,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
         }
 
-        if let AssocItemKind::Type(box TyAlias {
-            generics,
-            where_clauses,
-            where_predicates_split,
-            ty: Some(_),
-            ..
-        }) = &item.kind
+        if let AssocItemKind::Type(ty_alias) = &item.kind
+            && let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
         {
-            self.check_gat_where(
+            self.lint_buffer.buffer_lint_with_diagnostic(
+                DEPRECATED_WHERE_CLAUSE_LOCATION,
                 item.id,
-                generics.where_clause.predicates.split_at(*where_predicates_split).0,
-                *where_clauses,
+                err.span,
+                fluent::ast_passes_deprecated_where_clause_location,
+                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
+                    err.sugg.right,
+                    err.sugg.snippet,
+                ),
             );
         }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index ab8015c4a43..a6f217d4780 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -496,11 +496,37 @@ pub struct FieldlessUnion {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_where_after_type_alias)]
+#[diag(ast_passes_where_clause_after_type_alias)]
 #[note]
-pub struct WhereAfterTypeAlias {
+pub struct WhereClauseAfterTypeAlias {
     #[primary_span]
     pub span: Span,
+    #[help]
+    pub help: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_where_clause_before_type_alias)]
+#[note]
+pub struct WhereClauseBeforeTypeAlias {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: WhereClauseBeforeTypeAliasSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    ast_passes_suggestion,
+    applicability = "machine-applicable",
+    style = "verbose"
+)]
+pub struct WhereClauseBeforeTypeAliasSugg {
+    #[suggestion_part(code = "")]
+    pub left: Span,
+    pub snippet: String,
+    #[suggestion_part(code = "{snippet}")]
+    pub right: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 590db12a4cd..ede95dbf897 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, StmtKind};
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
     FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
@@ -163,7 +163,7 @@ fn make_format_args(
 
     let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
 
-    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
+    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
             fmt
@@ -171,17 +171,33 @@ fn make_format_args(
         Ok(fmt) => fmt,
         Err(err) => {
             if let Some((mut err, suggested)) = err {
-                let sugg_fmt = match args.explicit_args().len() {
-                    0 => "{}".to_string(),
-                    _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
-                };
                 if !suggested {
-                    err.span_suggestion(
-                        unexpanded_fmt_span.shrink_to_lo(),
-                        "you might be missing a string literal to format with",
-                        format!("\"{sugg_fmt}\", "),
-                        Applicability::MaybeIncorrect,
-                    );
+                    if let ExprKind::Block(block, None) = &efmt.kind
+                        && block.stmts.len() == 1
+                        && let StmtKind::Expr(expr) = &block.stmts[0].kind
+                        && let ExprKind::Path(None, path) = &expr.kind
+                            && path.is_potential_trivial_const_arg()
+                    {
+                        err.multipart_suggestion(
+                            "quote your inlined format argument to use as string literal",
+                            vec![
+                                (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
+                                (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
+                            ],
+                             Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let sugg_fmt = match args.explicit_args().len() {
+                            0 => "{}".to_string(),
+                            _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
+                        };
+                        err.span_suggestion(
+                            unexpanded_fmt_span.shrink_to_lo(),
+                            "you might be missing a string literal to format with",
+                            format!("\"{sugg_fmt}\", "),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
                 err.emit();
             }
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
new file mode 100644
index 00000000000..3efdec41559
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
@@ -0,0 +1,19 @@
+name: Security audit
+on:
+  workflow_dispatch:
+  schedule:
+    - cron: '0 10 * * 1' # every monday at 10:00 UTC
+permissions:
+  issues: write
+  checks: write
+jobs:
+  audit:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - run: |
+          sed -i 's/components.*/components = []/' rust-toolchain
+          echo 'profile = "minimal"' >> rust-toolchain
+      - uses: rustsec/audit-check@v1.4.1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index 29c127bf50e..2e7ba1b2060 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -1,8 +1,8 @@
-use super::build_sysroot;
-use super::path::Dirs;
-use super::prepare::GitRepo;
-use super::utils::{spawn_and_wait, CargoProject, Compiler};
-use super::{CodegenBackend, SysrootKind};
+use crate::build_sysroot;
+use crate::path::Dirs;
+use crate::prepare::GitRepo;
+use crate::utils::{spawn_and_wait, CargoProject, Compiler};
+use crate::{CodegenBackend, SysrootKind};
 
 static ABI_CAFE_REPO: GitRepo = GitRepo::github(
     "Gankra",
diff --git a/compiler/rustc_codegen_cranelift/build_system/bench.rs b/compiler/rustc_codegen_cranelift/build_system/bench.rs
index cec608ea042..6c64faaa256 100644
--- a/compiler/rustc_codegen_cranelift/build_system/bench.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/bench.rs
@@ -2,10 +2,10 @@ use std::env;
 use std::io::Write;
 use std::path::Path;
 
-use super::path::{Dirs, RelPath};
-use super::prepare::GitRepo;
-use super::rustc_info::get_file_name;
-use super::utils::{hyperfine_command, spawn_and_wait, Compiler};
+use crate::path::{Dirs, RelPath};
+use crate::prepare::GitRepo;
+use crate::rustc_info::get_file_name;
+use crate::utils::{hyperfine_command, spawn_and_wait, Compiler};
 
 static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
     "ebobby",
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index 1c5db23299d..e434c36f992 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -1,9 +1,9 @@
-use std::env;
 use std::path::PathBuf;
 
-use super::path::{Dirs, RelPath};
-use super::rustc_info::get_file_name;
-use super::utils::{is_ci, is_ci_opt, maybe_incremental, CargoProject, Compiler, LogGroup};
+use crate::path::{Dirs, RelPath};
+use crate::rustc_info::get_file_name;
+use crate::shared_utils::{rustflags_from_env, rustflags_to_cmd_env};
+use crate::utils::{is_ci, is_ci_opt, maybe_incremental, CargoProject, Compiler, LogGroup};
 
 pub(crate) static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
 
@@ -18,11 +18,11 @@ pub(crate) fn build_backend(
     let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
     maybe_incremental(&mut cmd);
 
-    let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default();
+    let mut rustflags = rustflags_from_env("RUSTFLAGS");
 
     if is_ci() {
         // Deny warnings on CI
-        rustflags += " -Dwarnings";
+        rustflags.push("-Dwarnings".to_owned());
 
         if !is_ci_opt() {
             cmd.env("CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS", "true");
@@ -42,10 +42,10 @@ pub(crate) fn build_backend(
         _ => unreachable!(),
     }
 
-    cmd.env("RUSTFLAGS", rustflags);
+    rustflags_to_cmd_env(&mut cmd, "RUSTFLAGS", &rustflags);
 
     eprintln!("[BUILD] rustc_codegen_cranelift");
-    super::utils::spawn_and_wait(cmd);
+    crate::utils::spawn_and_wait(cmd);
 
     CG_CLIF
         .target_dir(dirs)
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index 04097936d03..31a4b209826 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -2,13 +2,13 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use super::path::{Dirs, RelPath};
-use super::rustc_info::get_file_name;
-use super::utils::{
+use crate::path::{Dirs, RelPath};
+use crate::rustc_info::get_file_name;
+use crate::utils::{
     maybe_incremental, remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler,
     LogGroup,
 };
-use super::{CodegenBackend, SysrootKind};
+use crate::{config, CodegenBackend, SysrootKind};
 
 static DIST_DIR: RelPath = RelPath::DIST;
 static BIN_DIR: RelPath = RelPath::DIST.join("bin");
@@ -128,8 +128,8 @@ pub(crate) fn build_sysroot(
             cargo: bootstrap_host_compiler.cargo.clone(),
             rustc: rustc_clif.clone(),
             rustdoc: rustdoc_clif.clone(),
-            rustflags: String::new(),
-            rustdocflags: String::new(),
+            rustflags: vec![],
+            rustdocflags: vec![],
             triple: target_triple,
             runner: vec![],
         }
@@ -185,7 +185,7 @@ fn build_sysroot_for_triple(
 
 #[must_use]
 fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget {
-    let default_sysroot = super::rustc_info::get_default_sysroot(&compiler.rustc);
+    let default_sysroot = crate::rustc_info::get_default_sysroot(&compiler.rustc);
 
     let mut target_libs = SysrootTarget { triple: compiler.triple, libs: vec![] };
 
@@ -234,32 +234,32 @@ fn build_clif_sysroot_for_triple(
 
     let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join(channel);
 
-    if !super::config::get_bool("keep_sysroot") {
+    if !config::get_bool("keep_sysroot") {
         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
         // recompilation as they are not affected by changes in cg_clif.
         remove_dir_if_exists(&build_dir.join("deps"));
     }
 
     // Build sysroot
-    let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
+    let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned(), "-Cpanic=abort".to_owned()];
     match cg_clif_dylib_path {
         CodegenBackend::Local(path) => {
-            rustflags.push_str(&format!(" -Zcodegen-backend={}", path.to_str().unwrap()));
+            rustflags.push(format!("-Zcodegen-backend={}", path.to_str().unwrap()));
         }
         CodegenBackend::Builtin(name) => {
-            rustflags.push_str(&format!(" -Zcodegen-backend={name}"));
+            rustflags.push(format!("-Zcodegen-backend={name}"));
         }
     };
     // Necessary for MinGW to find rsbegin.o and rsend.o
-    rustflags
-        .push_str(&format!(" --sysroot {}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap()));
+    rustflags.push("--sysroot".to_owned());
+    rustflags.push(RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap().to_owned());
     if channel == "release" {
         // Incremental compilation by default disables mir inlining. This leads to both a decent
         // compile perf and a significant runtime perf regression. As such forcefully enable mir
         // inlining.
-        rustflags.push_str(" -Zinline-mir");
+        rustflags.push("-Zinline-mir".to_owned());
     }
-    compiler.rustflags += &rustflags;
+    compiler.rustflags.extend(rustflags);
     let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
     maybe_incremental(&mut build_cmd);
     if channel == "release" {
@@ -289,8 +289,8 @@ fn build_clif_sysroot_for_triple(
 }
 
 fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
-    if !super::config::get_bool("keep_sysroot") {
-        super::prepare::prepare_stdlib(dirs, &compiler.rustc);
+    if !config::get_bool("keep_sysroot") {
+        crate::prepare::prepare_stdlib(dirs, &compiler.rustc);
     }
 
     if !compiler.triple.ends_with("windows-gnu") {
@@ -306,6 +306,7 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
         let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
         let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
         build_rtstartup_cmd
+            .arg("-Ainternal_features") // Missing #[allow(internal_features)]
             .arg("--target")
             .arg(&compiler.triple)
             .arg("--emit=obj")
diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs
index 3bc78d5db94..798ae9dbd50 100644
--- a/compiler/rustc_codegen_cranelift/build_system/main.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/main.rs
@@ -16,6 +16,7 @@ mod config;
 mod path;
 mod prepare;
 mod rustc_info;
+mod shared_utils;
 mod tests;
 mod utils;
 
@@ -169,8 +170,8 @@ fn main() {
             cargo,
             rustc,
             rustdoc,
-            rustflags: String::new(),
-            rustdocflags: String::new(),
+            rustflags: vec![],
+            rustdocflags: vec![],
             triple,
             runner: vec![],
         }
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
index 4f86c0fd29d..8572815fc55 100644
--- a/compiler/rustc_codegen_cranelift/build_system/path.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/path.rs
@@ -1,7 +1,7 @@
 use std::fs;
 use std::path::PathBuf;
 
-use super::utils::remove_dir_if_exists;
+use crate::utils::remove_dir_if_exists;
 
 #[derive(Debug, Clone)]
 pub(crate) struct Dirs {
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 3ee2e8f4a4e..165296cb4a9 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -3,18 +3,18 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use super::build_sysroot::STDLIB_SRC;
-use super::path::{Dirs, RelPath};
-use super::rustc_info::get_default_sysroot;
-use super::utils::{
+use crate::build_sysroot::STDLIB_SRC;
+use crate::path::{Dirs, RelPath};
+use crate::rustc_info::get_default_sysroot;
+use crate::utils::{
     copy_dir_recursively, git_command, remove_dir_if_exists, retry_spawn_and_wait, spawn_and_wait,
 };
 
 pub(crate) fn prepare(dirs: &Dirs) {
     RelPath::DOWNLOAD.ensure_exists(dirs);
-    super::tests::RAND_REPO.fetch(dirs);
-    super::tests::REGEX_REPO.fetch(dirs);
-    super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
+    crate::tests::RAND_REPO.fetch(dirs);
+    crate::tests::REGEX_REPO.fetch(dirs);
+    crate::tests::PORTABLE_SIMD_REPO.fetch(dirs);
 }
 
 pub(crate) fn prepare_stdlib(dirs: &Dirs, rustc: &Path) {
diff --git a/compiler/rustc_codegen_cranelift/build_system/shared_utils.rs b/compiler/rustc_codegen_cranelift/build_system/shared_utils.rs
new file mode 100644
index 00000000000..0aea545ff7d
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/shared_utils.rs
@@ -0,0 +1,26 @@
+// This file is used by both the build system as well as cargo-clif.rs
+
+// Adapted from https://github.com/rust-lang/cargo/blob/6dc1deaddf62c7748c9097c7ea88e9ec77ff1a1a/src/cargo/core/compiler/build_context/target_info.rs#L750-L77
+pub(crate) fn rustflags_from_env(kind: &str) -> Vec<String> {
+    // First try CARGO_ENCODED_RUSTFLAGS from the environment.
+    // Prefer this over RUSTFLAGS since it's less prone to encoding errors.
+    if let Ok(a) = std::env::var(format!("CARGO_ENCODED_{}", kind)) {
+        if a.is_empty() {
+            return Vec::new();
+        }
+        return a.split('\x1f').map(str::to_string).collect();
+    }
+
+    // Then try RUSTFLAGS from the environment
+    if let Ok(a) = std::env::var(kind) {
+        let args = a.split(' ').map(str::trim).filter(|s| !s.is_empty()).map(str::to_string);
+        return args.collect();
+    }
+
+    // No rustflags to be collected from the environment
+    Vec::new()
+}
+
+pub(crate) fn rustflags_to_cmd_env(cmd: &mut std::process::Command, kind: &str, flags: &[String]) {
+    cmd.env(format!("CARGO_ENCODED_{}", kind), flags.join("\x1f"));
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 0254d18cf7c..e7bd8b1278c 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,16 +1,17 @@
-use super::build_sysroot;
-use super::config;
-use super::path::{Dirs, RelPath};
-use super::prepare::{apply_patches, GitRepo};
-use super::rustc_info::get_default_sysroot;
-use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler, LogGroup};
-use super::{CodegenBackend, SysrootKind};
-use std::env;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
 
+use crate::build_sysroot;
+use crate::config;
+use crate::path::{Dirs, RelPath};
+use crate::prepare::{apply_patches, GitRepo};
+use crate::rustc_info::get_default_sysroot;
+use crate::shared_utils::rustflags_from_env;
+use crate::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler, LogGroup};
+use crate::{CodegenBackend, SysrootKind};
+
 static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
 
 struct TestCase {
@@ -306,7 +307,7 @@ pub(crate) fn run_tests(
         );
         // Rust's build system denies a couple of lints that trigger on several of the test
         // projects. Changing the code to fix them is not worth it, so just silence all lints.
-        target_compiler.rustflags += " --cap-lints=allow";
+        target_compiler.rustflags.push("--cap-lints=allow".to_owned());
 
         let runner = TestRunner::new(
             dirs.clone(),
@@ -350,18 +351,15 @@ impl<'a> TestRunner<'a> {
         is_native: bool,
         stdlib_source: PathBuf,
     ) -> Self {
-        if let Ok(rustflags) = env::var("RUSTFLAGS") {
-            target_compiler.rustflags.push(' ');
-            target_compiler.rustflags.push_str(&rustflags);
-        }
-        if let Ok(rustdocflags) = env::var("RUSTDOCFLAGS") {
-            target_compiler.rustdocflags.push(' ');
-            target_compiler.rustdocflags.push_str(&rustdocflags);
-        }
+        target_compiler.rustflags.extend(rustflags_from_env("RUSTFLAGS"));
+        target_compiler.rustdocflags.extend(rustflags_from_env("RUSTDOCFLAGS"));
 
         // FIXME fix `#[linkage = "extern_weak"]` without this
         if target_compiler.triple.contains("darwin") {
-            target_compiler.rustflags.push_str(" -Clink-arg=-undefined -Clink-arg=dynamic_lookup");
+            target_compiler.rustflags.extend([
+                "-Clink-arg=-undefined".to_owned(),
+                "-Clink-arg=dynamic_lookup".to_owned(),
+            ]);
         }
 
         let jit_supported = use_unstable_features
@@ -470,7 +468,7 @@ impl<'a> TestRunner<'a> {
         S: AsRef<OsStr>,
     {
         let mut cmd = Command::new(&self.target_compiler.rustc);
-        cmd.args(self.target_compiler.rustflags.split_whitespace());
+        cmd.args(&self.target_compiler.rustflags);
         cmd.arg("-L");
         cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("--out-dir");
diff --git a/compiler/rustc_codegen_cranelift/build_system/usage.txt b/compiler/rustc_codegen_cranelift/build_system/usage.txt
index 6d3b3a13d6e..f652599447b 100644
--- a/compiler/rustc_codegen_cranelift/build_system/usage.txt
+++ b/compiler/rustc_codegen_cranelift/build_system/usage.txt
@@ -43,7 +43,7 @@ REQUIREMENTS:
     * Rustup: By default rustup is used to install the right nightly version. If you don't want to
       use rustup, you can manually install the nightly version indicated by rust-toolchain.toml and
       point the CARGO, RUSTC and RUSTDOC env vars to the right executables.
-    * Git: `./y.sh prepare` uses git for applying patches and on Windows for downloading test repos.
+    * Git: Git is used for applying patches and on Windows for downloading test repos.
     * Curl and tar (non-Windows only): Used by `./y.sh prepare` to download a single commit for
       repos. Git will be used to clone the whole repo when using Windows.
     * [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.sh bench`.
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index 97c82d501c5..24624cdeab1 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -5,15 +5,16 @@ use std::path::{Path, PathBuf};
 use std::process::{self, Command, Stdio};
 use std::sync::atomic::{AtomicBool, Ordering};
 
-use super::path::{Dirs, RelPath};
+use crate::path::{Dirs, RelPath};
+use crate::shared_utils::rustflags_to_cmd_env;
 
 #[derive(Clone, Debug)]
 pub(crate) struct Compiler {
     pub(crate) cargo: PathBuf,
     pub(crate) rustc: PathBuf,
     pub(crate) rustdoc: PathBuf,
-    pub(crate) rustflags: String,
-    pub(crate) rustdocflags: String,
+    pub(crate) rustflags: Vec<String>,
+    pub(crate) rustdocflags: Vec<String>,
     pub(crate) triple: String,
     pub(crate) runner: Vec<String>,
 }
@@ -23,8 +24,8 @@ impl Compiler {
         match self.triple.as_str() {
             "aarch64-unknown-linux-gnu" => {
                 // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-                self.rustflags += " -Clinker=aarch64-linux-gnu-gcc";
-                self.rustdocflags += " -Clinker=aarch64-linux-gnu-gcc";
+                self.rustflags.push("-Clinker=aarch64-linux-gnu-gcc".to_owned());
+                self.rustdocflags.push("-Clinker=aarch64-linux-gnu-gcc".to_owned());
                 self.runner = vec![
                     "qemu-aarch64".to_owned(),
                     "-L".to_owned(),
@@ -33,8 +34,8 @@ impl Compiler {
             }
             "s390x-unknown-linux-gnu" => {
                 // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
-                self.rustflags += " -Clinker=s390x-linux-gnu-gcc";
-                self.rustdocflags += " -Clinker=s390x-linux-gnu-gcc";
+                self.rustflags.push("-Clinker=s390x-linux-gnu-gcc".to_owned());
+                self.rustdocflags.push("-Clinker=s390x-linux-gnu-gcc".to_owned());
                 self.runner = vec![
                     "qemu-s390x".to_owned(),
                     "-L".to_owned(),
@@ -100,8 +101,8 @@ impl CargoProject {
 
         cmd.env("RUSTC", &compiler.rustc);
         cmd.env("RUSTDOC", &compiler.rustdoc);
-        cmd.env("RUSTFLAGS", &compiler.rustflags);
-        cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
+        rustflags_to_cmd_env(&mut cmd, "RUSTFLAGS", &compiler.rustflags);
+        rustflags_to_cmd_env(&mut cmd, "RUSTDOCFLAGS", &compiler.rustdocflags);
         if !compiler.runner.is_empty() {
             cmd.env(
                 format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 9ecc4c5dd5b..34c7e44b288 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -11,7 +11,7 @@
     thread_local
 )]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, internal_features)]
 
 #[lang = "sized"]
 pub trait Sized {}
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index d97fab9eb42..91de04d9770 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -1,6 +1,6 @@
 #![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, repr_simd)]
 #![no_core]
-#![allow(dead_code, non_camel_case_types)]
+#![allow(dead_code, non_camel_case_types, internal_features)]
 
 extern crate mini_core;
 
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch
new file mode 100644
index 00000000000..87252df1eab
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch
@@ -0,0 +1,24 @@
+From fcf75306d88e533b83eaff3f8d0ab9f307e8a84d Mon Sep 17 00:00:00 2001
+From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
+Date: Wed, 9 Aug 2023 10:01:17 +0000
+Subject: [PATCH] Allow internal features
+
+---
+ crates/core_simd/src/lib.rs | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs
+index fde406b..b386116 100644
+--- a/crates/core_simd/src/lib.rs
++++ b/crates/core_simd/src/lib.rs
+@@ -19,6 +19,7 @@
+ #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really
+ #![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)]
+ #![unstable(feature = "portable_simd", issue = "86656")]
++#![allow(internal_features)]
+ //! Portable SIMD module.
+ 
+ #[path = "mod.rs"]
+-- 
+2.34.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
index aea47bdfba2..fa175edcae6 100644
--- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
+++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
@@ -74,9 +74,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.95"
+version = "0.1.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6866e0f3638013234db3c89ead7a14d278354338e7237257407500009012b23f"
+checksum = "d6c0f24437059853f0fa64afc51f338f93647a3de4cf3358ba1bb4171a199775"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 34514658359..5689bdee64d 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-07-22"
+channel = "nightly-2023-08-08"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
index f73b2012684..1e14f41d4a2 100644
--- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
@@ -3,6 +3,8 @@ use std::env;
 use std::os::unix::process::CommandExt;
 use std::process::Command;
 
+include!("../build_system/shared_utils.rs");
+
 fn main() {
     let current_exe = env::current_exe().unwrap();
     let mut sysroot = current_exe.parent().unwrap();
@@ -10,27 +12,19 @@ fn main() {
         sysroot = sysroot.parent().unwrap();
     }
 
-    let mut rustflags = String::new();
-    rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend=");
+    let mut rustflags = vec!["-Cpanic=abort".to_owned(), "-Zpanic-abort-tests".to_owned()];
     if let Some(name) = option_env!("BUILTIN_BACKEND") {
-        rustflags.push_str(name);
+        rustflags.push(format!("-Zcodegen-backend={name}"));
     } else {
-        rustflags.push_str(
-            sysroot
-                .join(if cfg!(windows) { "bin" } else { "lib" })
-                .join(
-                    env::consts::DLL_PREFIX.to_string()
-                        + "rustc_codegen_cranelift"
-                        + env::consts::DLL_SUFFIX,
-                )
-                .to_str()
-                .unwrap(),
+        let dylib = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+            env::consts::DLL_PREFIX.to_string()
+                + "rustc_codegen_cranelift"
+                + env::consts::DLL_SUFFIX,
         );
+        rustflags.push(format!("-Zcodegen-backend={}", dylib.to_str().unwrap()));
     }
-    rustflags.push_str(" --sysroot ");
-    rustflags.push_str(sysroot.to_str().unwrap());
-    env::set_var("RUSTFLAGS", env::var("RUSTFLAGS").unwrap_or(String::new()) + &rustflags);
-    env::set_var("RUSTDOCFLAGS", env::var("RUSTDOCFLAGS").unwrap_or(String::new()) + &rustflags);
+    rustflags.push("--sysroot".to_owned());
+    rustflags.push(sysroot.to_str().unwrap().to_owned());
 
     let cargo = if let Some(cargo) = option_env!("CARGO") {
         cargo
@@ -49,10 +43,7 @@ fn main() {
 
     let args: Vec<_> = match args.get(0).map(|arg| &**arg) {
         Some("jit") => {
-            env::set_var(
-                "RUSTFLAGS",
-                env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
-            );
+            rustflags.push("-Cprefer-dynamic".to_owned());
             args.remove(0);
             IntoIterator::into_iter(["rustc".to_string()])
                 .chain(args)
@@ -64,10 +55,7 @@ fn main() {
                 .collect()
         }
         Some("lazy-jit") => {
-            env::set_var(
-                "RUSTFLAGS",
-                env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
-            );
+            rustflags.push("-Cprefer-dynamic".to_owned());
             args.remove(0);
             IntoIterator::into_iter(["rustc".to_string()])
                 .chain(args)
@@ -81,11 +69,28 @@ fn main() {
         _ => args,
     };
 
+    let mut cmd = Command::new(cargo);
+    cmd.args(args);
+    rustflags_to_cmd_env(
+        &mut cmd,
+        "RUSTFLAGS",
+        &rustflags_from_env("RUSTFLAGS")
+            .into_iter()
+            .chain(rustflags.iter().map(|flag| flag.clone()))
+            .collect::<Vec<_>>(),
+    );
+    rustflags_to_cmd_env(
+        &mut cmd,
+        "RUSTDOCFLAGS",
+        &rustflags_from_env("RUSTDOCFLAGS")
+            .into_iter()
+            .chain(rustflags.iter().map(|flag| flag.clone()))
+            .collect::<Vec<_>>(),
+    );
+
     #[cfg(unix)]
-    panic!("Failed to spawn cargo: {}", Command::new(cargo).args(args).exec());
+    panic!("Failed to spawn cargo: {}", cmd.exec());
 
     #[cfg(not(unix))]
-    std::process::exit(
-        Command::new(cargo).args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
-    );
+    std::process::exit(cmd.spawn().unwrap().wait().unwrap().code().unwrap_or(1));
 }
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 83cbe0db633..c163b854384 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -49,6 +49,8 @@ rm tests/ui/proc-macro/allowed-signatures.rs
 # vendor intrinsics
 rm tests/ui/sse2.rs # cpuid not supported, so sse2 not detected
 rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
+rm tests/ui/simd/intrinsic/generic-bswap-byte.rs # simd_bswap not yet implemented
+rm tests/ui/simd/intrinsic/generic-arithmetic-pass.rs # many missing simd intrinsics
 
 # exotic linkages
 rm tests/ui/issues/issue-33992.rs # unsupported linkages
@@ -124,6 +126,8 @@ rm tests/ui/typeck/issue-46112.rs # same
 rm tests/ui/consts/const_cmp_type_id.rs # same
 rm tests/ui/consts/issue-73976-monomorphic.rs # same
 rm tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs # same
+rm tests/ui/consts/const-eval/nonnull_as_ref_ub.rs # same
+rm tests/ui/consts/issue-94675.rs # same
 
 # rustdoc-clif passes extra args, suppressing the help message when no args are passed
 rm -r tests/run-make/issue-88756-default-output
@@ -158,8 +162,6 @@ rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
 
 rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
 
-rm tests/ui/panic-handler/weak-lang-item-2.rs # Will be fixed by #113568
-
 cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist
 
 # prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by
@@ -172,7 +174,7 @@ index ea06b620c4c..b969d0009c6 100644
 @@ -9,7 +9,7 @@ RUSTC_ORIGINAL := \$(RUSTC)
  BARE_RUSTC := \$(HOST_RPATH_ENV) '\$(RUSTC)'
  BARE_RUSTDOC := \$(HOST_RPATH_ENV) '\$(RUSTDOC)'
- RUSTC := \$(BARE_RUSTC) --out-dir \$(TMPDIR) -L \$(TMPDIR) \$(RUSTFLAGS)
+ RUSTC := \$(BARE_RUSTC) --out-dir \$(TMPDIR) -L \$(TMPDIR) \$(RUSTFLAGS) -Ainternal_features
 -RUSTDOC := \$(BARE_RUSTDOC) -L \$(TARGET_RPATH_DIR)
 +RUSTDOC := \$(BARE_RUSTDOC)
  ifdef RUSTC_LINKER
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 2c038f22ca9..b7f56a2986c 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -48,7 +48,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
             default_call_conv
         }
 
-        Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"),
+        Conv::X86Intr | Conv::RiscvInterrupt { .. } => {
+            sess.fatal(format!("interrupt call conv {c:?} not yet implemented"))
+        }
 
         Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"),
         Conv::CCmseNonSecureCall => {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 3ea38842148..1c606494f38 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -98,7 +98,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         tcx.sess.fatal("JIT mode doesn't work with `cargo check`");
     }
 
-    if !tcx.sess.crate_types().contains(&rustc_session::config::CrateType::Executable) {
+    if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) {
         tcx.sess.fatal("can't jit non-executable crate");
     }
 
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index ebd153cb71d..d01ded8abaa 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -260,6 +260,13 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn isa::Tar
     flags_builder.set("enable_verifier", enable_verifier).unwrap();
     flags_builder.set("regalloc_checker", enable_verifier).unwrap();
 
+    let preserve_frame_pointer = sess.target.options.frame_pointer
+        != rustc_target::spec::FramePointer::MayOmit
+        || matches!(sess.opts.cg.force_frame_pointers, Some(true));
+    if preserve_frame_pointer {
+        flags_builder.set("preserve_frame_pointers", "true").unwrap();
+    }
+
     let tls_model = match target_triple.binary_format {
         BinaryFormat::Elf => "elf_gd",
         BinaryFormat::Macho => "macho",
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index e02b457fd0b..c6a7dc95d77 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -383,13 +383,16 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
     }
 
     fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
-        let mut func_attrs = SmallVec::<[_; 2]>::new();
+        let mut func_attrs = SmallVec::<[_; 3]>::new();
         if self.ret.layout.abi.is_uninhabited() {
             func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
         }
         if !self.can_unwind {
             func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(cx.llcx));
         }
+        if let Conv::RiscvInterrupt { kind } = self.conv {
+            func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
+        }
         attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
 
         let mut i = 0;
@@ -565,7 +568,9 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
 impl From<Conv> for llvm::CallConv {
     fn from(conv: Conv) -> Self {
         match conv {
-            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv,
+            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => {
+                llvm::CCallConv
+            }
             Conv::RustCold => llvm::ColdCallConv,
             Conv::AmdGpuKernel => llvm::AmdGpuKernel,
             Conv::AvrInterrupt => llvm::AvrInterrupt,
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 46e6daed21f..47cc5bd52e2 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -320,6 +320,7 @@ impl<'a> DiagnosticHandlers<'a> {
             })
             .and_then(|dir| dir.to_str().and_then(|p| CString::new(p).ok()));
 
+        let pgo_available = cgcx.opts.cg.profile_use.is_some();
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
             let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
@@ -333,6 +334,7 @@ impl<'a> DiagnosticHandlers<'a> {
                 // The `as_ref()` is important here, otherwise the `CString` will be dropped
                 // too soon!
                 remark_file.as_ref().map(|dir| dir.as_ptr()).unwrap_or(std::ptr::null()),
+                pgo_available,
             );
             DiagnosticHandlers { data, llcx, old_handler }
         }
@@ -470,6 +472,8 @@ pub(crate) unsafe fn llvm_optimize(
         Some(llvm::SanitizerOptions {
             sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
             sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
+            sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI),
+            sanitize_kcfi: config.sanitizer.contains(SanitizerSet::KCFI),
             sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
             sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
             sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int,
@@ -505,6 +509,7 @@ pub(crate) unsafe fn llvm_optimize(
         &*module.module_llvm.tm,
         to_pass_builder_opt_level(opt_level),
         opt_stage,
+        cgcx.opts.cg.linker_plugin_lto.enabled(),
         config.no_prepopulate_passes,
         config.verify_llvm_ir,
         using_thin_buffers,
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 5408481df48..ac6d8f84142 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1512,9 +1512,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
         llfn: &'ll Value,
     ) {
-        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
-        if is_indirect_call && fn_abi.is_some() && self.tcx.sess.is_sanitizer_cfi_enabled() {
-            if fn_attrs.is_some() && fn_attrs.unwrap().no_sanitize.contains(SanitizerSet::CFI) {
+        let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
+        if self.tcx.sess.is_sanitizer_cfi_enabled() && let Some(fn_abi) = fn_abi && is_indirect_call {
+            if let Some(fn_attrs) = fn_attrs && fn_attrs.no_sanitize.contains(SanitizerSet::CFI) {
                 return;
             }
 
@@ -1526,7 +1526,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
                 options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
             }
 
-            let typeid = typeid_for_fnabi(self.tcx, fn_abi.unwrap(), options);
+            let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
             let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
 
             // Test whether the function pointer is associated with the type identifier.
@@ -1550,25 +1550,26 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
         llfn: &'ll Value,
     ) -> Option<llvm::OperandBundleDef<'ll>> {
-        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
-        let kcfi_bundle = if is_indirect_call && self.tcx.sess.is_sanitizer_kcfi_enabled() {
-            if fn_attrs.is_some() && fn_attrs.unwrap().no_sanitize.contains(SanitizerSet::KCFI) {
-                return None;
-            }
+        let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
+        let kcfi_bundle =
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && let Some(fn_abi) = fn_abi && is_indirect_call {
+                if let Some(fn_attrs) = fn_attrs && fn_attrs.no_sanitize.contains(SanitizerSet::KCFI) {
+                    return None;
+                }
 
-            let mut options = TypeIdOptions::empty();
-            if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() {
-                options.insert(TypeIdOptions::GENERALIZE_POINTERS);
-            }
-            if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() {
-                options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
-            }
+                let mut options = TypeIdOptions::empty();
+                if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() {
+                    options.insert(TypeIdOptions::GENERALIZE_POINTERS);
+                }
+                if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() {
+                    options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
+                }
 
-            let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap(), options);
-            Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
-        } else {
-            None
-        };
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
+                Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            } else {
+                None
+            };
         kcfi_bundle
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index b4f7e20e05d..24fd5bbf8c5 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -209,7 +209,7 @@ pub unsafe fn create_module<'ll>(
         // PIE is potentially more effective than PIC, but can only be used in executables.
         // If all our outputs are executables, then we can relax PIC to PIE.
         if reloc_model == RelocModel::Pie
-            || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable)
+            || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
         {
             llvm::LLVMRustSetModulePIELevel(llmod);
         }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index db9ba0abbde..97a99e51056 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -12,8 +12,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_middle::ty::TyCtxt;
-
-use std::ffi::CString;
+use rustc_span::Symbol;
 
 /// Generates and exports the Coverage Map.
 ///
@@ -89,7 +88,10 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
 
     // Encode all filenames referenced by counters/expressions in this module
     let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
-        coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
+        coverageinfo::write_filenames_section_to_buffer(
+            mapgen.filenames.iter().map(Symbol::as_str),
+            filenames_buffer,
+        );
     });
 
     let filenames_size = filenames_buffer.len();
@@ -117,7 +119,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
 }
 
 struct CoverageMapGenerator {
-    filenames: FxIndexSet<CString>,
+    filenames: FxIndexSet<Symbol>,
 }
 
 impl CoverageMapGenerator {
@@ -128,11 +130,10 @@ impl CoverageMapGenerator {
         // Since rustc generates coverage maps with relative paths, the
         // compilation directory can be combined with the relative paths
         // to get absolute paths, if needed.
-        let working_dir =
-            tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy().to_string();
-        let c_filename =
-            CString::new(working_dir).expect("null error converting filename to C string");
-        filenames.insert(c_filename);
+        let working_dir = Symbol::intern(
+            &tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy(),
+        );
+        filenames.insert(working_dir);
         Self { filenames }
     }
 
@@ -170,10 +171,8 @@ impl CoverageMapGenerator {
                     current_file_id += 1;
                 }
                 current_file_name = Some(file_name);
-                let c_filename = CString::new(file_name.to_string())
-                    .expect("null error converting filename to C string");
-                debug!("  file_id: {} = '{:?}'", current_file_id, c_filename);
-                let (filenames_index, _) = self.filenames.insert_full(c_filename);
+                debug!("  file_id: {} = '{:?}'", current_file_id, file_name);
+                let (filenames_index, _) = self.filenames.insert_full(file_name);
                 virtual_file_mapping.push(filenames_index as u32);
             }
             debug!("Adding counter {:?} to map for {:?}", counter, region);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index afceb7531e6..621fd36b2a3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -25,7 +25,6 @@ use rustc_middle::ty::Instance;
 use rustc_middle::ty::Ty;
 
 use std::cell::RefCell;
-use std::ffi::CString;
 
 pub(crate) mod ffi;
 pub(crate) mod map_data;
@@ -332,21 +331,32 @@ fn create_pgo_func_name_var<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     instance: Instance<'tcx>,
 ) -> &'ll llvm::Value {
-    let mangled_fn_name = CString::new(cx.tcx.symbol_name(instance).name)
-        .expect("error converting function name to C string");
+    let mangled_fn_name: &str = cx.tcx.symbol_name(instance).name;
     let llfn = cx.get_fn(instance);
-    unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
+    unsafe {
+        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
+            llfn,
+            mangled_fn_name.as_ptr().cast(),
+            mangled_fn_name.len(),
+        )
+    }
 }
 
 pub(crate) fn write_filenames_section_to_buffer<'a>(
-    filenames: impl IntoIterator<Item = &'a CString>,
+    filenames: impl IntoIterator<Item = &'a str>,
     buffer: &RustString,
 ) {
-    let c_str_vec = filenames.into_iter().map(|cstring| cstring.as_ptr()).collect::<Vec<_>>();
+    let (pointers, lengths) = filenames
+        .into_iter()
+        .map(|s: &str| (s.as_ptr().cast(), s.len()))
+        .unzip::<_, _, Vec<_>, Vec<_>>();
+
     unsafe {
         llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer(
-            c_str_vec.as_ptr(),
-            c_str_vec.len(),
+            pointers.as_ptr(),
+            pointers.len(),
+            lengths.as_ptr(),
+            lengths.len(),
             buffer,
         );
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index ef7c661936a..425e935bc9f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -92,7 +92,7 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
     // each rlib could produce a different set of visualizers that would be embedded
     // in the `.debug_gdb_scripts` section. For that reason, we make sure that the
     // section is only emitted for leaf crates.
-    let embed_visualizers = cx.sess().crate_types().iter().any(|&crate_type| match crate_type {
+    let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type {
         CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
             // These are crate types for which we will embed pretty printers since they
             // are treated as leaf crates.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index b167facfb02..84157d1e25c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -475,6 +475,8 @@ pub enum OptStage {
 pub struct SanitizerOptions {
     pub sanitize_address: bool,
     pub sanitize_address_recover: bool,
+    pub sanitize_cfi: bool,
+    pub sanitize_kcfi: bool,
     pub sanitize_memory: bool,
     pub sanitize_memory_recover: bool,
     pub sanitize_memory_track_origins: c_int,
@@ -894,6 +896,7 @@ extern "C" {
     pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
     pub fn LLVMIsAFunction(Val: &Value) -> Option<&Value>;
+    pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
 
     // Operations on constants of any type
     pub fn LLVMConstNull(Ty: &Type) -> &Value;
@@ -1704,6 +1707,8 @@ extern "C" {
     pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
         Filenames: *const *const c_char,
         FilenamesLen: size_t,
+        Lengths: *const size_t,
+        LengthsLen: size_t,
         BufferOut: &RustString,
     );
 
@@ -1718,7 +1723,11 @@ extern "C" {
         BufferOut: &RustString,
     );
 
-    pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &Value, FuncName: *const c_char) -> &Value;
+    pub fn LLVMRustCoverageCreatePGOFuncNameVar(
+        F: &Value,
+        FuncName: *const c_char,
+        FuncNameLen: size_t,
+    ) -> &Value;
     pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
 
     #[allow(improper_ctypes)]
@@ -2138,6 +2147,7 @@ extern "C" {
         TM: &'a TargetMachine,
         OptLevel: PassBuilderOptLevel,
         OptStage: OptStage,
+        IsLinkerPluginLTO: bool,
         NoPrepopulatePasses: bool,
         VerifyIR: bool,
         UseThinLTOBuffers: bool,
@@ -2332,6 +2342,7 @@ extern "C" {
         remark_passes: *const *const c_char,
         remark_passes_len: usize,
         remark_file: *const c_char,
+        pgo_available: bool,
     );
 
     #[allow(improper_ctypes)]
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index e8cda626f54..38e8220569a 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -111,7 +111,7 @@ impl CodegenCx<'_, '_> {
         }
 
         // Symbols from executables can't really be imported any further.
-        let all_exe = self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable);
+        let all_exe = self.tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable);
         let is_declaration_for_linker =
             is_declaration || linkage == llvm::Linkage::AvailableExternallyLinkage;
         if all_exe && !is_declaration_for_linker {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index cd6201648ee..bb65c3c81d9 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -69,7 +69,7 @@ pub fn link_binary<'a>(
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
-    for &crate_type in sess.crate_types().iter() {
+    for &crate_type in &codegen_results.crate_info.crate_types {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
         if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
             && !output_metadata
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 4c04fc60b98..11afe0fbc3c 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -13,6 +13,7 @@ use std::{env, mem, str};
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_metadata::find_native_static_library;
 use rustc_middle::middle::dependency_format::Linkage;
+use rustc_middle::middle::exported_symbols;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
@@ -659,8 +660,6 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
-        // FIXME(#99978) hide #[no_mangle] symbols for proc-macros
-
         let is_windows = self.sess.target.is_like_windows;
         let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
 
@@ -1679,8 +1678,15 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
         return exports.iter().map(ToString::to_string).collect();
     }
 
-    let mut symbols = Vec::new();
+    if let CrateType::ProcMacro = crate_type {
+        exported_symbols_for_proc_macro_crate(tcx)
+    } else {
+        exported_symbols_for_non_proc_macro(tcx, crate_type)
+    }
+}
 
+fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
+    let mut symbols = Vec::new();
     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
     for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
         if info.level.is_below_threshold(export_threshold) {
@@ -1691,6 +1697,19 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
     symbols
 }
 
+fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
+    // `exported_symbols` will be empty when !should_codegen.
+    if !tcx.sess.opts.output_types.should_codegen() {
+        return Vec::new();
+    }
+
+    let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
+    let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+    let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
+
+    vec![proc_macro_decls_name, metadata_symbol_name]
+}
+
 pub(crate) fn linked_symbols(
     tcx: TyCtxt<'_>,
     crate_type: CrateType,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 326b28ad104..8fb2ccb7e8a 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -19,7 +19,7 @@ use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
-    crates_export_threshold(&tcx.sess.crate_types())
+    crates_export_threshold(tcx.crate_types())
 }
 
 fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
@@ -290,8 +290,8 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if tcx.sess.crate_types().contains(&CrateType::Dylib)
-        || tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+    if tcx.crate_types().contains(&CrateType::Dylib)
+        || tcx.crate_types().contains(&CrateType::ProcMacro)
     {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 40718525741..f485af00bca 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -123,7 +123,7 @@ pub struct ModuleConfig {
 impl ModuleConfig {
     fn new(
         kind: ModuleKind,
-        sess: &Session,
+        tcx: TyCtxt<'_>,
         no_builtins: bool,
         is_compiler_builtins: bool,
     ) -> ModuleConfig {
@@ -135,6 +135,7 @@ impl ModuleConfig {
             };
         }
 
+        let sess = tcx.sess;
         let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None);
 
         let save_temps = sess.opts.cg.save_temps;
@@ -166,7 +167,7 @@ impl ModuleConfig {
             // `#![no_builtins]` is assumed to not participate in LTO and
             // instead goes on to generate object code.
             EmitObj::Bitcode
-        } else if need_bitcode_in_object(sess) {
+        } else if need_bitcode_in_object(tcx) {
             EmitObj::ObjectCode(BitcodeSection::Full)
         } else {
             EmitObj::ObjectCode(BitcodeSection::None)
@@ -414,9 +415,10 @@ pub struct CompiledModules {
     pub allocator_module: Option<CompiledModule>,
 }
 
-fn need_bitcode_in_object(sess: &Session) -> bool {
+fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
+    let sess = tcx.sess;
     let requested_for_rlib = sess.opts.cg.embed_bitcode
-        && sess.crate_types().contains(&CrateType::Rlib)
+        && tcx.crate_types().contains(&CrateType::Rlib)
         && sess.opts.output_types.contains_key(&OutputType::Exe);
     let forced_by_target = sess.target.forces_embed_bitcode;
     requested_for_rlib || forced_by_target
@@ -450,11 +452,11 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     let crate_info = CrateInfo::new(tcx, target_cpu);
 
     let regular_config =
-        ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins);
     let metadata_config =
-        ModuleConfig::new(ModuleKind::Metadata, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins, is_compiler_builtins);
     let allocator_config =
-        ModuleConfig::new(ModuleKind::Allocator, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins);
 
     let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
     let (codegen_worker_send, codegen_worker_receive) = channel();
@@ -1092,7 +1094,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     };
 
     let cgcx = CodegenContext::<B> {
-        crate_types: sess.crate_types().to_vec(),
+        crate_types: tcx.crate_types().to_vec(),
         each_linked_rlib_for_lto,
         lto: sess.lto(),
         fewer_names: sess.fewer_names(),
@@ -2063,7 +2065,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     );
 
     tcx.sess.target.is_like_windows &&
-        tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
+        tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
     // ThinLTO can't handle this workaround in all cases, so we don't
     // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
     // dynamic linking when linker plugin LTO is enabled.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 4819ab22723..aa003e4e898 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -779,18 +779,13 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
 impl CrateInfo {
     pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
-        let exported_symbols = tcx
-            .sess
-            .crate_types()
+        let crate_types = tcx.crate_types().to_vec();
+        let exported_symbols = crate_types
             .iter()
             .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
             .collect();
-        let linked_symbols = tcx
-            .sess
-            .crate_types()
-            .iter()
-            .map(|&c| (c, crate::back::linker::linked_symbols(tcx, c)))
-            .collect();
+        let linked_symbols =
+            crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
         let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
         let subsystem = attr::first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
@@ -829,6 +824,7 @@ impl CrateInfo {
 
         let mut info = CrateInfo {
             target_cpu,
+            crate_types,
             exported_symbols,
             linked_symbols,
             local_crate_name,
@@ -916,7 +912,7 @@ impl CrateInfo {
                 });
         }
 
-        let embed_visualizers = tcx.sess.crate_types().iter().any(|&crate_type| match crate_type {
+        let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type {
             CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => {
                 // These are crate types for which we invoke the linker and can embed
                 // NatVis visualizers.
@@ -1013,7 +1009,7 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
         match compute_per_cgu_lto_type(
             &tcx.sess.lto(),
             &tcx.sess.opts,
-            &tcx.sess.crate_types(),
+            tcx.crate_types(),
             ModuleKind::Regular,
         ) {
             ComputedLtoType::No => CguReuse::PostLto,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index be4c81638d6..f577f653ccd 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -150,6 +150,7 @@ impl From<&cstore::NativeLib> for NativeLib {
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
     pub target_cpu: String,
+    pub crate_types: Vec<CrateType>,
     pub exported_symbols: FxHashMap<CrateType, Vec<String>>,
     pub linked_symbols: FxHashMap<CrateType, Vec<(String, SymbolExportKind)>>,
     pub local_crate_name: Symbol,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 0b336109921..e5dd5729d89 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -303,8 +303,6 @@ const_eval_remainder_overflow =
     overflow in signed remainder (dividing MIN by -1)
 const_eval_scalar_size_mismatch =
     scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead
-const_eval_size_of_unsized =
-    size_of called on unsized type `{$ty}`
 const_eval_size_overflow =
     overflow computing total size of `{$name}`
 
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index cc39387c41f..4ee4ebbb9e4 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -40,7 +40,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
         | hir::Node::AnonConst(_)
         | hir::Node::ConstBlock(_)
         | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => hir::Constness::Const,
-        hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => tcx.generics_of(def_id).host_effect_index.map_or(hir::Constness::NotConst, |_| hir::Constness::Const),
         hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
             // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
             // foreign items cannot be evaluated at compile-time.
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index f785bcfed6c..b15a65d67a3 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -7,9 +7,10 @@ use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
     MemoryKind, Place, Projectable, Scalar,
 };
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
-use rustc_target::abi::{Align, FieldIdx, VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::VariantIdx;
 
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
@@ -154,52 +155,37 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
     }
 }
 
-#[instrument(skip(ecx), level = "debug")]
-fn create_mplace_from_layout<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
-    ty: Ty<'tcx>,
-) -> MPlaceTy<'tcx> {
-    let tcx = ecx.tcx;
-    let param_env = ecx.param_env;
-    let layout = tcx.layout_of(param_env.and(ty)).unwrap();
-    debug!(?layout);
-
-    ecx.allocate(layout, MemoryKind::Stack).unwrap()
-}
-
-// Walks custom DSTs and gets the type of the unsized field and the number of elements
-// in the unsized field.
-fn get_info_on_unsized_field<'tcx>(
-    ty: Ty<'tcx>,
+/// Valtrees don't store the `MemPlaceMeta` that all dynamically sized values have in the interpreter.
+/// This function reconstructs it.
+fn reconstruct_place_meta<'tcx>(
+    layout: TyAndLayout<'tcx>,
     valtree: ty::ValTree<'tcx>,
     tcx: TyCtxt<'tcx>,
-) -> (Ty<'tcx>, usize) {
+) -> MemPlaceMeta {
+    if layout.is_sized() {
+        return MemPlaceMeta::None;
+    }
+
     let mut last_valtree = valtree;
+    // Traverse the type, and update `last_valtree` as we go.
     let tail = tcx.struct_tail_with_normalize(
-        ty,
+        layout.ty,
         |ty| ty,
         || {
             let branches = last_valtree.unwrap_branch();
-            last_valtree = branches[branches.len() - 1];
+            last_valtree = *branches.last().unwrap();
             debug!(?branches, ?last_valtree);
         },
     );
-    let unsized_inner_ty = match tail.kind() {
-        ty::Slice(t) => *t,
-        ty::Str => tail,
-        _ => bug!("expected Slice or Str"),
-    };
-
-    // Have to adjust type for ty::Str
-    let unsized_inner_ty = match unsized_inner_ty.kind() {
-        ty::Str => tcx.types.u8,
-        _ => unsized_inner_ty,
+    // Sanity-check that we got a tail we support.
+    match tail.kind() {
+        ty::Slice(..) | ty::Str => {}
+        _ => bug!("unsized tail of a valtree must be Slice or Str"),
     };
 
-    // Get the number of elements in the unsized field
+    // Get the number of elements in the unsized field.
     let num_elems = last_valtree.unwrap_branch().len();
-
-    (unsized_inner_ty, num_elems)
+    MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx))
 }
 
 #[instrument(skip(ecx), level = "debug", ret)]
@@ -208,41 +194,9 @@ fn create_pointee_place<'tcx>(
     ty: Ty<'tcx>,
     valtree: ty::ValTree<'tcx>,
 ) -> MPlaceTy<'tcx> {
-    let tcx = ecx.tcx.tcx;
-
-    if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) {
-        // We need to create `Allocation`s for custom DSTs
-
-        let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
-        let unsized_inner_ty = match unsized_inner_ty.kind() {
-            ty::Str => tcx.types.u8,
-            _ => unsized_inner_ty,
-        };
-        let unsized_inner_ty_size =
-            tcx.layout_of(ty::ParamEnv::empty().and(unsized_inner_ty)).unwrap().layout.size();
-        debug!(?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems);
-
-        // for custom DSTs only the last field/element is unsized, but we need to also allocate
-        // space for the other fields/elements
-        let layout = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap();
-        let size_of_sized_part = layout.layout.size();
-
-        // Get the size of the memory behind the DST
-        let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
-
-        let size = size_of_sized_part.checked_add(dst_size, &tcx).unwrap();
-        let align = Align::from_bytes(size.bytes().next_power_of_two()).unwrap();
-        let ptr = ecx.allocate_ptr(size, align, MemoryKind::Stack).unwrap();
-        debug!(?ptr);
-
-        MPlaceTy::from_aligned_ptr_with_meta(
-            ptr.into(),
-            layout,
-            MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx)),
-        )
-    } else {
-        create_mplace_from_layout(ecx, ty)
-    }
+    let layout = ecx.layout_of(ty).unwrap();
+    let meta = reconstruct_place_meta(layout, valtree, ecx.tcx.tcx);
+    ecx.allocate_dyn(layout, MemoryKind::Stack, meta).unwrap()
 }
 
 /// Converts a `ValTree` to a `ConstValue`, which is needed after mir
@@ -282,10 +236,13 @@ pub fn valtree_to_const_value<'tcx>(
         ty::Ref(_, _, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
             let place = match ty.kind() {
                 ty::Ref(_, inner_ty, _) => {
-                    // Need to create a place for the pointee to fill for Refs
+                    // Need to create a place for the pointee (the reference itself will be an immediate)
                     create_pointee_place(&mut ecx, *inner_ty, valtree)
                 }
-                _ => create_mplace_from_layout(&mut ecx, ty),
+                _ => {
+                    // Need to create a place for this valtree.
+                    create_pointee_place(&mut ecx, ty, valtree)
+                }
             };
             debug!(?place);
 
@@ -399,45 +356,8 @@ fn valtree_into_mplace<'tcx>(
                 debug!(?i, ?inner_valtree);
 
                 let place_inner = match ty.kind() {
-                    ty::Str | ty::Slice(_) => ecx.project_index(place, i as u64).unwrap(),
-                    _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty())
-                        && i == branches.len() - 1 =>
-                    {
-                        // Note: For custom DSTs we need to manually process the last unsized field.
-                        // We created a `Pointer` for the `Allocation` of the complete sized version of
-                        // the Adt in `create_pointee_place` and now we fill that `Allocation` with the
-                        // values in the ValTree. For the unsized field we have to additionally add the meta
-                        // data.
-
-                        let (unsized_inner_ty, num_elems) =
-                            get_info_on_unsized_field(ty, valtree, tcx);
-                        debug!(?unsized_inner_ty);
-
-                        let inner_ty = match ty.kind() {
-                            ty::Adt(def, args) => {
-                                let i = FieldIdx::from_usize(i);
-                                def.variant(FIRST_VARIANT).fields[i].ty(tcx, args)
-                            }
-                            ty::Tuple(inner_tys) => inner_tys[i],
-                            _ => bug!("unexpected unsized type {:?}", ty),
-                        };
-
-                        let inner_layout =
-                            tcx.layout_of(ty::ParamEnv::empty().and(inner_ty)).unwrap();
-                        debug!(?inner_layout);
-
-                        let offset = place_adjusted.layout.fields.offset(i);
-                        place
-                            .offset_with_meta(
-                                offset,
-                                MemPlaceMeta::Meta(Scalar::from_target_usize(
-                                    num_elems as u64,
-                                    &tcx,
-                                )),
-                                inner_layout,
-                                &tcx,
-                            )
-                            .unwrap()
+                    ty::Str | ty::Slice(_) | ty::Array(..) => {
+                        ecx.project_index(place, i as u64).unwrap()
                     }
                     _ => ecx.project_field(&place_adjusted, i).unwrap(),
                 };
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 3a4e2648b80..4362cae7ed7 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -862,7 +862,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
             InvalidProgramInfo::FnAbiAdjustForForeignAbi(_) => {
                 rustc_middle::error::middle_adjust_for_foreign_abi_error
             }
-            InvalidProgramInfo::SizeOfUnsizedType(_) => const_eval_size_of_unsized,
             InvalidProgramInfo::ConstPropNonsense => {
                 panic!("We had const-prop nonsense, this should never be printed")
             }
@@ -890,9 +889,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
                 builder.set_arg("arch", arch);
                 builder.set_arg("abi", abi.name());
             }
-            InvalidProgramInfo::SizeOfUnsizedType(ty) => {
-                builder.set_arg("ty", ty);
-            }
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index ec226808f1b..daadb758964 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -934,14 +934,26 @@ where
         Ok(MPlaceTy { mplace, layout: place.layout, align: place.align })
     }
 
+    pub fn allocate_dyn(
+        &mut self,
+        layout: TyAndLayout<'tcx>,
+        kind: MemoryKind<M::MemoryKind>,
+        meta: MemPlaceMeta<M::Provenance>,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+        let Some((size, align)) = self.size_and_align_of(&meta, &layout)? else {
+            span_bug!(self.cur_span(), "cannot allocate space for `extern` type, size is not known")
+        };
+        let ptr = self.allocate_ptr(size, align, kind)?;
+        Ok(MPlaceTy::from_aligned_ptr_with_meta(ptr.into(), layout, meta))
+    }
+
     pub fn allocate(
         &mut self,
         layout: TyAndLayout<'tcx>,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
         assert!(layout.is_sized());
-        let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?;
-        Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout))
+        self.allocate_dyn(layout, kind, MemPlaceMeta::None)
     }
 
     /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation.
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index f04c73105d2..0740894a4ff 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -269,13 +269,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
                 let layout = self.layout_of(ty)?;
                 if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() {
-                    // FIXME: This should be a span_bug, but const generics can run MIR
-                    // that is not properly type-checked yet (#97477).
-                    self.tcx.sess.delay_span_bug(
+                    span_bug!(
                         self.frame().current_span(),
-                        format!("{null_op:?} MIR operator called for unsized type {ty}"),
+                        "{null_op:?} MIR operator called for unsized type {ty}",
                     );
-                    throw_inval!(SizeOfUnsizedType(ty));
                 }
                 let val = match null_op {
                     mir::NullOp::SizeOf => layout.size.bytes(),
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 1bd21473182..3c03172bbef 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -393,15 +393,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ));
             assert_eq!(dest_offset, None);
             // Allocate enough memory to hold `src`.
-            let Some((size, align)) = self.size_and_align_of_mplace(&src)? else {
-                span_bug!(
-                    self.cur_span(),
-                    "unsized fn arg with `extern` type tail should not be allowed"
-                )
-            };
-            let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?;
-            let dest_place =
-                MPlaceTy::from_aligned_ptr_with_meta(ptr.into(), callee_arg.layout, src.meta);
+            let dest_place = self.allocate_dyn(src.layout, MemoryKind::Stack, src.meta)?;
             // Update the local to be that new place.
             *M::access_local_mut(self, dest_frame, dest_local)? = Operand::Indirect(*dest_place);
         }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index e77fb4ea2a2..e51082e1ec0 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -127,15 +127,8 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
 
     let Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false };
-    let parent_def = tcx.hir().get(parent);
-
-    if !matches!(
-        parent_def,
-        hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
-            ..
-        })
-    ) {
+
+    if !tcx.is_const_trait_impl_raw(parent.owner.def_id.to_def_id()) {
         return false;
     }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index e785196c744..1f3cda35c2b 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -145,8 +145,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     let implsrc = selcx.select(&obligation);
 
                     if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
-                        let span = tcx.def_span(data.impl_def_id);
-                        err.subdiagnostic(errors::NonConstImplNote { span });
+                        // FIXME(effects) revisit this
+                        if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
+                            let span = tcx.def_span(data.impl_def_id);
+                            err.subdiagnostic(errors::NonConstImplNote { span });
+                        }
                     }
                 }
                 _ => {}
diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs
index 58704350706..a3eb2b9c416 100644
--- a/compiler/rustc_data_structures/src/base_n.rs
+++ b/compiler/rustc_data_structures/src/base_n.rs
@@ -30,7 +30,10 @@ pub fn push_str(mut n: u128, base: usize, output: &mut String) {
         }
     }
 
-    output.push_str(str::from_utf8(&s[index..]).unwrap());
+    output.push_str(unsafe {
+        // SAFETY: `s` is populated using only valid utf8 characters from `BASE_64`
+        str::from_utf8_unchecked(&s[index..])
+    });
 }
 
 #[inline]
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 60dc9b20077..7bbed0877f0 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -32,7 +32,7 @@ use rustc_feature::find_gated_cfg;
 use rustc_fluent_macro::fluent_messages;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
-use rustc_lint::LintStore;
+use rustc_lint::{unerased_lint_store, LintStore};
 use rustc_metadata::locator;
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
@@ -411,15 +411,11 @@ fn run_compiler(
                 return early_exit();
             }
 
-            {
-                let plugins = queries.register_plugins()?;
-                let (.., lint_store) = &*plugins.borrow();
-
-                // Lint plugins are registered; now we can process command line flags.
-                if sess.opts.describe_lints {
-                    describe_lints(sess, lint_store, true);
-                    return early_exit();
-                }
+            if sess.opts.describe_lints {
+                queries
+                    .global_ctxt()?
+                    .enter(|tcx| describe_lints(sess, unerased_lint_store(tcx), true));
+                return early_exit();
             }
 
             // Make sure name resolution and macro expansion is run.
@@ -657,8 +653,6 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
 pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
     if sess.opts.unstable_opts.link_only {
         if let Input::File(file) = &sess.io.input {
-            // FIXME: #![crate_type] and #![crate_name] support not implemented yet
-            sess.init_crate_types(collect_crate_types(sess, &[]));
             let outputs = compiler.build_output_filenames(sess, &[]);
             let rlink_data = fs::read(file).unwrap_or_else(|err| {
                 sess.emit_fatal(RlinkUnableToRead { err });
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index ede3570510a..898f5fd3b70 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -313,6 +313,8 @@ declare_features! (
     (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
     /// Allows `extern "ptx-*" fn()`.
     (active, abi_ptx, "1.15.0", Some(38788), None),
+    /// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`.
+    (active, abi_riscv_interrupt, "CURRENT_RUSTC_VERSION", Some(111889), None),
     /// Allows `extern "x86-interrupt" fn()`.
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
     /// Allows additional const parameter types, such as `&'static str` or user defined types
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c6f8d1e211d..6340f1dcca1 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1843,7 +1843,7 @@ impl Expr<'_> {
                 .iter()
                 .map(|field| field.expr)
                 .chain(init.into_iter())
-                .all(|e| e.can_have_side_effects()),
+                .any(|e| e.can_have_side_effects()),
 
             ExprKind::Array(args)
             | ExprKind::Tup(args)
@@ -1857,7 +1857,7 @@ impl Expr<'_> {
                     ..
                 },
                 args,
-            ) => args.iter().all(|arg| arg.can_have_side_effects()),
+            ) => args.iter().any(|arg| arg.can_have_side_effects()),
             ExprKind::If(..)
             | ExprKind::Match(..)
             | ExprKind::MethodCall(..)
@@ -2675,7 +2675,7 @@ pub struct OpaqueTy<'hir> {
     ///
     /// 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 [(&'hir Lifetime, LocalDefId)]>,
+    pub lifetime_mapping: &'hir [(&'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.
@@ -3359,7 +3359,6 @@ pub struct Impl<'hir> {
     // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
     // decoding as `Span`s cannot be decoded when a `Session` is not available.
     pub defaultness_span: Option<Span>,
-    pub constness: Constness,
     pub generics: &'hir Generics<'hir>,
 
     /// The trait being implemented, if any.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 9d1d899eef0..172f557f8e2 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -522,7 +522,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             unsafety: _,
             defaultness: _,
             polarity: _,
-            constness: _,
             defaultness_span: _,
             ref generics,
             ref of_trait,
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 319573c85b4..668763f9bf6 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -532,6 +532,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         if let Err(guar) = ty.error_reported() {
                             return ty::Const::new_error(tcx, guar, ty).into();
                         }
+                        // FIXME(effects) see if we should special case effect params here
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id)
                                 .instantiate(tcx, args.unwrap())
@@ -659,7 +660,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         trait_ref: &hir::TraitRef<'_>,
         self_ty: Ty<'tcx>,
-        constness: ty::BoundConstness,
     ) -> ty::TraitRef<'tcx> {
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
 
@@ -669,7 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self_ty,
             trait_ref.path.segments.last().unwrap(),
             true,
-            constness,
+            ty::BoundConstness::NotConst,
         )
     }
 
@@ -849,6 +849,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         trait_segment: &hir::PathSegment<'_>,
         is_impl: bool,
+        // FIXME(effects) move all host param things in astconv to hir lowering
         constness: ty::BoundConstness,
     ) -> ty::TraitRef<'tcx> {
         let (generic_args, _) = self.create_args_for_ast_trait_ref(
@@ -2714,11 +2715,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         };
         let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
 
-        let trait_ref = self.instantiate_mono_trait_ref(
-            i.of_trait.as_ref()?,
-            self.ast_ty_to_ty(i.self_ty),
-            ty::BoundConstness::NotConst,
-        );
+        let trait_ref =
+            self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
 
         let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
             tcx,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 49307d96cc2..8a5099804ed 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -407,7 +407,17 @@ fn check_opaque_meets_bounds<'tcx>(
         .build();
     let ocx = ObligationCtxt::new(&infcx);
 
-    let args = GenericArgs::identity_for_item(tcx, def_id.to_def_id());
+    let args = match *origin {
+        hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
+            GenericArgs::identity_for_item(tcx, parent).extend_to(
+                tcx,
+                def_id.to_def_id(),
+                |param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(),
+            )
+        }
+        hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id),
+    };
+
     let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
 
     // `ReErased` regions appear in the "parent_args" of closures/generators.
@@ -468,9 +478,10 @@ fn check_opaque_meets_bounds<'tcx>(
         }
     }
     // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
-    for (key, mut ty) in infcx.take_opaque_types() {
+    for (mut key, mut ty) in infcx.take_opaque_types() {
         ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
-        sanity_check_found_hidden_type(tcx, key, ty.hidden_type, defining_use_anchor, origin)?;
+        key = infcx.resolve_vars_if_possible(key);
+        sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
     }
     Ok(())
 }
@@ -479,8 +490,6 @@ fn sanity_check_found_hidden_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::OpaqueTypeKey<'tcx>,
     mut ty: ty::OpaqueHiddenType<'tcx>,
-    defining_use_anchor: LocalDefId,
-    origin: &hir::OpaqueTyOrigin,
 ) -> Result<(), ErrorGuaranteed> {
     if ty.ty.is_ty_var() {
         // Nothing was actually constrained.
@@ -493,29 +502,23 @@ fn sanity_check_found_hidden_type<'tcx>(
             return Ok(());
         }
     }
+    let strip_vars = |ty: Ty<'tcx>| {
+        ty.fold_with(&mut BottomUpFolder {
+            tcx,
+            ty_op: |t| t,
+            ct_op: |c| c,
+            lt_op: |l| match l.kind() {
+                RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
+                _ => l,
+            },
+        })
+    };
     // Closures frequently end up containing erased lifetimes in their final representation.
     // These correspond to lifetime variables that never got resolved, so we patch this up here.
-    ty.ty = ty.ty.fold_with(&mut BottomUpFolder {
-        tcx,
-        ty_op: |t| t,
-        ct_op: |c| c,
-        lt_op: |l| match l.kind() {
-            RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
-            _ => l,
-        },
-    });
+    ty.ty = strip_vars(ty.ty);
     // Get the hidden type.
-    let mut hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
-    if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin {
-        if hidden_ty != ty.ty {
-            hidden_ty = find_and_apply_rpit_args(
-                tcx,
-                hidden_ty,
-                defining_use_anchor.to_def_id(),
-                key.def_id.to_def_id(),
-            )?;
-        }
-    }
+    let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
+    let hidden_ty = strip_vars(hidden_ty);
 
     // If the hidden types differ, emit a type mismatch diagnostic.
     if hidden_ty == ty.ty {
@@ -527,105 +530,6 @@ fn sanity_check_found_hidden_type<'tcx>(
     }
 }
 
-/// In case it is in a nested opaque type, find that opaque type's
-/// usage in the function signature and use the generic arguments from the usage site.
-/// We need to do because RPITs ignore the lifetimes of the function,
-/// as they have their own copies of all the lifetimes they capture.
-/// So the only way to get the lifetimes represented in terms of the function,
-/// is to look how they are used in the function signature (or do some other fancy
-/// recording of this mapping at ast -> hir lowering time).
-///
-/// As an example:
-/// ```text
-/// trait Id {
-///     type Assoc;
-/// }
-/// impl<'a> Id for &'a () {
-///     type Assoc = &'a ();
-/// }
-/// fn func<'a>(x: &'a ()) -> impl Id<Assoc = impl Sized + 'a> { x }
-/// // desugared to
-/// fn func<'a>(x: &'a () -> Outer<'a> where <Outer<'a> as Id>::Assoc = Inner<'a> {
-///     // Note that in contrast to other nested items, RPIT type aliases can
-///     // access their parents' generics.
-///
-///     // hidden type is `&'aDupOuter ()`
-///     // During wfcheck the hidden type of `Inner<'aDupOuter>` is `&'a ()`, but
-///     // `typeof(Inner<'aDupOuter>) = &'aDupOuter ()`.
-///     // So we walk the signature of `func` to find the use of `Inner<'a>`
-///     // and then use that to replace the lifetimes in the hidden type, obtaining
-///     // `&'a ()`.
-///     type Outer<'aDupOuter> = impl Id<Assoc = Inner<'aDupOuter>>;
-///
-///     // hidden type is `&'aDupInner ()`
-///     type Inner<'aDupInner> = impl Sized + 'aDupInner;
-///
-///     x
-/// }
-/// ```
-fn find_and_apply_rpit_args<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mut hidden_ty: Ty<'tcx>,
-    function: DefId,
-    opaque: DefId,
-) -> Result<Ty<'tcx>, ErrorGuaranteed> {
-    // Find use of the RPIT in the function signature and thus find the right args to
-    // convert it into the parameter space of the function signature. This is needed,
-    // because that's what `type_of` returns, against which we compare later.
-    let ret = tcx.fn_sig(function).instantiate_identity().output();
-    struct Visitor<'tcx> {
-        tcx: TyCtxt<'tcx>,
-        opaque: DefId,
-        seen: FxHashSet<DefId>,
-    }
-    impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
-        type BreakTy = GenericArgsRef<'tcx>;
-
-        #[instrument(level = "trace", skip(self), ret)]
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-            trace!("{:#?}", t.kind());
-            match t.kind() {
-                ty::Alias(ty::Opaque, alias) => {
-                    trace!(?alias.def_id);
-                    if alias.def_id == self.opaque {
-                        return ControlFlow::Break(alias.args);
-                    } else if self.seen.insert(alias.def_id) {
-                        for clause in self
-                            .tcx
-                            .explicit_item_bounds(alias.def_id)
-                            .iter_instantiated_copied(self.tcx, alias.args)
-                        {
-                            trace!(?clause);
-                            clause.visit_with(self)?;
-                        }
-                    }
-                }
-                ty::Alias(ty::Weak, alias) => {
-                    self.tcx
-                        .type_of(alias.def_id)
-                        .instantiate(self.tcx, alias.args)
-                        .visit_with(self)?;
-                }
-                _ => (),
-            }
-
-            t.super_visit_with(self)
-        }
-    }
-    if let ControlFlow::Break(args) =
-        ret.visit_with(&mut Visitor { tcx, opaque, seen: Default::default() })
-    {
-        trace!(?args);
-        trace!("expected: {hidden_ty:#?}");
-        hidden_ty = ty::EarlyBinder::bind(hidden_ty).instantiate(tcx, args);
-        trace!("expected: {hidden_ty:#?}");
-    } else {
-        tcx.sess
-            .delay_span_bug(tcx.def_span(function), format!("{ret:?} does not contain {opaque:?}"));
-    }
-    Ok(hidden_ty)
-}
-
 fn is_enum_of_nonnullable_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
     adt_def: AdtDef<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f568b751951..02a5d28b1e2 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1359,38 +1359,60 @@ fn impl_trait_ref(
         .as_ref()
         .map(|ast_trait_ref| {
             let selfty = tcx.type_of(def_id).instantiate_identity();
-            icx.astconv().instantiate_mono_trait_ref(
-                ast_trait_ref,
-                selfty,
-                check_impl_constness(tcx, impl_.constness, ast_trait_ref),
-            )
+
+            if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
+                tcx,
+                tcx.is_const_trait_impl_raw(def_id.to_def_id()),
+                &ast_trait_ref,
+            ) {
+                // we have a const impl, but for a trait without `#[const_trait]`, so
+                // without the host param. If we continue with the HIR trait ref, we get
+                // ICEs for generic arg count mismatch. We do a little HIR editing to
+                // make astconv happy.
+                let mut path_segments = ast_trait_ref.path.segments.to_vec();
+                let last_segment = path_segments.len() - 1;
+                let mut args = path_segments[last_segment].args().clone();
+                let last_arg = args.args.len() - 1;
+                assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host)));
+                args.args = &args.args[..args.args.len() - 1];
+                path_segments[last_segment].args = Some(&args);
+                let path = hir::Path {
+                    span: ast_trait_ref.path.span,
+                    res: ast_trait_ref.path.res,
+                    segments: &path_segments,
+                };
+                let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id };
+                icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty)
+            } else {
+                icx.astconv().instantiate_mono_trait_ref(&ast_trait_ref, selfty)
+            }
         })
         .map(ty::EarlyBinder::bind)
 }
 
 fn check_impl_constness(
     tcx: TyCtxt<'_>,
-    constness: hir::Constness,
+    is_const: bool,
     ast_trait_ref: &hir::TraitRef<'_>,
-) -> ty::BoundConstness {
-    match constness {
-        hir::Constness::Const => {
-            if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
-                let trait_name = tcx.item_name(trait_def_id).to_string();
-                tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
-                    trait_ref_span: ast_trait_ref.path.span,
-                    trait_name,
-                    local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
-                    marking: (),
-                    adding: (),
-                });
-                ty::BoundConstness::NotConst
-            } else {
-                ty::BoundConstness::ConstIfConst
-            }
-        },
-        hir::Constness::NotConst => ty::BoundConstness::NotConst,
+) -> Option<ErrorGuaranteed> {
+    if !is_const {
+        return None;
     }
+
+    let trait_def_id = ast_trait_ref.trait_def_id()?;
+    if tcx.has_attr(trait_def_id, sym::const_trait) {
+        return None;
+    }
+
+    let trait_name = tcx.item_name(trait_def_id).to_string();
+    Some(tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
+        trait_ref_span: ast_trait_ref.path.span,
+        trait_name,
+        local_trait_span:
+            trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
+        marking: (),
+        adding: (),
+    }))
 }
 
 fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 6e1762c54f2..4842008279a 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
                 }
 
-                host_effect_index = Some(parent_count + index as usize);
+                host_effect_index = Some(index as usize);
             }
 
             Some(ty::GenericParamDef {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 83220be6883..495e663666c 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -2,16 +2,16 @@ use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
-use hir::{HirId, Lifetime, Node};
+use hir::{HirId, Node};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
 use rustc_span::symbol::Ident;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -55,17 +55,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     use rustc_hir::*;
 
     match tcx.opt_rpitit_info(def_id.to_def_id()) {
-        Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
-            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: Some(lifetime_mapping), .. }),
-                ..
-            }) = opaque_ty_node
-            else {
-                bug!("unexpected {opaque_ty_node:?}")
-            };
-
+        Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
             let mut predicates = Vec::new();
 
             // RPITITs should inherit the predicates of their parent. This is
@@ -78,13 +68,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
             // We also install bidirectional outlives predicates for the RPITIT
             // to keep the duplicates lifetimes from opaque lowering in sync.
+            // We only need to compute bidirectional outlives for the duplicated
+            // opaque lifetimes, which explains the slicing below.
             compute_bidirectional_outlives_predicates(
                 tcx,
-                def_id,
-                lifetime_mapping.iter().map(|(lifetime, def_id)| {
-                    (**lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
-                }),
-                tcx.generics_of(def_id.to_def_id()),
+                &tcx.generics_of(def_id.to_def_id()).params
+                    [tcx.generics_of(fn_def_id).params.len()..],
                 &mut predicates,
             );
 
@@ -351,21 +340,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         };
         debug!(?lifetimes);
 
-        let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
-            .map(|(arg, dup)| {
-                let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
-                (**arg, dup)
-            })
-            .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
-            .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
-
-        compute_bidirectional_outlives_predicates(
-            tcx,
-            def_id,
-            lifetime_mapping,
-            generics,
-            &mut predicates,
-        );
+        compute_bidirectional_outlives_predicates(tcx, &generics.params, &mut predicates);
         debug!(?predicates);
     }
 
@@ -379,41 +354,28 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 /// enforce that these lifetimes stay in sync.
 fn compute_bidirectional_outlives_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item_def_id: LocalDefId,
-    lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
-    generics: &Generics,
+    opaque_own_params: &[ty::GenericParamDef],
     predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
 ) {
-    let icx = ItemCtxt::new(tcx, item_def_id);
-
-    for (arg, (dup_def, name, span)) in lifetime_mapping {
-        let orig_region = icx.astconv().ast_region_to_region(&arg, None);
-        if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
-            // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
-            // show up in the opaque's parent's args.
-            continue;
+    for param in opaque_own_params {
+        let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
+        if let ty::ReEarlyBound(..) = *orig_lifetime {
+            let dup_lifetime = ty::Region::new_early_bound(
+                tcx,
+                ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name },
+            );
+            let span = tcx.def_span(param.def_id);
+            predicates.push((
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
+                    .to_predicate(tcx),
+                span,
+            ));
+            predicates.push((
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
+                    .to_predicate(tcx),
+                span,
+            ));
         }
-
-        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else {
-            bug!()
-        };
-
-        let dup_region = ty::Region::new_early_bound(
-            tcx,
-            ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
-        );
-
-        predicates.push((
-            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
-                .to_predicate(tcx),
-            span,
-        ));
-
-        predicates.push((
-            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
-                .to_predicate(tcx),
-            span,
-        ));
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 6be8d72aed2..61b182b1be7 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -578,6 +578,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             MissingTypesOrConsts { .. } => {
                 self.suggest_adding_type_and_const_args(err);
             }
+            ExcessTypesOrConsts { .. } => {
+                // this can happen with `~const T` where T isn't a const_trait.
+            }
             _ => unreachable!(),
         }
     }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index fda46798708..89efdc269c4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -626,7 +626,6 @@ impl<'a> State<'a> {
                 unsafety,
                 polarity,
                 defaultness,
-                constness,
                 defaultness_span: _,
                 generics,
                 ref of_trait,
@@ -643,10 +642,6 @@ impl<'a> State<'a> {
                     self.space();
                 }
 
-                if constness == hir::Constness::Const {
-                    self.word_nbsp("const");
-                }
-
                 if let hir::ImplPolarity::Negative(_) = polarity {
                     self.word("!");
                 }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index c68f2d94f35..dd79d1afc62 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -645,18 +645,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
             }
             hir::ExprKind::Call(ref inner_callee, _) => {
-                // If the call spans more than one line and the callee kind is
-                // itself another `ExprCall`, that's a clue that we might just be
-                // missing a semicolon (Issue #51055)
-                let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span);
-                if call_is_multiline {
-                    err.span_suggestion(
-                        callee_expr.span.shrink_to_hi(),
-                        "consider using a semicolon here",
-                        ";",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
                 if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
                     inner_callee_path = Some(inner_qpath);
                     self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
@@ -668,6 +656,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
+            // If the call spans more than one line and the callee kind is
+            // itself another `ExprCall`, that's a clue that we might just be
+            // missing a semicolon (#51055, #106515).
+            let call_is_multiline = self
+                .tcx
+                .sess
+                .source_map()
+                .is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
+                && call_expr.span.ctxt() == callee_expr.span.ctxt();
+            if call_is_multiline {
+                err.span_suggestion(
+                    callee_expr.span.shrink_to_hi(),
+                    "consider using a semicolon here to finish the statement",
+                    ";",
+                    Applicability::MaybeIncorrect,
+                );
+            }
             if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
                 && !self.type_is_sized_modulo_regions(self.param_env, output_ty)
             {
@@ -767,9 +772,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let tcx = self.tcx;
 
-        if !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
-            return;
-        }
+        // fast-reject if callee doesn't have the host effect param (non-const)
+        let generics = tcx.generics_of(callee_did);
+        let Some(host_effect_index) = generics.host_effect_index else { return };
+
+        // if the callee does have the param, we need to equate the param to some const
+        // value no matter whether the effects feature is enabled in the local crate,
+        // because inference will fail if we don't.
+        let mut host_always_on =
+            !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
 
         // Compute the constness required by the context.
         let context = tcx.hir().enclosing_body_owner(call_expr_hir);
@@ -780,10 +791,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) {
             trace!("do not const check this context");
-            return;
+            host_always_on = true;
         }
 
         let effect = match const_context {
+            _ if host_always_on => tcx.consts.true_,
             Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
             Some(hir::ConstContext::ConstFn) => {
                 let args = ty::GenericArgs::identity_for_item(tcx, context);
@@ -792,21 +804,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             None => tcx.consts.true_,
         };
 
-        let generics = tcx.generics_of(callee_did);
-
         trace!(?effect, ?generics, ?callee_args);
 
-        if let Some(idx) = generics.host_effect_index {
-            let param = callee_args.const_at(idx);
-            let cause = self.misc(span);
-            match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
-                Ok(infer::InferOk { obligations, value: () }) => {
-                    self.register_predicates(obligations);
-                }
-                Err(e) => {
-                    // FIXME(effects): better diagnostic
-                    self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
-                }
+        let param = callee_args.const_at(host_effect_index);
+        let cause = self.misc(span);
+        match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
+            Ok(infer::InferOk { obligations, value: () }) => {
+                self.register_predicates(obligations);
+            }
+            Err(e) => {
+                // FIXME(effects): better diagnostic
+                self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index b2b3f435505..1cfdc5b9e7f 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -510,9 +510,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         success(adjustments, ty, obligations)
     }
 
-    // &[T; n] or &mut [T; n] -> &[T]
-    // or &mut [T; n] -> &mut [T]
-    // or &Concrete -> &Trait, etc.
+    /// Performs [unsized coercion] by emulating a fulfillment loop on a
+    /// `CoerceUnsized` goal until all `CoerceUnsized` and `Unsize` goals
+    /// are successfully selected.
+    ///
+    /// [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions)
     #[instrument(skip(self), level = "debug")]
     fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceResult<'tcx> {
         source = self.shallow_resolve(source);
@@ -1007,15 +1009,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
-        target: Ty<'tcx>,
+        mut target: Ty<'tcx>,
         allow_two_phase: AllowTwoPhase,
         cause: Option<ObligationCause<'tcx>>,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
         let source = self.try_structurally_resolve_type(expr.span, expr_ty);
-        let target = self.try_structurally_resolve_type(
-            cause.as_ref().map_or(expr.span, |cause| cause.span),
-            target,
-        );
+        if self.next_trait_solver() {
+            target = self.try_structurally_resolve_type(
+                cause.as_ref().map_or(expr.span, |cause| cause.span),
+                target,
+            );
+        }
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
         let cause =
@@ -1037,6 +1041,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Returns false if the coercion creates any obligations that result in
     /// errors.
     pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
+        // FIXME(-Ztrait-solver=next): We need to structurally resolve both types here.
         let source = self.resolve_vars_with_obligations(expr_ty);
         debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 48383bd90fe..b05cef56ad2 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -260,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ));
         let expr = expr.peel_drop_temps();
         let cause = self.misc(expr.span);
-        let expr_ty = self.resolve_vars_with_obligations(checked_ty);
+        let expr_ty = self.resolve_vars_if_possible(checked_ty);
         let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e);
 
         let is_insufficiently_polymorphic =
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2af8648455b..7cea40fdd64 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -13,7 +13,7 @@ use crate::errors::{
     YieldExprOutsideOfGenerator,
 };
 use crate::fatally_break_rust;
-use crate::method::SelfSource;
+use crate::method::{MethodCallComponents, SelfSource};
 use crate::type_error_struct;
 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
 use crate::{
@@ -1281,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         segment.ident,
                         SelfSource::MethodCall(rcvr),
                         error,
-                        Some((rcvr, args)),
+                        Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }),
                         expected,
                         false,
                     ) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 322d726a89d..28fe2e062e5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -85,16 +85,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// to get more type information.
     // FIXME(-Ztrait-solver=next): A lot of the calls to this method should
     // probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
-    pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
-    }
-
-    #[instrument(skip(self, mutate_fulfillment_errors), level = "debug", ret)]
-    pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
-        &self,
-        mut ty: Ty<'tcx>,
-        mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
-    ) -> Ty<'tcx> {
+    #[instrument(skip(self), level = "debug", ret)]
+    pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         // No Infer()? Nothing needs doing.
         if !ty.has_non_region_infer() {
             debug!("no inference var, nothing needs doing");
@@ -112,7 +104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible(mutate_fulfillment_errors);
+        self.select_obligations_where_possible(|_| {});
         self.resolve_vars_if_possible(ty)
     }
 
@@ -626,8 +618,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         match *self_ty.kind() {
             ty::Infer(ty::TyVar(found_vid)) => {
-                // FIXME: consider using `sub_root_var` here so we
-                // can see through subtyping.
                 let found_vid = self.root_var(found_vid);
                 debug!("self_type_matches_expected_vid - found_vid={:?}", found_vid);
                 expected_vid == found_vid
@@ -642,8 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self_ty: ty::TyVid,
     ) -> impl DoubleEndedIterator<Item = traits::PredicateObligation<'tcx>> + Captures<'tcx> + 'b
     {
-        // FIXME: consider using `sub_root_var` here so we
-        // can see through subtyping.
         let ty_var_root = self.root_var(self_ty);
         trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations());
 
@@ -1349,7 +1337,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     GenericParamDefKind::Const { has_default } => {
-                        if !infer_args && has_default {
+                        if !infer_args
+                            && has_default
+                            && !tcx.has_attr(param.def_id, sym::rustc_host)
+                        {
                             tcx.const_param_default(param.def_id)
                                 .instantiate(tcx, args.unwrap())
                                 .into()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 89bbb4c2203..48358e338da 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -950,7 +950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if !expected.is_unit() {
             return;
         }
-        let found = self.resolve_vars_with_obligations(found);
+        let found = self.resolve_vars_if_possible(found);
 
         let in_loop = self.is_loop(id)
             || self
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 597696843c4..6dd131aa283 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,7 +7,7 @@ mod prelude2021;
 pub mod probe;
 mod suggest;
 
-pub use self::suggest::SelfSource;
+pub use self::suggest::{MethodCallComponents, SelfSource};
 pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index b9d8c5a7540..a0d31d3a22c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -50,6 +50,15 @@ use rustc_hir::intravisit::Visitor;
 use std::cmp::{self, Ordering};
 use std::iter;
 
+/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
+/// components readily available to us to point at the right place in diagnostics.
+#[derive(Debug, Clone, Copy)]
+pub struct MethodCallComponents<'tcx> {
+    pub receiver: &'tcx hir::Expr<'tcx>,
+    pub args: &'tcx [hir::Expr<'tcx>],
+    pub full_expr: &'tcx hir::Expr<'tcx>,
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
         let tcx = self.tcx;
@@ -115,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@@ -257,18 +266,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_missing_writer(
         &self,
         rcvr_ty: Ty<'tcx>,
-        args: (&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>]),
+        args: MethodCallComponents<'tcx>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
-        let mut err =
-            struct_span_err!(self.tcx.sess, args.0.span, E0599, "cannot write into `{}`", ty_str);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            args.receiver.span,
+            E0599,
+            "cannot write into `{}`",
+            ty_str
+        );
         err.span_note(
-            args.0.span,
+            args.receiver.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
         );
-        if let ExprKind::Lit(_) = args.0.kind {
+        if let ExprKind::Lit(_) = args.receiver.kind {
             err.span_help(
-                args.0.span.shrink_to_lo(),
+                args.receiver.span.shrink_to_lo(),
                 "a writer is needed before this format string",
             );
         };
@@ -282,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
@@ -953,6 +967,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 unsatisfied_bounds = true;
             }
+        } else if let ty::Adt(def, targs) = rcvr_ty.kind() && let Some(args) = args {
+            // This is useful for methods on arbitrary self types that might have a simple
+            // mutability difference, like calling a method on `Pin<&mut Self>` that is on
+            // `Pin<&Self>`.
+            if targs.len() == 1 {
+                let mut item_segment = hir::PathSegment::invalid();
+                item_segment.ident = item_name;
+                for t in [Ty::new_mut_ref, Ty::new_imm_ref, |_, _, t| t] {
+                    let new_args = tcx.mk_args_from_iter(
+                        targs
+                            .iter()
+                            .map(|arg| match arg.as_type() {
+                                Some(ty) => ty::GenericArg::from(
+                                    t(tcx, tcx.lifetimes.re_erased, ty.peel_refs()),
+                                ),
+                                _ => arg,
+                            })
+                    );
+                    let rcvr_ty = Ty::new_adt(tcx, *def, new_args);
+                    if let Ok(method) = self.lookup_method_for_diagnostic(
+                        rcvr_ty,
+                        &item_segment,
+                        span,
+                        args.full_expr,
+                        args.receiver,
+                    ) {
+                        err.span_note(
+                            tcx.def_span(method.def_id),
+                            format!("{item_kind} is available for `{rcvr_ty}`"),
+                        );
+                    }
+                }
+            }
         }
 
         let label_span_not_found = |err: &mut Diagnostic| {
@@ -1111,7 +1158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 rcvr_ty,
                 item_name,
-                args.map(|(_, args)| args.len() + 1),
+                args.map(|MethodCallComponents { args, .. }| args.len() + 1),
                 source,
                 no_match_data.out_of_scope_traits.clone(),
                 &unsatisfied_predicates,
@@ -1192,7 +1239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         span: Span,
         err: &mut Diagnostic,
         sources: &mut Vec<CandidateSource>,
@@ -1343,7 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         source: SelfSource<'tcx>,
         item_name: Ident,
-        args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         sugg_span: Span,
     ) {
         let mut has_unsuggestable_args = false;
@@ -1415,7 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 None
             };
             let mut applicability = Applicability::MachineApplicable;
-            let args = if let Some((receiver, args)) = args {
+            let args = if let Some(MethodCallComponents { receiver, args, .. }) = args {
                 // The first arg is the same kind as the receiver
                 let explicit_args = if first_arg.is_some() {
                     std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
@@ -2947,7 +2994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This occurs for UFCS desugaring of `T::method`, where there is no
         // receiver expression for the method call, and thus no autoderef.
         if let SelfSource::QPath(_) = source {
-            return is_local(self.resolve_vars_with_obligations(rcvr_ty));
+            return is_local(rcvr_ty);
         }
 
         self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
@@ -2995,7 +3042,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 
 fn print_disambiguation_help<'tcx>(
     item_name: Ident,
-    args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+    args: Option<MethodCallComponents<'tcx>>,
     err: &mut Diagnostic,
     trait_name: String,
     rcvr_ty: Ty<'_>,
@@ -3007,7 +3054,11 @@ fn print_disambiguation_help<'tcx>(
     fn_has_self_parameter: bool,
 ) {
     let mut applicability = Applicability::MachineApplicable;
-    let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
+    let (span, sugg) = if let (
+        ty::AssocKind::Fn,
+        Some(MethodCallComponents { receiver, args, .. }),
+    ) = (kind, args)
+    {
         let args = format!(
             "({}{})",
             rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index a34fdf4ecc9..def9fdcd3c7 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -72,43 +72,16 @@ fn count_nodes(krate: &ast::Crate) -> usize {
     counter.count
 }
 
-pub fn register_plugins<'a>(
-    sess: &'a Session,
-    metadata_loader: &'a dyn MetadataLoader,
-    register_lints: impl Fn(&Session, &mut LintStore),
+pub(crate) fn create_lint_store(
+    sess: &Session,
+    metadata_loader: &dyn MetadataLoader,
+    register_lints: Option<impl Fn(&Session, &mut LintStore)>,
     pre_configured_attrs: &[ast::Attribute],
-    crate_name: Symbol,
-) -> Result<LintStore> {
-    // these need to be set "early" so that expansion sees `quote` if enabled.
-    let features = rustc_expand::config::features(sess, pre_configured_attrs);
-    sess.init_features(features);
-
-    let crate_types = util::collect_crate_types(sess, pre_configured_attrs);
-    sess.init_crate_types(crate_types);
-
-    let stable_crate_id = StableCrateId::new(
-        crate_name,
-        sess.crate_types().contains(&CrateType::Executable),
-        sess.opts.cg.metadata.clone(),
-        sess.cfg_version,
-    );
-    sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
-    rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
-
-    if sess.opts.incremental.is_some() {
-        sess.time("incr_comp_garbage_collect_session_directories", || {
-            if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
-                warn!(
-                    "Error while trying to garbage collect incremental \
-                     compilation cache directory: {}",
-                    e
-                );
-            }
-        });
-    }
-
+) -> LintStore {
     let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
-    register_lints(sess, &mut lint_store);
+    if let Some(register_lints) = register_lints {
+        register_lints(sess, &mut lint_store);
+    }
 
     let registrars = sess.time("plugin_loading", || {
         plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
@@ -120,7 +93,7 @@ pub fn register_plugins<'a>(
         }
     });
 
-    Ok(lint_store)
+    lint_store
 }
 
 fn pre_expansion_lint<'a>(
@@ -275,7 +248,7 @@ fn configure_and_expand(
         rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer())
     });
 
-    let crate_types = sess.crate_types();
+    let crate_types = tcx.crate_types();
     let is_executable_crate = crate_types.contains(&CrateType::Executable);
     let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
 
@@ -367,11 +340,12 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
 
 // Returns all the paths that correspond to generated files.
 fn generated_output_paths(
-    sess: &Session,
+    tcx: TyCtxt<'_>,
     outputs: &OutputFilenames,
     exact_name: bool,
     crate_name: Symbol,
 ) -> Vec<PathBuf> {
+    let sess = tcx.sess;
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
         let out_filename = outputs.path(*output_type);
@@ -380,7 +354,7 @@ fn generated_output_paths(
             // If the filename has been overridden using `-o`, it will not be modified
             // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
             OutputType::Exe if !exact_name => {
-                for crate_type in sess.crate_types().iter() {
+                for crate_type in tcx.crate_types().iter() {
                     let p = filename_for_input(sess, *crate_type, crate_name, outputs);
                     out_filenames.push(p.as_path().to_path_buf());
                 }
@@ -613,7 +587,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
     let outputs = util::build_output_filenames(&krate.attrs, sess);
 
     let output_paths =
-        generated_output_paths(sess, &outputs, sess.io.output_file.is_some(), crate_name);
+        generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name);
 
     // Ensure the source file isn't accidentally overwritten during compilation.
     if let Some(ref input_path) = sess.io.input.opt_path() {
@@ -691,6 +665,8 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock:
 
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
+    crate_types: Vec<CrateType>,
+    stable_crate_id: StableCrateId,
     lint_store: Lrc<LintStore>,
     dep_graph: DepGraph,
     untracked: Untracked,
@@ -723,6 +699,8 @@ pub fn create_global_ctxt<'tcx>(
         gcx_cell.get_or_init(move || {
             TyCtxt::create_global_ctxt(
                 sess,
+                crate_types,
+                stable_crate_id,
                 lint_store,
                 arena,
                 hir_arena,
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 8c4cdc6696a..7687e83da76 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -1,6 +1,6 @@
 use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
 use crate::interface::{Compiler, Result};
-use crate::passes;
+use crate::{passes, util};
 
 use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
@@ -9,15 +9,14 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal};
-use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_incremental::DepGraphFuture;
-use rustc_lint::LintStore;
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::ty::{GlobalCtxt, TyCtxt};
-use rustc_session::config::{self, OutputFilenames, OutputType};
+use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
 use rustc_session::cstore::Untracked;
 use rustc_session::{output::find_crate_name, Session};
 use rustc_span::symbol::sym;
@@ -85,12 +84,11 @@ pub struct Queries<'tcx> {
     arena: WorkerLocal<Arena<'tcx>>,
     hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>,
 
-    dep_graph_future: Query<Option<DepGraphFuture>>,
     parse: Query<ast::Crate>,
     pre_configure: Query<(ast::Crate, ast::AttrVec)>,
     crate_name: Query<Symbol>,
-    register_plugins: Query<(ast::Crate, ast::AttrVec, Lrc<LintStore>)>,
-    dep_graph: Query<DepGraph>,
+    crate_types: Query<Vec<CrateType>>,
+    stable_crate_id: Query<StableCrateId>,
     // This just points to what's in `gcx_cell`.
     gcx: Query<&'tcx GlobalCtxt<'tcx>>,
 }
@@ -102,12 +100,11 @@ impl<'tcx> Queries<'tcx> {
             gcx_cell: OnceCell::new(),
             arena: WorkerLocal::new(|_| Arena::default()),
             hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
-            dep_graph_future: Default::default(),
             parse: Default::default(),
             pre_configure: Default::default(),
             crate_name: Default::default(),
-            register_plugins: Default::default(),
-            dep_graph: Default::default(),
+            crate_types: Default::default(),
+            stable_crate_id: Default::default(),
             gcx: Default::default(),
         }
     }
@@ -119,13 +116,6 @@ impl<'tcx> Queries<'tcx> {
         self.compiler.codegen_backend()
     }
 
-    fn dep_graph_future(&self) -> Result<QueryResult<'_, Option<DepGraphFuture>>> {
-        self.dep_graph_future.compute(|| {
-            let sess = self.session();
-            Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess)))
-        })
-    }
-
     pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
         self.parse
             .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
@@ -148,84 +138,111 @@ impl<'tcx> Queries<'tcx> {
         })
     }
 
-    pub fn register_plugins(
-        &self,
-    ) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec, Lrc<LintStore>)>> {
-        self.register_plugins.compute(|| {
-            let crate_name = *self.crate_name()?.borrow();
-            let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
-
-            let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
-            let lint_store = passes::register_plugins(
-                self.session(),
-                &*self.codegen_backend().metadata_loader(),
-                self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
-                &pre_configured_attrs,
-                crate_name,
-            )?;
-
-            // Compute the dependency graph (in the background). We want to do
-            // this as early as possible, to give the DepGraph maximum time to
-            // load before dep_graph() is called, but it also can't happen
-            // until after rustc_incremental::prepare_session_directory() is
-            // called, which happens within passes::register_plugins().
-            self.dep_graph_future().ok();
-
-            Ok((krate, pre_configured_attrs, Lrc::new(lint_store)))
+    fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
+        self.crate_name.compute(|| {
+            let pre_configure_result = self.pre_configure()?;
+            let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
+            // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
+            Ok(find_crate_name(self.session(), pre_configured_attrs))
         })
     }
 
-    fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
-        self.crate_name.compute(|| {
-            Ok({
-                let pre_configure_result = self.pre_configure()?;
-                let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
-                // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
-                find_crate_name(self.session(), pre_configured_attrs)
-            })
+    fn crate_types(&self) -> Result<QueryResult<'_, Vec<CrateType>>> {
+        self.crate_types.compute(|| {
+            let pre_configure_result = self.pre_configure()?;
+            let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
+            Ok(util::collect_crate_types(&self.session(), &pre_configured_attrs))
         })
     }
 
-    fn dep_graph(&self) -> Result<QueryResult<'_, DepGraph>> {
-        self.dep_graph.compute(|| {
+    fn stable_crate_id(&self) -> Result<QueryResult<'_, StableCrateId>> {
+        self.stable_crate_id.compute(|| {
             let sess = self.session();
-            let future_opt = self.dep_graph_future()?.steal();
-            let dep_graph = future_opt
-                .and_then(|future| {
-                    let (prev_graph, mut prev_work_products) =
-                        sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
-                    // Convert from UnordMap to FxIndexMap by sorting
-                    let prev_work_product_ids =
-                        prev_work_products.items().map(|x| *x.0).into_sorted_stable_ord();
-                    let prev_work_products = prev_work_product_ids
-                        .into_iter()
-                        .map(|x| (x, prev_work_products.remove(&x).unwrap()))
-                        .collect::<FxIndexMap<_, _>>();
-                    rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
-                })
-                .unwrap_or_else(DepGraph::new_disabled);
-            Ok(dep_graph)
+            Ok(StableCrateId::new(
+                *self.crate_name()?.borrow(),
+                self.crate_types()?.borrow().contains(&CrateType::Executable),
+                sess.opts.cg.metadata.clone(),
+                sess.cfg_version,
+            ))
         })
     }
 
+    fn dep_graph_future(&self) -> Result<Option<DepGraphFuture>> {
+        let sess = self.session();
+        let crate_name = *self.crate_name()?.borrow();
+        let stable_crate_id = *self.stable_crate_id()?.borrow();
+
+        // `load_dep_graph` can only be called after `prepare_session_directory`.
+        rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
+        let res = sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess));
+
+        if sess.opts.incremental.is_some() {
+            sess.time("incr_comp_garbage_collect_session_directories", || {
+                if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
+                    warn!(
+                        "Error while trying to garbage collect incremental \
+                         compilation cache directory: {}",
+                        e
+                    );
+                }
+            });
+        }
+
+        Ok(res)
+    }
+
+    fn dep_graph(&self, dep_graph_future: Option<DepGraphFuture>) -> DepGraph {
+        dep_graph_future
+            .and_then(|future| {
+                let sess = self.session();
+                let (prev_graph, mut prev_work_products) =
+                    sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
+                // Convert from UnordMap to FxIndexMap by sorting
+                let prev_work_product_ids =
+                    prev_work_products.items().map(|x| *x.0).into_sorted_stable_ord();
+                let prev_work_products = prev_work_product_ids
+                    .into_iter()
+                    .map(|x| (x, prev_work_products.remove(&x).unwrap()))
+                    .collect::<FxIndexMap<_, _>>();
+                rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
+            })
+            .unwrap_or_else(DepGraph::new_disabled)
+    }
+
     pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
         self.gcx.compute(|| {
-            let crate_name = *self.crate_name()?.borrow();
-            let (krate, pre_configured_attrs, lint_store) = self.register_plugins()?.steal();
+            // Compute the dependency graph (in the background). We want to do this as early as
+            // possible, to give the DepGraph maximum time to load before `dep_graph` is called.
+            let dep_graph_future = self.dep_graph_future()?;
 
-            let sess = self.session();
+            let crate_name = self.crate_name()?.steal();
+            let crate_types = self.crate_types()?.steal();
+            let stable_crate_id = self.stable_crate_id()?.steal();
+            let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
 
-            let cstore = RwLock::new(Box::new(CStore::new(sess)) as _);
-            let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id()));
+            let sess = self.session();
+            let lint_store = Lrc::new(passes::create_lint_store(
+                sess,
+                &*self.codegen_backend().metadata_loader(),
+                self.compiler.register_lints.as_deref(),
+                &pre_configured_attrs,
+            ));
+            let cstore = RwLock::new(Box::new(CStore::new(stable_crate_id)) as _);
+            let definitions = RwLock::new(Definitions::new(stable_crate_id));
             let source_span = AppendOnlyIndexVec::new();
             let _id = source_span.push(krate.spans.inner_span);
             debug_assert_eq!(_id, CRATE_DEF_ID);
             let untracked = Untracked { cstore, source_span, definitions };
 
+            // FIXME: Move features from session to tcx and make them immutable.
+            sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs));
+
             let qcx = passes::create_global_ctxt(
                 self.compiler,
+                crate_types,
+                stable_crate_id,
                 lint_store,
-                self.dep_graph()?.steal(),
+                self.dep_graph(dep_graph_future),
                 untracked,
                 &self.gcx_cell,
                 &self.arena,
@@ -303,7 +320,7 @@ impl<'tcx> Queries<'tcx> {
 
         let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| {
             (
-                if tcx.sess.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None },
+                if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None },
                 tcx.output_filenames(()).clone(),
                 tcx.dep_graph.clone(),
             )
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 80b6c0fb439..d61ec0b641c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -103,12 +103,20 @@ fromRust(LLVMRustCounterExprKind Kind) {
 }
 
 extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
-    const char* const Filenames[],
+    const char *const Filenames[],
     size_t FilenamesLen,
+    const size_t *const Lengths,
+    size_t LengthsLen,
     RustStringRef BufferOut) {
+  if (FilenamesLen != LengthsLen) {
+    report_fatal_error(
+        "Mismatched lengths in LLVMRustCoverageWriteFilenamesSectionToBuffer");
+  }
+
   SmallVector<std::string,32> FilenameRefs;
+  FilenameRefs.reserve(FilenamesLen);
   for (size_t i = 0; i < FilenamesLen; i++) {
-    FilenameRefs.push_back(std::string(Filenames[i]));
+    FilenameRefs.emplace_back(Filenames[i], Lengths[i]);
   }
   auto FilenamesWriter =
       coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs));
@@ -153,8 +161,11 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   CoverageMappingWriter.write(OS);
 }
 
-extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
-  StringRef FuncNameRef(FuncName);
+extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(
+    LLVMValueRef F,
+    const char *FuncName,
+    size_t FuncNameLen) {
+  StringRef FuncNameRef(FuncName, FuncNameLen);
   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
 }
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index ea045462845..3f2bf2c9b44 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -15,7 +15,6 @@
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/JSON.h"
-#include "llvm/Support/Host.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 48b5fd6e283..b3371dbe834 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -25,11 +25,11 @@
 #if LLVM_VERSION_GE(17, 0)
 #include "llvm/Support/VirtualFileSystem.h"
 #endif
-#include "llvm/Support/Host.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/IPO/Internalize.h"
+#include "llvm/Transforms/IPO/LowerTypeTests.h"
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
@@ -609,6 +609,8 @@ enum class LLVMRustOptStage {
 struct LLVMRustSanitizerOptions {
   bool SanitizeAddress;
   bool SanitizeAddressRecover;
+  bool SanitizeCFI;
+  bool SanitizeKCFI;
   bool SanitizeMemory;
   bool SanitizeMemoryRecover;
   int  SanitizeMemoryTrackOrigins;
@@ -625,6 +627,7 @@ LLVMRustOptimize(
     LLVMTargetMachineRef TMRef,
     LLVMRustPassBuilderOptLevel OptLevelRust,
     LLVMRustOptStage OptStage,
+    bool IsLinkerPluginLTO,
     bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
     bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
     bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
@@ -736,6 +739,18 @@ LLVMRustOptimize(
   std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
       OptimizerLastEPCallbacks;
 
+  if (!IsLinkerPluginLTO
+      && SanitizerOptions && SanitizerOptions->SanitizeCFI
+      && !NoPrepopulatePasses) {
+    PipelineStartEPCallbacks.push_back(
+      [](ModulePassManager &MPM, OptimizationLevel Level) {
+        MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
+                                       /*ImportSummary=*/nullptr,
+                                       /*DropTypeTests=*/false));
+      }
+    );
+  }
+
   if (VerifyIR) {
     PipelineStartEPCallbacks.push_back(
       [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) {
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 8ef39a6c866..70cdf3d6d23 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1869,7 +1869,8 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
     LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
     void *DiagnosticHandlerContext, bool RemarkAllPasses,
     const char * const * RemarkPasses, size_t RemarkPassesLen,
-    const char * RemarkFilePath
+    const char * RemarkFilePath,
+    bool PGOAvailable
 ) {
 
   class RustDiagnosticHandler final : public DiagnosticHandler {
@@ -1967,6 +1968,11 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
   std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer;
 
   if (RemarkFilePath != nullptr) {
+    if (PGOAvailable) {
+      // Enable PGO hotness data for remarks, if available
+      unwrap(C)->setDiagnosticsHotnessRequested(true);
+    }
+
     std::error_code EC;
     RemarkFile = std::make_unique<ToolOutputFile>(
       RemarkFilePath,
@@ -2027,3 +2033,14 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
 extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) {
   return identify_magic(StringRef(ptr, len)) == file_magic::bitcode;
 }
+
+extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) {
+  if (unwrap<Value>(V)->getType()->isPointerTy()) {
+    if (auto *GV = dyn_cast<GlobalValue>(unwrap<Value>(V))) {
+      if (GV->getValueType()->isFunctionTy())
+        return false;
+    }
+    return true;
+  }
+  return false;
+}
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 571af82d13a..3c76f9a8e52 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -20,7 +20,6 @@ use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
 use rustc_session::lint;
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
-use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -262,9 +261,9 @@ impl CStore {
         }
     }
 
-    pub fn new(sess: &Session) -> CStore {
+    pub fn new(local_stable_crate_id: StableCrateId) -> CStore {
         let mut stable_crate_ids = StableCrateIdMap::default();
-        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+        stable_crate_ids.insert(local_stable_crate_id, LOCAL_CRATE);
         CStore {
             // We add an empty entry for LOCAL_CRATE (which maps to zero) in
             // order to make array indices in `metas` match with the
@@ -544,6 +543,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 self.sess,
                 &**metadata_loader,
                 name,
+                // The all loop is because `--crate-type=rlib --crate-type=rlib` is
+                // legal and produces both inside this type.
+                self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
                 hash,
                 extra_filename,
                 false, // is_host
@@ -687,7 +689,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
-        let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
+        let any_non_rlib = self.tcx.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
         if !any_non_rlib {
             info!("panic runtime injection skipped, only generating rlib");
             return;
@@ -816,7 +818,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         // At this point we've determined that we need an allocator. Let's see
         // if our compilation session actually needs an allocator based on what
         // we're emitting.
-        let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
+        let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
         if all_rlib {
             return;
         }
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 72b208a7132..783d35ac7e6 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -66,8 +66,7 @@ use rustc_session::cstore::CrateDepKind;
 use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 
 pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
-    tcx.sess
-        .crate_types()
+    tcx.crate_types()
         .iter()
         .map(|&ty| {
             let linkage = calculate_type(tcx, ty);
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 69a77e82f98..2a9662b809a 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -56,7 +56,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
 
     // Always create a file at `metadata_filename`, even if we have nothing to write to it.
     // This simplifies the creation of the output `out_filename` when requested.
-    let metadata_kind = tcx.sess.metadata_kind();
+    let metadata_kind = tcx.metadata_kind();
     match metadata_kind {
         MetadataKind::None => {
             std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index a0c552f5fd6..bf6004ba864 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -222,7 +222,7 @@ use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
 use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_fs_util::try_canonicalize;
-use rustc_session::config::{self, CrateType};
+use rustc_session::config;
 use rustc_session::cstore::{CrateSource, MetadataLoader};
 use rustc_session::filesearch::FileSearch;
 use rustc_session::search_paths::PathKind;
@@ -305,14 +305,12 @@ impl<'a> CrateLocator<'a> {
         sess: &'a Session,
         metadata_loader: &'a dyn MetadataLoader,
         crate_name: Symbol,
+        is_rlib: bool,
         hash: Option<Svh>,
         extra_filename: Option<&'a str>,
         is_host: bool,
         path_kind: PathKind,
     ) -> CrateLocator<'a> {
-        // The all loop is because `--crate-type=rlib --crate-type=rlib` is
-        // legal and produces both inside this type.
-        let is_rlib = sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
         let needs_object_code = sess.opts.output_types.should_codegen();
         // If we're producing an rlib, then we don't need object code.
         // Or, if we're not producing object code, then we don't need it either
@@ -883,9 +881,10 @@ fn find_plugin_registrar_impl<'a>(
         sess,
         metadata_loader,
         name,
-        None, // hash
-        None, // extra_filename
-        true, // is_host
+        false, // is_rlib
+        None,  // hash
+        None,  // extra_filename
+        true,  // is_host
         PathKind::Crate,
     );
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index ca5043cc263..098c411c8d6 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -52,10 +52,11 @@ fn find_bundled_library(
     verbatim: Option<bool>,
     kind: NativeLibKind,
     has_cfg: bool,
-    sess: &Session,
+    tcx: TyCtxt<'_>,
 ) -> Option<Symbol> {
+    let sess = tcx.sess;
     if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
-        && sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
+        && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
         && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
     {
         let verbatim = verbatim.unwrap_or(false);
@@ -364,7 +365,7 @@ impl<'tcx> Collector<'tcx> {
             };
 
             let kind = kind.unwrap_or(NativeLibKind::Unspecified);
-            let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess);
+            let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
             self.libs.push(NativeLib {
                 name,
                 filename,
@@ -442,9 +443,13 @@ impl<'tcx> Collector<'tcx> {
                 // Add if not found
                 let new_name: Option<&str> = passed_lib.new_name.as_deref();
                 let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name));
-                let sess = self.tcx.sess;
-                let filename =
-                    find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess);
+                let filename = find_bundled_library(
+                    name,
+                    passed_lib.verbatim,
+                    passed_lib.kind,
+                    false,
+                    self.tcx,
+                );
                 self.libs.push(NativeLib {
                     name,
                     filename,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b34fead821f..be91ad4088a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1741,7 +1741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     }
 
     fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
-        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
+        let is_proc_macro = self.tcx.crate_types().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
             let hir = tcx.hir();
@@ -2204,7 +2204,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
         source_file_cache,
         interpret_allocs: Default::default(),
         required_source_files,
-        is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
+        is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
         hygiene_ctxt: &hygiene_ctxt,
         symbol_table: Default::default(),
     };
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 4e242c684e3..06251bccc98 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem;
 use crate::ty::TyCtxt;
 
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::{HirId, ItemLocalId, OwnerId};
 use rustc_query_system::dep_graph::FingerprintStyle;
@@ -371,7 +371,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
             let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
-            let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash);
+            let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
             let def_id = tcx
                 .def_path_hash_to_def_id(def_path_hash, &mut || {
                     panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash)
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index fbc32263874..224f897492b 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1210,7 +1210,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
             owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
         }
         tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-        tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+        tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
         // Hash visibility information since it does not appear in HIR.
         resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher);
         resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher);
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index f19812619b2..e30b6b203d7 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -72,6 +72,6 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
         "rust_metadata_{}_{:08x}",
         tcx.crate_name(LOCAL_CRATE),
-        tcx.sess.local_stable_crate_id(),
+        tcx.stable_crate_id(LOCAL_CRATE),
     )
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 2567170f39a..c787481bfbe 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -329,6 +329,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
 
     /// Try to create an Allocation of `size` bytes, panics if there is not enough memory
     /// available to the compiler to do so.
+    ///
+    /// Example use case: To obtain an Allocation filled with specific data,
+    /// first call this function and then call write_scalar to fill in the right data.
     pub fn uninit(size: Size, align: Align) -> Self {
         match Self::uninit_inner(size, align, || {
             panic!("Allocation::uninit called with panic_on_fail had allocation failure");
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2e46bfc1a38..e6ef5a41ee0 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -184,8 +184,6 @@ pub enum InvalidProgramInfo<'tcx> {
     /// (which unfortunately typeck does not reject).
     /// Not using `FnAbiError` as that contains a nested `LayoutError`.
     FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
-    /// SizeOf of unsized type was requested.
-    SizeOfUnsizedType(Ty<'tcx>),
     /// We are runnning into a nonsense situation due to ConstProp violating our invariants.
     ConstPropNonsense,
 }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ddb6cc15bc1..8fd980d5a9e 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -524,13 +524,13 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
             // local crate's ID. Otherwise there can be collisions between CGUs
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
-                let local_stable_crate_id = tcx.sess.local_stable_crate_id();
+                let local_stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
                 format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id)
             } else {
                 String::new()
             };
 
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
             format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id)
         });
 
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 2e5c6a44579..74bdd07a1c9 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -7,6 +7,7 @@ use std::fmt::Write;
 
 use crate::query::Providers;
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem};
 use rustc_span::def_id::LocalDefIdMap;
@@ -89,10 +90,18 @@ pub enum ClosureKind {
     FnOnce,
 }
 
-impl<'tcx> ClosureKind {
+impl ClosureKind {
     /// This is the initial value used when doing upvar inference.
     pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
 
+    pub const fn as_str(self) -> &'static str {
+        match self {
+            ClosureKind::Fn => "Fn",
+            ClosureKind::FnMut => "FnMut",
+            ClosureKind::FnOnce => "FnOnce",
+        }
+    }
+
     /// Returns `true` if a type that impls this closure kind
     /// must also implement `other`.
     pub fn extends(self, other: ty::ClosureKind) -> bool {
@@ -115,7 +124,7 @@ impl<'tcx> ClosureKind {
 
     /// Returns the representative scalar type for this closure kind.
     /// See `Ty::to_opt_closure_kind` for more details.
-    pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+    pub fn to_ty<'tcx>(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self {
             ClosureKind::Fn => tcx.types.i8,
             ClosureKind::FnMut => tcx.types.i16,
@@ -124,6 +133,12 @@ impl<'tcx> ClosureKind {
     }
 }
 
+impl IntoDiagnosticArg for ClosureKind {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(self.as_str().into())
+    }
+}
+
 /// A composite describing a `Place` that is captured by a closure.
 #[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0b2d95506bf..be839e03cff 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -59,8 +59,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
-use rustc_session::Limit;
-use rustc_session::Session;
+use rustc_session::{Limit, MetadataKind, Session};
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -527,6 +526,13 @@ pub struct GlobalCtxt<'tcx> {
     interners: CtxtInterners<'tcx>,
 
     pub sess: &'tcx Session,
+    crate_types: Vec<CrateType>,
+    /// The `stable_crate_id` is constructed out of the crate name and all the
+    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
+    /// global identifier for the crate. It is used to allow multiple crates
+    /// with the same name to coexist. See the
+    /// `rustc_symbol_mangling` crate for more information.
+    stable_crate_id: StableCrateId,
 
     /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
     ///
@@ -687,6 +693,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// has a valid reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
+        crate_types: Vec<CrateType>,
+        stable_crate_id: StableCrateId,
         lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
@@ -705,6 +713,8 @@ impl<'tcx> TyCtxt<'tcx> {
 
         GlobalCtxt {
             sess: s,
+            crate_types,
+            stable_crate_id,
             lint_store,
             arena,
             hir_arena,
@@ -801,9 +811,46 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
+    pub fn crate_types(self) -> &'tcx [CrateType] {
+        &self.crate_types
+    }
+
+    pub fn metadata_kind(self) -> MetadataKind {
+        self.crate_types()
+            .iter()
+            .map(|ty| match *ty {
+                CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => {
+                    MetadataKind::None
+                }
+                CrateType::Rlib => MetadataKind::Uncompressed,
+                CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
+            })
+            .max()
+            .unwrap_or(MetadataKind::None)
+    }
+
+    pub fn needs_metadata(self) -> bool {
+        self.metadata_kind() != MetadataKind::None
+    }
+
+    pub fn needs_crate_hash(self) -> bool {
+        // Why is the crate hash needed for these configurations?
+        // - debug_assertions: for the "fingerprint the result" check in
+        //   `rustc_query_system::query::plumbing::execute_job`.
+        // - incremental: for query lookups.
+        // - needs_metadata: for putting into crate metadata.
+        // - instrument_coverage: for putting into coverage data (see
+        //   `hash_mir_source`).
+        cfg!(debug_assertions)
+            || self.sess.opts.incremental.is_some()
+            || self.needs_metadata()
+            || self.sess.instrument_coverage()
+    }
+
+    #[inline]
     pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
         if crate_num == LOCAL_CRATE {
-            self.sess.local_stable_crate_id()
+            self.stable_crate_id
         } else {
             self.cstore_untracked().stable_crate_id(crate_num)
         }
@@ -813,7 +860,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// that the crate in question has already been loaded by the CrateStore.
     #[inline]
     pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
-        if stable_crate_id == self.sess.local_stable_crate_id() {
+        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
             LOCAL_CRATE
         } else {
             self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
@@ -830,7 +877,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // If this is a DefPathHash from the local crate, we can look up the
         // DefId in the tcx's `Definitions`.
-        if stable_crate_id == self.sess.local_stable_crate_id() {
+        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
             self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
         } else {
             // If this is a DefPathHash from an upstream crate, let the CrateStore map
@@ -847,7 +894,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // statements within the query system and we'd run into endless
         // recursion otherwise.
         let (crate_name, stable_crate_id) = if def_id.is_local() {
-            (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
+            (self.crate_name(LOCAL_CRATE), self.stable_crate_id(LOCAL_CRATE))
         } else {
             let cstore = &*self.cstore_untracked();
             (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
@@ -986,7 +1033,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn local_crate_exports_generics(self) -> bool {
         debug_assert!(self.sess.opts.share_generics());
 
-        self.sess.crate_types().iter().any(|crate_type| {
+        self.crate_types().iter().any(|crate_type| {
             match crate_type {
                 CrateType::Executable
                 | CrateType::Staticlib
@@ -1931,6 +1978,84 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
+    /// Given the def-id of an early-bound lifetime on an RPIT corresponding to
+    /// a duplicated captured lifetime, map it back to the early- or late-bound
+    /// lifetime of the function from which it originally as captured. If it is
+    /// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime
+    /// of the signature.
+    // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
+    // re-use the generics of the opaque, this function will need to be tweaked slightly.
+    pub fn map_rpit_lifetime_to_fn_lifetime(
+        self,
+        mut rpit_lifetime_param_def_id: LocalDefId,
+    ) -> ty::Region<'tcx> {
+        debug_assert!(
+            matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam),
+            "{rpit_lifetime_param_def_id:?} is a {}",
+            self.def_descr(rpit_lifetime_param_def_id.to_def_id())
+        );
+
+        loop {
+            let parent = self.local_parent(rpit_lifetime_param_def_id);
+            let hir::OpaqueTy { lifetime_mapping, .. } =
+                self.hir().get_by_def_id(parent).expect_item().expect_opaque_ty();
+
+            let Some((lifetime, _)) = lifetime_mapping
+                .iter()
+                .find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id)
+            else {
+                bug!("duplicated lifetime param should be present");
+            };
+
+            match self.named_bound_var(lifetime.hir_id) {
+                Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => {
+                    let new_parent = self.parent(ebv);
+
+                    // If we map to another opaque, then it should be a parent
+                    // of the opaque we mapped from. Continue mapping.
+                    if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
+                        debug_assert_eq!(self.parent(parent.to_def_id()), new_parent);
+                        rpit_lifetime_param_def_id = ebv.expect_local();
+                        continue;
+                    }
+
+                    let generics = self.generics_of(new_parent);
+                    return ty::Region::new_early_bound(
+                        self,
+                        ty::EarlyBoundRegion {
+                            def_id: ebv,
+                            index: generics
+                                .param_def_id_to_index(self, ebv)
+                                .expect("early-bound var should be present in fn generics"),
+                            name: self.hir().name(self.local_def_id_to_hir_id(ebv.expect_local())),
+                        },
+                    );
+                }
+                Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
+                    let new_parent = self.parent(lbv);
+                    return ty::Region::new_free(
+                        self,
+                        new_parent,
+                        ty::BoundRegionKind::BrNamed(
+                            lbv,
+                            self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())),
+                        ),
+                    );
+                }
+                Some(resolve_bound_vars::ResolvedArg::Error(guar)) => {
+                    return ty::Region::new_error(self, guar);
+                }
+                _ => {
+                    return ty::Region::new_error_with_message(
+                        self,
+                        lifetime.ident.span,
+                        "cannot resolve lifetime",
+                    );
+                }
+            }
+        }
+    }
+
     /// Whether the `def_id` counts as const fn in the current crate, considering all active
     /// feature gates
     pub fn is_const_fn(self, def_id: DefId) -> bool {
@@ -1963,9 +2088,9 @@ impl<'tcx> TyCtxt<'tcx> {
         matches!(
             node,
             hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
+                kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
                 ..
-            })
+            }) if generics.params.iter().any(|p| self.has_attr(p.def_id, sym::rustc_host))
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index df39103bc19..e362b3477c9 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1239,6 +1239,8 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         | EfiApi
         | AvrInterrupt
         | AvrNonBlockingInterrupt
+        | RiscvInterruptM
+        | RiscvInterruptS
         | CCmseNonSecureCall
         | Wasm
         | PlatformIntrinsic
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 27ade16739d..bb6513363c9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2841,6 +2841,11 @@ define_print_and_forward_display! {
 
     ty::TraitPredicate<'tcx> {
         p!(print(self.trait_ref.self_ty()), ": ");
+        if let Some(idx) = cx.tcx().generics_of(self.trait_ref.def_id).host_effect_index {
+            if self.trait_ref.args.const_at(idx) != cx.tcx().consts.true_ {
+                p!("~const ");
+            }
+        }
         // FIXME(effects) print `~const` here
         if let ty::ImplPolarity::Negative = self.polarity {
             p!("!");
@@ -2870,11 +2875,7 @@ define_print_and_forward_display! {
     }
 
     ty::ClosureKind {
-        match *self {
-            ty::ClosureKind::Fn => p!("Fn"),
-            ty::ClosureKind::FnMut => p!("FnMut"),
-            ty::ClosureKind::FnOnce => p!("FnOnce"),
-        }
+        p!(write("{}", self.as_str()))
     }
 
     ty::Predicate<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 58cc161ddcc..d202860840c 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -30,6 +30,8 @@ fn abi_can_unwind(abi: Abi) -> bool {
         | EfiApi
         | AvrInterrupt
         | AvrNonBlockingInterrupt
+        | RiscvInterruptM
+        | RiscvInterruptS
         | CCmseNonSecureCall
         | Wasm
         | RustIntrinsic
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index f99a51fea0b..bf798adee19 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -75,7 +75,7 @@ mod errors;
 mod ffi_unwind_calls;
 mod function_item_references;
 mod generator;
-mod inline;
+pub mod inline;
 mod instsimplify;
 mod large_enums;
 mod lower_intrinsics;
@@ -431,7 +431,9 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
     tcx.alloc_steal_mir(body)
 }
 
-fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves.
+pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial));
     let did = body.source.def_id();
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index ffd8f77b78b..6a29159e917 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -31,7 +31,7 @@ struct EntryContext<'tcx> {
 }
 
 fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
-    let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
+    let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable);
     if !any_exe {
         // No need to find a main function.
         return None;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 7dec5b0acc8..f9d34ea71ba 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -364,10 +364,10 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
     let effective_visibilities = &tcx.effective_visibilities(());
 
-    let any_library =
-        tcx.sess.crate_types().iter().any(|ty| {
-            *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro
-        });
+    let any_library = tcx
+        .crate_types()
+        .iter()
+        .any(|ty| *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro);
     let mut reachable_context = ReachableContext {
         tcx,
         maybe_typeck_results: None,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 25a3d38c144..3950ac9dd31 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -732,13 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(hir::Impl {
-                of_trait: Some(ref t),
-                self_ty,
-                items,
-                constness,
-                ..
-            }) => {
+            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
                 let features = self.tcx.features();
                 if features.staged_api {
                     let attrs = self.tcx.hir().attrs(item.hir_id());
@@ -769,7 +763,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
                     // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
                     // needs to have an error emitted.
                     if features.const_trait_impl
-                        && *constness == hir::Constness::Const
+                        && self.tcx.is_const_trait_impl_raw(item.owner_id.to_def_id())
                         && const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
                     {
                         self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index fc6372cf99e..75e071f1fcf 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -43,7 +43,7 @@ pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
 fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
     // emitting something that's not an rlib.
-    let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
+    let needs_check = tcx.crate_types().iter().any(|kind| match *kind {
         CrateType::Dylib
         | CrateType::ProcMacro
         | CrateType::Cdylib
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6007295b930..c87db96a5dd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4374,7 +4374,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 if let Some(res) = res
                     && let Some(def_id) = res.opt_def_id()
                     && !def_id.is_local()
-                    && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+                    && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                     && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) {
                     // Encoding foreign def ids in proc macro crate metadata will ICE.
                     return None;
@@ -4389,7 +4389,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         match self.r.tcx.sess.opts.resolve_doc_links {
             ResolveDocLinks::None => return,
             ResolveDocLinks::ExportedMetadata
-                if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata)
+                if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata)
                     || !maybe_exported.eval(self.r) =>
             {
                 return;
@@ -4448,7 +4448,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         .into_iter()
                         .filter_map(|tr| {
                             if !tr.def_id.is_local()
-                                && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+                                && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                                 && matches!(
                                     self.r.tcx.sess.opts.resolve_doc_links,
                                     ResolveDocLinks::ExportedMetadata
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index ba9bbbb1463..c34b7df9b46 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2404,7 +2404,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         should_continue = suggest(err, false, span, message, sugg);
                     }
                 }
-                LifetimeRibKind::Item => break,
+                LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy => break,
                 _ => {}
             }
             if !should_continue {
@@ -2510,7 +2510,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             .lifetime_ribs
             .iter()
             .rev()
-            .take_while(|rib| !matches!(rib.kind, LifetimeRibKind::Item))
+            .take_while(|rib| {
+                !matches!(rib.kind, LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy)
+            })
             .flat_map(|rib| rib.bindings.iter())
             .map(|(&ident, &res)| (ident, res))
             .filter(|(ident, _)| ident.name != kw::UnderscoreLifetime)
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index d4042a2e61a..b07c6db599e 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -89,7 +89,9 @@ session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-genera
 
 session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
 
-session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`
+
+session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
 
 session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
 
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 1ffee01b2f1..78940462b2c 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -115,6 +115,10 @@ pub struct CannotEnableCrtStaticLinux;
 pub struct SanitizerCfiRequiresLto;
 
 #[derive(Diagnostic)]
+#[diag(session_sanitizer_cfi_requires_single_codegen_unit)]
+pub struct SanitizerCfiRequiresSingleCodegenUnit;
+
+#[derive(Diagnostic)]
 #[diag(session_sanitizer_cfi_canonical_jump_tables_requires_cfi)]
 pub struct SanitizerCfiCanonicalJumpTablesRequiresCfi;
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index ac745d16161..5d7572f65a5 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -152,14 +152,6 @@ pub struct Session {
     /// Input, input file path and output file path to this compilation process.
     pub io: CompilerIO,
 
-    crate_types: OnceCell<Vec<CrateType>>,
-    /// The `stable_crate_id` is constructed out of the crate name and all the
-    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
-    /// global identifier for the crate. It is used to allow multiple crates
-    /// with the same name to coexist. See the
-    /// `rustc_symbol_mangling` crate for more information.
-    pub stable_crate_id: OnceCell<StableCrateId>,
-
     features: OnceCell<rustc_feature::Features>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
@@ -310,55 +302,11 @@ impl Session {
         self.parse_sess.span_diagnostic.emit_future_breakage_report(diags);
     }
 
-    pub fn local_stable_crate_id(&self) -> StableCrateId {
-        self.stable_crate_id.get().copied().unwrap()
-    }
-
-    pub fn crate_types(&self) -> &[CrateType] {
-        self.crate_types.get().unwrap().as_slice()
-    }
-
     /// Returns true if the crate is a testing one.
     pub fn is_test_crate(&self) -> bool {
         self.opts.test
     }
 
-    pub fn needs_crate_hash(&self) -> bool {
-        // Why is the crate hash needed for these configurations?
-        // - debug_assertions: for the "fingerprint the result" check in
-        //   `rustc_query_system::query::plumbing::execute_job`.
-        // - incremental: for query lookups.
-        // - needs_metadata: for putting into crate metadata.
-        // - instrument_coverage: for putting into coverage data (see
-        //   `hash_mir_source`).
-        cfg!(debug_assertions)
-            || self.opts.incremental.is_some()
-            || self.needs_metadata()
-            || self.instrument_coverage()
-    }
-
-    pub fn metadata_kind(&self) -> MetadataKind {
-        self.crate_types()
-            .iter()
-            .map(|ty| match *ty {
-                CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => {
-                    MetadataKind::None
-                }
-                CrateType::Rlib => MetadataKind::Uncompressed,
-                CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
-            })
-            .max()
-            .unwrap_or(MetadataKind::None)
-    }
-
-    pub fn needs_metadata(&self) -> bool {
-        self.metadata_kind() != MetadataKind::None
-    }
-
-    pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
-        self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
-    }
-
     #[rustc_lint_diagnostics]
     #[track_caller]
     pub fn struct_span_warn<S: Into<MultiSpan>>(
@@ -1516,8 +1464,6 @@ pub fn build_session(
         parse_sess,
         sysroot,
         io,
-        crate_types: OnceCell::new(),
-        stable_crate_id: OnceCell::new(),
         features: OnceCell::new(),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
@@ -1619,13 +1565,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
 
     // LLVM CFI requires LTO.
     if sess.is_sanitizer_cfi_enabled()
-        && !(sess.lto() == config::Lto::Fat
-            || sess.lto() == config::Lto::Thin
-            || sess.opts.cg.linker_plugin_lto.enabled())
+        && !(sess.lto() == config::Lto::Fat || sess.opts.cg.linker_plugin_lto.enabled())
     {
         sess.emit_err(errors::SanitizerCfiRequiresLto);
     }
 
+    // LLVM CFI using rustc LTO requires a single codegen unit.
+    if sess.is_sanitizer_cfi_enabled()
+        && sess.lto() == config::Lto::Fat
+        && !(sess.codegen_units().as_usize() == 1)
+    {
+        sess.emit_err(errors::SanitizerCfiRequiresSingleCodegenUnit);
+    }
+
     // LLVM CFI is incompatible with LLVM KCFI.
     if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
         sess.emit_err(errors::CannotMixAndMatchSanitizers {
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 39541c845b3..078ff67446f 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -63,6 +63,10 @@ pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef {
     with_tables(|t| t.trait_def(did))
 }
 
+pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef {
+    with_tables(|t| t.impl_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
@@ -72,6 +76,10 @@ impl<'tcx> Tables<'tcx> {
         self.def_ids[trait_def.0]
     }
 
+    pub fn impl_trait_def_id(&self, impl_def: &stable_mir::ty::ImplDef) -> DefId {
+        self.def_ids[impl_def.0]
+    }
+
     pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
         stable_mir::CrateItem(self.create_def_id(did))
     }
@@ -112,6 +120,14 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::TraitDef(self.create_def_id(did))
     }
 
+    pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
+        stable_mir::ty::ConstDef(self.create_def_id(did))
+    }
+
+    pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef {
+        stable_mir::ty::ImplDef(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 d12de92db8a..6ab473c3b54 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -9,11 +9,14 @@
 
 use crate::rustc_internal::{self, opaque};
 use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
-use crate::stable_mir::ty::{FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
+use crate::stable_mir::ty::{
+    allocation_filter, new_allocation, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy,
+};
 use crate::stable_mir::{self, Context};
 use rustc_hir as hir;
 use rustc_middle::mir::coverage::CodeRegion;
-use rustc_middle::mir::{self};
+use rustc_middle::mir::interpret::alloc_range;
+use rustc_middle::mir::{self, ConstantKind};
 use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
@@ -56,6 +59,20 @@ impl<'tcx> Context for Tables<'tcx> {
         trait_def.stable(self)
     }
 
+    fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls {
+        self.tcx
+            .trait_impls_in_crate(LOCAL_CRATE)
+            .iter()
+            .map(|impl_def_id| self.impl_def(*impl_def_id))
+            .collect()
+    }
+
+    fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
+        let def_id = self.impl_trait_def_id(impl_def);
+        let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
+        impl_trait.stable(self)
+    }
+
     fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
         let def_id = self.item_def_id(item);
         let mir = self.tcx.optimized_mir(def_id);
@@ -837,6 +854,19 @@ where
     }
 }
 
+impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<S>
+where
+    S: Stable<'tcx, T = V>,
+{
+    type T = stable_mir::ty::EarlyBinder<V>;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::EarlyBinder;
+
+        EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
     type T = stable_mir::ty::FnSig;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -877,6 +907,8 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
                 abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
                 abi::Abi::Unadjusted => Abi::Unadjusted,
                 abi::Abi::RustCold => Abi::RustCold,
+                abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
+                abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
             },
         }
     }
@@ -1080,30 +1112,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
     type T = stable_mir::ty::Allocation;
 
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        let size = self.size();
-        let mut bytes: Vec<Option<u8>> = self
-            .inspect_with_uninit_and_ptr_outside_interpreter(0..size.bytes_usize())
-            .iter()
-            .copied()
-            .map(Some)
-            .collect();
-        for (i, b) in bytes.iter_mut().enumerate() {
-            if !self.init_mask().get(rustc_target::abi::Size::from_bytes(i)) {
-                *b = None;
-            }
-        }
-        stable_mir::ty::Allocation {
-            bytes: bytes,
-            provenance: {
-                let mut ptrs = Vec::new();
-                for (size, prov) in self.provenance().ptrs().iter() {
-                    ptrs.push((size.bytes_usize(), opaque(prov)));
-                }
-                stable_mir::ty::ProvenanceMap { ptrs }
-            },
-            align: self.align.bytes(),
-            mutability: self.mutability.stable(tables),
-        }
+        allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
     }
 }
 
@@ -1145,3 +1154,39 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
         }
     }
 }
+
+impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
+    type T = stable_mir::ty::ConstantKind;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self {
+            ConstantKind::Ty(c) => match c.kind() {
+                ty::Value(val) => {
+                    let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
+                    stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
+                }
+                _ => todo!(),
+            },
+            ConstantKind::Unevaluated(unev_const, ty) => {
+                stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
+                    ty: tables.intern_ty(*ty),
+                    def: tables.const_def(unev_const.def),
+                    args: unev_const.args.stable(tables),
+                    promoted: unev_const.promoted.map(|u| u.as_u32()),
+                })
+            }
+            ConstantKind::Val(val, _) => {
+                stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
+            }
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
+    type T = stable_mir::ty::TraitRef;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::TraitRef;
+
+        TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index d93f25249b9..a74975cefc2 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -15,7 +15,7 @@ use std::cell::Cell;
 
 use crate::rustc_smir::Tables;
 
-use self::ty::{TraitDecl, TraitDef, Ty, TyKind};
+use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
 
 pub mod mir;
 pub mod ty;
@@ -32,9 +32,12 @@ pub type DefId = usize;
 /// A list of crate items.
 pub type CrateItems = Vec<CrateItem>;
 
-/// A list of crate items.
+/// A list of trait decls.
 pub type TraitDecls = Vec<TraitDef>;
 
+/// A list of impl trait decls.
+pub type ImplTraitDecls = Vec<ImplDef>;
+
 /// Holds information about a crate.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Crate {
@@ -89,6 +92,8 @@ pub trait Context {
     fn mir_body(&mut self, item: &CrateItem) -> mir::Body;
     fn all_trait_decls(&mut self) -> TraitDecls;
     fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
+    fn all_trait_impls(&mut self) -> ImplTraitDecls;
+    fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
     /// Get information about the local crate.
     fn local_crate(&self) -> Crate;
     /// Retrieve a list of all external crates.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index c487db5b732..8a23af75749 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,5 +1,10 @@
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
+
 use super::{mir::Mutability, mir::Safety, with, DefId};
-use crate::rustc_internal::Opaque;
+use crate::{
+    rustc_internal::{opaque, Opaque},
+    rustc_smir::{Stable, Tables},
+};
 
 #[derive(Copy, Clone, Debug)]
 pub struct Ty(pub usize);
@@ -105,12 +110,24 @@ pub struct AliasDef(pub(crate) DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct TraitDef(pub(crate) DefId);
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ConstDef(pub(crate) DefId);
+
 impl TraitDef {
     pub fn trait_decl(&self) -> TraitDecl {
         with(|cx| cx.trait_decl(self))
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ImplDef(pub(crate) DefId);
+
+impl ImplDef {
+    pub fn trait_impl(&self) -> ImplTrait {
+        with(|cx| cx.trait_impl(self))
+    }
+}
+
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
@@ -178,6 +195,8 @@ pub enum Abi {
     PlatformIntrinsic,
     Unadjusted,
     RustCold,
+    RiscvInterruptM,
+    RiscvInterruptS,
 }
 
 #[derive(Clone, Debug)]
@@ -187,6 +206,11 @@ pub struct Binder<T> {
 }
 
 #[derive(Clone, Debug)]
+pub struct EarlyBinder<T> {
+    pub value: T,
+}
+
+#[derive(Clone, Debug)]
 pub enum BoundVariableKind {
     Ty(BoundTyKind),
     Region(BoundRegionKind),
@@ -248,6 +272,7 @@ pub type Bytes = Vec<Option<u8>>;
 pub type Size = usize;
 pub type Prov = Opaque;
 pub type Align = u64;
+pub type Promoted = u32;
 pub type InitMaskMaterialized = Vec<u64>;
 
 /// Stores the provenance information of pointers stored in memory.
@@ -266,6 +291,142 @@ pub struct Allocation {
     pub mutability: Mutability,
 }
 
+impl Allocation {
+    /// Creates new empty `Allocation` from given `Align`.
+    fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
+        Allocation {
+            bytes: Vec::new(),
+            provenance: ProvenanceMap { ptrs: Vec::new() },
+            align: align.bytes(),
+            mutability: Mutability::Not,
+        }
+    }
+}
+
+// We need this method instead of a Stable implementation
+// because we need to get `Ty` of the const we are trying to create, to do that
+// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
+pub fn new_allocation<'tcx>(
+    const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
+    const_value: ConstValue<'tcx>,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    match const_value {
+        ConstValue::Scalar(scalar) => {
+            let size = scalar.size();
+            let align = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap()
+                .align;
+            let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
+            allocation
+                .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ZeroSized => {
+            let align = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
+                .unwrap()
+                .align;
+            Allocation::new_empty_allocation(align.abi)
+        }
+        ConstValue::Slice { data, start, end } => {
+            let alloc_id = tables.tcx.create_memory_alloc(data);
+            let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
+            let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
+            let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
+                (end - start) as u64,
+                &tables.tcx,
+            );
+            let layout = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap();
+            let mut allocation =
+                rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+                    scalar_ptr,
+                )
+                .unwrap();
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
+                    scalar_len,
+                )
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ByRef { alloc, offset } => {
+            let ty_size = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap()
+                .size;
+            allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
+        }
+    }
+}
+
+/// Creates an `Allocation` only from information within the `AllocRange`.
+pub fn allocation_filter<'tcx>(
+    alloc: &rustc_middle::mir::interpret::Allocation,
+    alloc_range: AllocRange,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    let mut bytes: Vec<Option<u8>> = alloc
+        .inspect_with_uninit_and_ptr_outside_interpreter(
+            alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
+        )
+        .iter()
+        .copied()
+        .map(Some)
+        .collect();
+    for (i, b) in bytes.iter_mut().enumerate() {
+        if !alloc
+            .init_mask()
+            .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
+        {
+            *b = None;
+        }
+    }
+    let mut ptrs = Vec::new();
+    for (offset, prov) in alloc
+        .provenance()
+        .ptrs()
+        .iter()
+        .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
+    {
+        ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
+    }
+    Allocation {
+        bytes: bytes,
+        provenance: ProvenanceMap { ptrs },
+        align: alloc.align.bytes(),
+        mutability: alloc.mutability.stable(tables),
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum ConstantKind {
+    Allocated(Allocation),
+    Unevaluated(UnevaluatedConst),
+}
+
+#[derive(Clone, Debug)]
+pub struct UnevaluatedConst {
+    pub ty: Ty,
+    pub def: ConstDef,
+    pub args: GenericArgs,
+    pub promoted: Option<Promoted>,
+}
+
 pub enum TraitSpecializationKind {
     None,
     Marker,
@@ -285,3 +446,10 @@ pub struct TraitDecl {
     pub implement_via_object: bool,
     pub deny_explicit_impl: bool,
 }
+
+pub type ImplTrait = EarlyBinder<TraitRef>;
+
+pub struct TraitRef {
+    pub def_id: TraitDef,
+    pub args: GenericArgs,
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9ea9efb047c..745a3590720 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -326,6 +326,7 @@ symbols! {
         abi_efiapi,
         abi_msp430_interrupt,
         abi_ptx,
+        abi_riscv_interrupt,
         abi_sysv64,
         abi_thiscall,
         abi_unadjusted,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 22fd1f09f3a..74538e9f5a3 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -180,7 +180,7 @@ fn compute_symbol_name<'tcx>(
 
     if let Some(def_id) = def_id.as_local() {
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
             return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 845b5791161..d345368d552 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -824,11 +824,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         }
 
         ty::Array(ty0, len) => {
-            let len = len
-                .try_to_scalar()
-                .unwrap()
-                .to_u64()
-                .unwrap_or_else(|_| panic!("failed to convert length to u64"));
+            let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
+
             ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, options), len);
         }
 
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 3d2ea017d8f..e4989bdfbcd 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -603,6 +603,25 @@ pub enum Conv {
     AmdGpuKernel,
     AvrInterrupt,
     AvrNonBlockingInterrupt,
+
+    RiscvInterrupt {
+        kind: RiscvInterruptKind,
+    },
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub enum RiscvInterruptKind {
+    Machine,
+    Supervisor,
+}
+
+impl RiscvInterruptKind {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Machine => "machine",
+            Self::Supervisor => "supervisor",
+        }
+    }
 }
 
 /// Metadata describing how the arguments to a native function
@@ -753,6 +772,12 @@ impl FromStr for Conv {
             "AmdGpuKernel" => Ok(Conv::AmdGpuKernel),
             "AvrInterrupt" => Ok(Conv::AvrInterrupt),
             "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
+            "RiscvInterrupt(machine)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine })
+            }
+            "RiscvInterrupt(supervisor)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor })
+            }
             _ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
         }
     }
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 084c917cc31..dd435dbb0a3 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -39,7 +39,7 @@ impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
 
 /// Trait that needs to be implemented by the higher-level type representation
 /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
-pub trait TyAbiInterface<'a, C>: Sized {
+pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
     fn ty_and_layout_for_variant(
         this: TyAndLayout<'a, Self>,
         cx: &C,
@@ -135,6 +135,11 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         for index in indices {
             offset += layout.fields.offset(index);
             layout = layout.field(cx, index);
+            assert!(
+                layout.is_sized(),
+                "offset of unsized field (type {:?}) cannot be computed statically",
+                layout.ty
+            );
         }
 
         offset
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 75bb76a9de0..af455b6432f 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -92,6 +92,7 @@ impl<A: ToJson> ToJson for Option<A> {
 
 impl ToJson for crate::abi::call::Conv {
     fn to_json(&self) -> Json {
+        let buf: String;
         let s = match self {
             Self::C => "C",
             Self::Rust => "Rust",
@@ -110,6 +111,10 @@ impl ToJson for crate::abi::call::Conv {
             Self::AmdGpuKernel => "AmdGpuKernel",
             Self::AvrInterrupt => "AvrInterrupt",
             Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt",
+            Self::RiscvInterrupt { kind } => {
+                buf = format!("RiscvInterrupt({})", kind.as_str());
+                &buf
+            }
         };
         Json::String(s.to_owned())
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs
new file mode 100644
index 00000000000..64a7dc681c8
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs
@@ -0,0 +1,16 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::teeos_base::opts();
+    base.features = "+strict-align,+neon,+fp-armv8".into();
+    base.max_atomic_width = Some(128);
+    base.linker = Some("aarch64-linux-gnu-ld".into());
+
+    Target {
+        llvm_target: "aarch64-unknown-none".into(),
+        pointer_width: 64,
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index dc233121f66..550cdf6bda6 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -38,6 +38,8 @@ pub enum Abi {
     PlatformIntrinsic,
     Unadjusted,
     RustCold,
+    RiscvInterruptM,
+    RiscvInterruptS,
 }
 
 impl Abi {
@@ -107,11 +109,29 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
     AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
     AbiData { abi: Abi::RustCold, name: "rust-cold" },
+    AbiData { abi: Abi::RiscvInterruptM, name: "riscv-interrupt-m" },
+    AbiData { abi: Abi::RiscvInterruptS, name: "riscv-interrupt-s" },
 ];
 
+#[derive(Copy, Clone, Debug)]
+pub enum AbiUnsupported {
+    Unrecognized,
+    Reason { explain: &'static str },
+}
+
 /// Returns the ABI with the given name (if any).
-pub fn lookup(name: &str) -> Option<Abi> {
-    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
+pub fn lookup(name: &str) -> Result<Abi, AbiUnsupported> {
+    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi).ok_or_else(|| match name {
+        "riscv-interrupt" => AbiUnsupported::Reason {
+            explain: "please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively",
+        },
+        "riscv-interrupt-u" => AbiUnsupported::Reason {
+            explain: "user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314",
+        },
+
+        _ => AbiUnsupported::Unrecognized,
+
+    })
 }
 
 pub fn all_names() -> Vec<&'static str> {
@@ -200,6 +220,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
             feature: sym::abi_avr_interrupt,
             explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
         }),
+        "riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable {
+            feature: sym::abi_riscv_interrupt,
+            explain: "riscv-interrupt ABIs are experimental and subject to change",
+        }),
         "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
             feature: sym::abi_c_cmse_nonsecure_call,
             explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
@@ -260,6 +284,8 @@ impl Abi {
             PlatformIntrinsic => 32,
             Unadjusted => 33,
             RustCold => 34,
+            RiscvInterruptM => 35,
+            RiscvInterruptS => 36,
         };
         debug_assert!(
             AbiDatas
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs
index 8bea5e5efe3..251a12fe7aa 100644
--- a/compiler/rustc_target/src/spec/abi/tests.rs
+++ b/compiler/rustc_target/src/spec/abi/tests.rs
@@ -4,19 +4,19 @@ use super::*;
 #[test]
 fn lookup_Rust() {
     let abi = lookup("Rust");
-    assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "Rust");
 }
 
 #[test]
 fn lookup_cdecl() {
     let abi = lookup("cdecl");
-    assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "cdecl");
 }
 
 #[test]
 fn lookup_baz() {
     let abi = lookup("baz");
-    assert!(abi.is_none());
+    assert!(matches!(abi, Err(AbiUnsupported::Unrecognized)))
 }
 
 #[test]
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c215a7c4b6e..1871239d7de 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -83,6 +83,7 @@ mod openbsd_base;
 mod redox_base;
 mod solaris_base;
 mod solid_base;
+mod teeos_base;
 mod thumb_base;
 mod uefi_msvc_base;
 mod unikraft_linux_musl_base;
@@ -1494,6 +1495,8 @@ supported_targets! {
 
     ("x86_64-unknown-none", x86_64_unknown_none),
 
+    ("aarch64-unknown-teeos", aarch64_unknown_teeos),
+
     ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
 
     ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx_710),
@@ -2267,6 +2270,7 @@ impl Target {
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
             AmdGpuKernel => self.arch == "amdgcn",
+            RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
             AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
             Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
             Thiscall { .. } => self.arch == "x86",
@@ -2698,7 +2702,7 @@ impl Target {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
                     match lookup_abi(s) {
-                        Some(abi) => base.$key_name = Some(abi),
+                        Ok(abi) => base.$key_name = Some(abi),
                         _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
                     }
                     Some(Ok(()))
diff --git a/compiler/rustc_target/src/spec/teeos_base.rs b/compiler/rustc_target/src/spec/teeos_base.rs
new file mode 100644
index 00000000000..1bc71bab016
--- /dev/null
+++ b/compiler/rustc_target/src/spec/teeos_base.rs
@@ -0,0 +1,29 @@
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy};
+use crate::spec::{RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+    let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
+    let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];
+
+    let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
+    super::add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args);
+
+    TargetOptions {
+        os: "teeos".into(),
+        vendor: "unknown".into(),
+        dynamic_linking: true,
+        linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+        // rpath hardcodes -Wl, so it can't be used together with ld.lld.
+        // C TAs also don't support rpath, so this is fine.
+        has_rpath: false,
+        // Note: Setting has_thread_local to true causes an error when
+        // loading / dyn-linking the TA
+        has_thread_local: false,
+        position_independent_executables: true,
+        relro_level: RelroLevel::Full,
+        crt_static_respected: true,
+        pre_link_args,
+        panic_strategy: PanicStrategy::Abort,
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index f57f1bad15d..f4c9dfa3488 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -8,6 +8,15 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
         *[other] arguments
     }
 
+trait_selection_closure_fn_mut_label = closure is `FnMut` because it mutates the variable `{$place}` here
+
+trait_selection_closure_fn_once_label = closure is `FnOnce` because it moves the variable `{$place}` out of its environment
+
+trait_selection_closure_kind_mismatch = expected a closure that implements the `{$expected}` trait, but this closure only implements `{$found}`
+    .label = this closure implements `{$found}`, not `{$expected}`
+
+trait_selection_closure_kind_requirement = the requirement to implement `{$expected}` derives from here
+
 trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
 
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index dde9e9c9ac6..c1fb287d63e 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -4,7 +4,7 @@ use rustc_errors::{
     SubdiagnosticMessage,
 };
 use rustc_macros::Diagnostic;
-use rustc_middle::ty::{self, PolyTraitRef, Ty};
+use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
@@ -131,3 +131,37 @@ impl AddToDiagnostic for AdjustSignatureBorrow {
         }
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_closure_kind_mismatch, code = "E0525")]
+pub struct ClosureKindMismatch {
+    #[primary_span]
+    #[label]
+    pub closure_span: Span,
+    pub expected: ClosureKind,
+    pub found: ClosureKind,
+    #[label(trait_selection_closure_kind_requirement)]
+    pub cause_span: Span,
+
+    #[subdiagnostic]
+    pub fn_once_label: Option<ClosureFnOnceLabel>,
+
+    #[subdiagnostic]
+    pub fn_mut_label: Option<ClosureFnMutLabel>,
+}
+
+#[derive(Subdiagnostic)]
+#[label(trait_selection_closure_fn_once_label)]
+pub struct ClosureFnOnceLabel {
+    #[primary_span]
+    pub span: Span,
+    pub place: String,
+}
+
+#[derive(Subdiagnostic)]
+#[label(trait_selection_closure_fn_mut_label)]
+pub struct ClosureFnMutLabel {
+    #[primary_span]
+    pub span: Span,
+    pub place: String,
+}
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
index 56f126e9157..be48447e27c 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
@@ -19,21 +19,25 @@ rustc_index::newtype_index! {
 
 #[derive(Debug, Clone)]
 pub(super) struct ProvisionalEntry<'tcx> {
-    // In case we have a coinductive cycle, this is the
-    // the currently least restrictive result of this goal.
-    pub(super) response: QueryResult<'tcx>,
-    // In case of a cycle, the position of deepest stack entry involved
-    // in that cycle. This is monotonically decreasing in the stack as all
-    // elements between the current stack element in the deepest stack entry
-    // involved have to also be involved in that cycle.
-    //
-    // We can only move entries to the global cache once we're complete done
-    // with the cycle. If this entry has not been involved in a cycle,
-    // this is just its own depth.
+    /// In case we have a coinductive cycle, this is the
+    /// the current provisional result of this goal.
+    ///
+    /// This starts out as `None` for all goals and gets to some
+    /// when the goal gets popped from the stack or we rerun evaluation
+    /// for this goal to reach a fixpoint.
+    pub(super) response: Option<QueryResult<'tcx>>,
+    /// In case of a cycle, the position of deepest stack entry involved
+    /// in that cycle. This is monotonically decreasing in the stack as all
+    /// elements between the current stack element in the deepest stack entry
+    /// involved have to also be involved in that cycle.
+    ///
+    /// We can only move entries to the global cache once we're complete done
+    /// with the cycle. If this entry has not been involved in a cycle,
+    /// this is just its own depth.
     pub(super) depth: StackDepth,
 
-    // The goal for this entry. Should always be equal to the corresponding goal
-    // in the lookup table.
+    /// The goal for this entry. Should always be equal to the corresponding goal
+    /// in the lookup table.
     pub(super) input: CanonicalInput<'tcx>,
 }
 
@@ -92,7 +96,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
         self.entries[entry_index].depth
     }
 
-    pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
+    pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> Option<QueryResult<'tcx>> {
         self.entries[entry_index].response
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index 21c8d476902..b860f374c0a 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -13,7 +13,7 @@ use rustc_middle::traits::solve::CacheData;
 use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Limit;
-use std::{collections::hash_map::Entry, mem};
+use std::collections::hash_map::Entry;
 
 rustc_index::newtype_index! {
     pub struct StackDepth {}
@@ -216,8 +216,8 @@ impl<'tcx> SearchGraph<'tcx> {
                     cycle_participants: Default::default(),
                 };
                 assert_eq!(self.stack.push(entry), depth);
-                let response = Self::response_no_constraints(tcx, input, Certainty::Yes);
-                let entry_index = cache.entries.push(ProvisionalEntry { response, depth, input });
+                let entry_index =
+                    cache.entries.push(ProvisionalEntry { response: None, depth, input });
                 v.insert(entry_index);
             }
             // We have a nested goal which relies on a goal `root` deeper in the stack.
@@ -243,23 +243,31 @@ impl<'tcx> SearchGraph<'tcx> {
                     root.cycle_participants.insert(e.input);
                 }
 
-                // NOTE: The goals on the stack aren't the only goals involved in this cycle.
-                // We can also depend on goals which aren't part of the stack but coinductively
-                // depend on the stack themselves. We already checked whether all the goals
-                // between these goals and their root on the stack. This means that as long as
-                // each goal in a cycle is checked for coinductivity by itself, simply checking
-                // the stack is enough.
-                if self.stack.raw[stack_depth.index()..]
-                    .iter()
-                    .all(|g| g.input.value.goal.predicate.is_coinductive(tcx))
-                {
-                    // If we're in a coinductive cycle, we have to retry proving the current goal
-                    // until we reach a fixpoint.
-                    self.stack[stack_depth].has_been_used = true;
-                    return cache.provisional_result(entry_index);
+                // If we're in a cycle, we have to retry proving the current goal
+                // until we reach a fixpoint.
+                self.stack[stack_depth].has_been_used = true;
+                return if let Some(result) = cache.provisional_result(entry_index) {
+                    result
                 } else {
-                    return Self::response_no_constraints(tcx, input, Certainty::OVERFLOW);
-                }
+                    // If we don't have a provisional result yet, the goal has to
+                    // still be on the stack.
+                    let mut goal_on_stack = false;
+                    let mut is_coinductive = true;
+                    for entry in self.stack.raw[stack_depth.index()..]
+                        .iter()
+                        .skip_while(|entry| entry.input != input)
+                    {
+                        goal_on_stack = true;
+                        is_coinductive &= entry.input.value.goal.predicate.is_coinductive(tcx);
+                    }
+                    debug_assert!(goal_on_stack);
+
+                    if is_coinductive {
+                        Self::response_no_constraints(tcx, input, Certainty::Yes)
+                    } else {
+                        Self::response_no_constraints(tcx, input, Certainty::OVERFLOW)
+                    }
+                };
             }
         }
 
@@ -288,15 +296,18 @@ impl<'tcx> SearchGraph<'tcx> {
                     let provisional_entry_index =
                         *cache.lookup_table.get(&stack_entry.input).unwrap();
                     let provisional_entry = &mut cache.entries[provisional_entry_index];
-                    let prev_response = mem::replace(&mut provisional_entry.response, response);
-                    if stack_entry.has_been_used && prev_response != response {
-                        // If so, remove all entries whose result depends on this goal
-                        // from the provisional cache...
+                    if stack_entry.has_been_used
+                        && provisional_entry.response.map_or(true, |r| r != response)
+                    {
+                        // If so, update the provisional result for this goal and remove
+                        // all entries whose result depends on this goal from the provisional
+                        // cache...
                         //
-                        // That's not completely correct, as a nested goal can also
+                        // That's not completely correct, as a nested goal can also only
                         // depend on a goal which is lower in the stack so it doesn't
                         // actually depend on the current goal. This should be fairly
                         // rare and is hopefully not relevant for performance.
+                        provisional_entry.response = Some(response);
                         #[allow(rustc::potential_query_instability)]
                         cache.lookup_table.retain(|_key, index| *index <= provisional_entry_index);
                         cache.entries.truncate(provisional_entry_index.index() + 1);
@@ -315,8 +326,8 @@ impl<'tcx> SearchGraph<'tcx> {
             });
 
         // We're now done with this goal. In case this goal is involved in a larger cycle
-        // do not remove it from the provisional cache and do not add it to the global
-        // cache.
+        // do not remove it from the provisional cache and update its provisional result.
+        // We only add the root of cycles to the global cache.
         //
         // It is not possible for any nested goal to depend on something deeper on the
         // stack, as this would have also updated the depth of the current goal.
@@ -348,6 +359,8 @@ impl<'tcx> SearchGraph<'tcx> {
                 dep_node,
                 result,
             )
+        } else {
+            provisional_entry.response = Some(result);
         }
 
         result
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 4d85e2b6089..457d5420ca3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -7,6 +7,7 @@ use super::{
     ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
     PredicateObligation, SelectionError, TraitNotObjectSafe,
 };
+use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt};
@@ -3110,27 +3111,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) -> UnsatisfiedConst {
         let unsatisfied_const = UnsatisfiedConst(false);
         // FIXME(effects)
-        /* if trait_predicate.is_const_if_const() {
-            let non_const_predicate = trait_ref.without_const();
-            let non_const_obligation = Obligation {
-                cause: obligation.cause.clone(),
-                param_env: obligation.param_env,
-                predicate: non_const_predicate.to_predicate(self.tcx),
-                recursion_depth: obligation.recursion_depth,
-            };
-            if self.predicate_may_hold(&non_const_obligation) {
-                unsatisfied_const = UnsatisfiedConst(true);
-                err.span_note(
-                    span,
-                    format!(
-                        "the trait `{}` is implemented for `{}`, \
-                        but that implementation is not `const`",
-                        non_const_predicate.print_modifiers_and_trait_path(),
-                        trait_ref.skip_binder().self_ty(),
-                    ),
-                );
-            }
-        } */
         unsatisfied_const
     }
 
@@ -3142,24 +3122,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         kind: ty::ClosureKind,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let closure_span = self.tcx.def_span(closure_def_id);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            closure_span,
-            E0525,
-            "expected a closure that implements the `{}` trait, \
-                but this closure only implements `{}`",
-            kind,
-            found_kind
-        );
 
-        err.span_label(
+        let mut err = ClosureKindMismatch {
             closure_span,
-            format!("this closure implements `{found_kind}`, not `{kind}`"),
-        );
-        err.span_label(
-            obligation.cause.span,
-            format!("the requirement to implement `{kind}` derives from here"),
-        );
+            expected: kind,
+            found: found_kind,
+            cause_span: obligation.cause.span,
+            fn_once_label: None,
+            fn_mut_label: None,
+        };
 
         // Additional context information explaining why the closure only implements
         // a particular trait.
@@ -3167,30 +3138,22 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
             match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
                 (ty::ClosureKind::FnOnce, Some((span, place))) => {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "closure is `FnOnce` because it moves the \
-                            variable `{}` out of its environment",
-                            ty::place_to_string_for_capture(self.tcx, place)
-                        ),
-                    );
+                    err.fn_once_label = Some(ClosureFnOnceLabel {
+                        span: *span,
+                        place: ty::place_to_string_for_capture(self.tcx, &place),
+                    })
                 }
                 (ty::ClosureKind::FnMut, Some((span, place))) => {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "closure is `FnMut` because it mutates the \
-                            variable `{}` here",
-                            ty::place_to_string_for_capture(self.tcx, place)
-                        ),
-                    );
+                    err.fn_mut_label = Some(ClosureFnMutLabel {
+                        span: *span,
+                        place: ty::place_to_string_for_capture(self.tcx, &place),
+                    })
                 }
                 _ => {}
             }
         }
 
-        err
+        self.tcx.sess.create_err(err)
     }
 
     fn report_type_parameter_mismatch_cyclic_type_error(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 2b8571796df..d071cf76fd3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2743,6 +2743,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::BindingObligation(item_def_id, span)
             | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
+                if self.tcx.is_diagnostic_item(sym::Send, item_def_id)
+                    || self.tcx.lang_items().sync_trait() == Some(item_def_id)
+                {
+                    return;
+                }
+
                 let item_name = tcx.def_path_str(item_def_id);
                 let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
                 let mut multispan = MultiSpan::from(span);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index f1bd9f8b71a..4371b6c1239 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2394,7 +2394,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             Ok(args) => args,
             Err(()) => {
                 // FIXME: A rematch may fail when a candidate cache hit occurs
-                // on thefreshened form of the trait predicate, but the match
+                // on the freshened form of the trait predicate, but the match
                 // fails for some reason that is not captured in the freshened
                 // cache key. For example, equating an impl trait ref against
                 // the placeholder trait ref may fail due the Generalizer relation
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index d0a7414b4ff..4d0b847533b 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -9,6 +9,7 @@ use rustc_session::config::OptLevel;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
+    RiscvInterruptKind,
 };
 use rustc_target::abi::*;
 use rustc_target::spec::abi::Abi as SpecAbi;
@@ -193,6 +194,8 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
         AmdGpuKernel => Conv::AmdGpuKernel,
         AvrInterrupt => Conv::AvrInterrupt,
         AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
+        RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine },
+        RiscvInterruptS => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor },
         Wasm => Conv::C,
 
         // These API constants ought to be more specific...
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index aa49a5561d1..436f10a4f7b 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -52,9 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
         }
         DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => match data {
-            ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => {
-                let hir::OpaqueTy { lifetime_mapping, .. } =
-                    *tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty();
+            ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => {
                 // We need to remap all of the late-bound lifetimes in theassumed wf types
                 // of the fn (which are represented as ReFree) to the early-bound lifetimes
                 // of the RPITIT (which are represented by ReEarlyBound owned by the opaque).
@@ -66,28 +63,22 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                 // predicates we insert in the `explicit_predicates_of` query for RPITITs.
                 let mut mapping = FxHashMap::default();
                 let generics = tcx.generics_of(def_id);
-                for &(lifetime, new_early_bound_def_id) in
-                    lifetime_mapping.expect("expected lifetime mapping for RPITIT")
-                {
-                    if let Some(rbv::ResolvedArg::LateBound(_, _, def_id)) =
-                        tcx.named_bound_var(lifetime.hir_id)
-                    {
-                        let name = tcx.hir().name(lifetime.hir_id);
-                        let index = generics
-                            .param_def_id_to_index(tcx, new_early_bound_def_id.to_def_id())
-                            .unwrap();
+
+                // For each captured opaque lifetime, if it's late-bound (`ReFree` in this case,
+                // since it has been liberated), map it back to the early-bound lifetime of
+                // the GAT. Since RPITITs also have all of the fn's generics, we slice only
+                // the end of the list corresponding to the opaque's generics.
+                for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
+                    let orig_lt = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
+                    if matches!(*orig_lt, ty::ReFree(..)) {
                         mapping.insert(
-                            ty::Region::new_free(
-                                tcx,
-                                fn_def_id,
-                                ty::BoundRegionKind::BrNamed(def_id, name),
-                            ),
+                            orig_lt,
                             ty::Region::new_early_bound(
                                 tcx,
                                 ty::EarlyBoundRegion {
-                                    def_id: new_early_bound_def_id.to_def_id(),
-                                    index,
-                                    name,
+                                    def_id: param.def_id,
+                                    index: param.index,
+                                    name: param.name,
                                 },
                             ),
                         );
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index a21b5ef05e6..e1a15b5cf9f 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,4 +1,5 @@
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
@@ -15,54 +16,48 @@ fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    let (param_env, (def, args)) = key.into_parts();
+    let (param_env, (def_id, args)) = key.into_parts();
 
-    let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
+    let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
         resolve_associated_item(
             tcx,
-            def,
+            def_id,
             param_env,
             trait_def_id,
             tcx.normalize_erasing_regions(param_env, args),
         )
     } else {
-        let ty = tcx.type_of(def);
-        let item_type = tcx.subst_and_normalize_erasing_regions(args, param_env, ty);
+        let def = if matches!(tcx.def_kind(def_id), DefKind::Fn) && tcx.is_intrinsic(def_id) {
+            debug!(" => intrinsic");
+            ty::InstanceDef::Intrinsic(def_id)
+        } else if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+            let ty = args.type_at(0);
 
-        let def = match *item_type.kind() {
-            ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
-                debug!(" => intrinsic");
-                ty::InstanceDef::Intrinsic(def)
-            }
-            ty::FnDef(def_id, args) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
-                let ty = args.type_at(0);
-
-                if ty.needs_drop(tcx, param_env) {
-                    debug!(" => nontrivial drop glue");
-                    match *ty.kind() {
-                        ty::Closure(..)
-                        | ty::Generator(..)
-                        | ty::Tuple(..)
-                        | ty::Adt(..)
-                        | ty::Dynamic(..)
-                        | ty::Array(..)
-                        | ty::Slice(..) => {}
-                        // Drop shims can only be built from ADTs.
-                        _ => return Ok(None),
-                    }
-
-                    ty::InstanceDef::DropGlue(def_id, Some(ty))
-                } else {
-                    debug!(" => trivial drop glue");
-                    ty::InstanceDef::DropGlue(def_id, None)
+            if ty.needs_drop(tcx, param_env) {
+                debug!(" => nontrivial drop glue");
+                match *ty.kind() {
+                    ty::Closure(..)
+                    | ty::Generator(..)
+                    | ty::Tuple(..)
+                    | ty::Adt(..)
+                    | ty::Dynamic(..)
+                    | ty::Array(..)
+                    | ty::Slice(..) => {}
+                    // Drop shims can only be built from ADTs.
+                    _ => return Ok(None),
                 }
+
+                ty::InstanceDef::DropGlue(def_id, Some(ty))
+            } else {
+                debug!(" => trivial drop glue");
+                ty::InstanceDef::DropGlue(def_id, None)
             }
-            _ => {
-                debug!(" => free item");
-                ty::InstanceDef::Item(def)
-            }
+        } else {
+            debug!(" => free item");
+            ty::InstanceDef::Item(def_id)
         };
+
         Ok(Some(Instance { def, args }))
     };
     debug!("inner_resolve_instance: result={:?}", result);
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index ec0dbffc22f..72bd50ace6d 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -200,7 +200,9 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::ListTy),
 
-    /// A projection or opaque type. Both of these types
+    /// A projection, opaque type, weak type alias, or inherent associated type.
+    /// All of these types are represented as pairs of def-id and args, and can
+    /// be normalized, so they are grouped conceptually.
     Alias(AliasKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.