From 335bd34470d24870e0cbdaddadc7408105b299b9 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 8 Nov 2019 00:56:58 +0100 Subject: [PATCH] Add "std" feature flag (#476) * core feature Signed-off-by: Yoshua Wuyts * introduce std + default features Signed-off-by: Yoshua Wuyts * test std features on ci Signed-off-by: Yoshua Wuyts * finish up all features Signed-off-by: Yoshua Wuyts * Fix task_local macro * Remove crossbeam-channel and futures-timer from std * Move future::timeout() behind cfg_default --- .github/workflows/ci.yml | 6 +++ Cargo.toml | 66 ++++++++++++++++++++++----------- src/future/future/mod.rs | 8 ++-- src/future/mod.rs | 7 +++- src/io/mod.rs | 80 +++++++++++++++++++++------------------- src/lib.rs | 43 ++++++++++++++------- src/macros.rs | 52 ++++++++++++++++++++++++++ src/os/unix/mod.rs | 11 ++++-- src/os/windows/mod.rs | 4 +- src/prelude.rs | 56 +++++++++++++++------------- src/sync/waker_set.rs | 3 +- src/task/mod.rs | 64 +++++++++++++++++--------------- src/task/task_local.rs | 51 ------------------------- src/utils.rs | 31 ++++++++++++++-- 14 files changed, 287 insertions(+), 195 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d5e7c7..031ffc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,12 @@ jobs: command: check args: --features unstable --all --benches --bins --examples --tests + - name: check std only + uses: actions-rs/cargo@v1 + with: + command: check + args: --no-default-features --features std + - name: tests uses: actions-rs/cargo@v1 with: diff --git a/Cargo.toml b/Cargo.toml index 54ab0f1..7c860c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,32 +21,54 @@ features = ["docs"] rustdoc-args = ["--cfg", "feature=\"docs\""] [features] -default = [] -docs = ["unstable", "attributes"] -unstable = ["broadcaster"] -attributes = ["async-attributes"] +default = [ + "std", + "async-task", + "crossbeam-channel", + "crossbeam-deque", + "futures-timer", + "kv-log-macro", + "log", + "mio", + "mio-uds", + "num_cpus", + "pin-project-lite", +] +docs = ["unstable"] +unstable = ["default", "broadcaster"] +std = [ + "async-macros", + "crossbeam-utils", + "futures-core", + "futures-io", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", +] [dependencies] async-attributes = { version = "1.1.0", optional = true } -async-macros = "1.0.0" -async-task = "1.0.0" +async-macros = { version = "1.0.0", optional = true } +async-task = { version = "1.0.0", optional = true } broadcaster = { version = "0.2.6", optional = true, default-features = false, features = ["default-channels"] } -crossbeam-channel = "0.3.9" -crossbeam-deque = "0.7.1" -crossbeam-utils = "0.6.6" -futures-core = "0.3.0" -futures-io = "0.3.0" -futures-timer = "1.0.2" -kv-log-macro = "1.0.4" -log = { version = "0.4.8", features = ["kv_unstable"] } -memchr = "2.2.1" -mio = "0.6.19" -mio-uds = "0.6.7" -num_cpus = "1.10.1" -once_cell = "1.2.0" -pin-project-lite = "0.1" -pin-utils = "0.1.0-alpha.4" -slab = "0.4.2" +crossbeam-channel = { version = "0.3.9", optional = true } +crossbeam-deque = { version = "0.7.1", optional = true } +crossbeam-utils = { version = "0.6.6", optional = true } +futures-core = { version = "0.3.0", optional = true } +futures-io = { version = "0.3.0", optional = true } +futures-timer = { version = "1.0.2", optional = true } +kv-log-macro = { version = "1.0.4", optional = true } +log = { version = "0.4.8", features = ["kv_unstable"], optional = true } +memchr = { version = "2.2.1", optional = true } +mio = { version = "0.6.19", optional = true } +mio-uds = { version = "0.6.7", optional = true } +num_cpus = { version = "1.10.1", optional = true } +once_cell = { version = "1.2.0", optional = true } +pin-project-lite = { version = "0.1", optional = true } +pin-utils = { version = "0.1.0-alpha.4", optional = true } +slab = { version = "0.4.2", optional = true } [dev-dependencies] femme = "1.2.0" diff --git a/src/future/future/mod.rs b/src/future/future/mod.rs index d7bd75b..d712dc8 100644 --- a/src/future/future/mod.rs +++ b/src/future/future/mod.rs @@ -144,8 +144,8 @@ extension_trait! { /// dbg!(a.await); /// # }) /// ``` + #[cfg(all(feature = "default", feature = "unstable"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - #[cfg(any(feature = "unstable", feature = "docs"))] fn delay(self, dur: Duration) -> impl Future [DelayFuture] where Self: Future + Sized @@ -167,8 +167,8 @@ extension_trait! { /// assert_eq!(future.await, 1); /// # }) /// ``` + #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - #[cfg(any(feature = "unstable", feature = "docs"))] fn flatten(self) -> impl Future::Output as IntoFuture>::Output> [FlattenFuture::Output as IntoFuture>::Future>] where Self: Future + Sized, @@ -206,7 +206,7 @@ extension_trait! { # }); ``` "#] - #[cfg(any(feature = "unstable", feature = "docs"))] + #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn race( self, @@ -252,7 +252,7 @@ extension_trait! { # Ok(()) }) } ``` "#] - #[cfg(any(feature = "unstable", feature = "docs"))] + #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn try_race( self, diff --git a/src/future/mod.rs b/src/future/mod.rs index dd28f28..4e7d79a 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -53,13 +53,16 @@ pub use future::Future; pub use pending::pending; pub use poll_fn::poll_fn; pub use ready::ready; -pub use timeout::{timeout, TimeoutError}; pub(crate) mod future; mod pending; mod poll_fn; mod ready; -mod timeout; + +cfg_default! { + pub use timeout::{timeout, TimeoutError}; + mod timeout; +} cfg_unstable! { pub use into_future::IntoFuture; diff --git a/src/io/mod.rs b/src/io/mod.rs index 93753d1..c471159 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -269,48 +269,54 @@ //! [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html //! [`.unwrap()`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap -#[doc(inline)] -pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom}; +cfg_std! { + #[doc(inline)] + pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom}; -pub use buf_read::{BufRead, Lines}; -pub use buf_reader::BufReader; -pub use buf_writer::BufWriter; -pub use copy::copy; -pub use cursor::Cursor; -pub use empty::{empty, Empty}; -pub use read::Read; -pub use repeat::{repeat, Repeat}; -pub use seek::Seek; -pub use sink::{sink, Sink}; -pub use stderr::{stderr, Stderr}; -pub use stdin::{stdin, Stdin}; -pub use stdout::{stdout, Stdout}; -pub use timeout::timeout; -pub use write::Write; + pub use buf_read::{BufRead, Lines}; + pub use buf_reader::BufReader; + pub use buf_writer::BufWriter; + pub use copy::copy; + pub use cursor::Cursor; + pub use empty::{empty, Empty}; + pub use read::Read; + pub use repeat::{repeat, Repeat}; + pub use seek::Seek; + pub use sink::{sink, Sink}; + pub use write::Write; -// For use in the print macros. -#[doc(hidden)] -pub use stdio::{_eprint, _print}; + pub mod prelude; -pub mod prelude; + pub(crate) mod buf_read; + pub(crate) mod read; + pub(crate) mod seek; + pub(crate) mod write; -pub(crate) mod buf_read; -pub(crate) mod read; -pub(crate) mod seek; -pub(crate) mod write; + mod buf_reader; + mod buf_writer; + mod copy; + mod cursor; + mod empty; + mod repeat; + mod sink; +} + +cfg_default! { + // For use in the print macros. + #[doc(hidden)] + pub use stdio::{_eprint, _print}; -mod buf_reader; -mod buf_writer; -mod copy; -mod cursor; -mod empty; -mod repeat; -mod sink; -mod stderr; -mod stdin; -mod stdio; -mod stdout; -mod timeout; + pub use stderr::{stderr, Stderr}; + pub use stdin::{stdin, Stdin}; + pub use stdout::{stdout, Stdout}; + pub use timeout::timeout; + + mod timeout; + mod stderr; + mod stdin; + mod stdio; + mod stdout; +} cfg_unstable! { pub use stderr::StderrLock; diff --git a/src/lib.rs b/src/lib.rs index 4863cbb..04ed8fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ //! # Async version of the Rust standard library //! //! `async-std` is a foundation of portable Rust software, a set of minimal and battle-tested -//! shared abstractions for the [broader Rust ecosystem][crates.io]. It offers core types, like +//! shared abstractions for the [broader Rust ecosystem][crates.io]. It offers std types, like //! [`Future`] and [`Stream`], library-defined [operations on language primitives](#primitives), //! [standard macros](#macros), [I/O] and [multithreading], among [many other things][other]. //! @@ -170,8 +170,17 @@ //! version = "0.99" //! features = ["attributes"] //! ``` +//! +//! Additionally it's possible to only use the core traits and combinators by +//! only enabling the `std` Cargo feature: +//! +//! ```toml +//! [dependencies.async-std] +//! version = "0.99" +//! default-features = false +//! features = ["std"] +//! ``` -#![cfg(feature = "default")] #![cfg_attr(feature = "docs", feature(doc_cfg))] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] #![allow(clippy::mutex_atomic, clippy::module_inception)] @@ -188,16 +197,24 @@ mod utils; #[doc(inline)] pub use async_attributes::{main, test}; -pub mod fs; -pub mod future; -pub mod io; -pub mod net; -pub mod os; -pub mod path; -pub mod prelude; -pub mod stream; -pub mod sync; -pub mod task; +#[cfg(feature = "std")] +mod macros; + +cfg_std! { + pub mod future; + pub mod io; + pub mod os; + pub mod prelude; + pub mod stream; + pub mod sync; + pub mod task; +} + +cfg_default! { + pub mod fs; + pub mod path; + pub mod net; +} cfg_unstable! { pub mod pin; @@ -213,5 +230,3 @@ cfg_unstable! { #[doc(inline)] pub use std::{write, writeln}; } - -mod macros; diff --git a/src/macros.rs b/src/macros.rs index f932e47..b7811d2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -165,3 +165,55 @@ macro_rules! eprintln { } ); } + +/// Declares task-local values. +/// +/// The macro wraps any number of static declarations and makes them task-local. Attributes and +/// visibility modifiers are allowed. +/// +/// Each declared value is of the accessor type [`LocalKey`]. +/// +/// [`LocalKey`]: task/struct.LocalKey.html +/// +/// # Examples +/// +/// ``` +/// # +/// use std::cell::Cell; +/// +/// use async_std::task; +/// use async_std::prelude::*; +/// +/// task_local! { +/// static VAL: Cell = Cell::new(5); +/// } +/// +/// task::block_on(async { +/// let v = VAL.with(|c| c.get()); +/// assert_eq!(v, 5); +/// }); +/// ``` +#[cfg(feature = "default")] +#[macro_export] +macro_rules! task_local { + () => (); + + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( + $(#[$attr])* $vis static $name: $crate::task::LocalKey<$t> = { + #[inline] + fn __init() -> $t { + $init + } + + $crate::task::LocalKey { + __init, + __key: ::std::sync::atomic::AtomicU32::new(0), + } + }; + ); + + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + $crate::task_local!($(#[$attr])* $vis static $name: $t = $init); + $crate::task_local!($($rest)*); + ); +} diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs index 722cfe6..c389d95 100644 --- a/src/os/unix/mod.rs +++ b/src/os/unix/mod.rs @@ -1,5 +1,10 @@ //! Platform-specific extensions for Unix platforms. -pub mod fs; -pub mod io; -pub mod net; +cfg_std! { + pub mod io; +} + +cfg_default! { + pub mod fs; + pub mod net; +} diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index 30218f0..f335000 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -1,3 +1,5 @@ //! Platform-specific extensions for Windows. -pub mod io; +cfg_std! { + pub mod io; +} diff --git a/src/prelude.rs b/src/prelude.rs index f8583fd..2a1fa41 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -11,35 +11,39 @@ //! use async_std::prelude::*; //! ``` -#[doc(no_inline)] -pub use crate::future::Future; -#[doc(no_inline)] -pub use crate::stream::Stream; -#[doc(no_inline)] -pub use crate::task_local; +cfg_std! { + #[doc(no_inline)] + pub use crate::future::Future; + #[doc(no_inline)] + pub use crate::stream::Stream; -#[doc(inline)] -pub use crate::future::future::FutureExt; -#[doc(inline)] -pub use crate::stream::stream::StreamExt; + #[doc(inline)] + pub use crate::future::future::FutureExt; + #[doc(inline)] + pub use crate::stream::stream::StreamExt; + #[doc(no_inline)] + pub use crate::io::BufRead as _; + #[doc(no_inline)] + pub use crate::io::Read as _; + #[doc(no_inline)] + pub use crate::io::Seek as _; + #[doc(no_inline)] + pub use crate::io::Write as _; -#[doc(no_inline)] -pub use crate::io::BufRead as _; -#[doc(no_inline)] -pub use crate::io::Read as _; -#[doc(no_inline)] -pub use crate::io::Seek as _; -#[doc(no_inline)] -pub use crate::io::Write as _; + #[doc(no_inline)] + pub use crate::io::prelude::BufReadExt as _; + #[doc(no_inline)] + pub use crate::io::prelude::ReadExt as _; + #[doc(no_inline)] + pub use crate::io::prelude::SeekExt as _; + #[doc(no_inline)] + pub use crate::io::prelude::WriteExt as _; +} -#[doc(no_inline)] -pub use crate::io::prelude::BufReadExt as _; -#[doc(no_inline)] -pub use crate::io::prelude::ReadExt as _; -#[doc(no_inline)] -pub use crate::io::prelude::SeekExt as _; -#[doc(no_inline)] -pub use crate::io::prelude::WriteExt as _; +cfg_default! { + #[doc(no_inline)] + pub use crate::task_local; +} cfg_unstable! { #[doc(no_inline)] diff --git a/src/sync/waker_set.rs b/src/sync/waker_set.rs index 7e3d8e1..5ba4cfb 100644 --- a/src/sync/waker_set.rs +++ b/src/sync/waker_set.rs @@ -7,12 +7,11 @@ use std::cell::UnsafeCell; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::task::{Context, Waker}; use crossbeam_utils::Backoff; use slab::Slab; -use crate::task::{Context, Waker}; - /// Set when the entry list is locked. #[allow(clippy::identity_op)] const LOCKED: usize = 1 << 0; diff --git a/src/task/mod.rs b/src/task/mod.rs index 72d559a..bcdea72 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -118,41 +118,45 @@ //! [`task_local!`]: ../macro.task_local.html //! [`with`]: struct.LocalKey.html#method.with -#[doc(inline)] -pub use std::task::{Context, Poll, Waker}; +cfg_std! { + #[doc(inline)] + pub use std::task::{Context, Poll, Waker}; -#[doc(inline)] -pub use async_macros::ready; + #[doc(inline)] + pub use async_macros::ready; +} -pub use block_on::block_on; -pub use builder::Builder; -pub use current::current; -pub use join_handle::JoinHandle; -pub use sleep::sleep; -pub use spawn::spawn; -pub use task::Task; -pub use task_id::TaskId; -pub use task_local::{AccessError, LocalKey}; +cfg_default! { + pub use block_on::block_on; + pub use builder::Builder; + pub use current::current; + pub use task::Task; + pub use task_id::TaskId; + pub use join_handle::JoinHandle; + pub use sleep::sleep; + pub use spawn::spawn; + pub use task_local::{AccessError, LocalKey}; -#[cfg(any(feature = "unstable", test))] -pub use spawn_blocking::spawn_blocking; -#[cfg(not(any(feature = "unstable", test)))] -pub(crate) use spawn_blocking::spawn_blocking; + use builder::Runnable; + use task_local::LocalsMap; -use builder::Runnable; -use task_local::LocalsMap; + mod block_on; + mod builder; + mod current; + mod executor; + mod join_handle; + mod sleep; + mod spawn; + mod spawn_blocking; + mod task; + mod task_id; + mod task_local; -mod block_on; -mod builder; -mod current; -mod executor; -mod join_handle; -mod sleep; -mod spawn; -mod spawn_blocking; -mod task; -mod task_id; -mod task_local; + #[cfg(any(feature = "unstable", test))] + pub use spawn_blocking::spawn_blocking; + #[cfg(not(any(feature = "unstable", test)))] + pub(crate) use spawn_blocking::spawn_blocking; +} cfg_unstable! { pub use yield_now::yield_now; diff --git a/src/task/task_local.rs b/src/task/task_local.rs index 0869cab..72e53d7 100644 --- a/src/task/task_local.rs +++ b/src/task/task_local.rs @@ -5,57 +5,6 @@ use std::sync::atomic::{AtomicU32, Ordering}; use crate::task::Task; -/// Declares task-local values. -/// -/// The macro wraps any number of static declarations and makes them task-local. Attributes and -/// visibility modifiers are allowed. -/// -/// Each declared value is of the accessor type [`LocalKey`]. -/// -/// [`LocalKey`]: task/struct.LocalKey.html -/// -/// # Examples -/// -/// ``` -/// # -/// use std::cell::Cell; -/// -/// use async_std::task; -/// use async_std::prelude::*; -/// -/// task_local! { -/// static VAL: Cell = Cell::new(5); -/// } -/// -/// task::block_on(async { -/// let v = VAL.with(|c| c.get()); -/// assert_eq!(v, 5); -/// }); -/// ``` -#[macro_export] -macro_rules! task_local { - () => (); - - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( - $(#[$attr])* $vis static $name: $crate::task::LocalKey<$t> = { - #[inline] - fn __init() -> $t { - $init - } - - $crate::task::LocalKey { - __init, - __key: ::std::sync::atomic::AtomicU32::new(0), - } - }; - ); - - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( - $crate::task_local!($(#[$attr])* $vis static $name: $t = $init); - $crate::task_local!($($rest)*); - ); -} - /// The key for accessing a task-local value. /// /// Every task-local value is lazily initialized on first access and destroyed when the task diff --git a/src/utils.rs b/src/utils.rs index cfdf5fa..13dbe37 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,7 @@ -use std::mem; - /// Calls a function and aborts if it panics. /// /// This is useful in unsafe code where we can't recover from panics. +#[cfg(feature = "default")] #[inline] pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { struct Bomb; @@ -15,11 +14,12 @@ pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { let bomb = Bomb; let t = f(); - mem::forget(bomb); + std::mem::forget(bomb); t } /// Generates a random number in `0..n`. +#[cfg(feature = "default")] pub fn random(n: u32) -> u32 { use std::cell::Cell; use std::num::Wrapping; @@ -53,6 +53,7 @@ pub fn random(n: u32) -> u32 { } /// Defers evaluation of a block of code until the end of the scope. +#[cfg(feature = "default")] #[doc(hidden)] macro_rules! defer { ($($body:tt)*) => { @@ -130,6 +131,30 @@ macro_rules! cfg_not_docs { } } +/// Declares std items. +#[allow(unused_macros)] +#[doc(hidden)] +macro_rules! cfg_std { + ($($item:item)*) => { + $( + #[cfg(feature = "std")] + $item + )* + } +} + +/// Declares default items. +#[allow(unused_macros)] +#[doc(hidden)] +macro_rules! cfg_default { + ($($item:item)*) => { + $( + #[cfg(feature = "default")] + $item + )* + } +} + /// Defines an extension trait for a base trait. /// /// In generated docs, the base trait will contain methods from the extension trait. In actual