about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs79
-rw-r--r--compiler/rustc_ast_lowering/src/lifetime_collector.rs53
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs33
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs4
-rw-r--r--compiler/rustc_const_eval/src/errors.rs24
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs32
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs4
-rw-r--r--compiler/rustc_fluent_macro/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs60
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs35
-rw-r--r--compiler/rustc_lint/src/types/improper_ctypes.rs51
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs20
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs61
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs2
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs1
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs25
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs43
-rw-r--r--config.example.toml5
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/primitive_docs.rs9
-rw-r--r--library/core/src/ptr/mod.rs14
-rw-r--r--library/proc_macro/src/bridge/client.rs23
-rw-r--r--library/proc_macro/src/bridge/server.rs8
-rw-r--r--library/std/src/keyword_docs.rs46
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs23
-rw-r--r--library/std/src/sys/pal/uefi/os.rs144
-rw-r--r--library/std/src/sys/pal/unix/fs.rs10
-rw-r--r--src/bootstrap/src/core/config/config.rs5
-rw-r--r--src/bootstrap/src/core/config/flags.rs3
-rw-r--r--src/bootstrap/src/core/config/tests.rs58
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/librustdoc/Cargo.toml1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css18
-rw-r--r--src/librustdoc/html/static_files.rs11
-rw-r--r--src/tools/compiletest/src/runtest.rs14
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs10
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs4
-rw-r--r--src/tools/miri/src/diagnostics.rs2
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs10
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs3
-rw-r--r--tests/assembly/x86-return-float.rs2
-rw-r--r--tests/codegen/float/f128.rs106
-rw-r--r--tests/codegen/float/f16.rs26
-rw-r--r--tests/codegen/i128-x86-align.rs32
-rw-r--r--tests/codegen/issues/issue-108395-branchy-bool-match.rs27
-rw-r--r--tests/codegen/mir-aggregate-no-alloca.rs30
-rw-r--r--tests/codegen/range-attribute.rs11
-rw-r--r--tests/codegen/tuple-layout-opt.rs22
-rw-r--r--tests/codegen/union-abi.rs18
-rw-r--r--tests/ui/associated-types/impl-trait-return-missing-constraint.stderr10
-rw-r--r--tests/ui/coroutine/type-mismatch-signature-deduction.stderr6
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr5
-rw-r--r--tests/ui/impl-trait/bound-normalization-fail.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.stderr2
-rw-r--r--tests/ui/impl-trait/precise-capturing/capturing-implicit.rs15
-rw-r--r--tests/ui/impl-trait/precise-capturing/capturing-implicit.stderr22
-rw-r--r--tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr2
-rw-r--r--tests/ui/issues/issue-33941.stderr6
-rw-r--r--tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr6
-rw-r--r--tests/ui/lint/issue-106991.stderr2
-rw-r--r--tests/ui/precondition-checks/layout.rs2
-rw-r--r--tests/ui/range/misleading-field-access-hint.rs8
-rw-r--r--tests/ui/range/misleading-field-access-hint.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs11
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs10
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr10
-rw-r--r--tests/ui/sanitizer/cfg.rs12
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed2
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.rs2
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed2
-rw-r--r--tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs7
-rw-r--r--tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr9
-rw-r--r--tests/ui/suggestions/trait-hidden-method.stderr8
-rw-r--r--tests/ui/traits/next-solver/async.fail.stderr4
-rw-r--r--tests/ui/traits/next-solver/more-object-bound.stderr15
-rw-r--r--tests/ui/try-block/try-block-bad-type.stderr4
-rw-r--r--tests/ui/try-block/try-block-type-error.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/issue-94429.stderr2
91 files changed, 974 insertions, 523 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 60f2f17c3ee..2ae6d6dc73f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4584,6 +4584,7 @@ dependencies = [
  "rustdoc-json-types",
  "serde",
  "serde_json",
+ "sha2",
  "smallvec",
  "tempfile",
  "threadpool",
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index ce744cc56e1..7416a1e39eb 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1574,7 +1574,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             .collect();
 
         // Introduce extra lifetimes if late resolution tells us to.
-        let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
+        let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
         params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
             self.lifetime_res_to_generic_param(
                 ident,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 00eafeb4d84..4d8d22e09d9 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -268,8 +268,8 @@ impl ResolverAstLowering {
     ///
     /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
     /// should appear at the enclosing `PolyTraitRef`.
-    fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
-        self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
+    fn extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
+        self.extra_lifetime_params_map.get(&id).cloned().unwrap_or_default()
     }
 }
 
@@ -885,7 +885,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut generic_params: Vec<_> = self
             .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
             .collect();
-        let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
+        let extra_lifetimes = self.resolver.extra_lifetime_params(binder);
         debug!(?extra_lifetimes);
         generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
             self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
@@ -1495,62 +1495,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let captured_lifetimes_to_duplicate = if let Some(args) =
-            // We only look for one `use<...>` syntax since we syntactially reject more than one.
-            bounds.iter().find_map(
-                |bound| match bound {
-                    ast::GenericBound::Use(a, _) => Some(a),
-                    _ => None,
-                },
-            ) {
-            // We'll actually validate these later on; all we need is the list of
-            // lifetimes to duplicate during this portion of lowering.
-            args.iter()
-                .filter_map(|arg| match arg {
-                    PreciseCapturingArg::Lifetime(lt) => Some(*lt),
-                    PreciseCapturingArg::Arg(..) => None,
-                })
-                // Add in all the lifetimes mentioned in the bounds. We will error
-                // them out later, but capturing them here is important to make sure
-                // they actually get resolved in resolve_bound_vars.
-                .chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds))
-                .collect()
-        } else {
-            match origin {
-                hir::OpaqueTyOrigin::TyAlias { .. } => {
-                    // type alias impl trait and associated type position impl trait were
-                    // decided to capture all in-scope lifetimes, which we collect for
-                    // all opaques during resolution.
-                    self.resolver
-                        .take_extra_lifetime_params(opaque_ty_node_id)
-                        .into_iter()
-                        .map(|(ident, id, _)| Lifetime { id, ident })
-                        .collect()
-                }
-                hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => {
-                    if in_trait_or_impl.is_some()
-                        || self.tcx.features().lifetime_capture_rules_2024
-                        || span.at_least_rust_2024()
-                    {
-                        // return-position impl trait in trait was decided to capture all
-                        // in-scope lifetimes, which we collect for all opaques during resolution.
-                        self.resolver
-                            .take_extra_lifetime_params(opaque_ty_node_id)
-                            .into_iter()
-                            .map(|(ident, id, _)| Lifetime { id, ident })
-                            .collect()
-                    } else {
-                        // in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
-                        // example, we only need to duplicate lifetimes that appear in the
-                        // bounds, since those are the only ones that are captured by the opaque.
-                        lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
-                    }
-                }
-                hir::OpaqueTyOrigin::AsyncFn { .. } => {
-                    unreachable!("should be using `lower_async_fn_ret_ty`")
-                }
+        // Whether this opaque always captures lifetimes in scope.
+        // Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
+        // is enabled. We don't check the span of the edition, since this is done
+        // on a per-opaque basis to account for nested opaques.
+        let always_capture_in_scope = match origin {
+            _ if self.tcx.features().lifetime_capture_rules_2024 => true,
+            hir::OpaqueTyOrigin::TyAlias { .. } => true,
+            hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
+            hir::OpaqueTyOrigin::AsyncFn { .. } => {
+                unreachable!("should be using `lower_coroutine_fn_ret_ty`")
             }
         };
+        let captured_lifetimes_to_duplicate = lifetime_collector::lifetimes_for_opaque(
+            self.resolver,
+            always_capture_in_scope,
+            opaque_ty_node_id,
+            bounds,
+            span,
+        );
         debug!(?captured_lifetimes_to_duplicate);
 
         // Feature gate for RPITIT + use<..>
@@ -1920,7 +1883,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let captured_lifetimes = self
             .resolver
-            .take_extra_lifetime_params(opaque_ty_node_id)
+            .extra_lifetime_params(opaque_ty_node_id)
             .into_iter()
             .map(|(ident, id, _)| Lifetime { id, ident })
             .collect();
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
index fe64160fb4d..8d47c856bdd 100644
--- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs
+++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
@@ -1,5 +1,7 @@
 use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
-use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
+use rustc_ast::{
+    GenericBound, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind,
+};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def::{DefKind, LifetimeRes, Res};
 use rustc_middle::span_bug;
@@ -10,14 +12,41 @@ use rustc_span::symbol::{Ident, kw};
 use super::ResolverAstLoweringExt;
 
 struct LifetimeCollectVisitor<'ast> {
-    resolver: &'ast ResolverAstLowering,
+    resolver: &'ast mut ResolverAstLowering,
+    always_capture_in_scope: bool,
     current_binders: Vec<NodeId>,
     collected_lifetimes: FxIndexSet<Lifetime>,
 }
 
 impl<'ast> LifetimeCollectVisitor<'ast> {
-    fn new(resolver: &'ast ResolverAstLowering) -> Self {
-        Self { resolver, current_binders: Vec::new(), collected_lifetimes: FxIndexSet::default() }
+    fn new(resolver: &'ast mut ResolverAstLowering, always_capture_in_scope: bool) -> Self {
+        Self {
+            resolver,
+            always_capture_in_scope,
+            current_binders: Vec::new(),
+            collected_lifetimes: FxIndexSet::default(),
+        }
+    }
+
+    fn visit_opaque(&mut self, opaque_ty_node_id: NodeId, bounds: &'ast GenericBounds, span: Span) {
+        // If we're edition 2024 or within a TAIT or RPITIT, *and* there is no
+        // `use<>` statement to override the default capture behavior, then
+        // capture all of the in-scope lifetimes.
+        if (self.always_capture_in_scope || span.at_least_rust_2024())
+            && bounds.iter().all(|bound| !matches!(bound, GenericBound::Use(..)))
+        {
+            for (ident, id, _) in self.resolver.extra_lifetime_params(opaque_ty_node_id) {
+                self.record_lifetime_use(Lifetime { id, ident });
+            }
+        }
+
+        // We also recurse on the bounds to make sure we capture all the lifetimes
+        // mentioned in the bounds. These may disagree with the `use<>` list, in which
+        // case we will error on these later. We will also recurse to visit any
+        // nested opaques, which may *implicitly* capture lifetimes.
+        for bound in bounds {
+            self.visit_param_bound(bound, BoundKind::Bound);
+        }
     }
 
     fn record_lifetime_use(&mut self, lifetime: Lifetime) {
@@ -99,6 +128,9 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
                 self.record_elided_anchor(t.id, t.span);
                 visit::walk_ty(self, t);
             }
+            TyKind::ImplTrait(opaque_ty_node_id, bounds) => {
+                self.visit_opaque(*opaque_ty_node_id, bounds, t.span)
+            }
             _ => {
                 visit::walk_ty(self, t);
             }
@@ -106,13 +138,14 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
     }
 }
 
-pub(crate) fn lifetimes_in_bounds(
-    resolver: &ResolverAstLowering,
+pub(crate) fn lifetimes_for_opaque(
+    resolver: &mut ResolverAstLowering,
+    always_capture_in_scope: bool,
+    opaque_ty_node_id: NodeId,
     bounds: &GenericBounds,
+    span: Span,
 ) -> FxIndexSet<Lifetime> {
-    let mut visitor = LifetimeCollectVisitor::new(resolver);
-    for bound in bounds {
-        visitor.visit_param_bound(bound, BoundKind::Bound);
-    }
+    let mut visitor = LifetimeCollectVisitor::new(resolver, always_capture_in_scope);
+    visitor.visit_opaque(opaque_ty_node_id, bounds, span);
     visitor.collected_lifetimes
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 20ecc665b1e..a5f3298b02c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1146,6 +1146,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     }
                     // don't create labels for compiler-generated spans
                     Some(_) => None,
+                    // don't create labels for the span not from user's code
+                    None if opt_assignment_rhs_span
+                        .is_some_and(|span| self.infcx.tcx.sess.source_map().is_imported(span)) =>
+                    {
+                        None
+                    }
                     None => {
                         let (has_sugg, decl_span, sugg) = if name != kw::SelfLower {
                             suggest_ampmut(
@@ -1198,18 +1204,21 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     sugg.push(s);
                 }
 
-                err.multipart_suggestion_verbose(
-                    format!(
-                        "consider changing this to be a mutable {pointer_desc}{}",
-                        if is_trait_sig {
-                            " in the `impl` method and the `trait` definition"
-                        } else {
-                            ""
-                        }
-                    ),
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
+                if sugg.iter().all(|(span, _)| !self.infcx.tcx.sess.source_map().is_imported(*span))
+                {
+                    err.multipart_suggestion_verbose(
+                        format!(
+                            "consider changing this to be a mutable {pointer_desc}{}",
+                            if is_trait_sig {
+                                " in the `impl` method and the `trait` definition"
+                            } else {
+                                ""
+                            }
+                        ),
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
             Some((false, err_label_span, message, _)) => {
                 let def_id = self.body.source.def_id();
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index fd05664e2f2..6686413bf02 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -11,7 +11,8 @@ use rustc_span::{Span, Symbol};
 use super::CompileTimeMachine;
 use crate::errors::{self, FrameNote, ReportErrorExt};
 use crate::interpret::{
-    ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType, err_inval, err_machine_stop,
+    ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
+    err_machine_stop,
 };
 
 /// The CTFE machine has some custom error kinds.
@@ -57,7 +58,7 @@ impl MachineStopType for ConstEvalErrKind {
     }
 }
 
-/// The errors become [`InterpError::MachineStop`] when being raised.
+/// The errors become [`InterpErrorKind::MachineStop`] when being raised.
 impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
     fn into(self) -> InterpErrorInfo<'tcx> {
         err_machine_stop!(self).into()
@@ -124,7 +125,7 @@ pub fn get_span_and_frames<'tcx>(
 /// `get_span_and_frames`.
 pub(super) fn report<'tcx, C, F, E>(
     tcx: TyCtxt<'tcx>,
-    error: InterpError<'tcx>,
+    error: InterpErrorKind<'tcx>,
     span: Span,
     get_span_and_frames: C,
     mk: F,
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 672353e629d..7319c251bbd 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -18,7 +18,7 @@ use tracing::{debug, instrument, trace};
 use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
 use crate::const_eval::CheckAlignment;
 use crate::interpret::{
-    CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
+    CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind,
     InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, create_static_alloc,
     eval_nullary_intrinsic, intern_const_alloc_recursive, interp_ok, throw_exhaust,
 };
@@ -463,7 +463,7 @@ fn report_validation_error<'tcx>(
     error: InterpErrorInfo<'tcx>,
     alloc_id: AllocId,
 ) -> ErrorHandled {
-    if !matches!(error.kind(), InterpError::UndefinedBehavior(_)) {
+    if !matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
         // Some other error happened during validation, e.g. an unsupported operation.
         return report_eval_error(ecx, cid, error);
     }
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index c943236affc..211668cf055 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -9,7 +9,7 @@ use rustc_errors::{
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::mir::interpret::{
-    CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpError, InvalidMetaKind,
+    CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind,
     InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
     UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
 };
@@ -835,23 +835,23 @@ impl ReportErrorExt for UnsupportedOpInfo {
     }
 }
 
-impl<'tcx> ReportErrorExt for InterpError<'tcx> {
+impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> {
     fn diagnostic_message(&self) -> DiagMessage {
         match self {
-            InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(),
-            InterpError::Unsupported(e) => e.diagnostic_message(),
-            InterpError::InvalidProgram(e) => e.diagnostic_message(),
-            InterpError::ResourceExhaustion(e) => e.diagnostic_message(),
-            InterpError::MachineStop(e) => e.diagnostic_message(),
+            InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(),
+            InterpErrorKind::Unsupported(e) => e.diagnostic_message(),
+            InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(),
+            InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(),
+            InterpErrorKind::MachineStop(e) => e.diagnostic_message(),
         }
     }
     fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
         match self {
-            InterpError::UndefinedBehavior(ub) => ub.add_args(diag),
-            InterpError::Unsupported(e) => e.add_args(diag),
-            InterpError::InvalidProgram(e) => e.add_args(diag),
-            InterpError::ResourceExhaustion(e) => e.add_args(diag),
-            InterpError::MachineStop(e) => e.add_args(&mut |name, value| {
+            InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag),
+            InterpErrorKind::Unsupported(e) => e.add_args(diag),
+            InterpErrorKind::InvalidProgram(e) => e.add_args(diag),
+            InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag),
+            InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| {
                 diag.arg(name, value);
             }),
         }
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 4945563f4a4..85d99900c6c 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -471,7 +471,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             // Don't forget to mark "initially live" locals as live.
             self.storage_live_for_always_live_locals()?;
         };
-        res.inspect_err(|_| {
+        res.inspect_err_kind(|_| {
             // Don't show the incomplete stack frame in the error stacktrace.
             self.stack_mut().pop();
         })
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 02dd7821ef6..a1c773a4b80 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -19,7 +19,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::{debug, instrument, trace};
 
 use super::{
-    Frame, FrameInfo, GlobalId, InterpError, InterpErrorInfo, InterpResult, MPlaceTy, Machine,
+    Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
     MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance,
     err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom,
 };
@@ -73,7 +73,7 @@ where
 }
 
 impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
-    type LayoutOfResult = Result<TyAndLayout<'tcx>, InterpError<'tcx>>;
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, InterpErrorKind<'tcx>>;
 
     #[inline]
     fn layout_tcx_at_span(&self) -> Span {
@@ -82,20 +82,25 @@ impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
     }
 
     #[inline]
-    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> InterpError<'tcx> {
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        _: Span,
+        _: Ty<'tcx>,
+    ) -> InterpErrorKind<'tcx> {
         err_inval!(Layout(err))
     }
 }
 
 impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
-    type FnAbiOfResult = Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, InterpError<'tcx>>;
+    type FnAbiOfResult = Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, InterpErrorKind<'tcx>>;
 
     fn handle_fn_abi_err(
         &self,
         err: FnAbiError<'tcx>,
         _span: Span,
         _fn_abi_request: FnAbiRequest<'tcx>,
-    ) -> InterpError<'tcx> {
+    ) -> InterpErrorKind<'tcx> {
         match err {
             FnAbiError::Layout(err) => err_inval!(Layout(err)),
             FnAbiError::AdjustForForeignAbi(err) => {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 540898ec645..4e603f57c56 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -324,13 +324,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large
                     CheckInAllocMsg::OffsetFromTest,
                 )
-                .map_err(|_| {
+                .map_err_kind(|_| {
                     // Make the error more specific.
                     err_ub_custom!(
                         fluent::const_eval_offset_from_different_allocations,
                         name = intrinsic_name,
                     )
-                    .into()
                 })?;
 
                 // Perform division by size to compute return value.
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 13641ef2bd3..b6120ce82fe 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -17,8 +17,8 @@ use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
 use rustc_middle::mir::interpret::{
-    ExpectedKind, InterpError, InterpErrorInfo, InvalidMetaKind, Misalignment, PointerKind,
-    Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok,
+    ExpectedKind, InterpErrorKind, InvalidMetaKind, Misalignment, PointerKind, Provenance,
+    UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok,
 };
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
@@ -37,8 +37,8 @@ use super::{
 
 // for the validation errors
 #[rustfmt::skip]
-use super::InterpError::UndefinedBehavior as Ub;
-use super::InterpError::Unsupported as Unsup;
+use super::InterpErrorKind::UndefinedBehavior as Ub;
+use super::InterpErrorKind::Unsupported as Unsup;
 use super::UndefinedBehaviorInfo::*;
 use super::UnsupportedOpInfo::*;
 
@@ -97,20 +97,19 @@ macro_rules! try_validation {
     ($e:expr, $where:expr,
     $( $( $p:pat_param )|+ => $kind: expr ),+ $(,)?
     ) => {{
-        $e.map_err(|e| {
+        $e.map_err_kind(|e| {
             // We catch the error and turn it into a validation failure. We are okay with
             // allocation here as this can only slow down builds that fail anyway.
-            let (kind, backtrace) = e.into_parts();
-            match kind {
+            match e {
                 $(
                     $($p)|+ => {
                         err_validation_failure!(
                             $where,
                             $kind
-                        ).into()
+                        )
                     }
                 ),+,
-                _ => InterpErrorInfo::from_parts(kind, backtrace),
+                e => e,
             }
         })?
     }};
@@ -1230,11 +1229,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                 // No need for an alignment check here, this is not an actual memory access.
                 let alloc = self.ecx.get_ptr_alloc(mplace.ptr(), size)?.expect("we already excluded size 0");
 
-                alloc.get_bytes_strip_provenance().map_err(|err| {
+                alloc.get_bytes_strip_provenance().map_err_kind(|kind| {
                     // Some error happened, try to provide a more detailed description.
                     // For some errors we might be able to provide extra information.
                     // (This custom logic does not fit the `try_validation!` macro.)
-                    let (kind, backtrace) = err.into_parts();
                     match kind {
                         Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
                             // Some byte was uninitialized, determine which
@@ -1247,14 +1245,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                             self.path.push(PathElem::ArrayElem(i));
 
                             if matches!(kind, Ub(InvalidUninitBytes(_))) {
-                                err_validation_failure!(self.path, Uninit { expected }).into()
+                                err_validation_failure!(self.path, Uninit { expected })
                             } else {
-                                err_validation_failure!(self.path, PointerAsInt { expected }).into()
+                                err_validation_failure!(self.path, PointerAsInt { expected })
                             }
                         }
 
                         // Propagate upwards (that will also check for unexpected errors).
-                        _ => return InterpErrorInfo::from_parts(kind, backtrace),
+                        err => err,
                     }
                 })?;
 
@@ -1368,12 +1366,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             v.reset_padding(val)?;
             interp_ok(())
         })
-        .map_err(|err| {
+        .map_err_info(|err| {
             if !matches!(
                 err.kind(),
                 err_ub!(ValidationError { .. })
-                    | InterpError::InvalidProgram(_)
-                    | InterpError::Unsupported(UnsupportedOpInfo::ExternTypeField)
+                    | InterpErrorKind::InvalidProgram(_)
+                    | InterpErrorKind::Unsupported(UnsupportedOpInfo::ExternTypeField)
             ) {
                 bug!(
                     "Unexpected error during validation: {}",
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index ead72e2a0e1..d4604c27e6d 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -8,6 +8,7 @@ use fluent_syntax::ast::{
     Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement,
 };
 use fluent_syntax::parser::ParserError;
+use proc_macro::tracked_path::path;
 use proc_macro::{Diagnostic, Level, Span};
 use proc_macro2::TokenStream;
 use quote::quote;
@@ -99,8 +100,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
 
     let crate_name = Ident::new(&crate_name, resource_str.span());
 
-    // As this macro also outputs an `include_str!` for this file, the macro will always be
-    // re-executed when the file changes.
+    path(absolute_ftl_path.to_str().unwrap());
     let resource_contents = match read_to_string(absolute_ftl_path) {
         Ok(resource_contents) => resource_contents,
         Err(e) => {
diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs
index 6e5add24bcc..3ad51fa1e64 100644
--- a/compiler/rustc_fluent_macro/src/lib.rs
+++ b/compiler/rustc_fluent_macro/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
 #![feature(rustdoc_internals)]
+#![feature(track_path)]
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 8f7ca089c91..6c7d521ebcf 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -516,7 +516,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     self_ty,
                     trait_segment,
                     false,
-                    ty::BoundConstness::NotConst,
                 );
 
                 // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index d760acf53bd..8ad9687b233 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -336,14 +336,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         def_id: DefId,
         item_segment: &hir::PathSegment<'tcx>,
     ) -> GenericArgsRef<'tcx> {
-        let (args, _) = self.lower_generic_args_of_path(
-            span,
-            def_id,
-            &[],
-            item_segment,
-            None,
-            ty::BoundConstness::NotConst,
-        );
+        let (args, _) = self.lower_generic_args_of_path(span, def_id, &[], item_segment, None);
         if let Some(c) = item_segment.args().constraints.first() {
             prohibit_assoc_item_constraint(self, c, Some((def_id, item_segment, span)));
         }
@@ -392,7 +385,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         parent_args: &[ty::GenericArg<'tcx>],
         segment: &hir::PathSegment<'tcx>,
         self_ty: Option<Ty<'tcx>>,
-        constness: ty::BoundConstness,
     ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
@@ -415,7 +407,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             assert!(self_ty.is_none());
         }
 
-        let mut arg_count = check_generic_arg_count(
+        let arg_count = check_generic_arg_count(
             self,
             def_id,
             segment,
@@ -573,16 +565,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 }
             }
         }
-        if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
-            && generics.has_self
-            && !tcx.is_const_trait(def_id)
-        {
-            let reported = self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
-                span,
-                modifier: constness.as_str(),
-            });
-            arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] });
-        }
 
         let mut args_ctx = GenericArgsCtxt {
             lowerer: self,
@@ -614,14 +596,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         parent_args: GenericArgsRef<'tcx>,
     ) -> GenericArgsRef<'tcx> {
         debug!(?span, ?item_def_id, ?item_segment);
-        let (args, _) = self.lower_generic_args_of_path(
-            span,
-            item_def_id,
-            parent_args,
-            item_segment,
-            None,
-            ty::BoundConstness::NotConst,
-        );
+        let (args, _) =
+            self.lower_generic_args_of_path(span, item_def_id, parent_args, item_segment, None);
         if let Some(c) = item_segment.args().constraints.first() {
             prohibit_assoc_item_constraint(self, c, Some((item_def_id, item_segment, span)));
         }
@@ -647,7 +623,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             self_ty,
             trait_ref.path.segments.last().unwrap(),
             true,
-            ty::BoundConstness::NotConst,
         )
     }
 
@@ -700,9 +675,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             &[],
             trait_segment,
             Some(self_ty),
-            constness,
         );
 
+        if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
+            && !self.tcx().is_const_trait(trait_def_id)
+        {
+            self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
+                span: trait_ref.path.span,
+                modifier: constness.as_str(),
+            });
+        }
+
         let tcx = self.tcx();
         let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
         debug!(?bound_vars);
@@ -762,19 +745,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         self_ty: Ty<'tcx>,
         trait_segment: &hir::PathSegment<'tcx>,
         is_impl: bool,
-        // FIXME(effects): Move all host param things in HIR ty lowering to AST lowering.
-        constness: ty::BoundConstness,
     ) -> ty::TraitRef<'tcx> {
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
 
-        let (generic_args, _) = self.lower_generic_args_of_path(
-            span,
-            trait_def_id,
-            &[],
-            trait_segment,
-            Some(self_ty),
-            constness,
-        );
+        let (generic_args, _) =
+            self.lower_generic_args_of_path(span, trait_def_id, &[], trait_segment, Some(self_ty));
         if let Some(c) = trait_segment.args().constraints.first() {
             prohibit_assoc_item_constraint(self, c, Some((trait_def_id, trait_segment, span)));
         }
@@ -1542,7 +1517,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         item_def_id: DefId,
         trait_segment: &hir::PathSegment<'tcx>,
         item_segment: &hir::PathSegment<'tcx>,
-        constness: ty::BoundConstness,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
 
@@ -1555,7 +1529,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         debug!(?self_ty);
 
         let trait_ref =
-            self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false, constness);
+            self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
         debug!(?trait_ref);
 
         let item_args =
@@ -1918,7 +1892,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     def_id,
                     &path.segments[path.segments.len() - 2],
                     path.segments.last().unwrap(),
-                    ty::BoundConstness::NotConst,
                 )
             }
             Res::PrimTy(prim_ty) => {
@@ -2151,7 +2124,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     &[],
                     &hir::PathSegment::invalid(),
                     None,
-                    ty::BoundConstness::NotConst,
                 );
                 tcx.at(span).type_of(def_id).instantiate(tcx, args)
             }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 6b0a897faba..9e36f7a9aea 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -419,7 +419,7 @@ fn report_unexpected_variant_res(
                 }
             }
 
-            err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
+            err.multipart_suggestion_verbose(descr, suggestion, Applicability::HasPlaceholders);
             err
         }
         Res::Def(DefKind::Variant, _) if expr.is_none() => {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index db4413149a4..e9c61a41d6d 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -18,6 +18,8 @@ use rustc_target::spec::abi::Abi as SpecAbi;
 use tracing::debug;
 use {rustc_ast as ast, rustc_hir as hir};
 
+mod improper_ctypes;
+
 use crate::lints::{
     AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
     AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
@@ -983,15 +985,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             // Empty enums are okay... although sort of useless.
                             return FfiSafe;
                         }
-
-                        if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
-                            return FfiUnsafe {
-                                ty,
-                                reason: fluent::lint_improper_ctypes_non_exhaustive,
-                                help: None,
-                            };
-                        }
-
                         // Check for a repr() attribute to specify the size of the
                         // discriminant.
                         if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none()
@@ -1010,21 +1003,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
+                        use improper_ctypes::{
+                            check_non_exhaustive_variant, non_local_and_non_exhaustive,
+                        };
+
+                        let non_local_def = non_local_and_non_exhaustive(def);
                         // Check the contained variants.
-                        for variant in def.variants() {
-                            let is_non_exhaustive = variant.is_field_list_non_exhaustive();
-                            if is_non_exhaustive && !variant.def_id.is_local() {
-                                return FfiUnsafe {
-                                    ty,
-                                    reason: fluent::lint_improper_ctypes_non_exhaustive_variant,
-                                    help: None,
-                                };
-                            }
+                        let ret = def.variants().iter().try_for_each(|variant| {
+                            check_non_exhaustive_variant(non_local_def, variant)
+                                .map_break(|reason| FfiUnsafe { ty, reason, help: None })?;
 
                             match self.check_variant_for_ffi(acc, ty, def, variant, args) {
-                                FfiSafe => (),
-                                r => return r,
+                                FfiSafe => ControlFlow::Continue(()),
+                                r => ControlFlow::Break(r),
                             }
+                        });
+                        if let ControlFlow::Break(result) = ret {
+                            return result;
                         }
 
                         FfiSafe
diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs
new file mode 100644
index 00000000000..1030101c545
--- /dev/null
+++ b/compiler/rustc_lint/src/types/improper_ctypes.rs
@@ -0,0 +1,51 @@
+use std::ops::ControlFlow;
+
+use rustc_errors::DiagMessage;
+use rustc_hir::def::CtorKind;
+use rustc_middle::ty;
+
+use crate::fluent_generated as fluent;
+
+/// Check a variant of a non-exhaustive enum for improper ctypes
+///
+/// We treat `#[non_exhaustive] enum` as "ensure that code will compile if new variants are added".
+/// This includes linting, on a best-effort basis. There are valid additions that are unlikely.
+///
+/// Adding a data-carrying variant to an existing C-like enum that is passed to C is "unlikely",
+/// so we don't need the lint to account for it.
+/// e.g. going from enum Foo { A, B, C } to enum Foo { A, B, C, D(u32) }.
+pub(crate) fn check_non_exhaustive_variant(
+    non_local_def: bool,
+    variant: &ty::VariantDef,
+) -> ControlFlow<DiagMessage, ()> {
+    // non_exhaustive suggests it is possible that someone might break ABI
+    // see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344
+    // so warn on complex enums being used outside their crate
+    if non_local_def {
+        // which is why we only warn about really_tagged_union reprs from https://rust.tf/rfc2195
+        // with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }`
+        // but exempt enums with unit ctors like C's (e.g. from rust-bindgen)
+        if variant_has_complex_ctor(variant) {
+            return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive);
+        }
+    }
+
+    let non_exhaustive_variant_fields = variant.is_field_list_non_exhaustive();
+    if non_exhaustive_variant_fields && !variant.def_id.is_local() {
+        return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant);
+    }
+
+    ControlFlow::Continue(())
+}
+
+fn variant_has_complex_ctor(variant: &ty::VariantDef) -> bool {
+    // CtorKind::Const means a "unit" ctor
+    !matches!(variant.ctor_kind(), Some(CtorKind::Const))
+}
+
+// non_exhaustive suggests it is possible that someone might break ABI
+// see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344
+// so warn on complex enums being used outside their crate
+pub(crate) fn non_local_and_non_exhaustive(def: ty::AdtDef<'_>) -> bool {
+    def.is_variant_list_non_exhaustive() && !def.did().is_local()
+}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 04d035e27ba..ac3baf74ca7 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -18,9 +18,9 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
 use super::{
-    AllocId, BadBytesAccess, CtfeProvenance, InterpError, InterpResult, Pointer, PointerArithmetic,
-    Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo,
-    UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
+    AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer,
+    PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
+    UndefinedBehaviorInfo, UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
 };
 use crate::ty;
 
@@ -199,22 +199,22 @@ impl From<ScalarSizeMismatch> for AllocError {
 }
 
 impl AllocError {
-    pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> {
+    pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpErrorKind<'tcx> {
         use AllocError::*;
         match self {
             ScalarSizeMismatch(s) => {
-                InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
+                InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
             }
-            ReadPointerAsInt(info) => InterpError::Unsupported(
+            ReadPointerAsInt(info) => InterpErrorKind::Unsupported(
                 UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
             ),
-            OverwritePartialPointer(offset) => InterpError::Unsupported(
+            OverwritePartialPointer(offset) => InterpErrorKind::Unsupported(
                 UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
             ),
-            ReadPartialPointer(offset) => InterpError::Unsupported(
+            ReadPartialPointer(offset) => InterpErrorKind::Unsupported(
                 UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
             ),
-            InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
+            InvalidUninitBytes(info) => InterpErrorKind::UndefinedBehavior(
                 UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
             ),
         }
@@ -318,7 +318,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
     pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
         Self::uninit_inner(size, align, || {
             ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
-            InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
+            InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
         })
         .into()
     }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index fcb87e19435..b520f21ce20 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -113,7 +113,7 @@ pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
 
 #[derive(Debug)]
 struct InterpErrorInfoInner<'tcx> {
-    kind: InterpError<'tcx>,
+    kind: InterpErrorKind<'tcx>,
     backtrace: InterpErrorBacktrace,
 }
 
@@ -154,21 +154,21 @@ impl InterpErrorBacktrace {
 }
 
 impl<'tcx> InterpErrorInfo<'tcx> {
-    pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
+    pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
         let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
         (kind, backtrace)
     }
 
-    pub fn into_kind(self) -> InterpError<'tcx> {
+    pub fn into_kind(self) -> InterpErrorKind<'tcx> {
         self.0.kind
     }
 
-    pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
+    pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
         Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
     }
 
     #[inline]
-    pub fn kind(&self) -> &InterpError<'tcx> {
+    pub fn kind(&self) -> &InterpErrorKind<'tcx> {
         &self.0.kind
     }
 }
@@ -179,13 +179,13 @@ fn print_backtrace(backtrace: &Backtrace) {
 
 impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
     fn from(err: ErrorGuaranteed) -> Self {
-        InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
+        InterpErrorKind::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
     }
 }
 
 impl From<ErrorHandled> for InterpErrorInfo<'_> {
     fn from(err: ErrorHandled) -> Self {
-        InterpError::InvalidProgram(match err {
+        InterpErrorKind::InvalidProgram(match err {
             ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
             ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
         })
@@ -193,8 +193,8 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
     }
 }
 
-impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
-    fn from(kind: InterpError<'tcx>) -> Self {
+impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
+    fn from(kind: InterpErrorKind<'tcx>) -> Self {
         InterpErrorInfo(Box::new(InterpErrorInfoInner {
             kind,
             backtrace: InterpErrorBacktrace::new(),
@@ -590,7 +590,7 @@ impl dyn MachineStopType {
 }
 
 #[derive(Debug)]
-pub enum InterpError<'tcx> {
+pub enum InterpErrorKind<'tcx> {
     /// The program caused undefined behavior.
     UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
     /// The program did something the interpreter does not support (some of these *might* be UB
@@ -606,25 +606,25 @@ pub enum InterpError<'tcx> {
     MachineStop(Box<dyn MachineStopType>),
 }
 
-impl InterpError<'_> {
+impl InterpErrorKind<'_> {
     /// Some errors do string formatting even if the error is never printed.
     /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
     /// so this method lets us detect them and `bug!` on unexpected errors.
     pub fn formatted_string(&self) -> bool {
         matches!(
             self,
-            InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
-                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+            InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
+                | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
+                | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
         )
     }
 }
 
-// Macros for constructing / throwing `InterpError`
+// Macros for constructing / throwing `InterpErrorKind`
 #[macro_export]
 macro_rules! err_unsup {
     ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::Unsupported(
+        $crate::mir::interpret::InterpErrorKind::Unsupported(
             $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
         )
     };
@@ -638,7 +638,7 @@ macro_rules! err_unsup_format {
 #[macro_export]
 macro_rules! err_inval {
     ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::InvalidProgram(
+        $crate::mir::interpret::InterpErrorKind::InvalidProgram(
             $crate::mir::interpret::InvalidProgramInfo::$($tt)*
         )
     };
@@ -647,7 +647,7 @@ macro_rules! err_inval {
 #[macro_export]
 macro_rules! err_ub {
     ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::UndefinedBehavior(
+        $crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
             $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
         )
     };
@@ -680,7 +680,7 @@ macro_rules! err_ub_custom {
 #[macro_export]
 macro_rules! err_exhaust {
     ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::ResourceExhaustion(
+        $crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
             $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
         )
     };
@@ -689,7 +689,7 @@ macro_rules! err_exhaust {
 #[macro_export]
 macro_rules! err_machine_stop {
     ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*))
+        $crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
     };
 }
 
@@ -792,9 +792,9 @@ impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
 }
 
 // Allow `yeet`ing `InterpError` in functions returning `InterpResult_`.
-impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpError<'tcx>>> for InterpResult_<'tcx, T> {
+impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
     #[inline]
-    fn from_residual(ops::Yeet(e): ops::Yeet<InterpError<'tcx>>) -> Self {
+    fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
         Self::new(Err(e.into()))
     }
 }
@@ -856,7 +856,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
     }
 
     #[inline]
-    pub fn map_err(
+    pub fn map_err_info(
         self,
         f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
     ) -> InterpResult<'tcx, T> {
@@ -864,8 +864,19 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
     }
 
     #[inline]
-    pub fn inspect_err(self, f: impl FnOnce(&InterpErrorInfo<'tcx>)) -> InterpResult<'tcx, T> {
-        InterpResult_::new(self.disarm().inspect_err(f))
+    pub fn map_err_kind(
+        self,
+        f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
+    ) -> InterpResult<'tcx, T> {
+        InterpResult_::new(self.disarm().map_err(|mut e| {
+            e.0.kind = f(e.0.kind);
+            e
+        }))
+    }
+
+    #[inline]
+    pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
+        InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 115bcdbc589..790ff3e2fe0 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -36,7 +36,7 @@ pub use self::allocation::{
 pub use self::error::{
     BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
     EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind,
-    InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo,
+    InterpErrorInfo, InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo,
     MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
     ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
     ValidationErrorKind, interp_ok,
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 8f490094d60..2f97c408f2a 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -232,7 +232,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
     {
         f(self)
-            .map_err(|err| {
+            .map_err_info(|err| {
                 trace!("InterpCx operation failed: {:?}", err);
                 // Some errors shouldn't come up because creating them causes
                 // an allocation, which we should avoid. When that happens,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index b84cbf9c629..98db36b12be 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4011,6 +4011,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 let instead = res.is_some();
                 let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
                     && path[0].ident.span.lo() == end.span.lo()
+                    && !matches!(start.kind, ExprKind::Lit(_))
                 {
                     let mut sugg = ".";
                     let mut span = start.span.between(end.span);
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 5076152dbff..44373ca4866 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1277,19 +1277,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     let normalized_term =
                         ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
 
-                    let is_normalized_term_expected = !matches!(
-                        obligation.cause.code().peel_derives(),
-                        ObligationCauseCode::WhereClause(..)
-                            | ObligationCauseCode::WhereClauseInExpr(..)
-                            | ObligationCauseCode::Coercion { .. }
-                    );
-
-                    let (expected, actual) = if is_normalized_term_expected {
-                        (normalized_term, data.term)
-                    } else {
-                        (data.term, normalized_term)
-                    };
-
                     // constrain inference variables a bit more to nested obligations from normalize so
                     // we can have more helpful errors.
                     //
@@ -1298,12 +1285,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     let _ = ocx.select_where_possible();
 
                     if let Err(new_err) =
-                        ocx.eq(&obligation.cause, obligation.param_env, expected, actual)
+                        ocx.eq(&obligation.cause, obligation.param_env, data.term, normalized_term)
                     {
                         (
                             Some((
                                 data.projection_term,
-                                is_normalized_term_expected,
+                                false,
                                 self.resolve_vars_if_possible(normalized_term),
                                 data.term,
                             )),
@@ -1444,12 +1431,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 &mut diag,
                 &obligation.cause,
                 secondary_span,
-                values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
-                    infer::ValuePairs::Terms(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        expected_ty,
-                    ))
+                values.map(|(_, _, normalized_ty, expected_ty)| {
+                    infer::ValuePairs::Terms(ExpectedFound::new(true, expected_ty, normalized_ty))
                 }),
                 err,
                 false,
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 7354ea5fb6a..13691204c96 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -728,6 +728,49 @@ fn fn_abi_adjust_for_abi<'tcx>(
                 };
             }
 
+            if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {
+                // Return values larger than 2 registers using a return area
+                // pointer. LLVM and Cranelift disagree about how to return
+                // values that don't fit in the registers designated for return
+                // values. LLVM will force the entire return value to be passed
+                // by return area pointer, while Cranelift will look at each IR level
+                // return value independently and decide to pass it in a
+                // register or not, which would result in the return value
+                // being passed partially in registers and partially through a
+                // return area pointer.
+                //
+                // While Cranelift may need to be fixed as the LLVM behavior is
+                // generally more correct with respect to the surface language,
+                // forcing this behavior in rustc itself makes it easier for
+                // other backends to conform to the Rust ABI and for the C ABI
+                // rustc already handles this behavior anyway.
+                //
+                // In addition LLVM's decision to pass the return value in
+                // registers or using a return area pointer depends on how
+                // exactly the return type is lowered to an LLVM IR type. For
+                // example `Option<u128>` can be lowered as `{ i128, i128 }`
+                // in which case the x86_64 backend would use a return area
+                // pointer, or it could be passed as `{ i32, i128 }` in which
+                // case the x86_64 backend would pass it in registers by taking
+                // advantage of an LLVM ABI extension that allows using 3
+                // registers for the x86_64 sysv call conv rather than the
+                // officially specified 2 registers.
+                //
+                // FIXME: Technically we should look at the amount of available
+                // return registers rather than guessing that there are 2
+                // registers for return values. In practice only a couple of
+                // architectures have less than 2 return registers. None of
+                // which supported by Cranelift.
+                //
+                // NOTE: This adjustment is only necessary for the Rust ABI as
+                // for other ABI's the calling convention implementations in
+                // rustc_target already ensure any return value which doesn't
+                // fit in the available amount of return registers is passed in
+                // the right way for the current target.
+                arg.make_indirect();
+                return;
+            }
+
             match arg.layout.abi {
                 Abi::Aggregate { .. } => {}
 
diff --git a/config.example.toml b/config.example.toml
index 4b591b949b3..168ac353cff 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -414,6 +414,11 @@
 # Specify the location of the Android NDK. Used when targeting Android.
 #android-ndk = "/path/to/android-ndk-r26d"
 
+# Number of parallel jobs to be used for building and testing. If set to `0` or
+# omitted, it will be automatically determined. This is the `-j`/`--jobs` flag
+# passed to cargo invocations.
+#jobs = 0
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 69ad4f41519..38e858626b9 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -3138,7 +3138,7 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
 /// [violate memory safety][read-ownership].
 ///
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointers must be non-null and properly aligned.
+/// `0`, the pointers must be properly aligned.
 ///
 /// [`read`]: crate::ptr::read
 /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
@@ -3261,7 +3261,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 /// [violate memory safety][read-ownership].
 ///
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointers must be non-null and properly aligned.
+/// `0`, the pointers must be properly aligned.
 ///
 /// [`read`]: crate::ptr::read
 /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
@@ -3342,7 +3342,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 /// * `dst` must be properly aligned.
 ///
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointer must be non-null and properly aligned.
+/// `0`, the pointer must be properly aligned.
 ///
 /// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB)
 /// later if the written bytes are not a valid representation of some `T`. For instance, the
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 89936dc12ac..22fd47b0596 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -505,9 +505,11 @@ impl () {}
 ///
 /// *[See also the `std::ptr` module](ptr).*
 ///
-/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
-/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
-/// dereferenced (using the `*` operator), it must be non-null and aligned.
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns. Raw pointers
+/// can be out-of-bounds, unaligned, or [`null`]. However, when loading from or storing to a raw
+/// pointer, it must be [valid] for the given access and aligned. When using a field expression,
+/// tuple index expression, or array/slice index expression on a raw pointer, it follows the rules
+/// of [in-bounds pointer arithmetic][`offset`].
 ///
 /// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
 /// [`write`] must be used if the type has drop glue and memory is not already
@@ -613,6 +615,7 @@ impl () {}
 /// [`offset`]: pointer::offset
 /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
 /// [`write`]: ptr::write
+/// [valid]: ptr#safety
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 09ff7f8cab1..f7036f30a99 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1024,7 +1024,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 ///
 /// * Both `x` and `y` must be properly aligned.
 ///
-/// Note that even if `T` has size `0`, the pointers must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointers must be properly aligned.
 ///
 /// [valid]: self#safety
 ///
@@ -1110,7 +1110,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
 ///   beginning at `y` with the same size.
 ///
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
-/// the pointers must be non-null and properly aligned.
+/// the pointers must be properly aligned.
 ///
 /// [valid]: self#safety
 ///
@@ -1243,7 +1243,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
 ///
 /// * `dst` must point to a properly initialized value of type `T`.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// [valid]: self#safety
 ///
@@ -1300,7 +1300,7 @@ pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
 ///
 /// * `src` must point to a properly initialized value of type `T`.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// # Examples
 ///
@@ -1555,7 +1555,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
 ///   case.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// [valid]: self#safety
 ///
@@ -1774,7 +1774,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 /// However, storing non-[`Copy`] types in volatile memory is almost certainly
 /// incorrect.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// [valid]: self#safety
 /// [read-ownership]: read#ownership-of-the-returned-value
@@ -1853,7 +1853,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// * `dst` must be properly aligned.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
+/// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// [valid]: self#safety
 ///
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 5a1086527a1..f6d4825c67b 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -18,17 +18,10 @@ macro_rules! define_client_handles {
             $(pub(super) $ity: AtomicU32,)*
         }
 
-        impl HandleCounters {
-            // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
-            // a wrapper `fn` pointer, once `const fn` can reference `static`s.
-            extern "C" fn get() -> &'static Self {
-                static COUNTERS: HandleCounters = HandleCounters {
-                    $($oty: AtomicU32::new(1),)*
-                    $($ity: AtomicU32::new(1),)*
-                };
-                &COUNTERS
-            }
-        }
+        static COUNTERS: HandleCounters = HandleCounters {
+            $($oty: AtomicU32::new(1),)*
+            $($ity: AtomicU32::new(1),)*
+        };
 
         $(
             pub(crate) struct $oty {
@@ -259,9 +252,7 @@ pub(crate) fn is_available() -> bool {
 /// and forcing the use of APIs that take/return `S::TokenStream`, server-side.
 #[repr(C)]
 pub struct Client<I, O> {
-    // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
-    // a wrapper `fn` pointer, once `const fn` can reference `static`s.
-    pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
+    pub(super) handle_counters: &'static HandleCounters,
 
     pub(super) run: extern "C" fn(BridgeConfig<'_>) -> Buffer,
 
@@ -346,7 +337,7 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
 impl Client<crate::TokenStream, crate::TokenStream> {
     pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self {
         Client {
-            get_handle_counters: HandleCounters::get,
+            handle_counters: &COUNTERS,
             run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
                 run_client(bridge, |input| f(crate::TokenStream(Some(input))).0)
             }),
@@ -360,7 +351,7 @@ impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> {
         f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
     ) -> Self {
         Client {
-            get_handle_counters: HandleCounters::get,
+            handle_counters: &COUNTERS,
             run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
                 run_client(bridge, |(input, input2)| {
                     f(crate::TokenStream(Some(input)), crate::TokenStream(Some(input2))).0
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 692b6038a38..97e5a603c3a 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -400,10 +400,10 @@ impl client::Client<crate::TokenStream, crate::TokenStream> {
         S: Server,
         S::TokenStream: Default,
     {
-        let client::Client { get_handle_counters, run, _marker } = *self;
+        let client::Client { handle_counters, run, _marker } = *self;
         run_server(
             strategy,
-            get_handle_counters(),
+            handle_counters,
             server,
             <MarkedTypes<S> as Types>::TokenStream::mark(input),
             run,
@@ -426,10 +426,10 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream
         S: Server,
         S::TokenStream: Default,
     {
-        let client::Client { get_handle_counters, run, _marker } = *self;
+        let client::Client { handle_counters, run, _marker } = *self;
         run_server(
             strategy,
-            get_handle_counters(),
+            handle_counters,
             server,
             (
                 <MarkedTypes<S> as Types>::TokenStream::mark(input),
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 453b2708daa..30d43c8bbfd 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -2146,10 +2146,13 @@ mod unsafe_keyword {}
 
 #[doc(keyword = "use")]
 //
-/// Import or rename items from other crates or modules.
+/// Import or rename items from other crates or modules, or specify precise capturing
+/// with `use<..>`.
 ///
-/// Usually a `use` keyword is used to shorten the path required to refer to a module item.
-/// The keyword may appear in modules, blocks and even functions, usually at the top.
+/// ## Importing items
+///
+/// The `use` keyword is employed to shorten the path required to refer to a module item.
+/// The keyword may appear in modules, blocks, and even functions, typically at the top.
 ///
 /// The most basic usage of the keyword is `use path::to::item;`,
 /// though a number of convenient shortcuts are supported:
@@ -2190,19 +2193,48 @@ mod unsafe_keyword {}
 /// // Compiles.
 /// let _ = VariantA;
 ///
-/// // Does not compile !
+/// // Does not compile!
 /// let n = new();
 /// ```
 ///
-/// For more information on `use` and paths in general, see the [Reference].
+/// For more information on `use` and paths in general, see the [Reference][ref-use-decls].
 ///
 /// The differences about paths and the `use` keyword between the 2015 and 2018 editions
-/// can also be found in the [Reference].
+/// can also be found in the [Reference][ref-use-decls].
+///
+/// ## Precise capturing
+///
+/// The `use<..>` syntax is used within certain `impl Trait` bounds to control which generic
+/// parameters are captured. This is important for return-position `impl Trait` (RPIT) types,
+/// as it affects borrow checking by controlling which generic parameters can be used in the
+/// hidden type.
+///
+/// For example, the following function demonstrates an error without precise capturing in
+/// Rust 2021 and earlier editions:
+///
+/// ```rust,compile_fail,edition2021
+/// fn f(x: &()) -> impl Sized { x }
+/// ```
+///
+/// By using `use<'_>` for precise capturing, it can be resolved:
+///
+/// ```rust
+/// fn f(x: &()) -> impl Sized + use<'_> { x }
+/// ```
+///
+/// This syntax specifies that the elided lifetime be captured and therefore available for
+/// use in the hidden type.
+///
+/// In Rust 2024, opaque types automatically capture all lifetime parameters in scope.
+/// `use<..>` syntax serves as an important way of opting-out of that default.
+///
+/// For more details about precise capturing, see the [Reference][ref-impl-trait].
 ///
 /// [`crate`]: keyword.crate.html
 /// [`self`]: keyword.self.html
 /// [`super`]: keyword.super.html
-/// [Reference]: ../reference/items/use-declarations.html
+/// [ref-use-decls]: ../reference/items/use-declarations.html
+/// [ref-impl-trait]: ../reference/types/impl-trait.html
 mod use_keyword {}
 
 #[doc(keyword = "where")]
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 4ced7065c82..abc8e69a285 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -10,7 +10,7 @@
 //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
 
 use r_efi::efi::{self, Guid};
-use r_efi::protocols::{device_path, device_path_to_text};
+use r_efi::protocols::{device_path, device_path_to_text, shell};
 
 use crate::ffi::{OsStr, OsString};
 use crate::io::{self, const_io_error};
@@ -424,3 +424,24 @@ pub(crate) fn os_string_to_raw(s: &OsStr) -> Option<Box<[r_efi::efi::Char16]>> {
     let temp = s.encode_wide().chain(Some(0)).collect::<Box<[r_efi::efi::Char16]>>();
     if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) }
 }
+
+pub(crate) fn open_shell() -> Option<NonNull<shell::Protocol>> {
+    static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+        AtomicPtr::new(crate::ptr::null_mut());
+
+    if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
+        if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
+            return Some(protocol);
+        }
+    }
+
+    let handles = locate_handles(shell::PROTOCOL_GUID).ok()?;
+    for handle in handles {
+        if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
+            LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
+            return Some(protocol);
+        }
+    }
+
+    None
+}
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index 4eb7698b43a..27395f7c3c0 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -125,7 +125,7 @@ pub fn error_string(errno: RawOsError) -> String {
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    match uefi_shell::open_shell() {
+    match helpers::open_shell() {
         Some(shell) => {
             // SAFETY: path_ptr is managed by UEFI shell and should not be deallocated
             let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) };
@@ -144,7 +144,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let shell = uefi_shell::open_shell().ok_or(unsupported_err())?;
+    let shell = helpers::open_shell().ok_or(unsupported_err())?;
 
     let mut p = helpers::os_string_to_raw(p.as_os_str())
         .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
@@ -192,44 +192,58 @@ pub fn current_exe() -> io::Result<PathBuf> {
     helpers::device_path_to_text(protocol).map(PathBuf::from)
 }
 
-pub struct Env(!);
+pub struct EnvStrDebug<'a> {
+    iter: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut list = f.debug_list();
+        for (a, b) in self.iter {
+            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
+        }
+        list.finish()
+    }
+}
+
+pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);
 
 impl Env {
     // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
     pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self(inner) = self;
-        match *inner {}
+        EnvStrDebug { iter: self.0.as_slice() }
     }
 }
 
 impl Iterator for Env {
     type Item = (OsString, OsString);
+
     fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.0
+        self.0.next()
     }
 }
 
 impl fmt::Debug for Env {
-    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self(inner) = self;
-        match *inner {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
     }
 }
 
 pub fn env() -> Env {
-    panic!("not supported on this platform")
+    let env = uefi_env::get_all().expect("not supported on this platform");
+    Env(env.into_iter())
 }
 
-pub fn getenv(_: &OsStr) -> Option<OsString> {
-    None
+pub fn getenv(key: &OsStr) -> Option<OsString> {
+    uefi_env::get(key)
 }
 
-pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
+pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
+    uefi_env::set(key, val)
 }
 
-pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
+pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
+    uefi_env::unset(key)
 }
 
 pub fn temp_dir() -> PathBuf {
@@ -261,36 +275,84 @@ pub fn getpid() -> u32 {
     panic!("no pids on this platform")
 }
 
-mod uefi_shell {
-    use r_efi::protocols::shell;
-
-    use super::super::helpers;
+mod uefi_env {
+    use crate::ffi::{OsStr, OsString};
+    use crate::io;
+    use crate::os::uefi::ffi::OsStringExt;
     use crate::ptr::NonNull;
-    use crate::sync::atomic::{AtomicPtr, Ordering};
-
-    pub fn open_shell() -> Option<NonNull<shell::Protocol>> {
-        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
-            AtomicPtr::new(crate::ptr::null_mut());
-
-        if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
-            if let Ok(protocol) = helpers::open_protocol::<shell::Protocol>(
-                handle,
-                r_efi::protocols::shell::PROTOCOL_GUID,
-            ) {
-                return Some(protocol);
-            }
+    use crate::sys::{helpers, unsupported_err};
+
+    pub(crate) fn get(key: &OsStr) -> Option<OsString> {
+        let shell = helpers::open_shell()?;
+        let mut key_ptr = helpers::os_string_to_raw(key)?;
+        unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
+    }
+
+    pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
+        let mut val_ptr = helpers::os_string_to_raw(val)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
+    }
+
+    pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
+    }
+
+    pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+
+        let mut vars = Vec::new();
+        let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
+
+        if val.is_null() {
+            return Ok(vars);
         }
 
-        let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?;
-        for handle in handles {
-            if let Ok(protocol) =
-                helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID)
-            {
-                LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
-                return Some(protocol);
+        let mut start = 0;
+
+        // UEFI Shell returns all keys seperated by NULL.
+        // End of string is denoted by two NULLs
+        for i in 0.. {
+            if unsafe { *val.add(i) } == 0 {
+                // Two NULL signal end of string
+                if i == start {
+                    break;
+                }
+
+                let key = OsString::from_wide(unsafe {
+                    crate::slice::from_raw_parts(val.add(start), i - start)
+                });
+                // SAFETY: val.add(start) is always NULL terminated
+                let val = unsafe { get_raw(shell, val.add(start)) }
+                    .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
+
+                vars.push((key, val));
+                start = i + 1;
             }
         }
 
-        None
+        Ok(vars)
+    }
+
+    unsafe fn get_raw(
+        shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
+        key_ptr: *mut r_efi::efi::Char16,
+    ) -> Option<OsString> {
+        let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
+        helpers::os_string_from_raw(val)
+    }
+
+    unsafe fn set_raw(
+        key_ptr: *mut r_efi::efi::Char16,
+        val_ptr: *mut r_efi::efi::Char16,
+    ) -> io::Result<()> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+        let r =
+            unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
+        if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
     }
 }
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 567577b2b4d..f1f843a5f7a 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -189,7 +189,7 @@ cfg_has_statx! {{
             // See: https://github.com/rust-lang/rust/issues/65662
             //
             // FIXME what about transient conditions like `ENOMEM`?
-            let err2 = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut()))
+            let err2 = cvt(statx(0, ptr::null(), 0, libc::STATX_BASIC_STATS | libc::STATX_BTIME, ptr::null_mut()))
                 .err()
                 .and_then(|e| e.raw_os_error());
             if err2 == Some(libc::EFAULT) {
@@ -910,7 +910,7 @@ impl DirEntry {
                 fd,
                 name,
                 libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_ALL,
+                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
             ) } {
                 return ret;
             }
@@ -1194,7 +1194,7 @@ impl File {
                 fd,
                 c"".as_ptr() as *const c_char,
                 libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_ALL,
+                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
             ) } {
                 return ret;
             }
@@ -1767,7 +1767,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
                 libc::AT_FDCWD,
                 p.as_ptr(),
                 libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_ALL,
+                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
             ) } {
                 return ret;
             }
@@ -1786,7 +1786,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
                 libc::AT_FDCWD,
                 p.as_ptr(),
                 libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_ALL,
+                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
             ) } {
                 return ret;
             }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index c2ab439891e..aeb81b14638 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -891,6 +891,7 @@ define_config! {
         metrics: Option<bool> = "metrics",
         android_ndk: Option<PathBuf> = "android-ndk",
         optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+        jobs: Option<u32> = "jobs",
     }
 }
 
@@ -1289,7 +1290,6 @@ impl Config {
         config.rustc_error_format = flags.rustc_error_format;
         config.json_output = flags.json_output;
         config.on_fail = flags.on_fail;
-        config.jobs = Some(threads_from_config(flags.jobs as u32));
         config.cmd = flags.cmd;
         config.incremental = flags.incremental;
         config.dry_run = if flags.dry_run { DryRun::UserSelected } else { DryRun::Disabled };
@@ -1511,8 +1511,11 @@ impl Config {
             metrics: _,
             android_ndk,
             optimized_compiler_builtins,
+            jobs,
         } = toml.build.unwrap_or_default();
 
+        config.jobs = Some(threads_from_config(flags.jobs.unwrap_or(jobs.unwrap_or(0))));
+
         if let Some(file_build) = build {
             config.build = TargetSelection::from_user(&file_build);
         };
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 3aefe517a5b..bfeb811508c 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -110,11 +110,10 @@ pub struct Flags {
         short,
         long,
         value_hint = clap::ValueHint::Other,
-        default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
         value_name = "JOBS"
     )]
     /// number of jobs to run in parallel
-    pub jobs: usize,
+    pub jobs: Option<u32>,
     // This overrides the deny-warnings configuration option,
     // which passes -Dwarnings to the compiler invocations.
     #[arg(global = true, long)]
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 2611b6cf51b..1f02757682c 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -352,3 +352,61 @@ fn parse_rust_std_features_empty() {
 fn parse_rust_std_features_invalid() {
     parse("rust.std-features = \"backtrace\"");
 }
+
+#[test]
+fn parse_jobs() {
+    assert_eq!(parse("build.jobs = 1").jobs, Some(1));
+}
+
+#[test]
+fn jobs_precedence() {
+    // `--jobs` should take precedence over using `--set build.jobs`.
+
+    let config = Config::parse_inner(
+        Flags::parse(&[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--jobs=67890".to_owned(),
+            "--set=build.jobs=12345".to_owned(),
+        ]),
+        |&_| toml::from_str(""),
+    );
+    assert_eq!(config.jobs, Some(67890));
+
+    // `--set build.jobs` should take precedence over `config.toml`.
+    let config = Config::parse_inner(
+        Flags::parse(&[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=build.jobs=12345".to_owned(),
+        ]),
+        |&_| {
+            toml::from_str(
+                r#"
+            [build]
+            jobs = 67890
+        "#,
+            )
+        },
+    );
+    assert_eq!(config.jobs, Some(12345));
+
+    // `--jobs` > `--set build.jobs` > `config.toml`
+    let config = Config::parse_inner(
+        Flags::parse(&[
+            "check".to_owned(),
+            "--jobs=123".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=build.jobs=456".to_owned(),
+        ]),
+        |&_| {
+            toml::from_str(
+                r#"
+            [build]
+            jobs = 789
+        "#,
+            )
+        },
+    );
+    assert_eq!(config.jobs, Some(123));
+}
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index b37786496cb..9169bc90a45 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -275,4 +275,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "New option `./x setup editor` added, replacing `./x setup vscode` and adding support for vim, emacs and helix.",
     },
+    ChangeInfo {
+        change_id: 131838,
+        severity: ChangeSeverity::Info,
+        summary: "Allow setting `--jobs` in config.toml with `build.jobs`.",
+    },
 ];
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 34332de80b3..42df0b28381 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -24,6 +24,7 @@ tracing = "0.1"
 tracing-tree = "0.3.0"
 threadpool = "1.8.1"
 unicode-segmentation = "1.9"
+sha2 = "0.10.8"
 
 [dependencies.tracing-subscriber]
 version = "0.3.3"
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index df9776ff5f8..2c17fd54006 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -44,7 +44,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-style: normal;
 	font-weight: 400;
 	src: local('Fira Sans'),
-		url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");
+		url("FiraSans-Regular-0fe48ade.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -52,7 +52,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-style: normal;
 	font-weight: 500;
 	src: local('Fira Sans Medium'),
-		url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");
+		url("FiraSans-Medium-e1aa3f0a.woff2") format("woff2");
 	font-display: swap;
 }
 
@@ -62,7 +62,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-style: normal;
 	font-weight: 400;
 	src: local('Source Serif 4'),
-		url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");
+		url("SourceSerif4-Regular-6b053e98.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -70,7 +70,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-style: italic;
 	font-weight: 400;
 	src: local('Source Serif 4 Italic'),
-		url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");
+		url("SourceSerif4-It-ca3b17ed.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -78,7 +78,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-style: normal;
 	font-weight: 700;
 	src: local('Source Serif 4 Bold'),
-		url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");
+		url("SourceSerif4-Bold-6d4fd4c0.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 
@@ -89,28 +89,28 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
 	font-weight: 400;
 	/* Avoid using locally installed font because bad versions are in circulation:
 	 * see https://github.com/rust-lang/rust/issues/24355 */
-	src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-Regular-8badfe75.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
 	font-family: 'Source Code Pro';
 	font-style: italic;
 	font-weight: 400;
-	src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-It-fc8b9304.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
 	font-family: 'Source Code Pro';
 	font-style: normal;
 	font-weight: 600;
-	src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-Semibold-aa29a496.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 
 /* Avoid using legacy CJK serif fonts in Windows like Batang. */
 @font-face {
 	font-family: 'NanumBarunGothic';
-	src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");
+	src: url("NanumBarunGothic-13b3dcba.ttf.woff2") format("woff2");
 	font-display: swap;
 	unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
 }
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 6157598ba38..9e0803f5d3f 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -3,12 +3,9 @@
 //! All the static files are included here for centralized access in case anything other than the
 //! HTML rendering code (say, the theme checker) needs to access one of these files.
 
-use std::hash::Hasher;
 use std::path::{Path, PathBuf};
 use std::{fmt, str};
 
-use rustc_data_structures::fx::FxHasher;
-
 pub(crate) struct StaticFile {
     pub(crate) filename: PathBuf,
     pub(crate) bytes: &'static [u8],
@@ -64,9 +61,11 @@ pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf {
 }
 
 fn static_suffix(bytes: &[u8]) -> String {
-    let mut hasher = FxHasher::default();
-    hasher.write(bytes);
-    format!("-{:016x}", hasher.finish())
+    use sha2::Digest;
+    let bytes = sha2::Sha256::digest(bytes);
+    let mut digest = format!("-{bytes:x}");
+    digest.truncate(9);
+    digest
 }
 
 macro_rules! static_files {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f0452008304..5b8a96a54c2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -468,7 +468,19 @@ impl<'test> TestCx<'test> {
 
         if let Some(revision) = self.revision {
             let normalized_revision = normalize_revision(revision);
-            cmd.args(&["--cfg", &normalized_revision]);
+            let cfg_arg = ["--cfg", &normalized_revision];
+            let arg = format!("--cfg={normalized_revision}");
+            if self
+                .props
+                .compile_flags
+                .windows(2)
+                .any(|args| args == cfg_arg || args[0] == arg || args[1] == arg)
+            {
+                panic!(
+                    "error: redundant cfg argument `{normalized_revision}` is already created by the revision"
+                );
+            }
+            cmd.args(cfg_arg);
         }
 
         if !self.props.no_auto_check_cfg {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 146f9902f6f..1684abeec6b 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -13,7 +13,7 @@ fn err_sb_ub<'tcx>(
     msg: String,
     help: Vec<String>,
     history: Option<TagHistory>,
-) -> InterpError<'tcx> {
+) -> InterpErrorKind<'tcx> {
     err_machine_stop!(TerminationInfo::StackedBorrowsUb { msg, help, history })
 }
 
@@ -376,7 +376,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
 
     /// Report a descriptive error when `new` could not be granted from `derived_from`.
     #[inline(never)] // This is only called on fatal code paths
-    pub(super) fn grant_error(&self, stack: &Stack) -> InterpError<'tcx> {
+    pub(super) fn grant_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
         let Operation::Retag(op) = &self.operation else {
             unreachable!("grant_error should only be called during a retag")
         };
@@ -402,7 +402,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
 
     /// Report a descriptive error when `access` is not permitted based on `tag`.
     #[inline(never)] // This is only called on fatal code paths
-    pub(super) fn access_error(&self, stack: &Stack) -> InterpError<'tcx> {
+    pub(super) fn access_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
         // Deallocation and retagging also do an access as part of their thing, so handle that here, too.
         let op = match &self.operation {
             Operation::Access(op) => op,
@@ -424,7 +424,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
     }
 
     #[inline(never)] // This is only called on fatal code paths
-    pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> InterpError<'tcx> {
+    pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> InterpErrorKind<'tcx> {
         let protected = match kind {
             ProtectorKind::WeakProtector => "weakly protected",
             ProtectorKind::StrongProtector => "strongly protected",
@@ -445,7 +445,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
     }
 
     #[inline(never)] // This is only called on fatal code paths
-    pub fn dealloc_error(&self, stack: &Stack) -> InterpError<'tcx> {
+    pub fn dealloc_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
         let Operation::Dealloc(op) = &self.operation else {
             unreachable!("dealloc_error should only be called during a deallocation")
         };
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
index cb840f19e3b..b2fd9b2bf05 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -298,7 +298,7 @@ pub(super) struct TbError<'node> {
 
 impl TbError<'_> {
     /// Produce a UB error.
-    pub fn build<'tcx>(self) -> InterpError<'tcx> {
+    pub fn build<'tcx>(self) -> InterpErrorKind<'tcx> {
         use TransitionError::*;
         let cause = self.access_cause;
         let accessed = self.accessed_info;
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 15cefab1a68..a551b017dfc 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -674,7 +674,7 @@ impl<'tcx> Tree {
                             Ok(())
                         }
                     },
-                    |args: ErrHandlerArgs<'_, TransitionError>| -> InterpError<'tcx> {
+                    |args: ErrHandlerArgs<'_, TransitionError>| -> InterpErrorKind<'tcx> {
                         let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
                         TbError {
                             conflicting_info,
@@ -772,7 +772,7 @@ impl<'tcx> Tree {
         let err_handler = |perms_range: Range<u64>,
                            access_cause: diagnostics::AccessCause,
                            args: ErrHandlerArgs<'_, TransitionError>|
-         -> InterpError<'tcx> {
+         -> InterpErrorKind<'tcx> {
             let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
             TbError {
                 conflicting_info,
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 475139a3b51..f055662891e 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -214,7 +214,7 @@ pub fn report_error<'tcx>(
     ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
     e: InterpErrorInfo<'tcx>,
 ) -> Option<(i64, bool)> {
-    use InterpError::*;
+    use InterpErrorKind::*;
     use UndefinedBehaviorInfo::*;
 
     let mut msg = vec![];
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index de293495e86..59776a484b5 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -245,17 +245,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     let val = match which {
                         Op::MirOp(mir_op) => {
                             // This does NaN adjustments.
-                            let val = this.binary_op(mir_op, &left, &right).map_err(|err| {
-                                match err.kind() {
-                                    &InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => {
+                            let val = this.binary_op(mir_op, &left, &right).map_err_kind(|kind| {
+                                match kind {
+                                    InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => {
                                         // This resets the interpreter backtrace, but it's not worth avoiding that.
                                         let shift_amount = match shift_amount {
                                             Either::Left(v) => v.to_string(),
                                             Either::Right(v) => v.to_string(),
                                         };
-                                        err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}").into()
+                                        err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}")
                                     }
-                                    _ => err
+                                    kind => kind
                                 }
                             })?;
                             if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) {
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 7fce5b63306..f6f91e58969 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -289,11 +289,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
             "miri_get_alloc_id" => {
                 let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
-                let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err(|_e| {
+                let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| {
                     err_machine_stop!(TerminationInfo::Abort(format!(
                         "pointer passed to `miri_get_alloc_id` must not be dangling, got {ptr:?}"
                     )))
-                    .into()
                 })?;
                 this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
             }
diff --git a/tests/assembly/x86-return-float.rs b/tests/assembly/x86-return-float.rs
index f9ebf53dddc..30c5e869633 100644
--- a/tests/assembly/x86-return-float.rs
+++ b/tests/assembly/x86-return-float.rs
@@ -315,10 +315,10 @@ pub fn return_f16(x: f16) -> f16 {
 #[no_mangle]
 pub fn return_f128(x: f128) -> f128 {
     // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
-    // CHECK-NEXT: movl [[#%d,OFFSET+16]](%ebp), %[[VAL4:.*]]
     // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
     // CHECK-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
     // CHECK-NEXT: movl [[#%d,OFFSET+12]](%ebp), %[[VAL3:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+16]](%ebp), %[[VAL4:.*]]
     // CHECK-NEXT: movl %[[VAL4:.*]] 12(%[[PTR]])
     // CHECK-NEXT: movl %[[VAL3:.*]] 8(%[[PTR]])
     // CHECK-NEXT: movl %[[VAL2:.*]] 4(%[[PTR]])
diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs
index 80b572fbbc9..4af264101de 100644
--- a/tests/codegen/float/f128.rs
+++ b/tests/codegen/float/f128.rs
@@ -1,7 +1,11 @@
 // 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack.
-//@ revisions: x86 other
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: x86 bit32 bit64
 //@[x86] only-x86
-//@[other] ignore-x86
+//@[bit32] ignore-x86
+//@[bit32] only-32bit
+//@[bit64] ignore-x86
+//@[bit64] only-64bit
 
 // Verify that our intrinsics generate the correct LLVM calls for f128
 
@@ -52,42 +56,54 @@ pub fn f128_le(a: f128, b: f128) -> bool {
     a <= b
 }
 
-// CHECK-LABEL: fp128 @f128_neg(
+// x86-LABEL: void @f128_neg({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_neg({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_neg(
 #[no_mangle]
 pub fn f128_neg(a: f128) -> f128 {
     // CHECK: fneg fp128
     -a
 }
 
-// CHECK-LABEL: fp128 @f128_add(
+// x86-LABEL: void @f128_add({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_add({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_add(
 #[no_mangle]
 pub fn f128_add(a: f128, b: f128) -> f128 {
     // CHECK: fadd fp128 %{{.+}}, %{{.+}}
     a + b
 }
 
-// CHECK-LABEL: fp128 @f128_sub(
+// x86-LABEL: void @f128_sub({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_sub({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_sub(
 #[no_mangle]
 pub fn f128_sub(a: f128, b: f128) -> f128 {
     // CHECK: fsub fp128 %{{.+}}, %{{.+}}
     a - b
 }
 
-// CHECK-LABEL: fp128 @f128_mul(
+// x86-LABEL: void @f128_mul({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_mul({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_mul(
 #[no_mangle]
 pub fn f128_mul(a: f128, b: f128) -> f128 {
     // CHECK: fmul fp128 %{{.+}}, %{{.+}}
     a * b
 }
 
-// CHECK-LABEL: fp128 @f128_div(
+// x86-LABEL: void @f128_div({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_div({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_div(
 #[no_mangle]
 pub fn f128_div(a: f128, b: f128) -> f128 {
     // CHECK: fdiv fp128 %{{.+}}, %{{.+}}
     a / b
 }
 
-// CHECK-LABEL: fp128 @f128_rem(
+// x86-LABEL: void @f128_rem({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_rem({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_rem(
 #[no_mangle]
 pub fn f128_rem(a: f128, b: f128) -> f128 {
     // CHECK: frem fp128 %{{.+}}, %{{.+}}
@@ -143,44 +159,56 @@ pub fn f128_as_f16(a: f128) -> f16 {
     a as f16
 }
 
-// other-LABEL: float @f128_as_f32(
 // x86-LABEL: i32 @f128_as_f32(
+// bit32-LABEL: float @f128_as_f32(
+// bit64-LABEL: float @f128_as_f32(
 #[no_mangle]
 pub fn f128_as_f32(a: f128) -> f32 {
     // CHECK: fptrunc fp128 %{{.+}} to float
     a as f32
 }
 
-// other-LABEL: double @f128_as_f64(
 // x86-LABEL: void @f128_as_f64(
+// bit32-LABEL: double @f128_as_f64(
+// bit64-LABEL: double @f128_as_f64(
 #[no_mangle]
 pub fn f128_as_f64(a: f128) -> f64 {
     // CHECK: fptrunc fp128 %{{.+}} to double
     a as f64
 }
 
-// CHECK-LABEL: fp128 @f128_as_self(
+// x86-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_as_self({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f128_as_self(
 #[no_mangle]
 pub fn f128_as_self(a: f128) -> f128 {
-    // CHECK: ret fp128 %{{.+}}
+    // x86: store fp128 %a, ptr %_0, align 16
+    // bit32: store fp128 %a, ptr %_0, align 16
+    // bit64: ret fp128 %{{.+}}
     a as f128
 }
 
-// CHECK-LABEL: fp128 @f16_as_f128(
+// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f16_as_f128(
 #[no_mangle]
 pub fn f16_as_f128(a: f16) -> f128 {
     // CHECK: fpext half %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @f32_as_f128(
+// x86-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f32_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f32_as_f128(
 #[no_mangle]
 pub fn f32_as_f128(a: f32) -> f128 {
     // CHECK: fpext float %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @f64_as_f128(
+// x86-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f64_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f64_as_f128(
 #[no_mangle]
 pub fn f64_as_f128(a: f64) -> f128 {
     // CHECK: fpext double %{{.+}} to fp128
@@ -216,7 +244,9 @@ pub fn f128_as_u64(a: f128) -> u64 {
     a as u64
 }
 
-// CHECK-LABEL: i128 @f128_as_u128(
+// x86-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_as_u128({{.*}}sret([16 x i8])
+// bit64-LABEL: i128 @f128_as_u128(
 #[no_mangle]
 pub fn f128_as_u128(a: f128) -> u128 {
     // CHECK: call i128 @llvm.fptoui.sat.i128.f128(fp128 %{{.+}})
@@ -250,7 +280,9 @@ pub fn f128_as_i64(a: f128) -> i64 {
     a as i64
 }
 
-// CHECK-LABEL: i128 @f128_as_i128(
+// x86-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f128_as_i128({{.*}}sret([16 x i8])
+// bit64-LABEL: i128 @f128_as_i128(
 #[no_mangle]
 pub fn f128_as_i128(a: f128) -> i128 {
     // CHECK: call i128 @llvm.fptosi.sat.i128.f128(fp128 %{{.+}})
@@ -259,70 +291,90 @@ pub fn f128_as_i128(a: f128) -> i128 {
 
 /* int to float conversions */
 
-// CHECK-LABEL: fp128 @u8_as_f128(
+// x86-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @u8_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @u8_as_f128(
 #[no_mangle]
 pub fn u8_as_f128(a: u8) -> f128 {
     // CHECK: uitofp i8 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @u16_as_f128(
+// x86-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @u16_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @u16_as_f128(
 #[no_mangle]
 pub fn u16_as_f128(a: u16) -> f128 {
     // CHECK: uitofp i16 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @u32_as_f128(
+// x86-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @u32_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @u32_as_f128(
 #[no_mangle]
 pub fn u32_as_f128(a: u32) -> f128 {
     // CHECK: uitofp i32 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @u64_as_f128(
+// x86-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @u64_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @u64_as_f128(
 #[no_mangle]
 pub fn u64_as_f128(a: u64) -> f128 {
     // CHECK: uitofp i64 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @u128_as_f128(
+// x86-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @u128_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @u128_as_f128(
 #[no_mangle]
 pub fn u128_as_f128(a: u128) -> f128 {
     // CHECK: uitofp i128 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @i8_as_f128(
+// x86-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @i8_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @i8_as_f128(
 #[no_mangle]
 pub fn i8_as_f128(a: i8) -> f128 {
     // CHECK: sitofp i8 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @i16_as_f128(
+// x86-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @i16_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @i16_as_f128(
 #[no_mangle]
 pub fn i16_as_f128(a: i16) -> f128 {
     // CHECK: sitofp i16 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @i32_as_f128(
+// x86-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @i32_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @i32_as_f128(
 #[no_mangle]
 pub fn i32_as_f128(a: i32) -> f128 {
     // CHECK: sitofp i32 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @i64_as_f128(
+// x86-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @i64_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @i64_as_f128(
 #[no_mangle]
 pub fn i64_as_f128(a: i64) -> f128 {
     // CHECK: sitofp i64 %{{.+}} to fp128
     a as f128
 }
 
-// CHECK-LABEL: fp128 @i128_as_f128(
+// x86-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @i128_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @i128_as_f128(
 #[no_mangle]
 pub fn i128_as_f128(a: i128) -> f128 {
     // CHECK: sitofp i128 %{{.+}} to fp128
diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs
index 2910d7d3e92..80931051f18 100644
--- a/tests/codegen/float/f16.rs
+++ b/tests/codegen/float/f16.rs
@@ -1,7 +1,11 @@
 // 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack.
-//@ revisions: x86 other
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: x86 bit32 bit64
 //@[x86] only-x86
-//@[other] ignore-x86
+//@[bit32] ignore-x86
+//@[bit32] only-32bit
+//@[bit64] ignore-x86
+//@[bit64] only-64bit
 
 // Verify that our intrinsics generate the correct LLVM calls for f16
 
@@ -145,23 +149,27 @@ pub fn f16_as_self(a: f16) -> f16 {
     a as f16
 }
 
-// other-LABEL: float @f16_as_f32(
 // x86-LABEL: i32 @f16_as_f32(
+// bit32-LABEL: float @f16_as_f32(
+// bit64-LABEL: float @f16_as_f32(
 #[no_mangle]
 pub fn f16_as_f32(a: f16) -> f32 {
     // CHECK: fpext half %{{.+}} to float
     a as f32
 }
 
-// other-LABEL: double @f16_as_f64(
 // x86-LABEL: void @f16_as_f64(
+// bit32-LABEL: double @f16_as_f64(
+// bit64-LABEL: double @f16_as_f64(
 #[no_mangle]
 pub fn f16_as_f64(a: f16) -> f64 {
     // CHECK: fpext half %{{.+}} to double
     a as f64
 }
 
-// CHECK-LABEL: fp128 @f16_as_f128(
+// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8])
+// bit64-LABEL: fp128 @f16_as_f128(
 #[no_mangle]
 pub fn f16_as_f128(a: f16) -> f128 {
     // CHECK: fpext half %{{.+}} to fp128
@@ -218,7 +226,9 @@ pub fn f16_as_u64(a: f16) -> u64 {
     a as u64
 }
 
-// CHECK-LABEL: i128 @f16_as_u128(
+// x86-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f16_as_u128({{.*}}sret([16 x i8])
+// bit64-LABEL: i128 @f16_as_u128(
 #[no_mangle]
 pub fn f16_as_u128(a: f16) -> u128 {
     // CHECK: call i128 @llvm.fptoui.sat.i128.f16(half %{{.+}})
@@ -252,7 +262,9 @@ pub fn f16_as_i64(a: f16) -> i64 {
     a as i64
 }
 
-// CHECK-LABEL: i128 @f16_as_i128(
+// x86-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
+// bit32-LABEL: void @f16_as_i128({{.*}}sret([16 x i8])
+// bit64-LABEL: i128 @f16_as_i128(
 #[no_mangle]
 pub fn f16_as_i128(a: f16) -> i128 {
     // CHECK: call i128 @llvm.fptosi.sat.i128.f16(half %{{.+}})
diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs
index 3e6ed2b8e16..6b1da445c40 100644
--- a/tests/codegen/i128-x86-align.rs
+++ b/tests/codegen/i128-x86-align.rs
@@ -19,13 +19,15 @@ pub struct ScalarPair {
 #[no_mangle]
 pub fn load(x: &ScalarPair) -> ScalarPair {
     // CHECK-LABEL: @load(
+    // CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0,
     // CHECK-SAME: align 16 dereferenceable(32) %x
     // CHECK:      [[A:%.*]] = load i32, ptr %x, align 16
     // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
     // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16
-    // CHECK-NEXT: [[IV1:%.*]] = insertvalue { i32, i128 } poison, i32 [[A]], 0
-    // CHECK-NEXT: [[IV2:%.*]] = insertvalue { i32, i128 } [[IV1]], i128 [[B]], 1
-    // CHECK-NEXT: ret { i32, i128 } [[IV2]]
+    // CHECK-NEXT: store i32 [[A]], ptr %_0, align 16
+    // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %_0, i64 16
+    // CHECK-NEXT: store i128 [[B]], ptr [[GEP]], align 16
+    // CHECK-NEXT: ret void
     *x
 }
 
@@ -53,29 +55,23 @@ pub fn alloca() {
 #[no_mangle]
 pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
     // CHECK-LABEL: @load_volatile(
+    // CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0,
     // CHECK-SAME: align 16 dereferenceable(32) %x
-    // CHECK:      [[TMP:%.*]] = alloca [32 x i8], align 16
     // CHECK:      [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16
-    // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr [[TMP]], align 16
-    // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16
-    // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16
-    // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16
+    // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr %_0, align 16
+    // CHECK-NEXT: ret void
     unsafe { std::intrinsics::volatile_load(x) }
 }
 
 #[no_mangle]
 pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit<i128>, i128) {
-    // CHECK-LABEL: define { i128, i128 } @transmute(i32 noundef %x.0, i128 noundef %x.1)
-    // CHECK:       [[TMP:%.*]] = alloca [32 x i8], align 16
-    // CHECK-NEXT:  store i32 %x.0, ptr [[TMP]], align 16
-    // CHECK-NEXT:  [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16
+    // CHECK-LABEL: @transmute(
+    // CHECK-SAME:  sret([32 x i8]) align 16 dereferenceable(32) %_0,
+    // CHECK-SAME:  i32 noundef %x.0, i128 noundef %x.1
+    // CHECK:       store i32 %x.0, ptr %_0, align 16
+    // CHECK-NEXT:  [[GEP:%.*]] = getelementptr inbounds i8, ptr %_0, i64 16
     // CHECK-NEXT:  store i128 %x.1, ptr [[GEP]], align 16
-    // CHECK-NEXT:  [[LOAD1:%.*]] = load i128, ptr %_0, align 16
-    // CHECK-NEXT:  [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16
-    // CHECK-NEXT:  [[LOAD2:%.*]] = load i128, ptr [[GEP2]], align 16
-    // CHECK-NEXT:  [[IV1:%.*]] = insertvalue { i128, i128 } poison, i128 [[LOAD1]], 0
-    // CHECK-NEXT:  [[IV2:%.*]] = insertvalue { i128, i128 } [[IV1]], i128 [[LOAD2]], 1
-    // CHECK-NEXT:  ret { i128, i128 } [[IV2]]
+    // CHECK-NEXT:  ret void
     unsafe { std::mem::transmute(x) }
 }
 
diff --git a/tests/codegen/issues/issue-108395-branchy-bool-match.rs b/tests/codegen/issues/issue-108395-branchy-bool-match.rs
new file mode 100644
index 00000000000..24f5c0f6635
--- /dev/null
+++ b/tests/codegen/issues/issue-108395-branchy-bool-match.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -O -Zmerge-functions=disabled
+//! Test for <https://github.com/rust-lang/rust/issues/108395>. Check that
+//! matching on two bools with wildcards does not produce branches.
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @wildcard(
+#[no_mangle]
+pub fn wildcard(a: u16, b: u16, v: u16) -> u16 {
+    // CHECK-NOT: br
+    match (a == v, b == v) {
+        (true, false) => 0,
+        (false, true) => u16::MAX,
+        _ => 1 << 15, // half
+    }
+}
+
+// CHECK-LABEL: @exhaustive(
+#[no_mangle]
+pub fn exhaustive(a: u16, b: u16, v: u16) -> u16 {
+    // CHECK-NOT: br
+    match (a == v, b == v) {
+        (true, false) => 0,
+        (false, true) => u16::MAX,
+        (true, true) => 1 << 15,
+        (false, false) => 1 << 15,
+    }
+}
diff --git a/tests/codegen/mir-aggregate-no-alloca.rs b/tests/codegen/mir-aggregate-no-alloca.rs
index c0e7e1a05e3..04ffb075538 100644
--- a/tests/codegen/mir-aggregate-no-alloca.rs
+++ b/tests/codegen/mir-aggregate-no-alloca.rs
@@ -1,3 +1,7 @@
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: bit32 bit64
+//@[bit32] only-32bit
+//@[bit64] only-64bit
 //@ compile-flags: -O -C no-prepopulate-passes -Z randomize-layout=no
 
 #![crate_type = "lib"]
@@ -98,26 +102,36 @@ pub fn make_struct_1(a: i32) -> Struct1 {
 
 pub struct Struct2Asc(i16, i64);
 
-// CHECK-LABEL: { i64, i16 } @make_struct_2_asc(i16 noundef %a, i64 noundef %b)
+// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s,
+// bit64-LABEL: { i64, i16 } @make_struct_2_asc(
+// CHECK-SAME: i16 noundef %a, i64 noundef %b)
 #[no_mangle]
 pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
     // CHECK-NOT: alloca
-    // CHECK: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %b, 0
-    // CHECK: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %a, 1
-    // CHECK: ret { i64, i16 } %[[TEMP1]]
+    // bit32: %[[GEP:.+]] = getelementptr inbounds i8, ptr %s, i32 8
+    // bit32: store i16 %a, ptr %[[GEP]]
+    // bit32: store i64 %b, ptr %s
+    // bit64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %b, 0
+    // bit64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %a, 1
+    // bit64: ret { i64, i16 } %[[TEMP1]]
     let s = Struct2Asc(a, b);
     s
 }
 
 pub struct Struct2Desc(i64, i16);
 
-// CHECK-LABEL: { i64, i16 } @make_struct_2_desc(i64 noundef %a, i16 noundef %b)
+// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s,
+// bit64-LABEL: { i64, i16 } @make_struct_2_desc(
+// CHECK-SAME: i64 noundef %a, i16 noundef %b)
 #[no_mangle]
 pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc {
     // CHECK-NOT: alloca
-    // CHECK: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %a, 0
-    // CHECK: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %b, 1
-    // CHECK: ret { i64, i16 } %[[TEMP1]]
+    // bit32: store i64 %a, ptr %s
+    // bit32: %[[GEP:.+]] = getelementptr inbounds i8, ptr %s, i32 8
+    // bit32: store i16 %b, ptr %[[GEP]]
+    // bit64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %a, 0
+    // bit64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %b, 1
+    // bit64: ret { i64, i16 } %[[TEMP1]]
     let s = Struct2Desc(a, b);
     s
 }
diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs
index bb19bec0fb9..8972fc76ca2 100644
--- a/tests/codegen/range-attribute.rs
+++ b/tests/codegen/range-attribute.rs
@@ -1,6 +1,10 @@
 // Checks that range metadata gets emitted on functions result and arguments
 // with scalar value.
 
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: bit32 bit64
+//@[bit32] only-32bit
+//@[bit64] only-64bit
 //@ compile-flags: -O -C no-prepopulate-passes
 //@ min-llvm-version: 19
 
@@ -13,7 +17,8 @@ use std::num::NonZero;
 #[no_mangle]
 pub fn helper(_: usize) {}
 
-// CHECK: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x)
+// bit32: void @nonzero_int({{.*}} sret([16 x i8]) {{.*}}, i128 noundef range(i128 1, 0) %x)
+// bit64: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x)
 #[no_mangle]
 pub fn nonzero_int(x: NonZero<u128>) -> NonZero<u128> {
     x
@@ -43,7 +48,9 @@ pub enum Enum1 {
     C(u64),
 }
 
-// CHECK: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]] noundef range([[ENUM1_TYP]] 0, 3) %x.0, i64 noundef %x.1)
+// bit32: void @enum1_value({{.*}} sret({{[^,]*}}) {{[^,]*}}, [[ENUM1_TYP:i[0-9]+]]
+// bit64: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]]
+// CHECK-SAME: noundef range([[ENUM1_TYP]] 0, 3) %x.0, i64 noundef %x.1)
 #[no_mangle]
 pub fn enum1_value(x: Enum1) -> Enum1 {
     x
diff --git a/tests/codegen/tuple-layout-opt.rs b/tests/codegen/tuple-layout-opt.rs
index 601563bc061..5b2f65e7aa7 100644
--- a/tests/codegen/tuple-layout-opt.rs
+++ b/tests/codegen/tuple-layout-opt.rs
@@ -1,3 +1,7 @@
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: bit32 bit64
+//@[bit32] only-32bit
+//@[bit64] only-64bit
 //@ compile-flags: -C no-prepopulate-passes -Copt-level=0
 
 // Test that tuples get optimized layout, in particular with a ZST in the last field (#63244)
@@ -5,42 +9,48 @@
 #![crate_type = "lib"]
 
 type ScalarZstLast = (u128, ());
-// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
+// bit32: define {{(dso_local )?}}void @test_ScalarZstLast({{.*}} sret([16 x i8]) {{.*}}, i128 %_1)
+// bit64: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
 #[no_mangle]
 pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast {
     loop {}
 }
 
 type ScalarZstFirst = ((), u128);
-// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
+// bit32: define {{(dso_local )?}}void @test_ScalarZstFirst({{.*}} sret([16 x i8]) {{.*}}, i128 %_1)
+// bit64: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
 #[no_mangle]
 pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst {
     loop {}
 }
 
 type ScalarPairZstLast = (u8, u128, ());
-// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}void @test_ScalarPairZstLast(ptr sret({{[^,]*}})
+// CHECK-SAME: %_0, i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast {
     loop {}
 }
 
 type ScalarPairZstFirst = ((), u8, u128);
-// CHECK: define {{(dso_local )?}}{ i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
+// CHECK: define {{(dso_local )?}}void @test_ScalarPairZstFirst(ptr sret({{[^,]*}})
+// CHECK-SAME: %_0, i8 %_1.0, i128 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst {
     loop {}
 }
 
 type ScalarPairLotsOfZsts = ((), u8, (), u128, ());
-// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}void @test_ScalarPairLotsOfZsts(ptr sret({{[^,]*}})
+// CHECK-SAME: %_0, i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts {
     loop {}
 }
 
 type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ());
-// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}void @test_ScalarPairLottaNesting(ptr sret({{[^,]*}})
+// CHECK-SAME: %_0, i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting {
     loop {}
diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs
index a1c081d7d61..b3c67a59730 100644
--- a/tests/codegen/union-abi.rs
+++ b/tests/codegen/union-abi.rs
@@ -1,9 +1,13 @@
 //@ ignore-emscripten vectors passed directly
 //@ compile-flags: -O -C no-prepopulate-passes
 // 32-bit x86 returns `f32` differently to avoid the x87 stack.
-//@ revisions: x86 other
+// 32-bit systems will return 128bit values using a return area pointer.
+//@ revisions: x86 bit32 bit64
 //@[x86] only-x86
-//@[other] ignore-x86
+//@[bit32] ignore-x86
+//@[bit32] only-32bit
+//@[bit64] ignore-x86
+//@[bit64] only-64bit
 
 // This test that using union forward the abi of the inner type, as
 // discussed in #54668
@@ -71,8 +75,9 @@ pub union UnionF32 {
     a: f32,
 }
 
-// other: define {{(dso_local )?}}float @test_UnionF32(float %_1)
 // x86: define {{(dso_local )?}}i32 @test_UnionF32(float %_1)
+// bit32: define {{(dso_local )?}}float @test_UnionF32(float %_1)
+// bit64: define {{(dso_local )?}}float @test_UnionF32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32(_: UnionF32) -> UnionF32 {
     loop {}
@@ -83,8 +88,9 @@ pub union UnionF32F32 {
     b: f32,
 }
 
-// other: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
 // x86: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1)
+// bit32: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
+// bit64: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 {
     loop {}
@@ -104,7 +110,9 @@ pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 {
 pub union UnionU128 {
     a: u128,
 }
-// CHECK: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
+// x86: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
+// bit32: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1)
+// bit64: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
 #[no_mangle]
 pub fn test_UnionU128(_: UnionU128) -> UnionU128 {
     loop {}
diff --git a/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr
index 24409b32ad3..2c6c8ee5d19 100644
--- a/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr
+++ b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr
@@ -2,18 +2,16 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
   --> $DIR/impl-trait-return-missing-constraint.rs:25:13
    |
 LL | fn bar() -> impl Bar {
-   |             -------- the expected opaque type
+   |             -------- the found opaque type
 ...
 LL | fn baz() -> impl Bar<Item = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32`
+   |             ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
 LL |
 LL |     bar()
    |     ----- return type was inferred to be `impl Bar` here
    |
-   = note: expected associated type `<impl Bar as Foo>::Item`
-                         found type `i32`
-   = help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` or calling a method that returns `<impl Bar as Foo>::Item`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+   = note:         expected type `i32`
+           found associated type `<impl Bar as Foo>::Item`
 help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
    |
 LL | fn bar() -> impl Bar<Item = i32> {
diff --git a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
index 08927196037..64dc3a8b1f8 100644
--- a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
+++ b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
@@ -22,10 +22,10 @@ error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-
   --> $DIR/type-mismatch-signature-deduction.rs:5:13
    |
 LL | fn foo() -> impl Coroutine<Return = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<{integer}, _>`, found `i32`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `Result<{integer}, _>`
    |
-   = note: expected enum `Result<{integer}, _>`
-              found type `i32`
+   = note: expected type `i32`
+              found enum `Result<{integer}, _>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index a686b913c55..8c01b61191e 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -29,10 +29,7 @@ error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Tex
   --> $DIR/as_expression.rs:57:5
    |
 LL |     SelectInt.check("bar");
-   |     ^^^^^^^^^^^^^^^^^^^^^^ expected `Integer`, found `Text`
-   |
-   = note: expected struct `Integer`
-              found struct `Text`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr
index fcac9ac34db..fc124bd1171 100644
--- a/tests/ui/impl-trait/bound-normalization-fail.stderr
+++ b/tests/ui/impl-trait/bound-normalization-fail.stderr
@@ -7,13 +7,13 @@ LL |
 LL |         Foo(())
    |         ------- return type was inferred to be `Foo<()>` here
    |
-note: expected this to be `()`
+note: expected this to be `<T as impl_trait::Trait>::Assoc`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note:    expected unit type `()`
-           found associated type `<T as impl_trait::Trait>::Assoc`
+   = note: expected associated type `<T as impl_trait::Trait>::Assoc`
+                    found unit type `()`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
@@ -28,13 +28,13 @@ LL |
 LL |         Foo(())
    |         ------- return type was inferred to be `Foo<()>` here
    |
-note: expected this to be `()`
+note: expected this to be `<T as lifetimes::Trait<'a>>::Assoc`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note:    expected unit type `()`
-           found associated type `<T as lifetimes::Trait<'a>>::Assoc`
+   = note: expected associated type `<T as lifetimes::Trait<'a>>::Assoc`
+                    found unit type `()`
 help: consider constraining the associated type `<T as lifetimes::Trait<'a>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
index 6f1ac4bce43..3c737f095ce 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
@@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
   --> $DIR/default-body-type-err.rs:4:22
    |
 LL |     fn lol(&self) -> impl Deref<Target = String> {
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `i32`
 LL |
 LL |         &1i32
    |         ----- return type was inferred to be `&i32` here
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr
index 2cf6b94dd9d..27b4b712830 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr
@@ -16,7 +16,7 @@ error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be
   --> $DIR/issue-78722-2.rs:11:30
    |
 LL |         fn concrete_use() -> F {
-   |                              ^ expected `()`, found `u8`
+   |                              ^ expected `u8`, found `()`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr
index 3642000597f..109bda0c5cd 100644
--- a/tests/ui/impl-trait/issues/issue-78722.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722.stderr
@@ -12,7 +12,7 @@ error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:18}` to be a
   --> $DIR/issue-78722.rs:8:30
    |
 LL |         fn concrete_use() -> F {
-   |                              ^ expected `()`, found `u8`
+   |                              ^ expected `u8`, found `()`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/precise-capturing/capturing-implicit.rs b/tests/ui/impl-trait/precise-capturing/capturing-implicit.rs
new file mode 100644
index 00000000000..5ef8542d862
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/capturing-implicit.rs
@@ -0,0 +1,15 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+#![feature(rustc_attrs)]
+#![feature(type_alias_impl_trait)]
+#![rustc_variance_of_opaques]
+
+fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
+    //~^ ERROR ['_: o]
+    //~| ERROR ['_: o]
+    //~| ERROR `impl Trait` captures lifetime parameter
+    [*x]
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/capturing-implicit.stderr b/tests/ui/impl-trait/precise-capturing/capturing-implicit.stderr
new file mode 100644
index 00000000000..b14ed20bd36
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/capturing-implicit.stderr
@@ -0,0 +1,22 @@
+error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+  --> $DIR/capturing-implicit.rs:8:11
+   |
+LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
+   |           ^       -------------------------------------------- lifetime captured due to being mentioned in the bounds of the `impl Trait`
+   |           |
+   |           this lifetime parameter is captured
+
+error: ['_: o]
+  --> $DIR/capturing-implicit.rs:8:19
+   |
+LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: ['_: o]
+  --> $DIR/capturing-implicit.rs:8:44
+   |
+LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
+   |                                            ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
index c4ea4474066..fa71adc6380 100644
--- a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
+++ b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
@@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
 LL | fn test() -> impl Test {
    |              ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()`
    |
-note: expected this to be `u8`
+note: expected this to be `()`
   --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18
    |
 LL |     type Assoc = u8;
diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr
index f1b6b6ba17e..9535ea57430 100644
--- a/tests/ui/issues/issue-33941.stderr
+++ b/tests/ui/issues/issue-33941.stderr
@@ -20,10 +20,10 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)`
    |
-   = note:  expected tuple `(&_, &_)`
-           found reference `&_`
+   = note: expected reference `&_`
+                  found tuple `(&_, &_)`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
index 1ea2d48b474..9164e4696eb 100644
--- a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
+++ b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
@@ -2,10 +2,10 @@ error[E0271]: type mismatch resolving `<Rc<Apple> as Deref>::Target == Rc<Apple>
   --> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29
    |
 LL |     let _ = Pin::new(Apple) == Rc::pin(Apple);
-   |                             ^^ expected `Apple`, found `Rc<Apple>`
+   |                             ^^ expected `Rc<Apple>`, found `Apple`
    |
-   = note: expected struct `Apple`
-              found struct `Rc<Apple>`
+   = note: expected struct `Rc<Apple>`
+              found struct `Apple`
    = note: required for `Pin<Apple>` to implement `PartialEq<Pin<Rc<Apple>>>`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr
index 4704e9ef835..9b4fab68102 100644
--- a/tests/ui/lint/issue-106991.stderr
+++ b/tests/ui/lint/issue-106991.stderr
@@ -2,7 +2,7 @@ error[E0271]: expected `foo` to be a fn item that returns `i32`, but it returns
   --> $DIR/issue-106991.rs:5:13
    |
 LL | fn bar() -> impl Iterator<Item = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `i32`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
    |
    = note: required for `Map<std::slice::IterMut<'_, Vec<u8>>, for<'a> fn(&'a mut Vec<u8>) {foo}>` to implement `Iterator`
 
diff --git a/tests/ui/precondition-checks/layout.rs b/tests/ui/precondition-checks/layout.rs
index 4fd1bbc4a99..4ee66cc9328 100644
--- a/tests/ui/precondition-checks/layout.rs
+++ b/tests/ui/precondition-checks/layout.rs
@@ -2,8 +2,6 @@
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires
 //@ revisions: toolarge badalign
-//@[toolarge] compile-flags: --cfg toolarge
-//@[badalign] compile-flags: --cfg badalign
 
 fn main() {
     unsafe {
diff --git a/tests/ui/range/misleading-field-access-hint.rs b/tests/ui/range/misleading-field-access-hint.rs
new file mode 100644
index 00000000000..252f1a4833c
--- /dev/null
+++ b/tests/ui/range/misleading-field-access-hint.rs
@@ -0,0 +1,8 @@
+// Check if rustc still displays the misleading hint to write `.` instead of `..`
+fn main() {
+    let width = 10;
+    // ...
+    for _ in 0..w {
+        //~^ ERROR cannot find value `w`
+    }
+}
diff --git a/tests/ui/range/misleading-field-access-hint.stderr b/tests/ui/range/misleading-field-access-hint.stderr
new file mode 100644
index 00000000000..9b112a5fdd8
--- /dev/null
+++ b/tests/ui/range/misleading-field-access-hint.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `w` in this scope
+  --> $DIR/misleading-field-access-hint.rs:5:17
+   |
+LL |     for _ in 0..w {
+   |                 ^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
index d6251fcb768..4dc5932feab 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
@@ -27,3 +27,14 @@ pub enum NonExhaustiveVariants {
     #[non_exhaustive] Tuple(u32),
     #[non_exhaustive] Struct { field: u32 }
 }
+
+// Note the absence of repr(C): it's not necessary, and recent C code can now use repr hints too.
+#[repr(u32)]
+#[non_exhaustive]
+pub enum NonExhaustiveCLikeEnum {
+    One = 1,
+    Two = 2,
+    Three = 3,
+    Four = 4,
+    Five = 5,
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
index 7a9b465bb56..c7f470fb787 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -6,7 +6,10 @@ extern crate types;
 // This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered
 // improper.
 
-use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct};
+use types::{
+    NonExhaustiveCLikeEnum, NonExhaustiveEnum, NonExhaustiveVariants,
+    NormalStruct, TupleStruct, UnitStruct,
+};
 
 extern "C" {
     pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
@@ -21,4 +24,9 @@ extern "C" {
     //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
 }
 
+// These should pass without remark, as they're C-compatible, despite being "non-exhaustive".
+extern "C" {
+    pub fn non_exhaustive_c_compat_enum(_: NonExhaustiveCLikeEnum);
+}
+
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
index 43c8e1015e6..afc3d3838ad 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
-  --> $DIR/extern_crate_improper.rs:12:35
+  --> $DIR/extern_crate_improper.rs:15:35
    |
 LL |     pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
    |                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -12,7 +12,7 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `NormalStruct`, which is not FFI-safe
-  --> $DIR/extern_crate_improper.rs:14:44
+  --> $DIR/extern_crate_improper.rs:17:44
    |
 LL |     pub fn non_exhaustive_normal_struct(_: NormalStruct);
    |                                            ^^^^^^^^^^^^ not FFI-safe
@@ -20,7 +20,7 @@ LL |     pub fn non_exhaustive_normal_struct(_: NormalStruct);
    = note: this struct is non-exhaustive
 
 error: `extern` block uses type `UnitStruct`, which is not FFI-safe
-  --> $DIR/extern_crate_improper.rs:16:42
+  --> $DIR/extern_crate_improper.rs:19:42
    |
 LL |     pub fn non_exhaustive_unit_struct(_: UnitStruct);
    |                                          ^^^^^^^^^^ not FFI-safe
@@ -28,7 +28,7 @@ LL |     pub fn non_exhaustive_unit_struct(_: UnitStruct);
    = note: this struct is non-exhaustive
 
 error: `extern` block uses type `TupleStruct`, which is not FFI-safe
-  --> $DIR/extern_crate_improper.rs:18:43
+  --> $DIR/extern_crate_improper.rs:21:43
    |
 LL |     pub fn non_exhaustive_tuple_struct(_: TupleStruct);
    |                                           ^^^^^^^^^^^ not FFI-safe
@@ -36,7 +36,7 @@ LL |     pub fn non_exhaustive_tuple_struct(_: TupleStruct);
    = note: this struct is non-exhaustive
 
 error: `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
-  --> $DIR/extern_crate_improper.rs:20:38
+  --> $DIR/extern_crate_improper.rs:23:38
    |
 LL |     pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
    |                                      ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/sanitizer/cfg.rs b/tests/ui/sanitizer/cfg.rs
index b1ba17d5713..7b8f285e41a 100644
--- a/tests/ui/sanitizer/cfg.rs
+++ b/tests/ui/sanitizer/cfg.rs
@@ -5,19 +5,19 @@
 //@ revisions: address cfi kcfi leak memory thread
 //@compile-flags: -Ctarget-feature=-crt-static
 //@[address]needs-sanitizer-address
-//@[address]compile-flags: -Zsanitizer=address --cfg address
+//@[address]compile-flags: -Zsanitizer=address
 //@[cfi]needs-sanitizer-cfi
-//@[cfi]compile-flags:     -Zsanitizer=cfi     --cfg cfi
+//@[cfi]compile-flags:     -Zsanitizer=cfi
 //@[cfi]compile-flags:     -Clto -Ccodegen-units=1
 //@[kcfi]needs-llvm-components: x86
-//@[kcfi]compile-flags:    -Zsanitizer=kcfi    --cfg kcfi --target x86_64-unknown-none
+//@[kcfi]compile-flags:    -Zsanitizer=kcfi --target x86_64-unknown-none
 //@[kcfi]compile-flags:    -C panic=abort
 //@[leak]needs-sanitizer-leak
-//@[leak]compile-flags:    -Zsanitizer=leak    --cfg leak
+//@[leak]compile-flags:    -Zsanitizer=leak
 //@[memory]needs-sanitizer-memory
-//@[memory]compile-flags:  -Zsanitizer=memory  --cfg memory
+//@[memory]compile-flags:  -Zsanitizer=memory
 //@[thread]needs-sanitizer-thread
-//@[thread]compile-flags:  -Zsanitizer=thread  --cfg thread
+//@[thread]compile-flags:  -Zsanitizer=thread
 
 #![feature(cfg_sanitize, no_core, lang_items)]
 #![crate_type="lib"]
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed
index 02d667d9844..b7b94a05121 100644
--- a/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed
@@ -4,7 +4,7 @@
 // For some reason, Rust 2018 or higher is required to reproduce the bug.
 //@ run-rustfix
 //@ revisions: no_std std
-//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+//@ [no_std]compile-flags: -C panic=abort
 #![cfg_attr(no_std, no_std)]
 
 use core::num::NonZero;
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.rs b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
index 5bb5bfe176b..4cfc9a6bf74 100644
--- a/tests/ui/suggestions/core-std-import-order-issue-83564.rs
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
@@ -4,7 +4,7 @@
 // For some reason, Rust 2018 or higher is required to reproduce the bug.
 //@ run-rustfix
 //@ revisions: no_std std
-//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+//@ [no_std]compile-flags: -C panic=abort
 #![cfg_attr(no_std, no_std)]
 
 fn main() {
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed
index 3492b42c685..84c7c19d19e 100644
--- a/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed
@@ -4,7 +4,7 @@
 // For some reason, Rust 2018 or higher is required to reproduce the bug.
 //@ run-rustfix
 //@ revisions: no_std std
-//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+//@ [no_std]compile-flags: -C panic=abort
 #![cfg_attr(no_std, no_std)]
 
 use std::num::NonZero;
diff --git a/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs
new file mode 100644
index 00000000000..03b736e60b6
--- /dev/null
+++ b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let val = 2;
+    let ptr = std::ptr::addr_of!(val);
+    unsafe {
+        *ptr = 3; //~ ERROR cannot assign to `*ptr`, which is behind a `*const` pointer
+    }
+}
diff --git a/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr
new file mode 100644
index 00000000000..5396db7940f
--- /dev/null
+++ b/tests/ui/suggestions/dont_suggest_raw_pointer_syntax-issue-127562.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to `*ptr`, which is behind a `*const` pointer
+  --> $DIR/dont_suggest_raw_pointer_syntax-issue-127562.rs:5:9
+   |
+LL |         *ptr = 3;
+   |         ^^^^^^^^ `ptr` is a `*const` pointer, so the data it refers to cannot be written
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr
index 5dec2071846..729523cde55 100644
--- a/tests/ui/suggestions/trait-hidden-method.stderr
+++ b/tests/ui/suggestions/trait-hidden-method.stderr
@@ -8,14 +8,14 @@ error[E0271]: expected `Box<dyn Iterator>` to be an iterator that yields `u32`,
   --> $DIR/trait-hidden-method.rs:3:32
    |
 LL | pub fn i_can_has_iterator() -> impl Iterator<Item = u32> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `u32`
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
 ...
 LL |     Box::new(1..=10) as Box<dyn Iterator>
    |     ------------------------------------- return type was inferred to be `Box<dyn Iterator>` here
    |
-   = note: expected associated type `<dyn Iterator as Iterator>::Item`
-                         found type `u32`
-   = help: consider constraining the associated type `<dyn Iterator as Iterator>::Item` to `u32` or calling a method that returns `<dyn Iterator as Iterator>::Item`
+   = note:         expected type `u32`
+           found associated type `<dyn Iterator as Iterator>::Item`
+   = help: consider constraining the associated type `<dyn Iterator as Iterator>::Item` to `u32`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr
index e47da338736..bc89842d16a 100644
--- a/tests/ui/traits/next-solver/async.fail.stderr
+++ b/tests/ui/traits/next-solver/async.fail.stderr
@@ -2,12 +2,10 @@ error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future
   --> $DIR/async.rs:12:17
    |
 LL |     needs_async(async {});
-   |     ----------- ^^^^^^^^ expected `()`, found `i32`
+   |     ----------- ^^^^^^^^ expected `i32`, found `()`
    |     |
    |     required by a bound introduced by this call
    |
-   = note: expected unit type `()`
-                   found type `i32`
 note: required by a bound in `needs_async`
   --> $DIR/async.rs:8:31
    |
diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr
index 043cbdff9ab..39849d4c865 100644
--- a/tests/ui/traits/next-solver/more-object-bound.stderr
+++ b/tests/ui/traits/next-solver/more-object-bound.stderr
@@ -2,19 +2,14 @@ error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::
   --> $DIR/more-object-bound.rs:12:5
    |
 LL | fn transmute<A, B>(x: A) -> B {
-   |              -  -
-   |              |  |
-   |              |  expected type parameter
-   |              |  found type parameter
+   |              -  - expected type parameter
+   |              |
    |              found type parameter
-   |              expected type parameter
 LL |     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `A`, found type parameter `B`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
    |
-   = note: expected type parameter `A`
-              found type parameter `B`
-   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
-   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+   = note: expected type parameter `B`
+              found type parameter `A`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    = note: required because it appears within the type `dyn Trait<A = A, B = B>`
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index 6c41b42dc64..e9e6255cd2a 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -15,13 +15,13 @@ error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str
   --> $DIR/try-block-bad-type.rs:12:9
    |
 LL |         ""
-   |         ^^ expected `i32`, found `&str`
+   |         ^^ expected `&str`, found `i32`
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()`
   --> $DIR/try-block-bad-type.rs:15:39
    |
 LL |     let res: Result<i32, i32> = try { };
-   |                                       ^ expected `i32`, found `()`
+   |                                       ^ expected `()`, found `i32`
 
 error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
   --> $DIR/try-block-bad-type.rs:17:25
diff --git a/tests/ui/try-block/try-block-type-error.stderr b/tests/ui/try-block/try-block-type-error.stderr
index 2cdb5fdee79..07b1209de9d 100644
--- a/tests/ui/try-block/try-block-type-error.stderr
+++ b/tests/ui/try-block/try-block-type-error.stderr
@@ -2,18 +2,13 @@ error[E0271]: type mismatch resolving `<Option<f32> as Try>::Output == {integer}
   --> $DIR/try-block-type-error.rs:10:9
    |
 LL |         42
-   |         ^^ expected `f32`, found integer
-   |
-help: use a float literal
-   |
-LL |         42.0
-   |           ++
+   |         ^^ expected integer, found `f32`
 
 error[E0271]: type mismatch resolving `<Option<i32> as Try>::Output == ()`
   --> $DIR/try-block-type-error.rs:16:5
    |
 LL |     };
-   |     ^ expected `i32`, found `()`
+   |     ^ expected `()`, found `i32`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
index 21d9ed93366..b05121a489e 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -2,18 +2,18 @@ error[E0271]: type mismatch resolving `<() as Proj>::Assoc == i32`
   --> $DIR/hidden_type_mismatch.rs:43:9
    |
 LL |     pub type Sep = impl Sized + std::fmt::Display;
-   |                    ------------------------------ the expected opaque type
+   |                    ------------------------------ the found opaque type
 ...
 LL |         Bar { inner: 1i32, _marker: () }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Proj>::Assoc == i32`
    |
-note: expected this to be `Sep`
+note: expected this to be `i32`
   --> $DIR/hidden_type_mismatch.rs:20:22
    |
 LL |         type Assoc = sus::Sep;
    |                      ^^^^^^^^
-   = note: expected opaque type `Sep`
-                     found type `i32`
+   = note:     expected type `i32`
+           found opaque type `Sep`
 note: required for `Bar<()>` to implement `Copy`
   --> $DIR/hidden_type_mismatch.rs:32:39
    |
diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr
index 4c2020becbe..f41b781f963 100644
--- a/tests/ui/type-alias-impl-trait/issue-94429.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr
@@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:18:9: 18:
   --> $DIR/issue-94429.rs:15:26
    |
 LL |     fn run(&mut self) -> Self::Coro {
-   |                          ^^^^^^^^^^ expected integer, found `()`
+   |                          ^^^^^^^^^^ expected `()`, found integer
 
 error: aborting due to 1 previous error