Skip to content

Add build support for Cargo's build-std feature. #74033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -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",
1 change: 1 addition & 0 deletions src/libpanic_abort/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
35 changes: 19 additions & 16 deletions src/libpanic_abort/lib.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}

20 changes: 16 additions & 4 deletions src/libpanic_unwind/lib.rs
Original file line number Diff line number Diff line change
@@ -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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

target_family = "unix" FWIW I think is the same as unix, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is the same. I have been waffling on which style I like better, and I think I ended up being really inconsistent. I think part of the issue is that I've run into a number of users being confused what cfg(unix) means, which makes me feel it is better to be explicit. But unix and windows is conveniently short.

One thing that surprises me is that it is possible to have family="unix" and os="none" at the same time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh either way is fine by me, I figured unix is a bit more idiomatic though. For unix, target_os = "none" being true that seems like it's either a mistake or something that hasn't been reviewed since it was added

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x86_64-linux-kernel is the only one. I'm not sure what values would make sense for that, since it is unusual.

Copy link
Member

@eddyb eddyb Jul 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the Linux kernel even have an UNIX API inside of itself? That doesn't sound right but maybe I just haven't seen it before.

(To be clear, I'm thinking that family="unix" is as valid for inside an OS kernel as os="thatosname" - if os="none" is used then surely there should also not be a family? Maybe we should enforce that the family is derived from the OS name and therefore means "OS family")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #74247 for further discussion.

Copy link
Member

@eddyb eddyb Jul 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it was related or coincidental but I just saw #74257 being open. Oh, highly relevant, just likely accidentally pointing to the wrong #.

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;
}
}

1 change: 1 addition & 0 deletions src/libproc_macro/lib.rs
Original file line number Diff line number Diff line change
@@ -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"]
3 changes: 2 additions & 1 deletion src/librustc_passes/stability.rs
Original file line number Diff line number Diff line change
@@ -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;
}

24 changes: 24 additions & 0 deletions src/libstd/build.rs
Original file line number Diff line number Diff line change
@@ -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());
}
77 changes: 1 addition & 76 deletions src/libstd/env.rs
Original file line number Diff line number Diff line change
@@ -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::*;
9 changes: 8 additions & 1 deletion src/libstd/lib.rs
Original file line number Diff line number Diff line change
@@ -197,7 +197,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/",
@@ -552,3 +553,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 {}
3 changes: 2 additions & 1 deletion src/libstd/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -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::*;
}
}

22 changes: 22 additions & 0 deletions src/libstd/sys/unsupported/alloc.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
38 changes: 38 additions & 0 deletions src/libstd/sys/unsupported/args.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
File renamed without changes.
48 changes: 48 additions & 0 deletions src/libstd/sys/unsupported/common.rs
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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]
9 changes: 9 additions & 0 deletions src/libstd/sys/unsupported/env.rs
Original file line number Diff line number Diff line change
@@ -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 = "";
}
File renamed without changes.
File renamed without changes.
24 changes: 24 additions & 0 deletions src/libstd/sys/unsupported/mod.rs
Original file line number Diff line number Diff line change
@@ -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::*;
Original file line number Diff line number Diff line change
@@ -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 {
File renamed without changes.
21 changes: 9 additions & 12 deletions src/libstd/sys/wasm/os.rs → src/libstd/sys/unsupported/os.rs
Original file line number Diff line number Diff line change
@@ -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,35 +72,33 @@ 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>> {
Ok(None)
}

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> {
None
}

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")
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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 {
File renamed without changes.
File renamed without changes.
41 changes: 41 additions & 0 deletions src/libstd/sys/unsupported/thread.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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");
}
Original file line number Diff line number Diff line change
@@ -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> {
45 changes: 11 additions & 34 deletions src/libstd/sys/wasi/mod.rs
Original file line number Diff line number Diff line change
@@ -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() }
}
1 change: 0 additions & 1 deletion src/libstd/sys/wasm/memchr.rs

This file was deleted.

63 changes: 19 additions & 44 deletions src/libstd/sys/wasm/mod.rs
Original file line number Diff line number Diff line change
@@ -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::*;
11 changes: 4 additions & 7 deletions src/libstd/sys_common/mod.rs
Original file line number Diff line number Diff line change
@@ -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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sort of forget what's going on here, could you remind me what's up with this module?

This may be a good candidate for movement to sys instead of sys_common?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I fully understand the question.

There are some things defined in sys_common::net that are used in various other places throughout std. In particular:

  • libstd/net/addr.rs: Needs LookupHost
  • libstd/net/tcp.rs: Needs TcpStream and TcpListener
  • libstd/net/udp.rs: Needs UdpSocket

sys_common/net.rs has implementations that work for almost every platform, except those listed above. cloudabi, wasm, and bare-metal targets don't support these (they have stub implementations). l4re, hermit, and sgx have custom implementations.

If it is moved to sys, I think it would need to use #[path] tricks to share amongst unix, windows, vxworks, wasi, etc. I have no objection to that, but I don't fully understand the philosophy of sys_common. A lot of stuff in there does not appear to be 100% common, so I'm not sure how the line gets drawn.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm ok so yeah if you're up for it I think the best way to deal with this is to use #[path] tricks like you are for other platforms. That'll make it easy to avoid code duplication while also making it easy to allow each platform to choose its own implementation.

Otherwise the original intention of sys_common was basically what it says on the tin, everything in common between all sys modules. That being said as you've realized this rarely holds up to be true over time. When you add a new platform that needs almost everything but not quite, it's way easier to add a few #[cfg] than to reorganize to align with the original principles.

Nowadays I sort of feel like sys_common should either be 100% (or maybe 99%) shared or otherwise everything should be shared with #[path].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind if I defer that to a separate PR? I'd actually like to do a pass of de-duplicating large sections of the sys module, and I think this would fit with that. In particular, there are large chunks of duplicate code in the cloudabi, hermit, sgx, and vxworks modules. It is not clear to me if there was a good reason for that, do you happen to know? Do you think there would be any objections to adding more #[path] attributes to share amongst those?

(This is a practical thing, I was recently looking at making a small change to Command, and saw that I needed to update several identical files.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah that's ok, a separate PR should work fine 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you could, please cc me on the follow-up PR.

all(target_arch = "wasm32", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
pub use crate::sys::net;
1 change: 1 addition & 0 deletions src/libstd/sys_common/mutex.rs
Original file line number Diff line number Diff line change
@@ -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")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity where did this come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit convoluted (and I don't 100% understand the const stability infrastructure).

Mutex::new is used inside a const fn here for std::io::lazy::Lazy::new. The const-stability checks are tied to the overall stability checks. When libstd is marked unstable (via restricted-std), somehow this propagates to const functions as well. Surprisingly this is the only const fn that tripped this issue. The specific error is:

error[E0723]: can only call other const fn within a const fn, but const sys_common::mutex::Mutex::new is not stable as const fn

I believe when a const fn has no stability attributes, it inherits whatever the crate (or module?) stability is. (Sorry, it's been months since I worked on this, so my memory is a bit fuzzy.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok no worries, I was a little curious but I'd believe that it falls out of something, and it's internal anyway so it doesn't matter too much.

pub const fn new() -> Mutex {
Mutex(imp::Mutex::new())
}
1 change: 1 addition & 0 deletions src/libtest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
171 changes: 69 additions & 102 deletions src/libtest/helpers/concurrency.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
56 changes: 27 additions & 29 deletions src/libtest/helpers/isatty.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
}
27 changes: 23 additions & 4 deletions src/libunwind/lib.rs
Original file line number Diff line number Diff line change
@@ -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.
}
}

1 change: 1 addition & 0 deletions src/tools/rustc-std-workspace-std/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#![feature(restricted_std)]
pub use std::*;