about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs16
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs21
-rw-r--r--compiler/rustc_driver_impl/src/print.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs6
-rw-r--r--compiler/rustc_interface/src/passes.rs12
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_interface/src/util.rs4
-rw-r--r--compiler/rustc_session/src/config/cfg.rs6
-rw-r--r--compiler/rustc_target/src/lib.rs23
-rw-r--r--compiler/rustc_target/src/spec/mod.rs16
-rw-r--r--library/core/src/ffi/va_list.rs1
-rw-r--r--library/std/src/os/unix/process.rs2
-rw-r--r--library/std/src/process.rs16
-rw-r--r--library/std/src/process/tests.rs102
-rw-r--r--library/std/src/sys/env_consts.rs2
-rw-r--r--library/std/src/sys/pal/trusty/mod.rs2
-rw-r--r--library/std/src/sys/pal/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/pal/zkvm/mod.rs2
-rw-r--r--library/std/src/sys/process/unix/unix/tests.rs1
-rw-r--r--library/std/src/sys/process/unix/vxworks.rs3
-rw-r--r--library/std/tests/process_spawning.rs1
-rw-r--r--src/bootstrap/src/core/builder/mod.rs22
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md31
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md22
-rw-r--r--src/doc/rustc/src/platform-support/apple-tvos.md13
-rw-r--r--src/doc/rustc/src/platform-support/apple-visionos.md13
-rw-r--r--src/doc/rustc/src/platform-support/apple-watchos.md13
-rw-r--r--src/tools/remote-test-server/src/main.rs19
-rw-r--r--tests/ui/backtrace/apple-no-dsymutil.rs1
-rw-r--r--tests/ui/backtrace/dylib-dep.rs4
-rw-r--r--tests/ui/backtrace/line-tables-only.rs4
-rw-r--r--tests/ui/command/command-current-dir.rs2
-rw-r--r--tests/ui/command/command-exec.rs2
-rw-r--r--tests/ui/command/command-pre-exec.rs2
-rw-r--r--tests/ui/command/command-uid-gid.rs2
-rw-r--r--tests/ui/compiletest-self-test/test-aux-bin.rs1
-rw-r--r--tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs5
-rw-r--r--tests/ui/issues/issue-45731.rs4
-rw-r--r--tests/ui/process/core-run-destroy.rs4
-rw-r--r--tests/ui/process/env-funky-keys.rs19
-rw-r--r--tests/ui/process/fds-are-cloexec.rs11
-rw-r--r--tests/ui/process/println-with-broken-pipe.rs4
-rw-r--r--tests/ui/process/process-envs.rs4
-rw-r--r--tests/ui/process/process-panic-after-fork.rs2
-rw-r--r--tests/ui/process/process-remove-from-env.rs4
-rw-r--r--tests/ui/process/process-sigpipe.rs4
-rw-r--r--tests/ui/process/process-spawn-failure.rs4
-rw-r--r--tests/ui/runtime/backtrace-debuginfo.rs4
-rw-r--r--tests/ui/runtime/on-broken-pipe/child-processes.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/inherit.rs1
52 files changed, 316 insertions, 168 deletions
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6fb23d09843..13bdb7cb1a2 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -45,6 +45,7 @@ use rustc_middle::util::Providers;
 use rustc_session::Session;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
 use rustc_span::Symbol;
+use rustc_target::spec::{RelocModel, TlsModel};
 
 mod abi;
 mod allocator;
@@ -244,16 +245,7 @@ impl CodegenBackend for LlvmCodegenBackend {
         match req.kind {
             PrintKind::RelocationModels => {
                 writeln!(out, "Available relocation models:").unwrap();
-                for name in &[
-                    "static",
-                    "pic",
-                    "pie",
-                    "dynamic-no-pic",
-                    "ropi",
-                    "rwpi",
-                    "ropi-rwpi",
-                    "default",
-                ] {
+                for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) {
                     writeln!(out, "    {name}").unwrap();
                 }
                 writeln!(out).unwrap();
@@ -267,9 +259,7 @@ impl CodegenBackend for LlvmCodegenBackend {
             }
             PrintKind::TlsModels => {
                 writeln!(out, "Available TLS models:").unwrap();
-                for name in
-                    &["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"]
-                {
+                for name in TlsModel::ALL.iter().map(TlsModel::desc) {
                     writeln!(out, "    {name}").unwrap();
                 }
                 writeln!(out).unwrap();
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 4f875cf99ec..8dab520cf36 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -206,7 +206,7 @@ impl Callbacks for TimePassesCallbacks {
         // time because it will mess up the --print output. See #64339.
         //
         self.time_passes = (config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes)
-            .then(|| config.opts.unstable_opts.time_passes_format);
+            .then_some(config.opts.unstable_opts.time_passes_format);
         config.opts.trimmed_def_paths = true;
     }
 }
@@ -439,8 +439,9 @@ fn make_input(early_dcx: &EarlyDiagCtxt, free_matches: &[String]) -> Option<Inpu
                         "when UNSTABLE_RUSTDOC_TEST_PATH is set \
                                     UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
                     );
-                    let line = isize::from_str_radix(&line, 10)
-                        .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
+                    let line = line
+                        .parse::<isize>()
+                        .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be a number");
                     FileName::doc_test_source_code(PathBuf::from(path), line)
                 }
                 Err(_) => FileName::anon_source_code(&input),
@@ -474,8 +475,7 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col
         let mut text = String::new();
         // Slice off the leading newline and print.
         for line in description.lines() {
-            let indent_level =
-                line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+            let indent_level = line.find(|c: char| !c.is_whitespace()).unwrap_or(line.len());
             let dedented_line = &line[indent_level..];
             if dedented_line.starts_with("```") {
                 is_in_code_block = !is_in_code_block;
@@ -547,7 +547,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
 
     // The pager failed. Try to print pretty output to stdout.
     if let Some((bufwtr, mdbuf)) = &pretty_data
-        && bufwtr.print(&mdbuf).is_ok()
+        && bufwtr.print(mdbuf).is_ok()
     {
         return;
     }
@@ -598,8 +598,7 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
 
 fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
     match sess.io.input {
-        Input::File(ref ifile) => {
-            let path = &(*ifile);
+        Input::File(ref path) => {
             let mut v = Vec::new();
             locator::list_file_metadata(
                 &sess.target,
@@ -833,7 +832,7 @@ fn print_crate_info(
             SupportedCrateTypes => {
                 let supported_crate_types = CRATE_TYPES
                     .iter()
-                    .filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type))
+                    .filter(|(_, crate_type)| !invalid_output_for_target(sess, *crate_type))
                     .filter(|(_, crate_type)| *crate_type != CrateType::Sdylib)
                     .map(|(crate_type_sym, _)| *crate_type_sym)
                     .collect::<BTreeSet<_>>();
@@ -1434,7 +1433,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt))
                 eprintln!();
 
                 if let Some(ice_path) = ice_path()
-                    && let Ok(mut out) = File::options().create(true).append(true).open(&ice_path)
+                    && let Ok(mut out) = File::options().create(true).append(true).open(ice_path)
                 {
                     // The current implementation always returns `Some`.
                     let location = info.location().unwrap();
@@ -1510,7 +1509,7 @@ fn report_ice(
 
     let file = if let Some(path) = ice_path() {
         // Create the ICE dump target file.
-        match crate::fs::File::options().create(true).append(true).open(&path) {
+        match crate::fs::File::options().create(true).append(true).open(path) {
             Ok(mut file) => {
                 dcx.emit_note(session_diagnostics::IcePath { path: path.clone() });
                 if FIRST_PANIC.swap(false, Ordering::SeqCst) {
diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs
index 70de55320f7..3f107eb7a61 100644
--- a/compiler/rustc_driver_impl/src/print.rs
+++ b/compiler/rustc_driver_impl/src/print.rs
@@ -14,7 +14,7 @@ macro_rules! safe_println {
 }
 
 pub(crate) fn print(args: fmt::Arguments<'_>) {
-    if let Err(_) = io::stdout().write_fmt(args) {
+    if io::stdout().write_fmt(args).is_err() {
         rustc_errors::FatalError.raise();
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 7f5397a7926..43a23822fd1 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -254,7 +254,7 @@ fn typeck_with_inspect<'tcx>(
     }
 
     fcx.select_obligations_where_possible(|_| {});
-    if let None = fcx.infcx.tainted_by_errors() {
+    if fcx.infcx.tainted_by_errors().is_none() {
         fcx.report_ambiguity_errors();
     }
 
@@ -295,7 +295,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
     } else if let Node::AnonConst(_) = node {
         let id = tcx.local_def_id_to_hir_id(def_id);
         match tcx.parent_hir_node(id) {
-            Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
+            Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(anon_const), span, .. })
                 if anon_const.hir_id == id =>
             {
                 Some(fcx.next_ty_var(span))
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 06acff06a51..0a7b458f3fb 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -421,7 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Not all upvars are captured by ref, so use
                         // `apply_capture_kind_on_capture_ty` to ensure that we
                         // compute the right captured type.
-                        return apply_capture_kind_on_capture_ty(
+                        apply_capture_kind_on_capture_ty(
                             self.tcx,
                             upvar_ty,
                             capture,
@@ -430,7 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             } else {
                                 self.tcx.lifetimes.re_erased
                             },
-                        );
+                        )
                     },
                 ),
             );
@@ -529,11 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // process any deferred resolutions.
         let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
         for deferred_call_resolution in deferred_call_resolutions {
-            deferred_call_resolution.resolve(&mut FnCtxt::new(
-                self,
-                self.param_env,
-                closure_def_id,
-            ));
+            deferred_call_resolution.resolve(&FnCtxt::new(self, self.param_env, closure_def_id));
         }
     }
 
@@ -1493,7 +1489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Notation:
     /// - Ty(place): Type of place
     /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs`
-    /// respectively.
+    ///   respectively.
     /// ```ignore (illustrative)
     ///                  (Ty(w), [ &[p, x], &[c] ])
     /// //                              |
@@ -2179,9 +2175,10 @@ fn restrict_precision_for_unsafe(
     (place, curr_mode)
 }
 
-/// Truncate projections so that following rules are obeyed by the captured `place`:
+/// Truncate projections so that the following rules are obeyed by the captured `place`:
 /// - No Index projections are captured, since arrays are captured completely.
-/// - No unsafe block is required to capture `place`
+/// - No unsafe block is required to capture `place`.
+///
 /// Returns the truncated place and updated capture mode.
 fn restrict_capture_precision(
     place: Place<'_>,
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 90301d1b391..6192420898f 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -220,7 +220,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     // to use builtin indexing because the index type is known to be
     // usize-ish
     fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
-        if let hir::ExprKind::Index(ref base, ref index, _) = e.kind {
+        if let hir::ExprKind::Index(base, index, _) = e.kind {
             // All valid indexing looks like this; might encounter non-valid indexes at this point.
             let base_ty = self.typeck_results.expr_ty_adjusted(base);
             if let ty::Ref(_, base_ty_inner, _) = *base_ty.kind() {
@@ -583,7 +583,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             }
 
             if let Err(err) = opaque_type_has_defining_use_args(
-                &self.fcx,
+                self.fcx,
                 opaque_type_key,
                 hidden_type.span,
                 DefiningScopeKind::HirTypeck,
@@ -792,7 +792,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     fn visit_potentially_region_dependent_goals(&mut self) {
         let obligations = self.fcx.take_hir_typeck_potentially_region_dependent_goals();
-        if let None = self.fcx.tainted_by_errors() {
+        if self.fcx.tainted_by_errors().is_none() {
             for obligation in obligations {
                 let (predicate, mut cause) =
                     self.fcx.resolve_vars_if_possible((obligation.predicate, obligation.cause));
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index d39219bfd66..6cefe887530 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -192,7 +192,7 @@ fn configure_and_expand(
             unsafe {
                 env::set_var(
                     "PATH",
-                    &env::join_paths(
+                    env::join_paths(
                         new_path.iter().filter(|p| env::join_paths(iter::once(p)).is_ok()),
                     )
                     .unwrap(),
@@ -446,7 +446,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
                 let prev_source = sess.psess.source_map().span_to_prev_source(first_span);
                 let ferris_fix = prev_source
                     .map_or(FerrisFix::SnakeCase, |source| {
-                        let mut source_before_ferris = source.trim_end().split_whitespace().rev();
+                        let mut source_before_ferris = source.split_whitespace().rev();
                         match source_before_ferris.next() {
                             Some("struct" | "trait" | "mod" | "union" | "type" | "enum") => {
                                 FerrisFix::PascalCase
@@ -500,7 +500,7 @@ fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr>
     // properly change-tracked.
     tcx.sess.psess.env_depinfo.borrow_mut().insert((
         Symbol::intern(&key.to_string_lossy()),
-        value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)),
+        value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(value)),
     ));
 
     value_tcx
@@ -824,7 +824,7 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) {
 
     let outputs = tcx.output_filenames(());
     let output_paths =
-        generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name);
+        generated_output_paths(tcx, outputs, sess.io.output_file.is_some(), crate_name);
 
     // Ensure the source file isn't accidentally overwritten during compilation.
     if let Some(input_path) = sess.io.input.opt_path() {
@@ -847,7 +847,7 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) {
         }
     }
 
-    write_out_deps(tcx, &outputs, &output_paths);
+    write_out_deps(tcx, outputs, &output_paths);
 
     let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
         && sess.opts.output_types.len() == 1;
@@ -1303,7 +1303,7 @@ pub(crate) fn parse_crate_name(
     let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) =
         AttributeParser::parse_limited_should_emit(
             sess,
-            &attrs,
+            attrs,
             sym::crate_name,
             DUMMY_SP,
             rustc_ast::node_id::CRATE_NODE_ID,
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 370e886c525..280214ab418 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -94,7 +94,7 @@ impl Linker {
                 &rlink_file,
                 &codegen_results,
                 &self.metadata,
-                &*self.output_filenames,
+                &self.output_filenames,
             )
             .unwrap_or_else(|error| {
                 sess.dcx().emit_fatal(FailedWritingFile { path: &rlink_file, error })
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 061c764e619..26e09c95e76 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -243,7 +243,7 @@ pub(crate) fn run_in_thread_pool_with_globals<
                                 let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || {
                                     // Ensure there was no errors collecting all active jobs.
                                     // We need the complete map to ensure we find a cycle to break.
-                                    QueryCtxt::new(tcx).collect_active_jobs().ok().expect("failed to collect active queries in deadlock handler")
+                                    QueryCtxt::new(tcx).collect_active_jobs().expect("failed to collect active queries in deadlock handler")
                                 });
                                 break_query_cycles(query_map, &registry);
                             })
@@ -561,7 +561,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
                 }
                 Some(out_file.clone())
             };
-            if sess.io.output_dir != None {
+            if sess.io.output_dir.is_some() {
                 sess.dcx().emit_warn(errors::IgnoringOutDir);
             }
 
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 8f63ce6f0ae..7e970461ab7 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -374,11 +374,13 @@ impl CheckCfg {
 
         ins!(sym::overflow_checks, no_values);
 
-        ins!(sym::panic, empty_values).extend(&PanicStrategy::all());
+        ins!(sym::panic, empty_values)
+            .extend(PanicStrategy::ALL.iter().map(PanicStrategy::desc_symbol));
 
         ins!(sym::proc_macro, no_values);
 
-        ins!(sym::relocation_model, empty_values).extend(RelocModel::all());
+        ins!(sym::relocation_model, empty_values)
+            .extend(RelocModel::ALL.iter().map(RelocModel::desc_symbol));
 
         let sanitize_values = SanitizerSet::all()
             .into_iter()
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index b3fe1fffcce..8c6a77cba8b 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -76,10 +76,10 @@ fn find_relative_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
 macro_rules! target_spec_enum {
     (
         $( #[$attr:meta] )*
-        pub enum $name:ident {
+        pub enum $Name:ident {
             $(
                 $( #[$variant_attr:meta] )*
-                $variant:ident = $string:literal,
+                $Variant:ident = $string:literal,
             )*
         }
         parse_error_type = $parse_error_type:literal;
@@ -87,20 +87,20 @@ macro_rules! target_spec_enum {
         $( #[$attr] )*
         #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
         #[derive(schemars::JsonSchema)]
-        pub enum $name {
+        pub enum $Name {
             $(
                 $( #[$variant_attr] )*
                 #[serde(rename = $string)] // for JSON schema generation only
-                $variant,
+                $Variant,
             )*
         }
 
-        impl FromStr for $name {
+        impl FromStr for $Name {
             type Err = String;
 
             fn from_str(s: &str) -> Result<Self, Self::Err> {
                 Ok(match s {
-                    $( $string => Self::$variant, )*
+                    $( $string => Self::$Variant, )*
                     _ => {
                         let all = [$( concat!("'", $string, "'") ),*].join(", ");
                         return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type));
@@ -109,24 +109,25 @@ macro_rules! target_spec_enum {
             }
         }
 
-        impl $name {
+        impl $Name {
+            pub const ALL: &'static [$Name] = &[ $( $Name::$Variant, )* ];
             pub fn desc(&self) -> &'static str {
                 match self {
-                    $( Self::$variant => $string, )*
+                    $( Self::$Variant => $string, )*
                 }
             }
         }
 
-        impl crate::json::ToJson for $name {
+        impl crate::json::ToJson for $Name {
             fn to_json(&self) -> crate::json::Json {
                 self.desc().to_json()
             }
         }
 
-        crate::json::serde_deserialize_from_str!($name);
+        crate::json::serde_deserialize_from_str!($Name);
 
 
-        impl std::fmt::Display for $name {
+        impl std::fmt::Display for $Name {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                 f.write_str(self.desc())
             }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 07fb1ce63f7..f705af52bd8 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -854,10 +854,6 @@ impl PanicStrategy {
             PanicStrategy::Abort => sym::abort,
         }
     }
-
-    pub const fn all() -> [Symbol; 2] {
-        [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
-    }
 }
 
 crate::target_spec_enum! {
@@ -974,18 +970,6 @@ impl RelocModel {
             RelocModel::RopiRwpi => sym::ropi_rwpi,
         }
     }
-
-    pub const fn all() -> [Symbol; 7] {
-        [
-            RelocModel::Static.desc_symbol(),
-            RelocModel::Pic.desc_symbol(),
-            RelocModel::Pie.desc_symbol(),
-            RelocModel::DynamicNoPic.desc_symbol(),
-            RelocModel::Ropi.desc_symbol(),
-            RelocModel::Rwpi.desc_symbol(),
-            RelocModel::RopiRwpi.desc_symbol(),
-        ]
-    }
 }
 
 crate::target_spec_enum! {
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index 643bd95df84..0d4ccb5aeb2 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -2,6 +2,7 @@
 //!
 //! Better known as "varargs".
 
+#[cfg(not(target_arch = "xtensa"))]
 use crate::ffi::c_void;
 #[allow(unused_imports)]
 use crate::fmt;
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 09429af06e3..5b7b5a8ea80 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -406,8 +406,10 @@ pub trait ChildExt: Sealed {
     /// use libc::SIGTERM;
     ///
     /// fn main() -> io::Result<()> {
+    ///     # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
     ///     let child = Command::new("cat").stdin(Stdio::piped()).spawn()?;
     ///     child.send_signal(SIGTERM)?;
+    ///     # }
     ///     Ok(())
     /// }
     /// ```
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 48265de90c4..0883e56342c 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -532,6 +532,7 @@ impl fmt::Debug for ChildStderr {
 /// to be changed (for example, by adding arguments) prior to spawning:
 ///
 /// ```
+/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
 /// use std::process::Command;
 ///
 /// let output = if cfg!(target_os = "windows") {
@@ -548,6 +549,7 @@ impl fmt::Debug for ChildStderr {
 /// };
 ///
 /// let hello = output.stdout;
+/// # }
 /// ```
 ///
 /// `Command` can be reused to spawn multiple processes. The builder methods
@@ -1348,7 +1350,7 @@ impl Output {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     /// assert!(Command::new("false").output().unwrap().exit_ok().is_err());
     /// # }
@@ -1695,7 +1697,7 @@ impl From<io::Stdout> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1724,7 +1726,7 @@ impl From<io::Stderr> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1800,7 +1802,7 @@ impl ExitStatus {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # if cfg!(unix) {
+    /// # if cfg!(all(unix, not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::process::Command;
     ///
     /// let status = Command::new("ls")
@@ -1907,7 +1909,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
 ///
 /// ```
 /// #![feature(exit_status_error)]
-/// # if cfg!(all(unix, not(target_os = "android"))) {
+/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
 /// use std::process::{Command, ExitStatusError};
 ///
 /// fn run(cmd: &str) -> Result<(), ExitStatusError> {
@@ -1950,7 +1952,7 @@ impl ExitStatusError {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     ///
     /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
@@ -1975,7 +1977,7 @@ impl ExitStatusError {
     /// ```
     /// #![feature(exit_status_error)]
     ///
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::num::NonZero;
     /// use std::process::Command;
     ///
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 5879914ca20..12c5130defe 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -5,7 +5,15 @@ use crate::mem::MaybeUninit;
 use crate::str;
 
 fn known_command() -> Command {
-    if cfg!(windows) { Command::new("help") } else { Command::new("echo") }
+    if cfg!(windows) {
+        Command::new("help")
+    } else if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
+        // iOS/tvOS/watchOS/visionOS have a very limited set of commandline
+        // binaries available.
+        Command::new("log")
+    } else {
+        Command::new("echo")
+    }
 }
 
 #[cfg(target_os = "android")]
@@ -19,7 +27,10 @@ fn shell_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn smoke() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 0"]).spawn()
@@ -41,7 +52,10 @@ fn smoke_failure() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn exit_reported_right() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn()
@@ -56,7 +70,10 @@ fn exit_reported_right() {
 
 #[test]
 #[cfg(unix)]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn signal_reported_right() {
     use crate::os::unix::process::ExitStatusExt;
 
@@ -80,7 +97,10 @@ pub fn run_output(mut cmd: Command) -> String {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdout_works() {
     if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -94,7 +114,11 @@ fn stdout_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn set_current_dir_works() {
     // On many Unix platforms this will use the posix_spawn path.
     let mut cmd = shell_cmd();
@@ -116,7 +140,11 @@ fn set_current_dir_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdin_works() {
     let mut p = shell_cmd()
         .arg("-c")
@@ -134,7 +162,10 @@ fn stdin_works() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn child_stdout_read_buf() {
     let mut cmd = if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -165,7 +196,10 @@ fn child_stdout_read_buf() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_status() {
     let mut status = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
@@ -191,7 +225,10 @@ fn test_process_output_fail_to_start() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_output() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
@@ -206,7 +243,10 @@ fn test_process_output_output() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_error() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
@@ -221,7 +261,10 @@ fn test_process_output_error() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_once() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -232,7 +275,10 @@ fn test_finish_once() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_twice() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -244,7 +290,10 @@ fn test_finish_twice() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_wait_with_output_once() {
     let prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
@@ -279,7 +328,10 @@ pub fn env_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_override_env() {
     use crate::env;
 
@@ -302,7 +354,10 @@ fn test_override_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_add_to_env() {
     let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
     let output = String::from_utf8_lossy(&result.stdout).to_string();
@@ -314,7 +369,10 @@ fn test_add_to_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_capture_env_at_spawn() {
     use crate::env;
 
@@ -378,7 +436,10 @@ fn test_interior_nul_in_current_dir_is_error() {
 
 // Regression tests for #30862.
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_key_is_error() {
     match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
@@ -387,7 +448,10 @@ fn test_interior_nul_in_env_key_is_error() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_value_is_error() {
     match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs
index 9683fd47cf9..711ba0a5f8a 100644
--- a/library/std/src/sys/env_consts.rs
+++ b/library/std/src/sys/env_consts.rs
@@ -2,7 +2,7 @@
 
 // Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates.
 // This ensures that they must be mutually exclusive and do not have precedence
-// like cfg_if!.
+// like cfg_select!.
 macro cfg_unordered(
     $(#[cfg($cfg:meta)] $os:item)*
     #[else] $fallback:item
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
index 275f6062463..cf0c098f8a2 100644
--- a/library/std/src/sys/pal/trusty/mod.rs
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -7,8 +7,6 @@ mod common;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/thread.rs"]
-pub mod thread;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 5e3295b1331..e64bbc7c616 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -2,7 +2,6 @@
 
 pub mod os;
 pub mod pipe;
-pub mod thread;
 pub mod time;
 
 mod common;
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index e1efa240685..9069c8d12fa 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -14,8 +14,6 @@ pub mod abi;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/thread.rs"]
-pub mod thread;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/process/unix/unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs
index f4d6ac6b4e3..663ba61f966 100644
--- a/library/std/src/sys/process/unix/unix/tests.rs
+++ b/library/std/src/sys/process/unix/unix/tests.rs
@@ -51,6 +51,7 @@ fn exitstatus_display_tests() {
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn test_command_fork_no_unwind() {
     let got = catch_unwind(|| {
         let mut c = Command::new("echo");
diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs
index 2275cbb946a..b9298f5fa44 100644
--- a/library/std/src/sys/process/unix/vxworks.rs
+++ b/library/std/src/sys/process/unix/vxworks.rs
@@ -4,8 +4,7 @@ use libc::{self, RTP_ID, c_char, c_int};
 use super::common::*;
 use crate::io::{self, ErrorKind};
 use crate::num::NonZero;
-use crate::sys::cvt;
-use crate::sys::pal::thread;
+use crate::sys::{cvt, thread};
 use crate::{fmt, sys};
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs
index 43b45cb2d2b..93f73ccad3e 100644
--- a/library/std/tests/process_spawning.rs
+++ b/library/std/tests/process_spawning.rs
@@ -7,6 +7,7 @@ mod common;
 #[test]
 // Process spawning not supported by Miri, Emscripten and wasi
 #[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn issue_15149() {
     // If we're the parent, copy our own binary to a new directory.
     let my_path = env::current_exe().unwrap();
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 75c8ee36528..8226b4325b6 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -590,18 +590,30 @@ impl StepDescription {
         // Attempt to resolve paths to be relative to the builder source directory.
         let mut paths: Vec<PathBuf> = paths
             .iter()
-            .map(|p| {
+            .map(|original_path| {
+                let mut path = original_path.clone();
+
+                // Someone could run `x <cmd> <path>` from a different repository than the source
+                // directory.
+                // In that case, we should not try to resolve the paths relative to the working
+                // directory, but rather relative to the source directory.
+                // So we forcefully "relocate" the path to the source directory here.
+                if !path.is_absolute() {
+                    path = builder.src.join(path);
+                }
+
                 // If the path does not exist, it may represent the name of a Step, such as `tidy` in `x test tidy`
-                if !p.exists() {
-                    return p.clone();
+                if !path.exists() {
+                    // Use the original path here
+                    return original_path.clone();
                 }
 
                 // Make the path absolute, strip the prefix, and convert to a PathBuf.
-                match std::path::absolute(p) {
+                match std::path::absolute(&path) {
                     Ok(p) => p.strip_prefix(&builder.src).unwrap_or(&p).to_path_buf(),
                     Err(e) => {
                         eprintln!("ERROR: {e:?}");
-                        panic!("Due to the above error, failed to resolve path: {p:?}");
+                        panic!("Due to the above error, failed to resolve path: {path:?}");
                     }
                 }
             })
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index 317b65f98cd..482f3c42578 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -339,9 +339,34 @@ results.  The Docker image is set up to launch `remote-test-server` and the
 build tools use `remote-test-client` to communicate with the server to
 coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 
-> **TODO**
->
-> - Is there any support for using an iOS emulator?
+To run on the iOS/tvOS/watchOS/visionOS simulator, we can similarly treat it as
+a "remote" machine. A curious detail here is that the network is shared between
+the simulator instance and the host macOS, so we can use the local loopback
+address `127.0.0.1`. Something like the following should work:
+
+```sh
+# Build the test server for the iOS simulator:
+./x build src/tools/remote-test-server --target aarch64-apple-ios-sim
+
+# If you already have a simulator instance open, copy the device UUID from:
+xcrun simctl list devices booted
+UDID=01234567-89AB-CDEF-0123-456789ABCDEF
+
+# Alternatively, create and boot a new simulator instance:
+xcrun simctl list runtimes
+xcrun simctl list devicetypes
+UDID=$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME)
+xcrun simctl boot $UDID
+# See https://nshipster.com/simctl/ for details.
+
+# Spawn the runner on port 12345:
+xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345
+
+# In a new terminal, run tests via the runner:
+export TEST_DEVICE_ADDR="127.0.0.1:12345"
+./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo
+# FIXME(madsmtm): Allow debuginfo tests to work (maybe needs `.dSYM` folder to be copied to the target?).
+```
 
 [armhf-gnu]: https://github.com/rust-lang/rust/tree/master/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
 [QEMU]: https://www.qemu.org/
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index 586afa65226..3ac14704754 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -66,6 +66,11 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios your-code.rs
 ```
 
+Or if using Cargo and `-Zbuild-std`:
+```console
+$ cargo +nightly build -Zbuild-std --target armv7s-apple-ios
+```
+
 The simulator variants can be differentiated from the variants running
 on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before
 Rust CURRENT_RUSTC_VERSION).
@@ -73,7 +78,7 @@ Rust CURRENT_RUSTC_VERSION).
 ```rust
 if cfg!(all(target_vendor = "apple", target_env = "sim")) {
     // Do something on the iOS/tvOS/visionOS/watchOS Simulator.
-} {
+} else {
     // Everything else, like Windows and non-Simulator iOS.
 }
 ```
@@ -82,8 +87,15 @@ This is similar to the `TARGET_OS_SIMULATOR` define in C code.
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
+Running and testing your code naturally requires either an actual device
+running iOS, or the equivalent Xcode simulator environment. There exists
+several tools in the ecosystem for running a Cargo project on one of these.
+One of these tools is [`cargo-dinghy`]. [madsmtm/objc2#459] contains a more
+exhaustive list.
+
+See also [testing on emulators in the `rustc-dev-guide`][test-sim] for
+instructions on running the standard library's test suite.
 
-It hopefully will be possible to improve this in the future.
+[`cargo-dinghy`]: https://github.com/sonos/dinghy
+[madsmtm/objc2#459]: https://github.com/madsmtm/objc2/issues/459
+[test-sim]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
index 193d6466612..a952d8e230d 100644
--- a/src/doc/rustc/src/platform-support/apple-tvos.md
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -65,17 +65,8 @@ Using the unstable `-Zbuild-std` with a nightly Cargo may also work.
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-tvos your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md
index ed96912da7a..2ac069248ee 100644
--- a/src/doc/rustc/src/platform-support/apple-visionos.md
+++ b/src/doc/rustc/src/platform-support/apple-visionos.md
@@ -46,20 +46,11 @@ be fixed in [#124560](https://github.com/rust-lang/rust/pull/124560).
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-visionos-sim your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
 
 ## Cross-compilation toolchains and C code
 
diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md
index 6ac09d0d1e5..c1a00961425 100644
--- a/src/doc/rustc/src/platform-support/apple-watchos.md
+++ b/src/doc/rustc/src/platform-support/apple-watchos.md
@@ -50,17 +50,8 @@ Using the unstable `-Zbuild-std` with a nightly Cargo may also work.
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-watchos-sim your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index 67a7ad6f3b4..5ec5e6e2898 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -53,6 +53,10 @@ impl Config {
             batch: false,
             bind: if cfg!(target_os = "android") || cfg!(windows) {
                 ([0, 0, 0, 0], 12345).into()
+            } else if cfg!(target_env = "sim") {
+                // iOS/tvOS/watchOS/visionOS simulators share network device
+                // with the host machine.
+                ([127, 0, 0, 1], 12345).into()
             } else {
                 ([10, 0, 2, 15], 12345).into()
             },
@@ -262,10 +266,17 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
     cmd.args(args);
     cmd.envs(env);
 
-    // On windows, libraries are just searched in the executable directory,
-    // system directories, PWD, and PATH, in that order. PATH is the only one
-    // we can change for this.
-    let library_path = if cfg!(windows) { "PATH" } else { "LD_LIBRARY_PATH" };
+    let library_path = if cfg!(windows) {
+        // On windows, libraries are just searched in the executable directory,
+        // system directories, PWD, and PATH, in that order. PATH is the only
+        // one we can change for this.
+        "PATH"
+    } else if cfg!(target_vendor = "apple") {
+        // On Apple platforms, the environment variable is named differently.
+        "DYLD_LIBRARY_PATH"
+    } else {
+        "LD_LIBRARY_PATH"
+    };
 
     // Support libraries were uploaded to `work` earlier, so make sure that's
     // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
diff --git a/tests/ui/backtrace/apple-no-dsymutil.rs b/tests/ui/backtrace/apple-no-dsymutil.rs
index e5aeced25ca..00c8349d129 100644
--- a/tests/ui/backtrace/apple-no-dsymutil.rs
+++ b/tests/ui/backtrace/apple-no-dsymutil.rs
@@ -3,6 +3,7 @@
 //@ compile-flags:-Cstrip=none
 //@ compile-flags:-g -Csplit-debuginfo=unpacked
 //@ only-apple
+//@ ignore-remote needs the compiler-produced `.o` file to be copied to the device
 
 use std::process::Command;
 use std::str;
diff --git a/tests/ui/backtrace/dylib-dep.rs b/tests/ui/backtrace/dylib-dep.rs
index 05fdb9afef8..cf420ec8d06 100644
--- a/tests/ui/backtrace/dylib-dep.rs
+++ b/tests/ui/backtrace/dylib-dep.rs
@@ -7,6 +7,10 @@
 //@ ignore-android FIXME #17520
 //@ ignore-fuchsia Backtraces not symbolized
 //@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 //@ needs-unwind
 //@ ignore-backends: gcc
 //@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes
diff --git a/tests/ui/backtrace/line-tables-only.rs b/tests/ui/backtrace/line-tables-only.rs
index 6624c71e184..5863cc1d17d 100644
--- a/tests/ui/backtrace/line-tables-only.rs
+++ b/tests/ui/backtrace/line-tables-only.rs
@@ -11,6 +11,10 @@
 //@ ignore-android FIXME #17520
 //@ ignore-fuchsia Backtraces not symbolized
 //@ ignore-emscripten Requires custom symbolization code
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 //@ needs-unwind
 //@ aux-build: line-tables-only-helper.rs
 
diff --git a/tests/ui/command/command-current-dir.rs b/tests/ui/command/command-current-dir.rs
index e264cbe4d70..a6b51df5f17 100644
--- a/tests/ui/command/command-current-dir.rs
+++ b/tests/ui/command/command-current-dir.rs
@@ -2,6 +2,8 @@
 //@ no-prefer-dynamic We move the binary around, so do not depend dynamically on libstd
 //@ needs-subprocess
 //@ ignore-fuchsia Needs directory creation privilege
+//@ ignore-tvos `Command::current_dir` requires fork, which is prohibited
+//@ ignore-watchos `Command::current_dir` requires fork, which is prohibited
 
 use std::env;
 use std::fs;
diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs
index 77336377e88..870f8b047b9 100644
--- a/tests/ui/command/command-exec.rs
+++ b/tests/ui/command/command-exec.rs
@@ -3,6 +3,8 @@
 //@ only-unix (this is a unix-specific test)
 //@ needs-subprocess
 //@ ignore-fuchsia no execvp syscall provided
+//@ ignore-tvos execvp is prohibited
+//@ ignore-watchos execvp is prohibited
 
 use std::env;
 use std::os::unix::process::CommandExt;
diff --git a/tests/ui/command/command-pre-exec.rs b/tests/ui/command/command-pre-exec.rs
index 7299f357bd0..a62ab0b5ed6 100644
--- a/tests/ui/command/command-pre-exec.rs
+++ b/tests/ui/command/command-pre-exec.rs
@@ -2,6 +2,8 @@
 //@ only-unix (this is a unix-specific test)
 //@ needs-subprocess
 //@ ignore-fuchsia no execvp syscall
+//@ ignore-tvos execvp is prohibited
+//@ ignore-watchos execvp is prohibited
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/command/command-uid-gid.rs b/tests/ui/command/command-uid-gid.rs
index f54a0f50708..ef0653eb2cb 100644
--- a/tests/ui/command/command-uid-gid.rs
+++ b/tests/ui/command/command-uid-gid.rs
@@ -1,6 +1,8 @@
 //@ run-pass
 //@ ignore-android
 //@ ignore-fuchsia no '/bin/sh', '/bin/ls'
+//@ ignore-tvos `Command::uid/gid` requires fork, which is prohibited
+//@ ignore-watchos `Command::uid/gid` requires fork, which is prohibited
 //@ needs-subprocess
 
 #![feature(rustc_private)]
diff --git a/tests/ui/compiletest-self-test/test-aux-bin.rs b/tests/ui/compiletest-self-test/test-aux-bin.rs
index c1c28e12b3b..9ac17e6e146 100644
--- a/tests/ui/compiletest-self-test/test-aux-bin.rs
+++ b/tests/ui/compiletest-self-test/test-aux-bin.rs
@@ -1,4 +1,5 @@
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ aux-bin: print-it-works.rs
 //@ run-pass
 
diff --git a/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs b/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
index 86d637b579d..c6cfae1e545 100644
--- a/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
+++ b/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 //@ aux-build:exporting-impl-from-root-causes-ice-2472-b.rs
-
+//@ ignore-ios FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-tvos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-watchos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-visionos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
 
 extern crate exporting_impl_from_root_causes_ice_2472_b as lib;
 
diff --git a/tests/ui/issues/issue-45731.rs b/tests/ui/issues/issue-45731.rs
index 49335362dd0..db11d1dbef1 100644
--- a/tests/ui/issues/issue-45731.rs
+++ b/tests/ui/issues/issue-45731.rs
@@ -1,6 +1,10 @@
 //@ run-pass
 #![allow(unused_variables)]
 //@ compile-flags:--test -g
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 
 #[cfg(target_vendor = "apple")]
 #[test]
diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs
index f4be54da8fe..f381997ef79 100644
--- a/tests/ui/process/core-run-destroy.rs
+++ b/tests/ui/process/core-run-destroy.rs
@@ -8,6 +8,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'cat' and 'sleep'
 //@ ignore-fuchsia no 'cat'
+//@ ignore-ios no 'cat' and 'sleep'
+//@ ignore-tvos no 'cat' and 'sleep'
+//@ ignore-watchos no 'cat' and 'sleep'
+//@ ignore-visionos no 'cat' and 'sleep'
 
 // N.B., these tests kill child processes. Valgrind sees these children as leaking
 // memory, which makes for some *confusing* logs. That's why these are here
diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs
index a4a71c94020..193659bea29 100644
--- a/tests/ui/process/env-funky-keys.rs
+++ b/tests/ui/process/env-funky-keys.rs
@@ -1,8 +1,7 @@
 //@ run-pass
 //@ edition: 2021
-// Ignore this test on Android, because it segfaults there.
 
-//@ ignore-android
+//@ ignore-android segfaults
 //@ ignore-windows
 //@ ignore-wasm32 no execve
 //@ ignore-sgx no execve
@@ -24,6 +23,9 @@ use std::ptr;
 fn main() {
     if env::args_os().count() == 2 {
         for (key, value) in env::vars_os() {
+            if key == "DYLD_ROOT_PATH" {
+                continue;
+            }
             panic!("found env value {:?} {:?}", key, value);
         }
         return;
@@ -35,7 +37,18 @@ fn main() {
                                        .as_bytes()).unwrap();
     let filename: *const c_char = current_exe.as_ptr();
     let argv: &[*const c_char] = &[filename, filename, ptr::null()];
-    let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()];
+
+    let root;
+    let envp: &[*const c_char] = if cfg!(all(target_vendor = "apple", target_env = "sim")) {
+        // Workaround: iOS/tvOS/watchOS/visionOS simulators need the root path
+        // from the current process.
+        root = format!("DYLD_ROOT_PATH={}\0", std::env::var("DYLD_ROOT_PATH").unwrap());
+        &[c"FOOBAR".as_ptr(), root.as_ptr().cast(), ptr::null()]
+    } else {
+        // Try to set an environment variable without a value.
+        &[c"FOOBAR".as_ptr(), ptr::null()]
+    };
+
     unsafe {
         execve(filename, &argv[0], &envp[0]);
     }
diff --git a/tests/ui/process/fds-are-cloexec.rs b/tests/ui/process/fds-are-cloexec.rs
index f6678379dd6..0fae7c2b502 100644
--- a/tests/ui/process/fds-are-cloexec.rs
+++ b/tests/ui/process/fds-are-cloexec.rs
@@ -74,8 +74,15 @@ fn child(args: &[String]) {
         let fd: libc::c_int = arg.parse().unwrap();
         unsafe {
             assert_eq!(libc::read(fd, b.as_mut_ptr() as *mut _, 2), -1);
-            assert_eq!(io::Error::last_os_error().raw_os_error(),
-                       Some(libc::EBADF));
+            let raw = io::Error::last_os_error().raw_os_error();
+            if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
+                // Workaround: iOS/tvOS/watchOS/visionOS seems to treat `tcp6`
+                // as a directory?
+                if raw == Some(libc::EISDIR) {
+                    continue;
+                }
+            }
+            assert_eq!(raw, Some(libc::EBADF));
         }
     }
 }
diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs
index 58b83a2dd9a..e87e2077370 100644
--- a/tests/ui/process/println-with-broken-pipe.rs
+++ b/tests/ui/process/println-with-broken-pipe.rs
@@ -5,6 +5,10 @@
 //@ ignore-fuchsia
 //@ ignore-horizon
 //@ ignore-android
+//@ ignore-ios no 'head'
+//@ ignore-tvos no 'head'
+//@ ignore-watchos no 'head'
+//@ ignore-visionos no 'head'
 //@ ignore-backends: gcc
 //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC"
 //@ compile-flags: -Zon-broken-pipe=error
diff --git a/tests/ui/process/process-envs.rs b/tests/ui/process/process-envs.rs
index 98052f1d3a5..cbe16704a8e 100644
--- a/tests/ui/process/process-envs.rs
+++ b/tests/ui/process/process-envs.rs
@@ -2,6 +2,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
+//@ ignore-ios no 'env'
+//@ ignore-tvos no 'env'
+//@ ignore-watchos no 'env'
+//@ ignore-visionos no 'env'
 
 use std::process::Command;
 use std::env;
diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs
index 6e0267e0a54..653ff6ce314 100644
--- a/tests/ui/process/process-panic-after-fork.rs
+++ b/tests/ui/process/process-panic-after-fork.rs
@@ -3,6 +3,8 @@
 //@ only-unix
 //@ needs-subprocess
 //@ ignore-fuchsia no fork
+//@ ignore-tvos fork is prohibited
+//@ ignore-watchos fork is prohibited
 
 #![feature(rustc_private)]
 #![feature(never_type)]
diff --git a/tests/ui/process/process-remove-from-env.rs b/tests/ui/process/process-remove-from-env.rs
index c1a2b2daf5b..68c3909b15a 100644
--- a/tests/ui/process/process-remove-from-env.rs
+++ b/tests/ui/process/process-remove-from-env.rs
@@ -2,6 +2,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
+//@ ignore-ios no 'env'
+//@ ignore-tvos no 'env'
+//@ ignore-watchos no 'env'
+//@ ignore-visionos no 'env'
 
 use std::process::Command;
 use std::env;
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 3ecf271599d..574d79ee1dd 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -15,6 +15,10 @@
 
 //@ ignore-vxworks no 'sh'
 //@ ignore-fuchsia no 'sh'
+//@ ignore-ios no 'sh'
+//@ ignore-tvos no 'sh'
+//@ ignore-watchos no 'sh'
+//@ ignore-visionos no 'sh'
 //@ needs-threads
 //@ only-unix SIGPIPE is a unix feature
 
diff --git a/tests/ui/process/process-spawn-failure.rs b/tests/ui/process/process-spawn-failure.rs
index 0950b044c97..ac2c34bc783 100644
--- a/tests/ui/process/process-spawn-failure.rs
+++ b/tests/ui/process/process-spawn-failure.rs
@@ -9,6 +9,10 @@
 //@ ignore-vxworks no 'ps'
 //@ ignore-fuchsia no 'ps'
 //@ ignore-nto no 'ps'
+//@ ignore-ios no 'ps'
+//@ ignore-tvos no 'ps'
+//@ ignore-watchos no 'ps'
+//@ ignore-visionos no 'ps'
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs
index 5fb9943d6c3..5e91f22aec0 100644
--- a/tests/ui/runtime/backtrace-debuginfo.rs
+++ b/tests/ui/runtime/backtrace-debuginfo.rs
@@ -11,6 +11,10 @@
 //@ compile-flags:-Cstrip=none
 //@ needs-subprocess
 //@ ignore-fuchsia Backtrace not symbolized, trace different line alignment
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 
 // FIXME(#117097): backtrace (possibly unwinding mechanism) seems to be different on at least
 // `i686-mingw` (32-bit windows-gnu)? cc #128911.
diff --git a/tests/ui/runtime/on-broken-pipe/child-processes.rs b/tests/ui/runtime/on-broken-pipe/child-processes.rs
index c0c8ad4e2f5..b7022e1b09d 100644
--- a/tests/ui/runtime/on-broken-pipe/child-processes.rs
+++ b/tests/ui/runtime/on-broken-pipe/child-processes.rs
@@ -1,5 +1,6 @@
 //@ revisions: default error kill inherit
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ only-unix because SIGPIPE is a unix thing
 //@ ignore-backends: gcc
 //@ run-pass
diff --git a/tests/ui/runtime/on-broken-pipe/inherit.rs b/tests/ui/runtime/on-broken-pipe/inherit.rs
index f3c8140eaae..e99c7c7a0fe 100644
--- a/tests/ui/runtime/on-broken-pipe/inherit.rs
+++ b/tests/ui/runtime/on-broken-pipe/inherit.rs
@@ -1,4 +1,5 @@
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ only-unix because SIGPIPE is a unix thing
 //@ aux-bin: assert-inherit-sig_dfl.rs
 //@ aux-bin: assert-inherit-sig_ign.rs