about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs14
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs26
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs13
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs16
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs351
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs18
-rw-r--r--library/alloc/src/string.rs10
-rw-r--r--library/core/src/cmp.rs74
-rw-r--r--library/core/src/hint.rs1
-rw-r--r--library/core/src/intrinsics.rs53
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/mem/mod.rs1
-rw-r--r--library/core/src/num/int_macros.rs5
-rw-r--r--library/core/src/num/uint_macros.rs5
-rw-r--r--library/core/src/ptr/const_ptr.rs11
-rw-r--r--library/core/src/ptr/mut_ptr.rs13
-rw-r--r--library/panic_abort/src/lib.rs3
-rw-r--r--library/proc_macro/src/lib.rs8
-rw-r--r--library/std/src/io/mod.rs1
-rw-r--r--library/std/src/io/tests.rs19
-rw-r--r--library/std/src/sys/solid/abi/mod.rs26
-rw-r--r--library/std/src/sys/solid/mod.rs15
-rw-r--r--library/std/src/sys/solid/os.rs9
-rw-r--r--src/test/run-make/export-executable-symbols/Makefile11
-rw-r--r--src/test/run-make/export-executable-symbols/main.rs8
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.rs38
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.stderr68
-rw-r--r--src/test/ui/process/nofile-limit.rs2
m---------src/tools/miri16
37 files changed, 320 insertions, 561 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 878a670cba3..48d24ecf412 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2082,7 +2082,12 @@ fn add_order_independent_options(
         // sections to ensure we have all the data for PGO.
         let keep_metadata =
             crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
-        cmd.gc_sections(keep_metadata);
+        if crate_type != CrateType::Executable || !sess.opts.unstable_opts.export_executable_symbols
+        {
+            cmd.gc_sections(keep_metadata);
+        } else {
+            cmd.no_gc_sections();
+        }
     }
 
     cmd.set_output_kind(link_output_kind, out_filename);
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index d4a9db4af23..8e5ac9da4ac 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -640,9 +640,14 @@ impl<'a> Linker for GccLinker<'a> {
 
     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
         // Symbol visibility in object files typically takes care of this.
-        if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none()
-        {
-            return;
+        if crate_type == CrateType::Executable {
+            let should_export_executable_symbols =
+                self.sess.opts.unstable_opts.export_executable_symbols;
+            if self.sess.target.override_export_symbols.is_none()
+                && !should_export_executable_symbols
+            {
+                return;
+            }
         }
 
         // We manually create a list of exported symbols to ensure we don't expose any more.
@@ -969,7 +974,11 @@ impl<'a> Linker for MsvcLinker<'a> {
     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
         // Symbol visibility takes care of this typically
         if crate_type == CrateType::Executable {
-            return;
+            let should_export_executable_symbols =
+                self.sess.opts.unstable_opts.export_executable_symbols;
+            if !should_export_executable_symbols {
+                return;
+            }
         }
 
         let path = tmpdir.join("lib.def");
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 58cee0c8bb0..268c4d76503 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -435,18 +435,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             LocalRef::Place(place) => place,
             LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
             LocalRef::Operand(..) => {
-                if let Some(elem) = place_ref
-                    .projection
-                    .iter()
-                    .enumerate()
-                    .find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
-                {
-                    base = elem.0 + 1;
+                if place_ref.has_deref() {
+                    base = 1;
                     let cg_base = self.codegen_consume(
                         bx,
-                        mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref },
+                        mir::PlaceRef { projection: &place_ref.projection[..0], ..place_ref },
                     );
-
                     cg_base.deref(bx.cx())
                 } else {
                     bug!("using operand local {:?} as place", place_ref);
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index bfdef2dc0e8..ecad0518533 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -249,6 +249,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("bulk-memory", Some(sym::wasm_target_feature)),
     ("mutable-globals", Some(sym::wasm_target_feature)),
     ("reference-types", Some(sym::wasm_target_feature)),
+    ("sign-ext", Some(sym::wasm_target_feature)),
 ];
 
 const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 42de0dbdca9..d563e35f910 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -571,8 +571,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 // Now determine the actual method to call. We can do that in two different ways and
                 // compare them to ensure everything fits.
-                let ty::VtblEntry::Method(fn_inst) = self.get_vtable_entries(vptr)?[idx] else {
-                    span_bug!(self.cur_span(), "dyn call index points at something that is not a method")
+                let Some(ty::VtblEntry::Method(fn_inst)) = self.get_vtable_entries(vptr)?.get(idx).copied() else {
+                    throw_ub_format!("`dyn` call trying to call something that is not a method")
                 };
                 if cfg!(debug_assertions) {
                     let tcx = *self.tcx;
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index d07e17f6792..0a0eb99cd92 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -733,6 +733,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
     tracked!(drop_tracking, true);
+    tracked!(export_executable_symbols, true);
     tracked!(dual_proc_macros, true);
     tracked!(dwarf_version, Some(5));
     tracked!(emit_thin_lto, false);
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 702cc48ff7b..f7311ebdabf 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1461,6 +1461,14 @@ impl<'tcx> Place<'tcx> {
         self.projection.iter().any(|elem| elem.is_indirect())
     }
 
+    /// If MirPhase >= Derefered and if projection contains Deref,
+    /// It's guaranteed to be in the first place
+    pub fn has_deref(&self) -> bool {
+        // To make sure this is not accidently used in wrong mir phase
+        debug_assert!(!self.projection[1..].contains(&PlaceElem::Deref));
+        self.projection.first() == Some(&PlaceElem::Deref)
+    }
+
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
     #[inline(always)]
@@ -1533,6 +1541,12 @@ impl<'tcx> PlaceRef<'tcx> {
         }
     }
 
+    /// If MirPhase >= Derefered and if projection contains Deref,
+    /// It's guaranteed to be in the first place
+    pub fn has_deref(&self) -> bool {
+        self.projection.first() == Some(&PlaceElem::Deref)
+    }
+
     /// If this place represents a local variable like `_X` with no
     /// projections, return `Some(_X)`.
     #[inline]
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index b91ae083cf5..9c5896c4e4a 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -15,22 +15,9 @@ pub struct AddRetag;
 /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
 /// copies.  Data races are UB.)
 fn is_stable(place: PlaceRef<'_>) -> bool {
-    place.projection.iter().all(|elem| {
-        match elem {
-            // Which place this evaluates to can change with any memory write,
-            // so cannot assume this to be stable.
-            ProjectionElem::Deref => false,
-            // Array indices are interesting, but MIR building generates a *fresh*
-            // temporary for every array access, so the index cannot be changed as
-            // a side-effect.
-            ProjectionElem::Index { .. } |
-            // The rest is completely boring, they just offset by a constant.
-            ProjectionElem::Field { .. } |
-            ProjectionElem::ConstantIndex { .. } |
-            ProjectionElem::Subslice { .. } |
-            ProjectionElem::Downcast { .. } => true,
-        }
-    })
+    // Which place this evaluates to can change with any memory write,
+    // so cannot assume deref to be stable.
+    !place.has_deref()
 }
 
 /// Determine whether this type may contain a reference (or box), and thus needs retagging.
@@ -91,11 +78,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         };
         let place_base_raw = |place: &Place<'tcx>| {
             // If this is a `Deref`, get the type of what we are deref'ing.
-            let deref_base =
-                place.projection.iter().rposition(|p| matches!(p, ProjectionElem::Deref));
-            if let Some(deref_base) = deref_base {
-                let base_proj = &place.projection[..deref_base];
-                let ty = Place::ty_from(place.local, base_proj, &*local_decls, tcx).ty;
+            if place.has_deref() {
+                let ty = &local_decls[place.local].ty;
                 ty.is_unsafe_ptr()
             } else {
                 // Not a deref, and thus not raw.
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 2eb38941f1a..c21c1efe991 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -36,13 +36,16 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| {
         // FIXME: when we make this a hard error, this should have its
         // own error code.
-        let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
-            "`#[derive]` can't be used on a `#[repr(packed)]` struct with \
-             type or const parameters (error E0133)"
+        let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
+            "with type or const parameters"
         } else {
-            "`#[derive]` can't be used on a `#[repr(packed)]` struct that \
-             does not derive Copy (error E0133)"
+            "that does not derive `Copy`"
         };
+        let message = format!(
+            "`{}` can't be derived on this `#[repr(packed)]` struct {} (error E0133)",
+            tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
+            extra
+        );
         lint.build(message).emit();
     });
 }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index f6484a9b54d..85ad6b8f2fe 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -155,18 +155,18 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
     }
 }
 
-struct ConstPropMachine<'mir, 'tcx> {
+pub struct ConstPropMachine<'mir, 'tcx> {
     /// The virtual call stack.
     stack: Vec<Frame<'mir, 'tcx>>,
     /// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
-    written_only_inside_own_block_locals: FxHashSet<Local>,
+    pub written_only_inside_own_block_locals: FxHashSet<Local>,
     /// Locals that need to be cleared after every block terminates.
-    only_propagate_inside_block_locals: BitSet<Local>,
-    can_const_prop: IndexVec<Local, ConstPropMode>,
+    pub only_propagate_inside_block_locals: BitSet<Local>,
+    pub can_const_prop: IndexVec<Local, ConstPropMode>,
 }
 
 impl ConstPropMachine<'_, '_> {
-    fn new(
+    pub fn new(
         only_propagate_inside_block_locals: BitSet<Local>,
         can_const_prop: IndexVec<Local, ConstPropMode>,
     ) -> Self {
@@ -816,7 +816,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
 /// The mode that `ConstProp` is allowed to run in for a given `Local`.
 #[derive(Clone, Copy, Debug, PartialEq)]
-enum ConstPropMode {
+pub enum ConstPropMode {
     /// The `Local` can be propagated into and reads of this `Local` can also be propagated.
     FullConstProp,
     /// The `Local` can only be propagated into and from its own block.
@@ -828,7 +828,7 @@ enum ConstPropMode {
     NoPropagation,
 }
 
-struct CanConstProp {
+pub struct CanConstProp {
     can_const_prop: IndexVec<Local, ConstPropMode>,
     // False at the beginning. Once set, no more assignments are allowed to that local.
     found_assignment: BitSet<Local>,
@@ -838,7 +838,7 @@ struct CanConstProp {
 
 impl CanConstProp {
     /// Returns true if `local` can be propagated
-    fn check<'tcx>(
+    pub fn check<'tcx>(
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
         body: &Body<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 97b1433f5d2..3ae6a88a140 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -1,19 +1,24 @@
 //! Propagates constants for early reporting of statically known
 //! assertion failures
 
-use std::cell::Cell;
-
-use rustc_ast::Mutability;
-use rustc_data_structures::fx::FxHashSet;
+use crate::const_prop::CanConstProp;
+use crate::const_prop::ConstPropMachine;
+use crate::const_prop::ConstPropMode;
+use crate::MirLint;
+use rustc_const_eval::const_eval::ConstEvalErr;
+use rustc_const_eval::interpret::{
+    self, InterpCx, InterpResult, LocalState, LocalValue, MemoryKind, OpTy, Scalar,
+    ScalarMaybeUninit, StackPopCleanup,
+};
 use rustc_hir::def::DefKind;
 use rustc_hir::HirId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
-use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{
-    AssertKind, BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind,
-    Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
-    StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
+    AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place,
+    Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
+    TerminatorKind, UnOp, RETURN_PLACE,
 };
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -22,42 +27,15 @@ use rustc_middle::ty::{
     TypeVisitable,
 };
 use rustc_session::lint;
-use rustc_span::{def_id::DefId, Span};
+use rustc_span::Span;
 use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
-use rustc_target::spec::abi::Abi as CallAbi;
 use rustc_trait_selection::traits;
-
-use crate::MirLint;
-use rustc_const_eval::const_eval::ConstEvalErr;
-use rustc_const_eval::interpret::{
-    self, compile_time_machine, AllocId, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
-    LocalState, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
-    StackPopCleanup, StackPopUnwind,
-};
+use std::cell::Cell;
 
 /// The maximum number of bytes that we'll allocate space for a local or the return value.
 /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
 /// Severely regress performance.
 const MAX_ALLOC_LIMIT: u64 = 1024;
-
-/// Macro for machine-specific `InterpError` without allocation.
-/// (These will never be shown to the user, but they help diagnose ICEs.)
-macro_rules! throw_machine_stop_str {
-    ($($tt:tt)*) => {{
-        // We make a new local type for it. The type itself does not carry any information,
-        // but its vtable (for the `MachineStopType` trait) does.
-        struct Zst;
-        // Printing this type shows the desired string.
-        impl std::fmt::Display for Zst {
-            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-                write!(f, $($tt)*)
-            }
-        }
-        impl rustc_middle::mir::interpret::MachineStopType for Zst {}
-        throw_machine_stop!(Zst)
-    }};
-}
-
 pub struct ConstProp;
 
 impl<'tcx> MirLint<'tcx> for ConstProp {
@@ -151,172 +129,6 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
     }
 }
 
-struct ConstPropMachine<'mir, 'tcx> {
-    /// The virtual call stack.
-    stack: Vec<Frame<'mir, 'tcx>>,
-    /// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
-    written_only_inside_own_block_locals: FxHashSet<Local>,
-    /// Locals that need to be cleared after every block terminates.
-    only_propagate_inside_block_locals: BitSet<Local>,
-    can_const_prop: IndexVec<Local, ConstPropMode>,
-}
-
-impl ConstPropMachine<'_, '_> {
-    fn new(
-        only_propagate_inside_block_locals: BitSet<Local>,
-        can_const_prop: IndexVec<Local, ConstPropMode>,
-    ) -> Self {
-        Self {
-            stack: Vec::new(),
-            written_only_inside_own_block_locals: Default::default(),
-            only_propagate_inside_block_locals,
-            can_const_prop,
-        }
-    }
-}
-
-impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
-    compile_time_machine!(<'mir, 'tcx>);
-    const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
-
-    type MemoryKind = !;
-
-    fn load_mir(
-        _ecx: &InterpCx<'mir, 'tcx, Self>,
-        _instance: ty::InstanceDef<'tcx>,
-    ) -> InterpResult<'tcx, &'tcx Body<'tcx>> {
-        throw_machine_stop_str!("calling functions isn't supported in ConstProp")
-    }
-
-    fn find_mir_or_eval_fn(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _instance: ty::Instance<'tcx>,
-        _abi: CallAbi,
-        _args: &[OpTy<'tcx>],
-        _destination: &PlaceTy<'tcx>,
-        _target: Option<BasicBlock>,
-        _unwind: StackPopUnwind,
-    ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
-        Ok(None)
-    }
-
-    fn call_intrinsic(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _instance: ty::Instance<'tcx>,
-        _args: &[OpTy<'tcx>],
-        _destination: &PlaceTy<'tcx>,
-        _target: Option<BasicBlock>,
-        _unwind: StackPopUnwind,
-    ) -> InterpResult<'tcx> {
-        throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
-    }
-
-    fn assert_panic(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _msg: &rustc_middle::mir::AssertMessage<'tcx>,
-        _unwind: Option<rustc_middle::mir::BasicBlock>,
-    ) -> InterpResult<'tcx> {
-        bug!("panics terminators are not evaluated in ConstProp")
-    }
-
-    fn binary_ptr_op(
-        _ecx: &InterpCx<'mir, 'tcx, Self>,
-        _bin_op: BinOp,
-        _left: &ImmTy<'tcx>,
-        _right: &ImmTy<'tcx>,
-    ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
-        // We can't do this because aliasing of memory can differ between const eval and llvm
-        throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp")
-    }
-
-    fn access_local<'a>(
-        frame: &'a Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
-        local: Local,
-    ) -> InterpResult<'tcx, &'a interpret::Operand<Self::Provenance>> {
-        let l = &frame.locals[local];
-
-        if matches!(
-            l.value,
-            LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit))
-        ) {
-            // For us "uninit" means "we don't know its value, might be initiailized or not".
-            // So stop here.
-            throw_machine_stop_str!("tried to access a local with unknown value")
-        }
-
-        l.access()
-    }
-
-    fn access_local_mut<'a>(
-        ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
-        frame: usize,
-        local: Local,
-    ) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::Provenance>> {
-        if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation {
-            throw_machine_stop_str!("tried to write to a local that is marked as not propagatable")
-        }
-        if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) {
-            trace!(
-                "mutating local {:?} which is restricted to its block. \
-                Will remove it from const-prop after block is finished.",
-                local
-            );
-            ecx.machine.written_only_inside_own_block_locals.insert(local);
-        }
-        ecx.machine.stack[frame].locals[local].access_mut()
-    }
-
-    fn before_access_global(
-        _tcx: TyCtxt<'tcx>,
-        _machine: &Self,
-        _alloc_id: AllocId,
-        alloc: ConstAllocation<'tcx, Self::Provenance, Self::AllocExtra>,
-        _static_def_id: Option<DefId>,
-        is_write: bool,
-    ) -> InterpResult<'tcx> {
-        if is_write {
-            throw_machine_stop_str!("can't write to global");
-        }
-        // If the static allocation is mutable, then we can't const prop it as its content
-        // might be different at runtime.
-        if alloc.inner().mutability == Mutability::Mut {
-            throw_machine_stop_str!("can't access mutable globals in ConstProp");
-        }
-
-        Ok(())
-    }
-
-    #[inline(always)]
-    fn expose_ptr(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _ptr: Pointer<AllocId>,
-    ) -> InterpResult<'tcx> {
-        throw_machine_stop_str!("exposing pointers isn't supported in ConstProp")
-    }
-
-    #[inline(always)]
-    fn init_frame_extra(
-        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        frame: Frame<'mir, 'tcx>,
-    ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
-        Ok(frame)
-    }
-
-    #[inline(always)]
-    fn stack<'a>(
-        ecx: &'a InterpCx<'mir, 'tcx, Self>,
-    ) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
-        &ecx.machine.stack
-    }
-
-    #[inline(always)]
-    fn stack_mut<'a>(
-        ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
-    ) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
-        &mut ecx.machine.stack
-    }
-}
-
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
@@ -711,139 +523,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     }
 }
 
-/// The mode that `ConstProp` is allowed to run in for a given `Local`.
-#[derive(Clone, Copy, Debug, PartialEq)]
-enum ConstPropMode {
-    /// The `Local` can be propagated into and reads of this `Local` can also be propagated.
-    FullConstProp,
-    /// The `Local` can only be propagated into and from its own block.
-    OnlyInsideOwnBlock,
-    /// The `Local` can be propagated into but reads cannot be propagated.
-    OnlyPropagateInto,
-    /// The `Local` cannot be part of propagation at all. Any statement
-    /// referencing it either for reading or writing will not get propagated.
-    NoPropagation,
-}
-
-struct CanConstProp {
-    can_const_prop: IndexVec<Local, ConstPropMode>,
-    // False at the beginning. Once set, no more assignments are allowed to that local.
-    found_assignment: BitSet<Local>,
-    // Cache of locals' information
-    local_kinds: IndexVec<Local, LocalKind>,
-}
-
-impl CanConstProp {
-    /// Returns true if `local` can be propagated
-    fn check<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
-        body: &Body<'tcx>,
-    ) -> IndexVec<Local, ConstPropMode> {
-        let mut cpv = CanConstProp {
-            can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls),
-            found_assignment: BitSet::new_empty(body.local_decls.len()),
-            local_kinds: IndexVec::from_fn_n(
-                |local| body.local_kind(local),
-                body.local_decls.len(),
-            ),
-        };
-        for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
-            let ty = body.local_decls[local].ty;
-            match tcx.layout_of(param_env.and(ty)) {
-                Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
-                // Either the layout fails to compute, then we can't use this local anyway
-                // or the local is too large, then we don't want to.
-                _ => {
-                    *val = ConstPropMode::NoPropagation;
-                    continue;
-                }
-            }
-            // Cannot use args at all
-            // Cannot use locals because if x < y { y - x } else { x - y } would
-            //        lint for x != y
-            // FIXME(oli-obk): lint variables until they are used in a condition
-            // FIXME(oli-obk): lint if return value is constant
-            if cpv.local_kinds[local] == LocalKind::Arg {
-                *val = ConstPropMode::OnlyPropagateInto;
-                trace!(
-                    "local {:?} can't be const propagated because it's a function argument",
-                    local
-                );
-            } else if cpv.local_kinds[local] == LocalKind::Var {
-                *val = ConstPropMode::OnlyInsideOwnBlock;
-                trace!(
-                    "local {:?} will only be propagated inside its block, because it's a user variable",
-                    local
-                );
-            }
-        }
-        cpv.visit_body(&body);
-        cpv.can_const_prop
-    }
-}
-
-impl Visitor<'_> for CanConstProp {
-    fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
-        use rustc_middle::mir::visit::PlaceContext::*;
-        match context {
-            // Projections are fine, because `&mut foo.x` will be caught by
-            // `MutatingUseContext::Borrow` elsewhere.
-            MutatingUse(MutatingUseContext::Projection)
-            // These are just stores, where the storing is not propagatable, but there may be later
-            // mutations of the same local via `Store`
-            | MutatingUse(MutatingUseContext::Call)
-            | MutatingUse(MutatingUseContext::AsmOutput)
-            | MutatingUse(MutatingUseContext::Deinit)
-            // Actual store that can possibly even propagate a value
-            | MutatingUse(MutatingUseContext::SetDiscriminant)
-            | MutatingUse(MutatingUseContext::Store) => {
-                if !self.found_assignment.insert(local) {
-                    match &mut self.can_const_prop[local] {
-                        // If the local can only get propagated in its own block, then we don't have
-                        // to worry about multiple assignments, as we'll nuke the const state at the
-                        // end of the block anyway, and inside the block we overwrite previous
-                        // states as applicable.
-                        ConstPropMode::OnlyInsideOwnBlock => {}
-                        ConstPropMode::NoPropagation => {}
-                        ConstPropMode::OnlyPropagateInto => {}
-                        other @ ConstPropMode::FullConstProp => {
-                            trace!(
-                                "local {:?} can't be propagated because of multiple assignments. Previous state: {:?}",
-                                local, other,
-                            );
-                            *other = ConstPropMode::OnlyInsideOwnBlock;
-                        }
-                    }
-                }
-            }
-            // Reading constants is allowed an arbitrary number of times
-            NonMutatingUse(NonMutatingUseContext::Copy)
-            | NonMutatingUse(NonMutatingUseContext::Move)
-            | NonMutatingUse(NonMutatingUseContext::Inspect)
-            | NonMutatingUse(NonMutatingUseContext::Projection)
-            | NonUse(_) => {}
-
-            // These could be propagated with a smarter analysis or just some careful thinking about
-            // whether they'd be fine right now.
-            MutatingUse(MutatingUseContext::Yield)
-            | MutatingUse(MutatingUseContext::Drop)
-            | MutatingUse(MutatingUseContext::Retag)
-            // These can't ever be propagated under any scheme, as we can't reason about indirect
-            // mutation.
-            | NonMutatingUse(NonMutatingUseContext::SharedBorrow)
-            | NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
-            | NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
-            | NonMutatingUse(NonMutatingUseContext::AddressOf)
-            | MutatingUse(MutatingUseContext::Borrow)
-            | MutatingUse(MutatingUseContext::AddressOf) => {
-                trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
-                self.can_const_prop[local] = ConstPropMode::NoPropagation;
-            }
-        }
-    }
-}
-
 impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
     fn visit_body(&mut self, body: &Body<'tcx>) {
         for (bb, data) in body.basic_blocks().iter_enumerated() {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 1b583417ca0..28e2e0db89a 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1282,6 +1282,8 @@ options! {
         "emit a section containing stack size metadata (default: no)"),
     emit_thin_lto: bool = (true, parse_bool, [TRACKED],
         "emit the bc module with thin LTO info (default: yes)"),
+    export_executable_symbols: bool = (false, parse_bool, [TRACKED],
+        "export symbols from executables, as if they were dynamic libraries"),
     fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
         (default: no)"),
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index faa4f3700bb..1d7406e00ad 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -538,9 +538,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
 
     impl ConstraintLocator<'_> {
         #[instrument(skip(self), level = "debug")]
-        fn check(&mut self, def_id: LocalDefId) {
+        fn check(&mut self, item_def_id: LocalDefId) {
             // Don't try to check items that cannot possibly constrain the type.
-            if !self.tcx.has_typeck_results(def_id) {
+            if !self.tcx.has_typeck_results(item_def_id) {
                 debug!("no constraint: no typeck results");
                 return;
             }
@@ -555,26 +555,20 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
             // // because we again need to reveal `Foo` so we can check whether the
             // // constant does not contain interior mutability.
             // ```
-            let tables = self.tcx.typeck(def_id);
+            let tables = self.tcx.typeck(item_def_id);
             if let Some(_) = tables.tainted_by_errors {
                 self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() });
                 return;
             }
-            if tables.concrete_opaque_types.get(&self.def_id).is_none() {
+            if !tables.concrete_opaque_types.contains_key(&self.def_id) {
                 debug!("no constraints in typeck results");
                 return;
             }
             // Use borrowck to get the type with unerased regions.
-            let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+            let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
             debug!(?concrete_opaque_types);
-            for &(def_id, concrete_type) in concrete_opaque_types {
-                if def_id != self.def_id {
-                    // Ignore constraints for other opaque types.
-                    continue;
-                }
-
+            if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
                 debug!(?concrete_type, "found constraint");
-
                 if let Some(prev) = self.found {
                     if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() {
                         prev.report_mismatch(&concrete_type, self.tcx);
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index b1513e5e0f3..a5118e5333b 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -317,11 +317,11 @@ use crate::vec::Vec;
 ///
 /// ```text
 /// 0
-/// 5
-/// 10
-/// 20
-/// 20
-/// 40
+/// 8
+/// 16
+/// 16
+/// 32
+/// 32
 /// ```
 ///
 /// At first, we have no memory allocated at all, but as we append to the
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 1d3466696ed..ac286c171f0 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -22,6 +22,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use crate::marker::Destruct;
+
 use self::Ordering::*;
 
 /// Trait for equality comparisons which are [partial equivalence
@@ -603,7 +605,8 @@ impl Ordering {
 pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
 
 #[stable(feature = "reverse_cmp_key", since = "1.19.0")]
-impl<T: PartialOrd> PartialOrd for Reverse<T> {
+#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+impl<T: ~const PartialOrd> const PartialOrd for Reverse<T> {
     #[inline]
     fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
         other.0.partial_cmp(&self.0)
@@ -761,6 +764,7 @@ impl<T: Clone> Clone for Reverse<T> {
 #[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Ord"]
+#[const_trait]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an [`Ordering`] between `self` and `other`.
     ///
@@ -796,8 +800,15 @@ pub trait Ord: Eq + PartialOrd<Self> {
     fn max(self, other: Self) -> Self
     where
         Self: Sized,
+        Self: ~const Destruct,
     {
-        max_by(self, other, Ord::cmp)
+        // HACK(fee1-dead): go back to using `self.max_by(other, Ord::cmp)`
+        // when trait methods are allowed to be used when a const closure is
+        // expected.
+        match self.cmp(&other) {
+            Ordering::Less | Ordering::Equal => other,
+            Ordering::Greater => self,
+        }
     }
 
     /// Compares and returns the minimum of two values.
@@ -816,8 +827,15 @@ pub trait Ord: Eq + PartialOrd<Self> {
     fn min(self, other: Self) -> Self
     where
         Self: Sized,
+        Self: ~const Destruct,
     {
-        min_by(self, other, Ord::cmp)
+        // HACK(fee1-dead): go back to using `self.min_by(other, Ord::cmp)`
+        // when trait methods are allowed to be used when a const closure is
+        // expected.
+        match self.cmp(&other) {
+            Ordering::Less | Ordering::Equal => self,
+            Ordering::Greater => other,
+        }
     }
 
     /// Restrict a value to a certain interval.
@@ -841,6 +859,8 @@ pub trait Ord: Eq + PartialOrd<Self> {
     fn clamp(self, min: Self, max: Self) -> Self
     where
         Self: Sized,
+        Self: ~const Destruct,
+        Self: ~const PartialOrd,
     {
         assert!(min <= max);
         if self < min {
@@ -862,7 +882,8 @@ pub macro Ord($item:item) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Ordering {
+#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+impl const Ord for Ordering {
     #[inline]
     fn cmp(&self, other: &Ordering) -> Ordering {
         (*self as i32).cmp(&(*other as i32))
@@ -870,7 +891,8 @@ impl Ord for Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Ordering {
+#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+impl const PartialOrd for Ordering {
     #[inline]
     fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
         (*self as i32).partial_cmp(&(*other as i32))
@@ -1187,8 +1209,9 @@ pub macro PartialOrd($item:item) {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")]
-pub fn min<T: Ord>(v1: T, v2: T) -> T {
+pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T {
     v1.min(v2)
 }
 
@@ -1250,8 +1273,9 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")]
-pub fn max<T: Ord>(v1: T, v2: T) -> T {
+pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T {
     v1.max(v2)
 }
 
@@ -1304,7 +1328,8 @@ mod impls {
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl PartialEq for $t {
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl const PartialEq for $t {
                 #[inline]
                 fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
                 #[inline]
@@ -1314,7 +1339,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl PartialEq for () {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const PartialEq for () {
         #[inline]
         fn eq(&self, _other: &()) -> bool {
             true
@@ -1341,7 +1367,8 @@ mod impls {
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl PartialOrd for $t {
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl const PartialOrd for $t {
                 #[inline]
                 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
                     match (*self <= *other, *self >= *other) {
@@ -1364,7 +1391,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl PartialOrd for () {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const PartialOrd for () {
         #[inline]
         fn partial_cmp(&self, _: &()) -> Option<Ordering> {
             Some(Equal)
@@ -1372,7 +1400,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl PartialOrd for bool {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const PartialOrd for bool {
         #[inline]
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
             Some(self.cmp(other))
@@ -1384,7 +1413,8 @@ mod impls {
     macro_rules! ord_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl PartialOrd for $t {
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl const PartialOrd for $t {
                 #[inline]
                 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
                     Some(self.cmp(other))
@@ -1400,7 +1430,8 @@ mod impls {
             }
 
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl Ord for $t {
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl const Ord for $t {
                 #[inline]
                 fn cmp(&self, other: &$t) -> Ordering {
                     // The order here is important to generate more optimal assembly.
@@ -1414,7 +1445,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl Ord for () {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const Ord for () {
         #[inline]
         fn cmp(&self, _other: &()) -> Ordering {
             Equal
@@ -1422,7 +1454,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl Ord for bool {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
             // Casting to i8's and converting the difference to an Ordering generates
@@ -1441,7 +1474,8 @@ mod impls {
     ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
     #[unstable(feature = "never_type", issue = "35121")]
-    impl PartialEq for ! {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const PartialEq for ! {
         fn eq(&self, _: &!) -> bool {
             *self
         }
@@ -1451,14 +1485,16 @@ mod impls {
     impl Eq for ! {}
 
     #[unstable(feature = "never_type", issue = "35121")]
-    impl PartialOrd for ! {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const PartialOrd for ! {
         fn partial_cmp(&self, _: &!) -> Option<Ordering> {
             *self
         }
     }
 
     #[unstable(feature = "never_type", issue = "35121")]
-    impl Ord for ! {
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl const Ord for ! {
         fn cmp(&self, _: &!) -> Ordering {
             *self
         }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 7ae1bfd4f35..81b6d5737ea 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -96,6 +96,7 @@ use crate::intrinsics;
 #[inline]
 #[stable(feature = "unreachable", since = "1.27.0")]
 #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn unreachable_unchecked() -> ! {
     // SAFETY: the safety contract for `intrinsics::unreachable` must
     // be upheld by the caller.
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 9ae31a31aaa..7e65f4ebdad 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2449,6 +2449,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
 #[inline]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2535,6 +2536,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
 #[inline]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2564,14 +2566,23 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 ///
 /// * `dst` must be properly aligned.
 ///
-/// Additionally, the caller must ensure that writing `count *
-/// size_of::<T>()` bytes to the given region of memory results in a valid
-/// value of `T`. Using a region of memory typed as a `T` that contains an
-/// invalid value of `T` is undefined behavior.
-///
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
 /// `0`, the pointer must be non-null and 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
+/// following is an **incorrect** use of this function:
+///
+/// ```rust,no_run
+/// unsafe {
+///     let mut value: u8 = 0;
+///     let ptr: *mut bool = &mut value as *mut u8 as *mut bool;
+///     let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`.
+///     ptr.write_bytes(42u8, 1); // This function itself does not cause UB...
+///     let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️
+/// }
+/// ```
+///
 /// [valid]: crate::ptr#safety
 ///
 /// # Examples
@@ -2588,38 +2599,6 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 /// }
 /// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
 /// ```
-///
-/// Creating an invalid value:
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut v = Box::new(0i32);
-///
-/// unsafe {
-///     // Leaks the previously held value by overwriting the `Box<T>` with
-///     // a null pointer.
-///     ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
-/// }
-///
-/// // At this point, using or dropping `v` results in undefined behavior.
-/// // drop(v); // ERROR
-///
-/// // Even leaking `v` "uses" it, and hence is undefined behavior.
-/// // mem::forget(v); // ERROR
-///
-/// // In fact, `v` is invalid according to basic type layout invariants, so *any*
-/// // operation touching it is undefined behavior.
-/// // let v2 = v; // ERROR
-///
-/// unsafe {
-///     // Let us instead put in a valid value
-///     ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
-/// }
-///
-/// // Now the box is fine
-/// assert_eq!(*v, 42);
-/// ```
 #[doc(alias = "memset")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(bootstrap), rustc_allowed_through_unstable_modules)]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f24a7ab61ae..30f2f0ee05c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -105,6 +105,7 @@
 #![feature(const_cell_into_inner)]
 #![feature(const_char_convert)]
 #![feature(const_clone)]
+#![feature(const_cmp)]
 #![feature(const_discriminant)]
 #![feature(const_eval_select)]
 #![feature(const_float_bits_conv)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 66af4916074..6dc8563c421 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1124,6 +1124,7 @@ impl<T> fmt::Debug for Discriminant<T> {
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
     Discriminant(intrinsics::discriminant_value(v))
 }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index eb458f3866e..a66de19bad0 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -449,6 +449,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_add`.
@@ -517,6 +518,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_sub`.
@@ -585,6 +587,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_mul`.
@@ -757,6 +760,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_shl`.
@@ -803,6 +807,7 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_shr`.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 715e78350a4..73365544233 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -459,6 +459,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_add`.
@@ -528,6 +529,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_sub`.
@@ -574,6 +576,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_mul`.
@@ -933,6 +936,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_shl`.
@@ -979,6 +983,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
         #[inline(always)]
+        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self {
             // SAFETY: the caller must uphold the safety contract for
             // `unchecked_shr`.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 6cdbab30589..e289a8e6bd5 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -449,6 +449,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn offset(self, count: isize) -> *const T
     where
         T: Sized,
@@ -471,6 +472,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset(self, count: isize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `offset`.
         let this = unsafe { self.cast::<u8>().offset(count).cast::<()>() };
@@ -641,6 +643,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "ptr_offset_from", since = "1.47.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn offset_from(self, origin: *const T) -> isize
     where
         T: Sized,
@@ -663,6 +666,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize {
         // SAFETY: the caller must uphold the safety contract for `offset_from`.
         unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
@@ -731,6 +735,7 @@ impl<T: ?Sized> *const T {
     #[unstable(feature = "ptr_sub_ptr", issue = "95892")]
     #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub_ptr(self, origin: *const T) -> usize
     where
         T: Sized,
@@ -862,6 +867,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
@@ -884,6 +890,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_add(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `add`.
         let this = unsafe { self.cast::<u8>().add(count).cast::<()>() };
@@ -946,6 +953,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
@@ -969,6 +977,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_sub(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `sub`.
         let this = unsafe { self.cast::<u8>().sub(count).cast::<()>() };
@@ -1205,6 +1214,7 @@ impl<T: ?Sized> *const T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1224,6 +1234,7 @@ impl<T: ?Sized> *const T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index e323f63115b..fc3dd2a9b25 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -461,6 +461,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn offset(self, count: isize) -> *mut T
     where
         T: Sized,
@@ -485,6 +486,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset(self, count: isize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `offset`.
         let this = unsafe { self.cast::<u8>().offset(count).cast::<()>() };
@@ -824,6 +826,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "ptr_offset_from", since = "1.47.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn offset_from(self, origin: *const T) -> isize
     where
         T: Sized,
@@ -844,6 +847,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize {
         // SAFETY: the caller must uphold the safety contract for `offset_from`.
         unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
@@ -913,6 +917,7 @@ impl<T: ?Sized> *mut T {
     #[unstable(feature = "ptr_sub_ptr", issue = "95892")]
     #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub_ptr(self, origin: *const T) -> usize
     where
         T: Sized,
@@ -976,6 +981,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
@@ -998,6 +1004,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_add(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `add`.
         let this = unsafe { self.cast::<u8>().add(count).cast::<()>() };
@@ -1060,6 +1067,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
@@ -1083,6 +1091,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
     #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn byte_sub(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `sub`.
         let this = unsafe { self.cast::<u8>().sub(count).cast::<()>() };
@@ -1319,6 +1328,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1338,6 +1348,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1357,6 +1368,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_from(self, src: *const T, count: usize)
     where
         T: Sized,
@@ -1376,6 +1388,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
+    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
     where
         T: Sized,
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 6a01b4a2e28..8801c670bc9 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -37,12 +37,11 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 {
     abort();
 
     cfg_if::cfg_if! {
-        if #[cfg(unix)] {
+        if #[cfg(any(unix, target_os = "solid_asp3"))] {
             unsafe fn abort() -> ! {
                 libc::abort();
             }
         } else if #[cfg(any(target_os = "hermit",
-                            target_os = "solid_asp3",
                             all(target_vendor = "fortanix", target_env = "sgx")
         ))] {
             unsafe fn abort() -> ! {
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 08b45ac11a1..8e478cd7bc8 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -382,6 +382,14 @@ pub mod token_stream {
                 bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)),
             })
         }
+
+        fn size_hint(&self) -> (usize, Option<usize>) {
+            self.0.size_hint()
+        }
+
+        fn count(self) -> usize {
+            self.0.count()
+        }
     }
 
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index f4f2e3f2434..18f7f6a35e9 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2577,6 +2577,7 @@ impl<T: Read> Read for Take<T> {
 
         let max = cmp::min(buf.len() as u64, self.limit) as usize;
         let n = self.inner.read(&mut buf[..max])?;
+        assert!(n as u64 <= self.limit, "number of read bytes exceeds limit");
         self.limit -= n as u64;
         Ok(n)
     }
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index d5a8c93b0ce..f357f33ec52 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -583,6 +583,25 @@ fn test_write_all_vectored() {
     }
 }
 
+// Issue 94981
+#[test]
+#[should_panic = "number of read bytes exceeds limit"]
+fn test_take_wrong_length() {
+    struct LieAboutSize(bool);
+
+    impl Read for LieAboutSize {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            // Lie about the read size at first time of read.
+            if core::mem::take(&mut self.0) { Ok(buf.len() + 1) } else { Ok(buf.len()) }
+        }
+    }
+
+    let mut buffer = vec![0; 4];
+    let mut reader = LieAboutSize(true).take(4);
+    // Primed the `Limit` by lying about the read size.
+    let _ = reader.read(&mut buffer[..]);
+}
+
 #[bench]
 fn bench_take_read(b: &mut test::Bencher) {
     b.iter(|| {
diff --git a/library/std/src/sys/solid/abi/mod.rs b/library/std/src/sys/solid/abi/mod.rs
index 1afc83f766d..8440d572cfb 100644
--- a/library/std/src/sys/solid/abi/mod.rs
+++ b/library/std/src/sys/solid/abi/mod.rs
@@ -4,32 +4,6 @@ mod fs;
 pub mod sockets;
 pub use self::fs::*;
 
-#[inline(always)]
-pub fn breakpoint_program_exited(tid: usize) {
-    unsafe {
-        match () {
-            // SOLID_BP_PROGRAM_EXITED = 15
-            #[cfg(target_arch = "arm")]
-            () => core::arch::asm!("bkpt #15", in("r0") tid),
-            #[cfg(target_arch = "aarch64")]
-            () => core::arch::asm!("hlt #15", in("x0") tid),
-        }
-    }
-}
-
-#[inline(always)]
-pub fn breakpoint_abort() {
-    unsafe {
-        match () {
-            // SOLID_BP_CSABORT = 16
-            #[cfg(target_arch = "arm")]
-            () => core::arch::asm!("bkpt #16"),
-            #[cfg(target_arch = "aarch64")]
-            () => core::arch::asm!("hlt #16"),
-        }
-    }
-}
-
 // `solid_types.h`
 pub use super::itron::abi::{ER, ER_ID, E_TMOUT, ID};
 
diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs
index 2d21e4764fc..778a589d1b7 100644
--- a/library/std/src/sys/solid/mod.rs
+++ b/library/std/src/sys/solid/mod.rs
@@ -76,20 +76,9 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
     error::decode_error_kind(code)
 }
 
-#[inline(always)]
+#[inline]
 pub fn abort_internal() -> ! {
-    loop {
-        abi::breakpoint_abort();
-    }
-}
-
-// This function is needed by the panic runtime. The symbol is named in
-// pre-link args for the target specification, so keep that in sync.
-#[cfg(not(test))]
-#[no_mangle]
-// NB. used by both libunwind and libpanic_abort
-pub extern "C" fn __rust_abort() {
-    abort_internal();
+    unsafe { libc::abort() }
 }
 
 pub fn hashmap_random_keys() -> (u64, u64) {
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 719d95bbe50..b5649d6e0ff 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -11,7 +11,7 @@ use crate::path::{self, PathBuf};
 use crate::sys_common::rwlock::StaticRwLock;
 use crate::vec;
 
-use super::{abi, error, itron, memchr};
+use super::{error, itron, memchr};
 
 // `solid` directly maps `errno`s to μITRON error codes.
 impl itron::error::ItronError {
@@ -184,11 +184,8 @@ pub fn home_dir() -> Option<PathBuf> {
     None
 }
 
-pub fn exit(_code: i32) -> ! {
-    let tid = itron::task::try_current_task_id().unwrap_or(0);
-    loop {
-        abi::breakpoint_program_exited(tid as usize);
-    }
+pub fn exit(code: i32) -> ! {
+    rtabort!("exit({}) called", code);
 }
 
 pub fn getpid() -> u32 {
diff --git a/src/test/run-make/export-executable-symbols/Makefile b/src/test/run-make/export-executable-symbols/Makefile
new file mode 100644
index 00000000000..5006f9cb8cf
--- /dev/null
+++ b/src/test/run-make/export-executable-symbols/Makefile
@@ -0,0 +1,11 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-wasm32
+# ignore-wasm64
+# ignore-none no-std is not supported
+# only-linux
+
+all:
+	$(RUSTC) -Zexport-executable-symbols  main.rs --target $(TARGET) --crate-type=bin
+	nm $(TMPDIR)/main | $(CGREP) exported_symbol
+
diff --git a/src/test/run-make/export-executable-symbols/main.rs b/src/test/run-make/export-executable-symbols/main.rs
new file mode 100644
index 00000000000..c498381a33f
--- /dev/null
+++ b/src/test/run-make/export-executable-symbols/main.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+fn main() {}
+
+#[no_mangle]
+pub fn exported_symbol() -> i8 {
+    42
+}
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index bcf323e1cab..86e42440bd0 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -37,6 +37,7 @@
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
     -Z                           emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
+    -Z               export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
     -Z                             fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
     -Z              force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
     -Z                                    fuel=val -- set the optimization fuel quota for a crate
diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs
index b78eeaa9055..3884e397764 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.rs
+++ b/src/test/ui/derives/deriving-with-repr-packed.rs
@@ -1,29 +1,43 @@
 #![deny(unaligned_references)]
 
-// check that derive on a packed struct with non-Copy fields
-// correctly. This can't be made to work perfectly because
-// we can't just use the field from the struct as it might
-// not be aligned.
+// Check that deriving certain builtin traits on certain packed structs cause
+// errors. This happens when the derived trait would need to use a potentially
+// misaligned reference. But there are two cases that are allowed:
+// - If all the fields within the struct meet the required alignment: 1 for
+//   `repr(packed)`, or `N` for `repr(packed(N))`.
+// - If `Default` is the only trait derived, because it doesn't involve any
+//   references.
 
-#[derive(Copy, Clone, PartialEq, Eq)]
-//~^ ERROR `#[derive]` can't be used
+#[derive(Copy, Clone, Default, PartialEq, Eq)]
+//~^ ERROR `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
 //~| hard error
-//~^^^ ERROR `#[derive]` can't be used
+//~^^^ ERROR `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
 //~| hard error
 #[repr(packed)]
 pub struct Foo<T>(T, T, T);
 
-#[derive(PartialEq, Eq)]
-//~^ ERROR `#[derive]` can't be used
+#[derive(Default, Hash)]
+//~^ ERROR `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
 //~| hard error
 #[repr(packed)]
 pub struct Bar(u32, u32, u32);
 
-#[derive(PartialEq)]
+// This one is fine because the field alignment is 1.
+#[derive(Default, Hash)]
+#[repr(packed)]
+pub struct Bar2(u8, i8, bool);
+
+// This one is fine because the field alignment is 2, matching `packed(2)`.
+#[derive(Default, Hash)]
+#[repr(packed(2))]
+pub struct Bar3(u16, i16, bool);
+
+// This one is fine because it's not packed.
+#[derive(Debug, Default)]
 struct Y(usize);
 
-#[derive(PartialEq)]
-//~^ ERROR `#[derive]` can't be used
+#[derive(Debug, Default)]
+//~^ ERROR `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
 //~| hard error
 #[repr(packed)]
 struct X(Y);
diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr
index 1002b359f60..1f98da5b70e 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.stderr
+++ b/src/test/ui/derives/deriving-with-repr-packed.stderr
@@ -1,7 +1,7 @@
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:8:16
+error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:11:16
    |
-LL | #[derive(Copy, Clone, PartialEq, Eq)]
+LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
    |                ^^^^^
    |
 note: the lint level is defined here
@@ -13,43 +13,43 @@ LL | #![deny(unaligned_references)]
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:8:23
+error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:11:32
    |
-LL | #[derive(Copy, Clone, PartialEq, Eq)]
-   |                       ^^^^^^^^^
+LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
+   |                                ^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:16:10
+error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:19:19
    |
-LL | #[derive(PartialEq, Eq)]
-   |          ^^^^^^^^^
+LL | #[derive(Default, Hash)]
+   |                   ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:25:10
+error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:39:10
    |
-LL | #[derive(PartialEq)]
-   |          ^^^^^^^^^
+LL | #[derive(Debug, Default)]
+   |          ^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
 Future incompatibility report: Future breakage diagnostic:
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:8:16
+error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:11:16
    |
-LL | #[derive(Copy, Clone, PartialEq, Eq)]
+LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
    |                ^^^^^
    |
 note: the lint level is defined here
@@ -62,11 +62,11 @@ LL | #![deny(unaligned_references)]
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 Future breakage diagnostic:
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:8:23
+error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:11:32
    |
-LL | #[derive(Copy, Clone, PartialEq, Eq)]
-   |                       ^^^^^^^^^
+LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
+   |                                ^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/deriving-with-repr-packed.rs:1:9
@@ -78,11 +78,11 @@ LL | #![deny(unaligned_references)]
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 Future breakage diagnostic:
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:16:10
+error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:19:19
    |
-LL | #[derive(PartialEq, Eq)]
-   |          ^^^^^^^^^
+LL | #[derive(Default, Hash)]
+   |                   ^^^^
    |
 note: the lint level is defined here
   --> $DIR/deriving-with-repr-packed.rs:1:9
@@ -91,14 +91,14 @@ LL | #![deny(unaligned_references)]
    |         ^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 Future breakage diagnostic:
-error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
-  --> $DIR/deriving-with-repr-packed.rs:25:10
+error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:39:10
    |
-LL | #[derive(PartialEq)]
-   |          ^^^^^^^^^
+LL | #[derive(Debug, Default)]
+   |          ^^^^^
    |
 note: the lint level is defined here
   --> $DIR/deriving-with-repr-packed.rs:1:9
@@ -107,5 +107,5 @@ LL | #![deny(unaligned_references)]
    |         ^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/process/nofile-limit.rs b/src/test/ui/process/nofile-limit.rs
index 549135a46cf..3ddf8d6ef24 100644
--- a/src/test/ui/process/nofile-limit.rs
+++ b/src/test/ui/process/nofile-limit.rs
@@ -6,7 +6,7 @@
 // dont-check-compiler-stderr
 // only-linux
 // no-prefer-dynamic
-// compile-flags: -Ctarget-feature=+crt-static -Crpath=no
+// compile-flags: -Ctarget-feature=+crt-static -Crpath=no -Crelocation-model=static
 #![feature(exit_status_error)]
 #![feature(rustc_private)]
 extern crate libc;
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 963f08b702caf7a06eed564312933ec50dd07f5
+Subproject b938529fb8ed8f7b5b374282ffc3ffa74c31311