about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/entry.rs26
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs9
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs8
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/entry.rs42
-rw-r--r--compiler/rustc_passes/src/errors.rs16
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs29
-rw-r--r--config.example.toml4
-rw-r--r--library/core/src/slice/mod.rs11
-rw-r--r--library/std/src/io/cursor.rs21
-rw-r--r--library/std/src/io/impls.rs13
-rw-r--r--library/std/src/io/mod.rs5
-rw-r--r--library/std/src/process.rs4
-rw-r--r--rustfmt.toml6
-rw-r--r--src/bootstrap/Cargo.toml6
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs7
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rwxr-xr-xsrc/ci/docker/run.sh74
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/alloc.rs9
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs166
-rw-r--r--src/tools/miri/src/shims/intrinsics/atomic.rs6
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs91
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs6
-rw-r--r--src/tools/miri/src/shims/mod.rs10
-rw-r--r--src/tools/miri/src/shims/panic.rs8
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs7
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs7
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs9
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs7
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs7
-rw-r--r--src/tools/miri/src/shims/x86/aesni.rs7
-rw-r--r--src/tools/miri/src/shims/x86/avx.rs7
-rw-r--r--src/tools/miri/src/shims/x86/avx2.rs7
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs11
-rw-r--r--src/tools/miri/src/shims/x86/sse.rs7
-rw-r--r--src/tools/miri/src/shims/x86/sse2.rs7
-rw-r--r--src/tools/miri/src/shims/x86/sse3.rs7
-rw-r--r--src/tools/miri/src/shims/x86/sse41.rs7
-rw-r--r--src/tools/miri/src/shims/x86/ssse3.rs7
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr12
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr12
-rw-r--r--tests/ui/check-cfg/diagnotics.cargo.stderr18
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr20
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.rs23
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr22
52 files changed, 461 insertions, 380 deletions
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index cd8a5a66920..dd231e286d5 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -4,11 +4,35 @@ use rustc_span::Symbol;
 
 #[derive(Debug)]
 pub enum EntryPointType {
+    /// This function is not an entrypoint.
     None,
+    /// This is a function called `main` at the root level.
+    /// ```
+    /// fn main() {}
+    /// ```
     MainNamed,
+    /// This is a function with the `#[rustc_main]` attribute.
+    /// Used by the testing harness to create the test entrypoint.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[rustc_main]
+    /// fn main() {}
+    /// ```
     RustcMainAttr,
+    /// This is a function with the `#[start]` attribute.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[start]
+    /// fn main() {}
+    /// ```
     Start,
-    OtherMain, // Not an entry point, but some other function named main
+    /// This function is **not** an entrypoint but simply named `main` (not at the root).
+    /// This is only used for diagnostics.
+    /// ```
+    /// #[allow(dead_code)]
+    /// mod meow {
+    ///     fn main() {}
+    /// }
+    /// ```
+    OtherMain,
 }
 
 pub fn entry_point_type(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index a2015445b42..8cf431482ff 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -266,7 +266,7 @@ fn generate_test_harness(
 ///
 /// By default this expands to
 ///
-/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?)
+/// ```ignore (messes with test internals)
 /// #[rustc_main]
 /// pub fn main() {
 ///     extern crate test;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index e9cf5a3d769..6e6fa70107b 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         let intrinsic_name = ecx.tcx.item_name(instance.def_id());
 
         // CTFE-specific intrinsics.
-        let Some(ret) = target else {
-            // Handle diverging intrinsics. We can't handle any of them (that are not already
-            // handled above), but check if there is a fallback body.
-            if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
-                throw_unsup_format!(
-                    "intrinsic `{intrinsic_name}` is not supported at compile-time"
-                );
-            }
-            return Ok(Some(ty::Instance {
-                def: ty::InstanceDef::Item(instance.def_id()),
-                args: instance.args,
-            }));
-        };
         match intrinsic_name {
             sym::ptr_guaranteed_cmp => {
                 let a = ecx.read_scalar(&args[0])?;
@@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             }
         }
 
-        ecx.go_to_block(ret);
+        // Intrinsic is done, jump to next block.
+        ecx.return_to_block(target)?;
         Ok(None)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index f73293856c7..88ce5a7cbeb 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
-        let Some(ret) = ret else {
-            // We don't support any intrinsic without return place.
-            return Ok(false);
-        };
 
         match intrinsic_name {
             sym::caller_location => {
@@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     };
 
                     M::panic_nounwind(self, &msg)?;
-                    // Skip the `go_to_block` at the end.
+                    // Skip the `return_to_block` at the end (we panicked, we do not return).
                     return Ok(true);
                 }
             }
@@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
             }
 
+            // Unsupported intrinsic: skip the return_to_block below.
             _ => return Ok(false),
         }
 
         trace!("{:?}", self.dump_place(&dest.clone().into()));
-        self.go_to_block(ret);
+        self.return_to_block(ret)?;
         Ok(true)
     }
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9c33cc8ed0b..dbb88e42a3e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // RFC 2397
     gated!(
         do_not_recommend, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(do_not_recommend)
+        EncodeCrossCrate::Yes, experimental!(do_not_recommend)
     ),
 
     // `#[cfi_encoding = ""]`
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index e9a6276192e..3c423b4e2aa 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -164,9 +164,9 @@ pub(super) fn unexpected_cfg_name(
 
     if is_from_cargo {
         if !is_feature_cfg {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
         diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
@@ -266,9 +266,9 @@ pub(super) fn unexpected_cfg_value(
                 diag.help("consider defining some features in `Cargo.toml`");
             }
         } else if !is_cfg_a_well_know_name {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         if !is_cfg_a_well_know_name {
             diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 8878310d6e9..9d58d301e2b 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -49,12 +49,6 @@ passes_attr_crate_level =
 passes_attr_only_in_functions =
     `{$attr}` attribute can only be used on functions
 
-passes_attr_only_on_main =
-    `{$attr}` attribute can only be used on `fn main()`
-
-passes_attr_only_on_root_main =
-    `{$attr}` attribute can only be used on root `fn main()`
-
 passes_both_ffi_const_and_pure =
     `#[ffi_const]` function cannot be `#[ffi_pure]`
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index d52092f2aa9..b43c8282db1 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -18,10 +18,10 @@ use crate::errors::{
 struct EntryContext<'tcx> {
     tcx: TyCtxt<'tcx>,
 
-    /// The function that has attribute named `main`.
-    attr_main_fn: Option<(LocalDefId, Span)>,
+    /// The function has the `#[rustc_main]` attribute.
+    rustc_main_fn: Option<(LocalDefId, Span)>,
 
-    /// The function that has the attribute 'start' on it.
+    /// The function that has the attribute `#[start]` on it.
     start_fn: Option<(LocalDefId, Span)>,
 
     /// The functions that one might think are `main` but aren't, e.g.
@@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     }
 
     let mut ctxt =
-        EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
+        EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
 
     for id in tcx.hir().items() {
-        find_item(id, &mut ctxt);
+        check_and_search_item(id, &mut ctxt);
     }
 
     configure_main(tcx, &ctxt)
@@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
     attr::find_by_name(attrs, sym).map(|attr| attr.span)
 }
 
-fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+    if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
+        for attr in [sym::start, sym::rustc_main] {
+            if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
+                ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
+            }
+        }
+        return;
+    }
+
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
     let attrs = ctxt.tcx.hir().attrs(id.hir_id());
@@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
         at_root,
         ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
     );
+
     match entry_point_type {
-        EntryPointType::None => (),
-        _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
-            for attr in [sym::start, sym::rustc_main] {
-                if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
-                    ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
-                }
-            }
-        }
-        EntryPointType::MainNamed => (),
+        EntryPointType::None => {}
+        EntryPointType::MainNamed => {}
         EntryPointType::OtherMain => {
             ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
         }
         EntryPointType::RustcMainAttr => {
-            if ctxt.attr_main_fn.is_none() {
-                ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
+            if ctxt.rustc_main_fn.is_none() {
+                ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
             } else {
                 ctxt.tcx.dcx().emit_err(MultipleRustcMain {
                     span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
-                    first: ctxt.attr_main_fn.unwrap().1,
+                    first: ctxt.rustc_main_fn.unwrap().1,
                     additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
                 });
             }
@@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
-    } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+    } else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
         let def_id = local_def_id.to_def_id();
         Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
     } else {
+        // The actual resolution of main happens in the resolver, this here
         if let Some(main_def) = tcx.resolutions(()).main_def
             && let Some(def_id) = main_def.opt_fn_def_id()
         {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 743faf54560..65cad82cc8c 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1207,22 +1207,6 @@ pub struct NakedFunctionsMustUseNoreturn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_attr_only_on_main)]
-pub struct AttrOnlyOnMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_attr_only_on_root_main)]
-pub struct AttrOnlyOnRootMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_attr_only_in_functions)]
 pub struct AttrOnlyInFunctions {
     #[primary_span]
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 796222129f1..fd4b5805f02 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -11,6 +11,7 @@ use rustc_infer::traits::{
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
 
 use super::eval_ctxt::GenerateProofTree;
 use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
@@ -137,7 +138,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .collect();
 
         errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            obligation: find_best_leaf_obligation(infcx, &obligation),
+            obligation: find_best_leaf_obligation(infcx, &obligation, true),
             code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
             root_obligation: obligation,
         }));
@@ -198,7 +199,7 @@ fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
     root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
-    let obligation = find_best_leaf_obligation(infcx, &root_obligation);
+    let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
 
     let code = match obligation.predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
@@ -266,7 +267,7 @@ fn fulfillment_error_for_stalled<'tcx>(
     });
 
     FulfillmentError {
-        obligation: find_best_leaf_obligation(infcx, &obligation),
+        obligation: find_best_leaf_obligation(infcx, &obligation, true),
         code,
         root_obligation: obligation,
     }
@@ -275,12 +276,13 @@ fn fulfillment_error_for_stalled<'tcx>(
 fn find_best_leaf_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 ) -> PredicateObligation<'tcx> {
     let obligation = infcx.resolve_vars_if_possible(obligation.clone());
     infcx
         .visit_proof_tree(
             obligation.clone().into(),
-            &mut BestObligation { obligation: obligation.clone() },
+            &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
         )
         .break_value()
         .unwrap_or(obligation)
@@ -288,6 +290,7 @@ fn find_best_leaf_obligation<'tcx>(
 
 struct BestObligation<'tcx> {
     obligation: PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 }
 
 impl<'tcx> BestObligation<'tcx> {
@@ -320,6 +323,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             return ControlFlow::Break(self.obligation.clone());
         };
 
+        // Don't walk into impls that have `do_not_recommend`.
+        if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } =
+            candidate.kind()
+            && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
+        {
+            return ControlFlow::Break(self.obligation.clone());
+        }
+
         // FIXME: Could we extract a trait ref from a projection here too?
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
@@ -355,11 +366,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                 }
             }
 
-            // Skip nested goals that hold.
-            //FIXME: We should change the max allowed certainty based on if we're
-            // visiting an ambiguity or error obligation.
-            if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
-                continue;
+            // Skip nested goals that aren't the *reason* for our goal's failure.
+            match self.consider_ambiguities {
+                true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {}
+                false if matches!(nested_goal.result(), Err(_)) => {}
+                _ => continue,
             }
 
             self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
diff --git a/config.example.toml b/config.example.toml
index 5c1fac7672a..3b76952504f 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -254,6 +254,10 @@
 # executing the debuginfo test suite.
 #gdb = "gdb"
 
+# The path to (or name of) the LLDB executable to use. This is only used for
+# executing the debuginfo test suite.
+#lldb = "lldb"
+
 # The node.js executable to use. Note that this is only used for the emscripten
 # target when running tests, otherwise this can be omitted.
 #nodejs = "node"
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index de766a4b977..ed7bcec89b9 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -9,7 +9,7 @@
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::fmt;
 use crate::hint;
-use crate::intrinsics::exact_div;
+use crate::intrinsics::{exact_div, unchecked_sub};
 use crate::mem::{self, SizedTypeProperties};
 use crate::num::NonZero;
 use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
@@ -1983,7 +1983,7 @@ impl<T> [T] {
         );
 
         // SAFETY: Caller has to check that `0 <= mid <= self.len()`
-        unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) }
+        unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) }
     }
 
     /// Divides one mutable slice into two at an index, without doing bounds checking.
@@ -2035,7 +2035,12 @@ impl<T> [T] {
         //
         // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
         // is fine.
-        unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
+        unsafe {
+            (
+                from_raw_parts_mut(ptr, mid),
+                from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)),
+            )
+        }
     }
 
     /// Divides one slice into two at an index, returning `None` if the slice is
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index f6680b211c7..37492e9efab 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -364,6 +364,27 @@ where
         self.pos += n as u64;
         Ok(())
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        let content = self.remaining_slice();
+        let len = content.len();
+        buf.try_reserve(len)?;
+        buf.extend_from_slice(content);
+        self.pos += len as u64;
+
+        Ok(len)
+    }
+
+    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
+        let content =
+            crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
+        let len = content.len();
+        buf.try_reserve(len)?;
+        buf.push_str(content);
+        self.pos += len as u64;
+
+        Ok(len)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index dd7e0725176..46f04c7cd39 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -329,8 +329,9 @@ impl Read for &[u8] {
     #[inline]
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
         let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?;
-        buf.push_str(content);
         let len = self.len();
+        buf.try_reserve(len)?;
+        buf.push_str(content);
         *self = &self[len..];
         Ok(len)
     }
@@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
 
     #[inline]
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        // We have to use a single contiguous slice because the `VecDequeue` might be split in the
-        // middle of an UTF-8 character.
-        let len = self.len();
-        let content = self.make_contiguous();
-        let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?;
-        buf.push_str(string);
-        self.clear();
-        Ok(len)
+        // SAFETY: We only append to the buffer
+        unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) }
     }
 }
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index a3fdcdc2d07..af055152cbe 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -384,7 +384,10 @@ where
 {
     let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
     let ret = f(g.buf);
-    if str::from_utf8(&g.buf[g.len..]).is_err() {
+
+    // SAFETY: the caller promises to only append data to `buf`
+    let appended = g.buf.get_unchecked(g.len..);
+    if str::from_utf8(appended).is_err() {
         ret.and_then(|_| Err(Error::INVALID_UTF8))
     } else {
         g.len = g.buf.len();
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 4a73a9be88b..d1848224251 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -486,6 +486,10 @@ impl Read for ChildStderr {
     fn is_read_vectored(&self) -> bool {
         self.inner.is_read_vectored()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.inner.read_to_end(buf)
+    }
 }
 
 impl AsInner<AnonPipe> for ChildStderr {
diff --git a/rustfmt.toml b/rustfmt.toml
index 67219b15d20..850d01ea7cb 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -13,6 +13,12 @@ ignore = [
 
     # tests for now are not formatted, as they are sometimes pretty-printing constrained
     # (and generally rustfmt can move around comments in UI-testing incompatible ways)
+    "/tests/*",
+
+    # but we still want to format rmake.rs files in tests/run-make/ so we need to do this
+    # dance to avoid the parent directory from being excluded
+    "!/tests/run-make/",
+    "/tests/run-make/*/*.rs",
     "!/tests/run-make/*/rmake.rs",
 
     # do not format submodules
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index c7a513d0890..e9675e20452 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -33,9 +33,9 @@ path = "src/bin/sccache-plus-cl.rs"
 test = false
 
 [dependencies]
-# Most of the time updating these dependencies requires modifications
-# to the bootstrap codebase; otherwise, some targets will fail. That's
-# why these dependencies are explicitly pinned.
+# Most of the time updating these dependencies requires modifications to the
+# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
+# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
 cc = "=1.0.73"
 cmake = "=0.1.48"
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9a585a39e1e..360bd3840d4 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1892,15 +1892,16 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                     .to_string()
             })
         };
-        let lldb_exe = "lldb";
-        let lldb_version = Command::new(lldb_exe)
+
+        let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
+        let lldb_version = Command::new(&lldb_exe)
             .arg("--version")
             .output()
             .map(|output| String::from_utf8_lossy(&output.stdout).to_string())
             .ok();
         if let Some(ref vers) = lldb_version {
             cmd.arg("--lldb-version").arg(vers);
-            let lldb_python_dir = run(Command::new(lldb_exe).arg("-P")).ok();
+            let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
             if let Some(ref dir) = lldb_python_dir {
                 cmd.arg("--lldb-python-dir").arg(dir);
             }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index ed45bc30362..0167c51fc7e 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -329,6 +329,7 @@ pub struct Config {
     pub nodejs: Option<PathBuf>,
     pub npm: Option<PathBuf>,
     pub gdb: Option<PathBuf>,
+    pub lldb: Option<PathBuf>,
     pub python: Option<PathBuf>,
     pub reuse: Option<PathBuf>,
     pub cargo_native_static: bool,
@@ -834,6 +835,7 @@ define_config! {
         docs_minification: Option<bool> = "docs-minification",
         submodules: Option<bool> = "submodules",
         gdb: Option<String> = "gdb",
+        lldb: Option<String> = "lldb",
         nodejs: Option<String> = "nodejs",
         npm: Option<String> = "npm",
         python: Option<String> = "python",
@@ -1410,6 +1412,7 @@ impl Config {
             docs_minification,
             submodules,
             gdb,
+            lldb,
             nodejs,
             npm,
             python,
@@ -1502,6 +1505,7 @@ impl Config {
         config.nodejs = nodejs.map(PathBuf::from);
         config.npm = npm.map(PathBuf::from);
         config.gdb = gdb.map(PathBuf::from);
+        config.lldb = lldb.map(PathBuf::from);
         config.python = python.map(PathBuf::from);
         config.reuse = reuse.map(PathBuf::from);
         config.submodules = submodules;
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index db3df598a0c..c3a03693f71 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -175,4 +175,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.",
     },
+    ChangeInfo {
+        change_id: 124501,
+        severity: ChangeSeverity::Info,
+        summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests",
+    },
 ];
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index fcc507b572c..22dcb808c74 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -50,39 +50,35 @@ fi
 CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}"
 
 if [ -f "$docker_dir/$image/Dockerfile" ]; then
-    if isCI; then
-      hash_key=/tmp/.docker-hash-key.txt
-      rm -f "${hash_key}"
-      echo $image >> $hash_key
-
-      cat "$docker_dir/$image/Dockerfile" >> $hash_key
-      # Look for all source files involves in the COPY command
-      copied_files=/tmp/.docker-copied-files.txt
-      rm -f "$copied_files"
-      for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
-          "$docker_dir/$image/Dockerfile"); do
-        # List the file names
-        find "$script_dir/$i" -type f >> $copied_files
-      done
-      # Sort the file names and cat the content into the hash key
-      sort $copied_files | xargs cat >> $hash_key
-
-      # Include the architecture in the hash key, since our Linux CI does not
-      # only run in x86_64 machines.
-      uname -m >> $hash_key
-
-      docker --version >> $hash_key
-
-      # Include cache version. Can be used to manually bust the Docker cache.
-      echo "2" >> $hash_key
-
-      echo "Image input"
-      cat $hash_key
-
-      cksum=$(sha512sum $hash_key | \
-        awk '{print $1}')
-      echo "Image input checksum ${cksum}"
-    fi
+    hash_key=/tmp/.docker-hash-key.txt
+    rm -f "${hash_key}"
+    echo $image >> $hash_key
+
+    cat "$docker_dir/$image/Dockerfile" >> $hash_key
+    # Look for all source files involves in the COPY command
+    copied_files=/tmp/.docker-copied-files.txt
+    rm -f "$copied_files"
+    for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
+      "$docker_dir/$image/Dockerfile"); do
+    # List the file names
+    find "$script_dir/$i" -type f >> $copied_files
+    done
+    # Sort the file names and cat the content into the hash key
+    sort $copied_files | xargs cat >> $hash_key
+
+    # Include the architecture in the hash key, since our Linux CI does not
+    # only run in x86_64 machines.
+    uname -m >> $hash_key
+
+    # Include cache version. Can be used to manually bust the Docker cache.
+    echo "2" >> $hash_key
+
+    echo "Image input"
+    cat $hash_key
+
+    cksum=$(sha512sum $hash_key | \
+    awk '{print $1}')
+    echo "Image input checksum ${cksum}"
 
     dockerfile="$docker_dir/$image/Dockerfile"
     if [ -x /usr/bin/cygpath ]; then
@@ -105,10 +101,18 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
     # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
     CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
 
-    # On non-CI jobs, we don't do any caching.
+    # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci
+    # ghcr.io registry. If it is not possible, we fall back to building the image
+    # locally.
     if ! isCI;
     then
-        retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+        if docker pull "${IMAGE_TAG}"; then
+            echo "Downloaded Docker image from CI"
+            docker tag "${IMAGE_TAG}" rust-ci
+        else
+            echo "Building local Docker image"
+            retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+        fi
     # On PR CI jobs, we don't have permissions to write to the registry cache,
     # but we can still read from it.
     elif [[ "$PR_CI_JOB" == "1" ]];
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f47c84842b1..3b1d7687d02 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -95,6 +95,7 @@ pub use rustc_const_eval::interpret::*;
 #[doc(no_inline)]
 pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};
 
+pub use crate::shims::EmulateItemResult;
 pub use crate::shims::env::{EnvVars, EvalContextExt as _};
 pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _};
 pub use crate::shims::intrinsics::EvalContextExt as _;
diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs
index b5ae06c2a49..79531598c00 100644
--- a/src/tools/miri/src/shims/alloc.rs
+++ b/src/tools/miri/src/shims/alloc.rs
@@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_target::abi::{Align, Size};
 
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 /// Check some basic requirements for this allocation request:
 /// non-zero size, power-of-two alignment.
@@ -55,12 +54,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn emulate_allocator(
         &mut self,
         default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
             // in real code, this symbol does not exist without an allocator
-            return Ok(EmulateForeignItemResult::NotSupported);
+            return Ok(EmulateItemResult::NotSupported);
         };
 
         match allocator_kind {
@@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // and not execute any Miri shim. Somewhat unintuitively doing so is done
                 // by returning `NotSupported`, which triggers the `lookup_exported_symbol`
                 // fallback case in `emulate_foreign_item`.
-                return Ok(EmulateForeignItemResult::NotSupported);
+                return Ok(EmulateItemResult::NotSupported);
             }
             AllocatorKind::Default => {
                 default(this)?;
-                Ok(EmulateForeignItemResult::NeedsJumping)
+                Ok(EmulateItemResult::NeedsJumping)
             }
         }
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 636361148a4..8a38c6c11a8 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -28,16 +28,6 @@ impl DynSym {
     }
 }
 
-/// Returned by `emulate_foreign_item_inner`.
-pub enum EmulateForeignItemResult {
-    /// The caller is expected to jump to the return block.
-    NeedsJumping,
-    /// Jumping has already been taken care of.
-    AlreadyJumped,
-    /// The item is not supported.
-    NotSupported,
-}
-
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Emulates calling a foreign item, failing if the item is not supported.
@@ -58,84 +48,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let tcx = this.tcx.tcx;
 
-        // First: functions that diverge.
-        let ret = match ret {
-            None =>
-                match link_name.as_str() {
-                    "miri_start_unwind" => {
-                        // `check_shim` happens inside `handle_miri_start_unwind`.
-                        this.handle_miri_start_unwind(abi, link_name, args, unwind)?;
-                        return Ok(None);
-                    }
-                    // This matches calls to the foreign item `panic_impl`.
-                    // The implementation is provided by the function with the `#[panic_handler]` attribute.
-                    "panic_impl" => {
-                        // We don't use `check_shim` here because we are just forwarding to the lang
-                        // item. Argument count checking will be performed when the returned `Body` is
-                        // called.
-                        this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?;
-                        let panic_impl_id = tcx.lang_items().panic_impl().unwrap();
-                        let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id);
-                        return Ok(Some((
-                            this.load_mir(panic_impl_instance.def, None)?,
-                            panic_impl_instance,
-                        )));
-                    }
-                    "__rust_alloc_error_handler" => {
-                        // Forward to the right symbol that implements this function.
-                        let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
-                            // in real code, this symbol does not exist without an allocator
-                            throw_unsup_format!(
-                                "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
-                            );
-                        };
-                        let name = alloc_error_handler_name(handler_kind);
-                        let handler = this
-                            .lookup_exported_symbol(Symbol::intern(name))?
-                            .expect("missing alloc error handler symbol");
-                        return Ok(Some(handler));
-                    }
-                    #[rustfmt::skip]
-                    | "exit"
-                    | "ExitProcess"
-                    => {
-                        let exp_abi = if link_name.as_str() == "exit" {
-                            Abi::C { unwind: false }
-                        } else {
-                            Abi::System { unwind: false }
-                        };
-                        let [code] = this.check_shim(abi, exp_abi, link_name, args)?;
-                        // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
-                        let code = this.read_scalar(code)?.to_i32()?;
-                        throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
-                    }
-                    "abort" => {
-                        let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                        throw_machine_stop!(TerminationInfo::Abort(
-                            "the program aborted execution".to_owned()
-                        ))
-                    }
-                    _ => {
-                        if let Some(body) = this.lookup_exported_symbol(link_name)? {
-                            return Ok(Some(body));
-                        }
-                        this.handle_unsupported(format!(
-                            "can't call (diverging) foreign function: {link_name}"
-                        ))?;
-                        return Ok(None);
-                    }
-                },
-            Some(p) => p,
-        };
+        // Some shims forward to other MIR bodies.
+        match link_name.as_str() {
+            // This matches calls to the foreign item `panic_impl`.
+            // The implementation is provided by the function with the `#[panic_handler]` attribute.
+            "panic_impl" => {
+                // We don't use `check_shim` here because we are just forwarding to the lang
+                // item. Argument count checking will be performed when the returned `Body` is
+                // called.
+                this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?;
+                let panic_impl_id = tcx.lang_items().panic_impl().unwrap();
+                let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id);
+                return Ok(Some((
+                    this.load_mir(panic_impl_instance.def, None)?,
+                    panic_impl_instance,
+                )));
+            }
+            "__rust_alloc_error_handler" => {
+                // Forward to the right symbol that implements this function.
+                let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
+                    // in real code, this symbol does not exist without an allocator
+                    throw_unsup_format!(
+                        "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
+                    );
+                };
+                let name = alloc_error_handler_name(handler_kind);
+                let handler = this
+                    .lookup_exported_symbol(Symbol::intern(name))?
+                    .expect("missing alloc error handler symbol");
+                return Ok(Some(handler));
+            }
+            _ => {}
+        }
 
-        // Second: functions that return immediately.
-        match this.emulate_foreign_item_inner(link_name, abi, args, dest)? {
-            EmulateForeignItemResult::NeedsJumping => {
+        // The rest either implements the logic, or falls back to `lookup_exported_symbol`.
+        match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? {
+            EmulateItemResult::NeedsJumping => {
                 trace!("{:?}", this.dump_place(&dest.clone().into()));
-                this.go_to_block(ret);
+                this.return_to_block(ret)?;
             }
-            EmulateForeignItemResult::AlreadyJumped => (),
-            EmulateForeignItemResult::NotSupported => {
+            EmulateItemResult::AlreadyJumped => (),
+            EmulateItemResult::NotSupported => {
                 if let Some(body) = this.lookup_exported_symbol(link_name)? {
                     return Ok(Some(body));
                 }
@@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+        unwind: mir::UnwindAction,
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         // First deal with any external C functions in linked .so file.
@@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // by the specified `.so` file; we should continue and check if it corresponds to
             // a provided shim.
             if this.call_external_c_fct(link_name, dest, args)? {
-                return Ok(EmulateForeignItemResult::NeedsJumping);
+                return Ok(EmulateItemResult::NeedsJumping);
             }
         }
 
@@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // shim, add it to the corresponding submodule.
         match link_name.as_str() {
             // Miri-specific extern functions
+            "miri_start_unwind" => {
+                // `check_shim` happens inside `handle_miri_start_unwind`.
+                this.handle_miri_start_unwind(abi, link_name, args, unwind)?;
+                return Ok(EmulateItemResult::AlreadyJumped);
+            }
             "miri_run_provenance_gc" => {
                 let [] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 this.run_provenance_gc();
@@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Return value: 0 on success, otherwise the size it would have needed.
                 this.write_int(if success { 0 } else { needed_size }, dest)?;
             }
-
             // Obtains the size of a Miri backtrace. See the README for details.
             "miri_backtrace_size" => {
                 this.handle_miri_backtrace_size(abi, link_name, args, dest)?;
             }
-
             // Obtains a Miri backtrace. See the README for details.
             "miri_get_backtrace" => {
                 // `check_shim` happens inside `handle_miri_get_backtrace`.
                 this.handle_miri_get_backtrace(abi, link_name, args, dest)?;
             }
-
             // Resolves a Miri backtrace frame. See the README for details.
             "miri_resolve_frame" => {
                 // `check_shim` happens inside `handle_miri_resolve_frame`.
                 this.handle_miri_resolve_frame(abi, link_name, args, dest)?;
             }
-
             // Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details.
             "miri_resolve_frame_names" => {
                 this.handle_miri_resolve_frame_names(abi, link_name, args)?;
             }
-
             // Writes some bytes to the interpreter's stdout/stderr. See the
             // README for details.
             "miri_write_to_stdout" | "miri_write_to_stderr" => {
@@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     _ => unreachable!(),
                 };
             }
-
             // Promises that a pointer has a given symbolic alignment.
             "miri_promise_symbolic_alignment" => {
                 use rustc_target::abi::AlignFromBytesError;
@@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
 
+            // Aborting the process.
+            "exit" | "ExitProcess" => {
+                let exp_abi = if link_name.as_str() == "exit" {
+                    Abi::C { unwind: false }
+                } else {
+                    Abi::System { unwind: false }
+                };
+                let [code] = this.check_shim(abi, exp_abi, link_name, args)?;
+                // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
+                let code = this.read_scalar(code)?.to_i32()?;
+                throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
+            }
+            "abort" => {
+                let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                throw_machine_stop!(TerminationInfo::Abort(
+                    "the program aborted execution".to_owned()
+                ))
+            }
+
             // Standard C allocation
             "malloc" => {
                 let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -504,7 +476,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "__rust_alloc" => return this.emulate_allocator(default),
                     "miri_alloc" => {
                         default(this)?;
-                        return Ok(EmulateForeignItemResult::NeedsJumping);
+                        return Ok(EmulateItemResult::NeedsJumping);
                     }
                     _ => unreachable!(),
                 }
@@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     }
                     "miri_dealloc" => {
                         default(this)?;
-                        return Ok(EmulateForeignItemResult::NeedsJumping);
+                        return Ok(EmulateItemResult::NeedsJumping);
                     }
                     _ => unreachable!(),
                 }
@@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner(
                             this, link_name, abi, args, dest,
                         ),
-                    _ => Ok(EmulateForeignItemResult::NotSupported),
+                    _ => Ok(EmulateItemResult::NotSupported),
                 },
         };
         // We only fall through to here if we did *not* hit the `_` arm above,
         // i.e., if we actually emulated the function with one of the shims.
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs
index 4c5e2192e5c..40f6b8a64ef 100644
--- a/src/tools/miri/src/shims/intrinsics/atomic.rs
+++ b/src/tools/miri/src/shims/intrinsics/atomic.rs
@@ -20,7 +20,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         intrinsic_name: &str,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, bool> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         let intrinsic_structure: Vec<_> = intrinsic_name.split('_').collect();
@@ -114,9 +114,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
             }
 
-            _ => return Ok(false),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(true)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
 
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 2bf6980200f..974943432aa 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -10,8 +10,8 @@ use rustc_middle::{
     mir,
     ty::{self, FloatTy},
 };
-use rustc_target::abi::Size;
 use rustc_span::{sym, Symbol};
+use rustc_target::abi::Size;
 
 use crate::*;
 use atomic::EvalContextExt as _;
@@ -37,51 +37,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let intrinsic_name = this.tcx.item_name(instance.def_id());
         let intrinsic_name = intrinsic_name.as_str();
 
-        // Handle intrinsics without return place.
-        match intrinsic_name {
-            "abort" => {
-                throw_machine_stop!(TerminationInfo::Abort(
-                    "the program aborted execution".to_owned()
-                ))
-            }
-            _ => {}
-        }
-
-        // All remaining supported intrinsics have a return place.
-        let ret = match ret {
-            // FIXME: add fallback body support once we actually have a diverging intrinsic with a fallback body
-            None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"),
-            Some(p) => p,
-        };
-
-        // Some intrinsics are special and need the "ret".
-        match intrinsic_name {
-            "catch_unwind" => {
-                this.handle_catch_unwind(args, dest, ret)?;
-                return Ok(None);
-            }
-            _ => {}
-        }
-
-        // The rest jumps to `ret` immediately.
-        if !this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)? {
-            // We haven't handled the intrinsic, let's see if we can use a fallback body.
-            if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
-                throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`")
+        match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? {
+            EmulateItemResult::NotSupported => {
+                // We haven't handled the intrinsic, let's see if we can use a fallback body.
+                if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
+                    throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`")
+                }
+                let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub");
+                if this
+                    .tcx
+                    .get_attrs_by_path(
+                        instance.def_id(),
+                        &[sym::miri, intrinsic_fallback_checks_ub],
+                    )
+                    .next()
+                    .is_none()
+                {
+                    throw_unsup_format!(
+                        "miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that"
+                    );
+                }
+                Ok(Some(ty::Instance {
+                    def: ty::InstanceDef::Item(instance.def_id()),
+                    args: instance.args,
+                }))
             }
-            let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub");
-            if this.tcx.get_attrs_by_path(instance.def_id(), &[sym::miri, intrinsic_fallback_checks_ub]).next().is_none() {
-                throw_unsup_format!("miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that");
+            EmulateItemResult::NeedsJumping => {
+                trace!("{:?}", this.dump_place(&dest.clone().into()));
+                this.return_to_block(ret)?;
+                Ok(None)
             }
-            return Ok(Some(ty::Instance {
-                def: ty::InstanceDef::Item(instance.def_id()),
-                args: instance.args,
-            }))
+            EmulateItemResult::AlreadyJumped => Ok(None),
         }
-
-        trace!("{:?}", this.dump_place(&dest.clone().into()));
-        this.go_to_block(ret);
-        Ok(None)
     }
 
     /// Emulates a Miri-supported intrinsic (not supported by the core engine).
@@ -92,7 +79,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, bool> {
+        ret: Option<mir::BasicBlock>,
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         if let Some(name) = intrinsic_name.strip_prefix("atomic_") {
@@ -103,6 +91,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         match intrinsic_name {
+            "abort" => {
+                throw_machine_stop!(TerminationInfo::Abort(
+                    "the program aborted execution".to_owned()
+                ));
+            }
+            "catch_unwind" => {
+                this.handle_catch_unwind(args, dest, ret)?;
+                // THis pushed a stack frame, don't jump to `ret`.
+                return Ok(EmulateItemResult::AlreadyJumped);
+            }
+
             // Raw memory accesses
             "volatile_load" => {
                 let [place] = check_arg_count(args)?;
@@ -426,9 +425,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
             }
 
-            _ => return Ok(false),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
 
-        Ok(true)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index dca4c4ea5ad..c7de587443a 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, bool> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match intrinsic_name {
             #[rustfmt::skip]
@@ -744,9 +744,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
 
-            _ => return Ok(false),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(true)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 
     fn fminmax_op(
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 85c9a202f7d..975efe29b4b 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -16,3 +16,13 @@ pub mod os_str;
 pub mod panic;
 pub mod time;
 pub mod tls;
+
+/// What needs to be done after emulating an item (a shim or an intrinsic) is done.
+pub enum EmulateItemResult {
+    /// The caller is expected to jump to the return block.
+    NeedsJumping,
+    /// Jumping has already been taken care of.
+    AlreadyJumped,
+    /// The item is not supported.
+    NotSupported,
+}
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index bb31ef733cf..4444d297469 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -30,7 +30,7 @@ pub struct CatchUnwindData<'tcx> {
     /// The return place from the original call to `try`.
     dest: MPlaceTy<'tcx, Provenance>,
     /// The return block from the original call to `try`.
-    ret: mir::BasicBlock,
+    ret: Option<mir::BasicBlock>,
 }
 
 impl VisitProvenance for CatchUnwindData<'_> {
@@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-        ret: mir::BasicBlock,
+        ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -103,7 +103,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             &[data.into()],
             None,
             // Directly return to caller.
-            StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue },
+            StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue },
         )?;
 
         // We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
@@ -155,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 None,
                 // Directly return to caller of `try`.
                 StackPopCleanup::Goto {
-                    ret: Some(catch_unwind.ret),
+                    ret: catch_unwind.ret,
                     unwind: mir::UnwindAction::Continue,
                 },
             )?;
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index bd299aaa125..7f6a3ba0887 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -9,7 +9,6 @@ use rustc_target::spec::abi::Abi;
 use crate::shims::alloc::EvalContextExt as _;
 use crate::shims::unix::*;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 use shims::unix::freebsd::foreign_items as freebsd;
 use shims::unix::linux::foreign_items as linux;
@@ -43,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
@@ -750,11 +749,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
                     "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
                     "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
-                    _ => Ok(EmulateForeignItemResult::NotSupported),
+                    _ => Ok(EmulateItemResult::NotSupported),
                 };
             }
         };
 
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index ffb583123d4..1e0e7d16320 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi;
 
 use crate::shims::unix::*;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 pub fn is_dyn_sym(_name: &str) -> bool {
     false
@@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
             // Threading
@@ -97,8 +96,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
             }
 
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 497e8bee70e..dd4ec8cfaa7 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -5,7 +5,6 @@ use crate::machine::SIGRTMAX;
 use crate::machine::SIGRTMIN;
 use crate::shims::unix::*;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 use shims::unix::linux::epoll::EvalContextExt as _;
 use shims::unix::linux::eventfd::EvalContextExt as _;
 use shims::unix::linux::mem::EvalContextExt as _;
@@ -23,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
@@ -156,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     }
                     id => {
                         this.handle_unsupported(format!("can't execute syscall with ID {id}"))?;
-                        return Ok(EmulateForeignItemResult::AlreadyJumped);
+                        return Ok(EmulateItemResult::AlreadyJumped);
                     }
                 }
             }
@@ -204,10 +203,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_null(dest)?;
             }
 
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         };
 
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
 
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 66a8dce753f..912623b7225 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi;
 
 use crate::shims::unix::*;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 pub fn is_dyn_sym(_name: &str) -> bool {
     false
@@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
@@ -175,9 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(res, dest)?;
             }
 
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         };
 
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index e8ae80261c6..08aee04254b 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -12,7 +12,6 @@ use crate::shims::alloc::EvalContextExt as _;
 use crate::shims::os_str::bytes_to_os_str;
 use crate::shims::windows::*;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 use shims::windows::handle::{Handle, PseudoHandle};
 
 fn is_dyn_sym(name: &str) -> bool {
@@ -86,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
         // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
@@ -721,9 +720,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_null(dest)?;
             }
 
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
 
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs
index 6c090d877ea..8dc3748a12d 100644
--- a/src/tools/miri/src/shims/x86/aesni.rs
+++ b/src/tools/miri/src/shims/x86/aesni.rs
@@ -4,7 +4,6 @@ use rustc_span::Symbol;
 use rustc_target::spec::abi::Abi;
 
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "aes")?;
         // Prefix should have already been checked.
@@ -126,9 +125,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
             }
             // TODO: Implement the `llvm.x86.aesni.aeskeygenassist` when possible
             // with an external crate.
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
 
diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs
index 41c20d768f7..86ef180a448 100644
--- a/src/tools/miri/src/shims/x86/avx.rs
+++ b/src/tools/miri/src/shims/x86/avx.rs
@@ -11,7 +11,6 @@ use super::{
     FloatBinOp, FloatUnaryOp,
 };
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -23,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "avx")?;
         // Prefix should have already been checked.
@@ -343,8 +342,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 this.write_scalar(Scalar::from_i32(res.into()), dest)?;
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs
index bbf53f9f1e5..6e3468c0189 100644
--- a/src/tools/miri/src/shims/x86/avx2.rs
+++ b/src/tools/miri/src/shims/x86/avx2.rs
@@ -9,7 +9,6 @@ use super::{
     packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, ShiftOp,
 };
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -21,7 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "avx2")?;
         // Prefix should have already been checked.
@@ -437,8 +436,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 shift_simd_by_simd(this, left, right, which, dest)?;
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index cf4d6a04bec..2ab2ae85905 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -10,7 +10,6 @@ use rustc_target::spec::abi::Abi;
 
 use crate::*;
 use helpers::bool_to_simd_element;
-use shims::foreign_items::EmulateForeignItemResult;
 
 mod aesni;
 mod avx;
@@ -31,7 +30,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         // Prefix should have already been checked.
         let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap();
@@ -43,7 +42,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
             // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html
             "addcarry.32" | "addcarry.64" => {
                 if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" {
-                    return Ok(EmulateForeignItemResult::NotSupported);
+                    return Ok(EmulateItemResult::NotSupported);
                 }
 
                 let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
@@ -69,7 +68,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
             // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html
             "subborrow.32" | "subborrow.64" => {
                 if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" {
-                    return Ok(EmulateForeignItemResult::NotSupported);
+                    return Ok(EmulateItemResult::NotSupported);
                 }
 
                 let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
@@ -143,9 +142,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 );
             }
 
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
 
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index 17608837319..ea967a8cf72 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -8,7 +8,6 @@ use super::{
     FloatUnaryOp,
 };
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -20,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse")?;
         // Prefix should have already been checked.
@@ -211,8 +210,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
                 }
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index c9ed751d36c..31fa66a496f 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -7,7 +7,6 @@ use super::{
     packuswb, shift_simd_by_scalar, FloatBinOp, ShiftOp,
 };
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -19,7 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse2")?;
         // Prefix should have already been checked.
@@ -387,8 +386,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
                 }
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
index 5ac30dca79a..8de339eb9e5 100644
--- a/src/tools/miri/src/shims/x86/sse3.rs
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi;
 
 use super::horizontal_bin_op;
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse3")?;
         // Prefix should have already been checked.
@@ -50,8 +49,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?;
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs
index 19bc27421d3..011a7a16c68 100644
--- a/src/tools/miri/src/shims/x86/sse41.rs
+++ b/src/tools/miri/src/shims/x86/sse41.rs
@@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi;
 
 use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked};
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -15,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?;
         // Prefix should have already been checked.
@@ -175,8 +174,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 this.write_scalar(Scalar::from_i32(res.into()), dest)?;
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs
index 4f8e52dbb7d..d30de430088 100644
--- a/src/tools/miri/src/shims/x86/ssse3.rs
+++ b/src/tools/miri/src/shims/x86/ssse3.rs
@@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi;
 
 use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
 use crate::*;
-use shims::foreign_items::EmulateForeignItemResult;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+    ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "ssse3")?;
         // Prefix should have already been checked.
@@ -136,8 +135,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 psign(this, left, right, dest)?;
             }
-            _ => return Ok(EmulateForeignItemResult::NotSupported),
+            _ => return Ok(EmulateItemResult::NotSupported),
         }
-        Ok(EmulateForeignItemResult::NeedsJumping)
+        Ok(EmulateItemResult::NeedsJumping)
     }
 }
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 09a1c950267..ae2351b82ce 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: no expected values for `feature`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: no expected values for `feature`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -26,8 +26,8 @@ LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `CONFIG_NVME`
   --> $DIR/cargo-feature.rs:26:7
@@ -35,8 +35,8 @@ warning: unexpected `cfg` condition name: `CONFIG_NVME`
 LL | #[cfg(CONFIG_NVME = "m")]
    |       ^^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 4db9c66fc86..191efbf2d54 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -26,8 +26,8 @@ LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
    = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `m`
   --> $DIR/cargo-feature.rs:26:7
@@ -38,8 +38,8 @@ LL | #[cfg(CONFIG_NVME = "m")]
    |                     help: there is a expected value with a similar name: `"y"`
    |
    = note: expected values for `CONFIG_NVME` are: `y`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/diagnotics.cargo.stderr b/tests/ui/check-cfg/diagnotics.cargo.stderr
index 16417fe0105..1b7505682da 100644
--- a/tests/ui/check-cfg/diagnotics.cargo.stderr
+++ b/tests/ui/check-cfg/diagnotics.cargo.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(featur)]
    |       ^^^^^^ help: there is a config with a similar name: `feature`
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `featur`
@@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `featur`
 LL | #[cfg(featur = "foo")]
    |       ^^^^^^^^^^^^^^
    |
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and value
    |
 LL | #[cfg(feature = "foo")]
@@ -27,7 +27,7 @@ LL | #[cfg(featur = "fo")]
    |       ^^^^^^^^^^^^^
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and different values
    |
 LL | #[cfg(feature = "foo")]
@@ -39,8 +39,8 @@ warning: unexpected `cfg` condition name: `no_value`
 LL | #[cfg(no_value)]
    |       ^^^^^^^^ help: there is a config with a similar name: `no_values`
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `no_value`
   --> $DIR/diagnotics.rs:27:7
@@ -48,8 +48,8 @@ warning: unexpected `cfg` condition name: `no_value`
 LL | #[cfg(no_value = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and no value
    |
 LL | #[cfg(no_values)]
@@ -64,8 +64,8 @@ LL | #[cfg(no_values = "bar")]
    |                help: remove the value
    |
    = note: no expected value for `no_values`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
new file mode 100644
index 00000000000..a4d4b7b359e
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo`
+   |
+note: required for `*mut ()` to implement `Foo`
+  --> $DIR/simple.rs:10:9
+   |
+LL | impl<T> Foo for T where T: Send {}
+   |         ^^^     ^          ---- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
new file mode 100644
index 00000000000..1341ca8175a
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
+   |
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
new file mode 100644
index 00000000000..15ff80ae4d9
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
@@ -0,0 +1,23 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+trait Foo {}
+
+#[do_not_recommend]
+impl<T> Foo for T where T: Send {}
+//[current]~^ NOTE required for `*mut ()` to implement `Foo`
+//[current]~| NOTE unsatisfied trait bound introduced here
+
+fn needs_foo<T: Foo>() {}
+//~^ NOTE required by a bound in `needs_foo`
+//~| NOTE required by this bound in `needs_foo`
+
+fn main() {
+    needs_foo::<*mut ()>();
+    //~^ ERROR the trait bound `*mut (): Foo` is not satisfied
+    //[current]~| NOTE the trait `Send` is not implemented for `*mut ()`
+    //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()`
+}
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
index bc9bb6ce2d7..8bb4ff46907 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
@@ -61,7 +61,7 @@ where
     // entering the cycle from `A` fails, but would work if we were to use the cache
     // result of `B<X>`.
     impls_trait::<A<X>, _, _, _>();
-    //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
+    //~^ ERROR the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
 }
 
 fn main() {
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
index 78116ebba82..cdb4ff4588f 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
@@ -1,26 +1,28 @@
-error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
+error[E0277]: the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
   --> $DIR/incompleteness-unstable-result.rs:63:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
-   |                   ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>`
+   |                   ^^^^ the trait `Trait<i32, u8, u8>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
    |
-   = help: the following other types implement trait `IncompleteGuidance<T, V>`:
-             <T as IncompleteGuidance<U, i16>>
-             <T as IncompleteGuidance<U, i8>>
-             <T as IncompleteGuidance<U, u8>>
-note: required for `A<X>` to implement `Trait<_, _, u8>`
+note: required for `A<X>` to implement `Trait<i32, u8, u8>`
   --> $DIR/incompleteness-unstable-result.rs:32:50
    |
 LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
    |                                                  ^^^^^^^^^^^^^^     ^^^^
-LL | where
-LL |     T: IncompleteGuidance<U, V>,
-   |        ------------------------ unsatisfied trait bound introduced here
+...
+LL |     A<T>: Trait<U, D, V>,
+   |           -------------- unsatisfied trait bound introduced here
+   = note: 8 redundant requirements hidden
+   = note: required for `A<X>` to implement `Trait<i32, u8, u8>`
 note: required by a bound in `impls_trait`
   --> $DIR/incompleteness-unstable-result.rs:51:28
    |
 LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
    |                            ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
+help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL |     X: IncompleteGuidance<u32, i16>, A<X>: Trait<i32, u8, u8>
+   |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error