about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--src/libpanic_abort/Cargo.toml1
-rw-r--r--src/libpanic_abort/lib.rs35
-rw-r--r--src/libpanic_unwind/lib.rs20
-rw-r--r--src/libproc_macro/lib.rs1
-rw-r--r--src/librustc_passes/stability.rs3
-rw-r--r--src/libstd/build.rs24
-rw-r--r--src/libstd/env.rs77
-rw-r--r--src/libstd/lib.rs9
-rw-r--r--src/libstd/sys/mod.rs3
-rw-r--r--src/libstd/sys/unsupported/alloc.rs22
-rw-r--r--src/libstd/sys/unsupported/args.rs38
-rw-r--r--src/libstd/sys/unsupported/cmath.rs (renamed from src/libstd/sys/wasm/cmath.rs)0
-rw-r--r--src/libstd/sys/unsupported/common.rs48
-rw-r--r--src/libstd/sys/unsupported/condvar.rs (renamed from src/libstd/sys/wasm/condvar.rs)4
-rw-r--r--src/libstd/sys/unsupported/env.rs9
-rw-r--r--src/libstd/sys/unsupported/fs.rs (renamed from src/libstd/sys/wasm/fs.rs)0
-rw-r--r--src/libstd/sys/unsupported/io.rs (renamed from src/libstd/sys/wasm/io.rs)0
-rw-r--r--src/libstd/sys/unsupported/mod.rs24
-rw-r--r--src/libstd/sys/unsupported/mutex.rs (renamed from src/libstd/sys/wasm/mutex.rs)7
-rw-r--r--src/libstd/sys/unsupported/net.rs (renamed from src/libstd/sys/wasm/net.rs)0
-rw-r--r--src/libstd/sys/unsupported/os.rs (renamed from src/libstd/sys/wasm/os.rs)21
-rw-r--r--src/libstd/sys/unsupported/path.rs (renamed from src/libstd/sys/wasm/path.rs)0
-rw-r--r--src/libstd/sys/unsupported/pipe.rs (renamed from src/libstd/sys/wasm/pipe.rs)0
-rw-r--r--src/libstd/sys/unsupported/process.rs (renamed from src/libstd/sys/wasm/process.rs)0
-rw-r--r--src/libstd/sys/unsupported/rwlock.rs (renamed from src/libstd/sys/wasm/rwlock.rs)2
-rw-r--r--src/libstd/sys/unsupported/stack_overflow.rs (renamed from src/libstd/sys/wasm/stack_overflow.rs)0
-rw-r--r--src/libstd/sys/unsupported/stdio.rs (renamed from src/libstd/sys/wasm/stdio.rs)0
-rw-r--r--src/libstd/sys/unsupported/thread.rs41
-rw-r--r--src/libstd/sys/unsupported/thread_local_dtor.rs (renamed from src/libstd/sys/wasm/thread_local_dtor.rs)0
-rw-r--r--src/libstd/sys/unsupported/thread_local_key.rs (renamed from src/libstd/sys/wasm/thread_local_key.rs)10
-rw-r--r--src/libstd/sys/unsupported/time.rs (renamed from src/libstd/sys/wasm/time.rs)4
-rw-r--r--src/libstd/sys/wasi/mod.rs45
-rw-r--r--src/libstd/sys/wasm/memchr.rs1
-rw-r--r--src/libstd/sys/wasm/mod.rs63
-rw-r--r--src/libstd/sys_common/mod.rs11
-rw-r--r--src/libstd/sys_common/mutex.rs1
-rw-r--r--src/libtest/Cargo.toml1
-rw-r--r--src/libtest/helpers/concurrency.rs171
-rw-r--r--src/libtest/helpers/isatty.rs56
-rw-r--r--src/libunwind/lib.rs27
-rw-r--r--src/tools/rustc-std-workspace-std/lib.rs1
42 files changed, 437 insertions, 345 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5309c03ee23..28ff6b3b1eb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2056,6 +2056,7 @@ dependencies = [
 name = "panic_abort"
 version = "0.0.0"
 dependencies = [
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -4552,6 +4553,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
+ "cfg-if",
  "core",
  "getopts",
  "libc",
diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml
index 2bee0b716c7..dc385022440 100644
--- a/src/libpanic_abort/Cargo.toml
+++ b/src/libpanic_abort/Cargo.toml
@@ -11,6 +11,7 @@ bench = false
 doc = false
 
 [dependencies]
+cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 core = { path = "../libcore" }
 libc = { version = "0.2", default-features = false }
 compiler_builtins = "0.1.0"
diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs
index 27056d5f934..95f3966228a 100644
--- a/src/libpanic_abort/lib.rs
+++ b/src/libpanic_abort/lib.rs
@@ -40,23 +40,26 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
 pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
     abort();
 
-    #[cfg(any(unix, target_os = "cloudabi"))]
-    unsafe fn abort() -> ! {
-        libc::abort();
-    }
-
-    #[cfg(any(windows, all(target_arch = "wasm32", not(target_os = "emscripten"))))]
-    unsafe fn abort() -> ! {
-        core::intrinsics::abort();
-    }
-
-    #[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx")))]
-    unsafe fn abort() -> ! {
-        // call std::sys::abort_internal
-        extern "C" {
-            pub fn __rust_abort() -> !;
+    cfg_if::cfg_if! {
+        if #[cfg(any(unix, target_os = "cloudabi"))] {
+            unsafe fn abort() -> ! {
+                libc::abort();
+            }
+        } else if #[cfg(any(target_os = "hermit",
+                            all(target_vendor = "fortanix", target_env = "sgx")
+        ))] {
+            unsafe fn abort() -> ! {
+                // call std::sys::abort_internal
+                extern "C" {
+                    pub fn __rust_abort() -> !;
+                }
+                __rust_abort();
+            }
+        } else {
+            unsafe fn abort() -> ! {
+                core::intrinsics::abort();
+            }
         }
-        __rust_abort();
     }
 }
 
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index f361354da2a..430062d4ac4 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -41,21 +41,33 @@ cfg_if::cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         #[path = "emcc.rs"]
         mod real_imp;
-    } else if #[cfg(target_arch = "wasm32")] {
-        #[path = "dummy.rs"]
-        mod real_imp;
     } else if #[cfg(target_os = "hermit")] {
         #[path = "hermit.rs"]
         mod real_imp;
     } else if #[cfg(target_env = "msvc")] {
         #[path = "seh.rs"]
         mod real_imp;
-    } else {
+    } else if #[cfg(any(
+        all(target_family = "windows", target_env = "gnu"),
+        target_os = "cloudabi",
+        target_family = "unix",
+        all(target_vendor = "fortanix", target_env = "sgx"),
+    ))] {
         // Rust runtime's startup objects depend on these symbols, so make them public.
         #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
         pub use real_imp::eh_frame_registry::*;
         #[path = "gcc.rs"]
         mod real_imp;
+    } else {
+        // Targets that don't support unwinding.
+        // - arch=wasm32
+        // - os=none ("bare metal" targets)
+        // - os=uefi
+        // - nvptx64-nvidia-cuda
+        // - avr-unknown-unknown
+        // - mipsel-sony-psp
+        #[path = "dummy.rs"]
+        mod real_imp;
     }
 }
 
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 2d5bd7e872b..f960bdecc57 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -26,6 +26,7 @@
 #![feature(in_band_lifetimes)]
 #![feature(negative_impls)]
 #![feature(optin_builtin_traits)]
+#![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
 #![recursion_limit = "256"]
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 76bc6b6c85f..5d972c70d13 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -502,7 +502,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
         match item.kind {
             hir::ItemKind::ExternCrate(_) => {
                 // compiler-generated `extern crate` items have a dummy span.
-                if item.span.is_dummy() {
+                // `std` is still checked for the `restricted-std` feature.
+                if item.span.is_dummy() && item.ident.as_str() != "std" {
                     return;
                 }
 
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 743a1778fbd..eb2753d6245 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -62,5 +62,29 @@ fn main() {
         }
         println!("cargo:rustc-link-lib=c");
         println!("cargo:rustc-link-lib=compiler_rt");
+    } else if (target.contains("sgx") && target.contains("fortanix"))
+        || target.contains("hermit")
+        || target.contains("l4re")
+        || target.contains("redox")
+        || target.contains("haiku")
+        || target.contains("vxworks")
+        || target.contains("wasm32")
+        || target.contains("asmjs")
+    {
+        // These platforms don't have any special requirements.
+    } else {
+        // This is for Cargo's build-std support, to mark std as unstable for
+        // typically no_std platforms.
+        // This covers:
+        // - os=none ("bare metal" targets)
+        // - mipsel-sony-psp
+        // - nvptx64-nvidia-cuda
+        // - avr-unknown-unknown
+        // - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
+        // - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
+        // - JSON targets
+        // - Any new targets that have not been explicitly added above.
+        println!("cargo:rustc-cfg=feature=\"restricted-std\"");
     }
+    println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
 }
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 97c20ca9459..6489e0709cb 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -882,7 +882,7 @@ pub mod consts {
     /// - s390x
     /// - sparc64
     #[stable(feature = "env", since = "1.0.0")]
-    pub const ARCH: &str = super::arch::ARCH;
+    pub const ARCH: &str = env!("STD_ENV_ARCH");
 
     /// The family of the operating system. Example value is `unix`.
     ///
@@ -966,81 +966,6 @@ pub mod consts {
     pub const EXE_EXTENSION: &str = os::EXE_EXTENSION;
 }
 
-#[cfg(target_arch = "x86")]
-mod arch {
-    pub const ARCH: &str = "x86";
-}
-
-#[cfg(target_arch = "x86_64")]
-mod arch {
-    pub const ARCH: &str = "x86_64";
-}
-
-#[cfg(target_arch = "arm")]
-mod arch {
-    pub const ARCH: &str = "arm";
-}
-
-#[cfg(target_arch = "aarch64")]
-mod arch {
-    pub const ARCH: &str = "aarch64";
-}
-
-#[cfg(target_arch = "mips")]
-mod arch {
-    pub const ARCH: &str = "mips";
-}
-
-#[cfg(target_arch = "mips64")]
-mod arch {
-    pub const ARCH: &str = "mips64";
-}
-
-#[cfg(target_arch = "powerpc")]
-mod arch {
-    pub const ARCH: &str = "powerpc";
-}
-
-#[cfg(target_arch = "powerpc64")]
-mod arch {
-    pub const ARCH: &str = "powerpc64";
-}
-
-#[cfg(target_arch = "s390x")]
-mod arch {
-    pub const ARCH: &str = "s390x";
-}
-
-#[cfg(target_arch = "sparc64")]
-mod arch {
-    pub const ARCH: &str = "sparc64";
-}
-
-#[cfg(target_arch = "le32")]
-mod arch {
-    pub const ARCH: &str = "le32";
-}
-
-#[cfg(target_arch = "asmjs")]
-mod arch {
-    pub const ARCH: &str = "asmjs";
-}
-
-#[cfg(target_arch = "wasm32")]
-mod arch {
-    pub const ARCH: &str = "wasm32";
-}
-
-#[cfg(target_arch = "hexagon")]
-mod arch {
-    pub const ARCH: &'static str = "hexagon";
-}
-
-#[cfg(target_arch = "riscv64")]
-mod arch {
-    pub const ARCH: &'static str = "riscv64";
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index cbc24009a94..b5ba0da7ae5 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -198,7 +198,8 @@
 //! [primitive types]: ../book/ch03-02-data-types.html
 //! [rust-discord]: https://discord.gg/rust-lang
 
-#![stable(feature = "rust1", since = "1.0.0")]
+#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
+#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
     html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
@@ -554,3 +555,9 @@ include!("primitive_docs.rs");
 // the rustdoc documentation for the existing keywords. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
 include!("keyword_docs.rs");
+
+// This is required to avoid an unstable error when `restricted-std` is not
+// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std
+// is unconditional, so the unstable feature needs to be defined somewhere.
+#[cfg_attr(not(feature = "restricted-std"), unstable(feature = "restricted_std", issue = "none"))]
+mod __restricted_std_workaround {}
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index 875ff1af920..7b5fac922d0 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -48,7 +48,8 @@ cfg_if::cfg_if! {
         mod sgx;
         pub use self::sgx::*;
     } else {
-        compile_error!("libstd doesn't compile for this platform yet");
+        mod unsupported;
+        pub use self::unsupported::*;
     }
 }
 
diff --git a/src/libstd/sys/unsupported/alloc.rs b/src/libstd/sys/unsupported/alloc.rs
new file mode 100644
index 00000000000..8d5d0a2f5cc
--- /dev/null
+++ b/src/libstd/sys/unsupported/alloc.rs
@@ -0,0 +1,22 @@
+use crate::alloc::{GlobalAlloc, Layout, System};
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
+        0 as *mut u8
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 {
+        0 as *mut u8
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+
+    #[inline]
+    unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 {
+        0 as *mut u8
+    }
+}
diff --git a/src/libstd/sys/unsupported/args.rs b/src/libstd/sys/unsupported/args.rs
new file mode 100644
index 00000000000..71d0c5fa13e
--- /dev/null
+++ b/src/libstd/sys/unsupported/args.rs
@@ -0,0 +1,38 @@
+use crate::ffi::OsString;
+
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn cleanup() {}
+
+pub struct Args {}
+
+pub fn args() -> Args {
+    Args {}
+}
+
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        &[]
+    }
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        None
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(0))
+    }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize {
+        0
+    }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> {
+        None
+    }
+}
diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/unsupported/cmath.rs
index 304cf906b2a..304cf906b2a 100644
--- a/src/libstd/sys/wasm/cmath.rs
+++ b/src/libstd/sys/unsupported/cmath.rs
diff --git a/src/libstd/sys/unsupported/common.rs b/src/libstd/sys/unsupported/common.rs
new file mode 100644
index 00000000000..80311d26819
--- /dev/null
+++ b/src/libstd/sys/unsupported/common.rs
@@ -0,0 +1,48 @@
+use crate::io as std_io;
+
+pub mod memchr {
+    pub use core::slice::memchr::{memchr, memrchr};
+}
+
+pub use crate::sys_common::os_str_bytes as os_str;
+
+// This is not necessarily correct. May want to consider making it part of the
+// spec definition?
+use crate::os::raw::c_char;
+
+#[cfg(not(test))]
+pub fn init() {}
+
+pub fn unsupported<T>() -> std_io::Result<T> {
+    Err(unsupported_err())
+}
+
+pub fn unsupported_err() -> std_io::Error {
+    std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform")
+}
+
+pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
+    crate::io::ErrorKind::Other
+}
+
+pub fn abort_internal() -> ! {
+    core::intrinsics::abort();
+}
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    (1, 2)
+}
+
+// This enum is used as the storage for a bunch of types which can't actually
+// exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub unsafe fn strlen(mut s: *const c_char) -> usize {
+    let mut n = 0;
+    while *s != 0 {
+        n += 1;
+        s = s.offset(1);
+    }
+    return n;
+}
diff --git a/src/libstd/sys/wasm/condvar.rs b/src/libstd/sys/unsupported/condvar.rs
index 9fd781c7282..a578eee8ccc 100644
--- a/src/libstd/sys/wasm/condvar.rs
+++ b/src/libstd/sys/unsupported/condvar.rs
@@ -18,11 +18,11 @@ impl Condvar {
     pub unsafe fn notify_all(&self) {}
 
     pub unsafe fn wait(&self, _mutex: &Mutex) {
-        panic!("can't block with web assembly")
+        panic!("condvar wait not supported")
     }
 
     pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
-        panic!("can't block with web assembly");
+        panic!("condvar wait not supported");
     }
 
     #[inline]
diff --git a/src/libstd/sys/unsupported/env.rs b/src/libstd/sys/unsupported/env.rs
new file mode 100644
index 00000000000..d2efec506c5
--- /dev/null
+++ b/src/libstd/sys/unsupported/env.rs
@@ -0,0 +1,9 @@
+pub mod os {
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = "";
+    pub const DLL_EXTENSION: &str = "";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/unsupported/fs.rs
index ecb5b51cccd..ecb5b51cccd 100644
--- a/src/libstd/sys/wasm/fs.rs
+++ b/src/libstd/sys/unsupported/fs.rs
diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/unsupported/io.rs
index d5f475b4310..d5f475b4310 100644
--- a/src/libstd/sys/wasm/io.rs
+++ b/src/libstd/sys/unsupported/io.rs
diff --git a/src/libstd/sys/unsupported/mod.rs b/src/libstd/sys/unsupported/mod.rs
new file mode 100644
index 00000000000..87f655eecd5
--- /dev/null
+++ b/src/libstd/sys/unsupported/mod.rs
@@ -0,0 +1,24 @@
+pub mod alloc;
+pub mod args;
+pub mod cmath;
+pub mod condvar;
+pub mod env;
+pub mod fs;
+pub mod io;
+pub mod mutex;
+pub mod net;
+pub mod os;
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[cfg(target_thread_local)]
+pub mod thread_local_dtor;
+pub mod thread_local_key;
+pub mod time;
+
+mod common;
+pub use common::*;
diff --git a/src/libstd/sys/wasm/mutex.rs b/src/libstd/sys/unsupported/mutex.rs
index 7aaf1b3a343..9ef8af52eb5 100644
--- a/src/libstd/sys/wasm/mutex.rs
+++ b/src/libstd/sys/unsupported/mutex.rs
@@ -5,9 +5,10 @@ pub struct Mutex {
 }
 
 unsafe impl Send for Mutex {}
-unsafe impl Sync for Mutex {} // no threads on wasm
+unsafe impl Sync for Mutex {} // no threads on this platform
 
 impl Mutex {
+    #[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")]
     pub const fn new() -> Mutex {
         Mutex { locked: UnsafeCell::new(false) }
     }
@@ -42,8 +43,8 @@ impl Mutex {
     pub unsafe fn destroy(&self) {}
 }
 
-// All empty stubs because wasm has no threads yet, so lock acquisition always
-// succeeds.
+// All empty stubs because this platform does not yet support threads, so lock
+// acquisition always succeeds.
 pub struct ReentrantMutex {}
 
 impl ReentrantMutex {
diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/unsupported/net.rs
index 5c9f1098f9b..5c9f1098f9b 100644
--- a/src/libstd/sys/wasm/net.rs
+++ b/src/libstd/sys/unsupported/net.rs
diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/unsupported/os.rs
index 91afdc8a5a0..0615780c242 100644
--- a/src/libstd/sys/wasm/os.rs
+++ b/src/libstd/sys/unsupported/os.rs
@@ -1,10 +1,9 @@
+use super::{unsupported, Void};
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::path::{self, PathBuf};
-use crate::str;
-use crate::sys::{unsupported, Void};
 
 pub fn errno() -> i32 {
     0
@@ -48,14 +47,14 @@ where
 
 impl fmt::Display for JoinPathsError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on wasm yet".fmt(f)
+        "not supported on this platform yet".fmt(f)
     }
 }
 
 impl StdError for JoinPathsError {
     #[allow(deprecated)]
     fn description(&self) -> &str {
-        "not supported on wasm yet"
+        "not supported on this platform yet"
     }
 }
 
@@ -73,7 +72,7 @@ impl Iterator for Env {
 }
 
 pub fn env() -> Env {
-    panic!("not supported on web assembly")
+    panic!("not supported on this platform")
 }
 
 pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
@@ -81,15 +80,15 @@ pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
 }
 
 pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown"))
+    Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform"))
 }
 
 pub fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown"))
+    Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform"))
 }
 
 pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on wasm")
+    panic!("no filesystem on this platform")
 }
 
 pub fn home_dir() -> Option<PathBuf> {
@@ -97,11 +96,9 @@ pub fn home_dir() -> Option<PathBuf> {
 }
 
 pub fn exit(_code: i32) -> ! {
-    unsafe {
-        crate::arch::wasm32::unreachable();
-    }
+    crate::intrinsics::abort()
 }
 
 pub fn getpid() -> u32 {
-    panic!("no pids on wasm")
+    panic!("no pids on this platform")
 }
diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/unsupported/path.rs
index 840a7ae0426..840a7ae0426 100644
--- a/src/libstd/sys/wasm/path.rs
+++ b/src/libstd/sys/unsupported/path.rs
diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/unsupported/pipe.rs
index 10d0925823e..10d0925823e 100644
--- a/src/libstd/sys/wasm/pipe.rs
+++ b/src/libstd/sys/unsupported/pipe.rs
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/unsupported/process.rs
index 4702e5c5492..4702e5c5492 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/unsupported/process.rs
diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/unsupported/rwlock.rs
index a59944482e9..d37f34ac935 100644
--- a/src/libstd/sys/wasm/rwlock.rs
+++ b/src/libstd/sys/unsupported/rwlock.rs
@@ -5,7 +5,7 @@ pub struct RWLock {
 }
 
 unsafe impl Send for RWLock {}
-unsafe impl Sync for RWLock {} // no threads on wasm
+unsafe impl Sync for RWLock {} // no threads on this platform
 
 impl RWLock {
     pub const fn new() -> RWLock {
diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/unsupported/stack_overflow.rs
index 32555394cd5..32555394cd5 100644
--- a/src/libstd/sys/wasm/stack_overflow.rs
+++ b/src/libstd/sys/unsupported/stack_overflow.rs
diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/unsupported/stdio.rs
index 5a4e4505e93..5a4e4505e93 100644
--- a/src/libstd/sys/wasm/stdio.rs
+++ b/src/libstd/sys/unsupported/stdio.rs
diff --git a/src/libstd/sys/unsupported/thread.rs b/src/libstd/sys/unsupported/thread.rs
new file mode 100644
index 00000000000..20ae309db30
--- /dev/null
+++ b/src/libstd/sys/unsupported/thread.rs
@@ -0,0 +1,41 @@
+use super::{unsupported, Void};
+use crate::ffi::CStr;
+use crate::io;
+use crate::time::Duration;
+
+pub struct Thread(Void);
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+
+impl Thread {
+    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
+    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
+        unsupported()
+    }
+
+    pub fn yield_now() {
+        // do nothing
+    }
+
+    pub fn set_name(_name: &CStr) {
+        // nope
+    }
+
+    pub fn sleep(_dur: Duration) {
+        panic!("can't sleep");
+    }
+
+    pub fn join(self) {
+        match self.0 {}
+    }
+}
+
+pub mod guard {
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> {
+        None
+    }
+    pub unsafe fn init() -> Option<Guard> {
+        None
+    }
+}
diff --git a/src/libstd/sys/wasm/thread_local_dtor.rs b/src/libstd/sys/unsupported/thread_local_dtor.rs
index 85d66098302..85d66098302 100644
--- a/src/libstd/sys/wasm/thread_local_dtor.rs
+++ b/src/libstd/sys/unsupported/thread_local_dtor.rs
diff --git a/src/libstd/sys/wasm/thread_local_key.rs b/src/libstd/sys/unsupported/thread_local_key.rs
index f8be9863ed5..c31b61cbf56 100644
--- a/src/libstd/sys/wasm/thread_local_key.rs
+++ b/src/libstd/sys/unsupported/thread_local_key.rs
@@ -2,25 +2,25 @@ pub type Key = usize;
 
 #[inline]
 pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
-    panic!("should not be used on the wasm target");
+    panic!("should not be used on this target");
 }
 
 #[inline]
 pub unsafe fn set(_key: Key, _value: *mut u8) {
-    panic!("should not be used on the wasm target");
+    panic!("should not be used on this target");
 }
 
 #[inline]
 pub unsafe fn get(_key: Key) -> *mut u8 {
-    panic!("should not be used on the wasm target");
+    panic!("should not be used on this target");
 }
 
 #[inline]
 pub unsafe fn destroy(_key: Key) {
-    panic!("should not be used on the wasm target");
+    panic!("should not be used on this target");
 }
 
 #[inline]
 pub fn requires_synchronized_create() -> bool {
-    panic!("should not be used on the wasm target");
+    panic!("should not be used on this target");
 }
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/unsupported/time.rs
index d9edc7fdc44..8aaf1777f24 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/unsupported/time.rs
@@ -10,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
 
 impl Instant {
     pub fn now() -> Instant {
-        panic!("time not implemented on wasm32-unknown-unknown")
+        panic!("time not implemented on this platform")
     }
 
     pub const fn zero() -> Instant {
@@ -36,7 +36,7 @@ impl Instant {
 
 impl SystemTime {
     pub fn now() -> SystemTime {
-        panic!("time not implemented on wasm32-unknown-unknown")
+        panic!("time not implemented on this platform")
     }
 
     pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
index 85f5282034f..2704ff484f9 100644
--- a/src/libstd/sys/wasi/mod.rs
+++ b/src/libstd/sys/wasi/mod.rs
@@ -16,21 +16,18 @@
 
 use crate::io as std_io;
 use crate::mem;
-use crate::os::raw::c_char;
 
 pub mod alloc;
 pub mod args;
-#[path = "../wasm/cmath.rs"]
+#[path = "../unsupported/cmath.rs"]
 pub mod cmath;
-#[path = "../wasm/condvar.rs"]
+#[path = "../unsupported/condvar.rs"]
 pub mod condvar;
 pub mod env;
 pub mod fd;
 pub mod fs;
 pub mod io;
-#[path = "../wasm/memchr.rs"]
-pub mod memchr;
-#[path = "../wasm/mutex.rs"]
+#[path = "../unsupported/mutex.rs"]
 pub mod mutex;
 pub mod net;
 pub mod os;
@@ -39,28 +36,22 @@ pub mod ext;
 pub mod path;
 pub mod pipe;
 pub mod process;
-#[path = "../wasm/rwlock.rs"]
+#[path = "../unsupported/rwlock.rs"]
 pub mod rwlock;
-#[path = "../wasm/stack_overflow.rs"]
+#[path = "../unsupported/stack_overflow.rs"]
 pub mod stack_overflow;
 pub mod stdio;
 pub mod thread;
-#[path = "../wasm/thread_local_dtor.rs"]
+#[path = "../unsupported/thread_local_dtor.rs"]
 pub mod thread_local_dtor;
-#[path = "../wasm/thread_local_key.rs"]
+#[path = "../unsupported/thread_local_key.rs"]
 pub mod thread_local_key;
 pub mod time;
 
-#[cfg(not(test))]
-pub fn init() {}
-
-pub fn unsupported<T>() -> std_io::Result<T> {
-    Err(unsupported_err())
-}
-
-pub fn unsupported_err() -> std_io::Error {
-    std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on wasm yet")
-}
+#[path = "../unsupported/common.rs"]
+#[allow(unused)]
+mod common;
+pub use common::*;
 
 pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
     use std_io::ErrorKind::*;
@@ -86,20 +77,6 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
     }
 }
 
-// This enum is used as the storage for a bunch of types which can't actually
-// exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
-pub unsafe fn strlen(mut s: *const c_char) -> usize {
-    let mut n = 0;
-    while *s != 0 {
-        n += 1;
-        s = s.offset(1);
-    }
-    return n;
-}
-
 pub fn abort_internal() -> ! {
     unsafe { libc::abort() }
 }
diff --git a/src/libstd/sys/wasm/memchr.rs b/src/libstd/sys/wasm/memchr.rs
deleted file mode 100644
index 9967482197e..00000000000
--- a/src/libstd/sys/wasm/memchr.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use core::slice::memchr::{memchr, memrchr};
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
index 6939596e52d..3de58904043 100644
--- a/src/libstd/sys/wasm/mod.rs
+++ b/src/libstd/sys/wasm/mod.rs
@@ -14,25 +14,35 @@
 //! compiling for wasm. That way it's a compile time error for something that's
 //! guaranteed to be a runtime error!
 
-use crate::os::raw::c_char;
-
 pub mod alloc;
 pub mod args;
+#[path = "../unsupported/cmath.rs"]
 pub mod cmath;
 pub mod env;
+#[path = "../unsupported/fs.rs"]
 pub mod fs;
+#[path = "../unsupported/io.rs"]
 pub mod io;
-pub mod memchr;
+#[path = "../unsupported/net.rs"]
 pub mod net;
+#[path = "../unsupported/os.rs"]
 pub mod os;
+#[path = "../unsupported/path.rs"]
 pub mod path;
+#[path = "../unsupported/pipe.rs"]
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
+#[path = "../unsupported/stack_overflow.rs"]
 pub mod stack_overflow;
+#[path = "../unsupported/stdio.rs"]
 pub mod stdio;
 pub mod thread;
+#[path = "../unsupported/thread_local_dtor.rs"]
 pub mod thread_local_dtor;
+#[path = "../unsupported/thread_local_key.rs"]
 pub mod thread_local_key;
+#[path = "../unsupported/time.rs"]
 pub mod time;
 
 pub use crate::sys_common::os_str_bytes as os_str;
@@ -46,50 +56,15 @@ cfg_if::cfg_if! {
         #[path = "rwlock_atomics.rs"]
         pub mod rwlock;
     } else {
+        #[path = "../unsupported/condvar.rs"]
         pub mod condvar;
+        #[path = "../unsupported/mutex.rs"]
         pub mod mutex;
+        #[path = "../unsupported/rwlock.rs"]
         pub mod rwlock;
     }
 }
 
-#[cfg(not(test))]
-pub fn init() {}
-
-pub fn unsupported<T>() -> crate::io::Result<T> {
-    Err(unsupported_err())
-}
-
-pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on wasm yet")
-}
-
-pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
-    crate::io::ErrorKind::Other
-}
-
-// This enum is used as the storage for a bunch of types which can't actually
-// exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
-pub unsafe fn strlen(mut s: *const c_char) -> usize {
-    let mut n = 0;
-    while *s != 0 {
-        n += 1;
-        s = s.offset(1);
-    }
-    return n;
-}
-
-pub fn abort_internal() -> ! {
-    unsafe { crate::arch::wasm32::unreachable() }
-}
-
-// We don't have randomness yet, but I totally used a random number generator to
-// generate these numbers.
-//
-// More seriously though this is just for DOS protection in hash maps. It's ok
-// if we don't do that on wasm just yet.
-pub fn hashmap_random_keys() -> (u64, u64) {
-    (1, 2)
-}
+#[path = "../unsupported/common.rs"]
+mod common;
+pub use common::*;
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index e57bb267cbd..840f9093e00 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -51,13 +51,9 @@ pub mod condvar;
 pub mod fs;
 pub mod io;
 pub mod mutex;
-#[cfg(any(doc, // see `mod os`, docs are generated for multiple platforms
-          unix,
-          target_os = "redox",
-          target_os = "cloudabi",
-          target_os = "hermit",
-          target_arch = "wasm32",
-          all(target_vendor = "fortanix", target_env = "sgx")))]
+// `doc` is required because `sys/mod.rs` imports `unix/ext/mod.rs` on Windows
+// when generating documentation.
+#[cfg(any(doc, not(windows)))]
 pub mod os_str_bytes;
 pub mod poison;
 pub mod process;
@@ -74,6 +70,7 @@ cfg_if::cfg_if! {
     if #[cfg(any(target_os = "cloudabi",
                  target_os = "l4re",
                  target_os = "hermit",
+                 feature = "restricted-std",
                  all(target_arch = "wasm32", not(target_os = "emscripten")),
                  all(target_vendor = "fortanix", target_env = "sgx")))] {
         pub use crate::sys::net;
diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs
index 899fc6a7235..e66d8994147 100644
--- a/src/libstd/sys_common/mutex.rs
+++ b/src/libstd/sys_common/mutex.rs
@@ -17,6 +17,7 @@ impl Mutex {
     /// Also, until `init` is called, behavior is undefined if this
     /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
     /// are called by the thread currently holding the lock.
+    #[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")]
     pub const fn new() -> Mutex {
         Mutex(imp::Mutex::new())
     }
diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
index 1667334871d..a4748c5a466 100644
--- a/src/libtest/Cargo.toml
+++ b/src/libtest/Cargo.toml
@@ -10,6 +10,7 @@ path = "lib.rs"
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
+cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
 term = { path = "../libterm" }
 std = { path = "../libstd" }
diff --git a/src/libtest/helpers/concurrency.rs b/src/libtest/helpers/concurrency.rs
index e8f3820558a..2fe87247e3a 100644
--- a/src/libtest/helpers/concurrency.rs
+++ b/src/libtest/helpers/concurrency.rs
@@ -14,61 +14,36 @@ pub fn get_concurrency() -> usize {
         }
         Err(..) => num_cpus(),
     };
+}
 
-    #[cfg(windows)]
-    #[allow(nonstandard_style)]
-    fn num_cpus() -> usize {
-        #[repr(C)]
-        struct SYSTEM_INFO {
-            wProcessorArchitecture: u16,
-            wReserved: u16,
-            dwPageSize: u32,
-            lpMinimumApplicationAddress: *mut u8,
-            lpMaximumApplicationAddress: *mut u8,
-            dwActiveProcessorMask: *mut u8,
-            dwNumberOfProcessors: u32,
-            dwProcessorType: u32,
-            dwAllocationGranularity: u32,
-            wProcessorLevel: u16,
-            wProcessorRevision: u16,
-        }
-        extern "system" {
-            fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
-        }
-        unsafe {
-            let mut sysinfo = std::mem::zeroed();
-            GetSystemInfo(&mut sysinfo);
-            sysinfo.dwNumberOfProcessors as usize
+cfg_if::cfg_if! {
+    if #[cfg(windows)] {
+        #[allow(nonstandard_style)]
+        fn num_cpus() -> usize {
+            #[repr(C)]
+            struct SYSTEM_INFO {
+                wProcessorArchitecture: u16,
+                wReserved: u16,
+                dwPageSize: u32,
+                lpMinimumApplicationAddress: *mut u8,
+                lpMaximumApplicationAddress: *mut u8,
+                dwActiveProcessorMask: *mut u8,
+                dwNumberOfProcessors: u32,
+                dwProcessorType: u32,
+                dwAllocationGranularity: u32,
+                wProcessorLevel: u16,
+                wProcessorRevision: u16,
+            }
+            extern "system" {
+                fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
+            }
+            unsafe {
+                let mut sysinfo = std::mem::zeroed();
+                GetSystemInfo(&mut sysinfo);
+                sysinfo.dwNumberOfProcessors as usize
+            }
         }
-    }
-
-    #[cfg(target_os = "vxworks")]
-    fn num_cpus() -> usize {
-        // FIXME: Implement num_cpus on vxWorks
-        1
-    }
-
-    #[cfg(target_os = "redox")]
-    fn num_cpus() -> usize {
-        // FIXME: Implement num_cpus on Redox
-        1
-    }
-
-    #[cfg(target_os = "hermit")]
-    fn num_cpus() -> usize {
-        // FIXME: Implement num_cpus on HermitCore
-        1
-    }
-
-    #[cfg(any(
-        all(target_arch = "wasm32", not(target_os = "emscripten")),
-        all(target_vendor = "fortanix", target_env = "sgx")
-    ))]
-    fn num_cpus() -> usize {
-        1
-    }
-
-    #[cfg(any(
+    } else if #[cfg(any(
         target_os = "android",
         target_os = "cloudabi",
         target_os = "emscripten",
@@ -78,23 +53,46 @@ pub fn get_concurrency() -> usize {
         target_os = "macos",
         target_os = "solaris",
         target_os = "illumos",
-    ))]
-    fn num_cpus() -> usize {
-        unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
-    }
-
-    #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
-    fn num_cpus() -> usize {
-        use std::ptr;
+    ))] {
+        fn num_cpus() -> usize {
+            unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
+        }
+    } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
+        fn num_cpus() -> usize {
+            use std::ptr;
 
-        let mut cpus: libc::c_uint = 0;
-        let mut cpus_size = std::mem::size_of_val(&cpus);
+            let mut cpus: libc::c_uint = 0;
+            let mut cpus_size = std::mem::size_of_val(&cpus);
 
-        unsafe {
-            cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
+            unsafe {
+                cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
+            }
+            if cpus < 1 {
+                let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+                unsafe {
+                    libc::sysctl(
+                        mib.as_mut_ptr(),
+                        2,
+                        &mut cpus as *mut _ as *mut _,
+                        &mut cpus_size as *mut _ as *mut _,
+                        ptr::null_mut(),
+                        0,
+                    );
+                }
+                if cpus < 1 {
+                    cpus = 1;
+                }
+            }
+            cpus as usize
         }
-        if cpus < 1 {
+    } else if #[cfg(target_os = "openbsd")] {
+        fn num_cpus() -> usize {
+            use std::ptr;
+
+            let mut cpus: libc::c_uint = 0;
+            let mut cpus_size = std::mem::size_of_val(&cpus);
             let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+
             unsafe {
                 libc::sysctl(
                     mib.as_mut_ptr(),
@@ -108,43 +106,12 @@ pub fn get_concurrency() -> usize {
             if cpus < 1 {
                 cpus = 1;
             }
+            cpus as usize
         }
-        cpus as usize
-    }
-
-    #[cfg(target_os = "openbsd")]
-    fn num_cpus() -> usize {
-        use std::ptr;
-
-        let mut cpus: libc::c_uint = 0;
-        let mut cpus_size = std::mem::size_of_val(&cpus);
-        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
-
-        unsafe {
-            libc::sysctl(
-                mib.as_mut_ptr(),
-                2,
-                &mut cpus as *mut _ as *mut _,
-                &mut cpus_size as *mut _ as *mut _,
-                ptr::null_mut(),
-                0,
-            );
-        }
-        if cpus < 1 {
-            cpus = 1;
+    } else {
+        // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re
+        fn num_cpus() -> usize {
+            1
         }
-        cpus as usize
-    }
-
-    #[cfg(target_os = "haiku")]
-    fn num_cpus() -> usize {
-        // FIXME: implement
-        1
-    }
-
-    #[cfg(target_os = "l4re")]
-    fn num_cpus() -> usize {
-        // FIXME: implement
-        1
     }
 }
diff --git a/src/libtest/helpers/isatty.rs b/src/libtest/helpers/isatty.rs
index 831094f7545..874ecc37645 100644
--- a/src/libtest/helpers/isatty.rs
+++ b/src/libtest/helpers/isatty.rs
@@ -1,34 +1,32 @@
 //! Helper module which provides a function to test
 //! if stdout is a tty.
 
-#[cfg(any(
-    target_os = "cloudabi",
-    target_os = "hermit",
-    all(target_arch = "wasm32", not(target_os = "emscripten")),
-    all(target_vendor = "fortanix", target_env = "sgx")
-))]
-pub fn stdout_isatty() -> bool {
-    // FIXME: Implement isatty on SGX
-    false
-}
-#[cfg(unix)]
-pub fn stdout_isatty() -> bool {
-    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
-}
-#[cfg(windows)]
-pub fn stdout_isatty() -> bool {
-    type DWORD = u32;
-    type BOOL = i32;
-    type HANDLE = *mut u8;
-    type LPDWORD = *mut u32;
-    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
-    extern "system" {
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
-    }
-    unsafe {
-        let handle = GetStdHandle(STD_OUTPUT_HANDLE);
-        let mut out = 0;
-        GetConsoleMode(handle, &mut out) != 0
+cfg_if::cfg_if! {
+    if #[cfg(unix)] {
+        pub fn stdout_isatty() -> bool {
+            unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
+        }
+    } else if #[cfg(windows)] {
+        pub fn stdout_isatty() -> bool {
+            type DWORD = u32;
+            type BOOL = i32;
+            type HANDLE = *mut u8;
+            type LPDWORD = *mut u32;
+            const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+            extern "system" {
+                fn GetStdHandle(which: DWORD) -> HANDLE;
+                fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
+            }
+            unsafe {
+                let handle = GetStdHandle(STD_OUTPUT_HANDLE);
+                let mut out = 0;
+                GetConsoleMode(handle, &mut out) != 0
+            }
+        }
+    } else {
+        // FIXME: Implement isatty on SGX
+        pub fn stdout_isatty() -> bool {
+            false
+        }
     }
 }
diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs
index cc025da1af5..c4d10ab177b 100644
--- a/src/libunwind/lib.rs
+++ b/src/libunwind/lib.rs
@@ -9,12 +9,31 @@
 
 cfg_if::cfg_if! {
     if #[cfg(target_env = "msvc")] {
-        // no extra unwinder support needed
-    } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
-        // no unwinder on the system!
-    } else {
+        // Windows MSVC no extra unwinder support needed
+    } else if #[cfg(any(
+        target_os = "l4re",
+        target_os = "none",
+    ))] {
+        // These "unix" family members do not have unwinder.
+        // Note this also matches x86_64-linux-kernel.
+    } else if #[cfg(any(
+        unix,
+        windows,
+        target_os = "cloudabi",
+        all(target_vendor = "fortanix", target_env = "sgx"),
+    ))] {
         mod libunwind;
         pub use libunwind::*;
+    } else {
+        // no unwinder on the system!
+        // - wasm32 (not emscripten, which is "unix" family)
+        // - os=none ("bare metal" targets)
+        // - os=hermit
+        // - os=uefi
+        // - os=cuda
+        // - nvptx64-nvidia-cuda
+        // - mipsel-sony-psp
+        // - Any new targets not listed above.
     }
 }
 
diff --git a/src/tools/rustc-std-workspace-std/lib.rs b/src/tools/rustc-std-workspace-std/lib.rs
index f40d09cafbb..1e955c61ac8 100644
--- a/src/tools/rustc-std-workspace-std/lib.rs
+++ b/src/tools/rustc-std-workspace-std/lib.rs
@@ -1 +1,2 @@
+#![feature(restricted_std)]
 pub use std::*;