Skip to content

[WIP] Add no_std + alloc support #1438

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

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -54,6 +54,14 @@ matrix:
- cargo build --manifest-path futures-sink/Cargo.toml --no-default-features
- cargo build --manifest-path futures-util/Cargo.toml --no-default-features

- name: cargo build (alloc)
rust: nightly
script:
- cargo build --manifest-path futures/Cargo.toml --no-default-features --features=alloc,nightly
- cargo build --manifest-path futures-core/Cargo.toml --no-default-features --features=alloc,nightly
- cargo build --manifest-path futures-sink/Cargo.toml --no-default-features --features=alloc,nightly
- cargo build --manifest-path futures-util/Cargo.toml --no-default-features --features=alloc,nightly

- name: cargo build (default features)
rust: nightly
script:
4 changes: 3 additions & 1 deletion futures-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -16,11 +16,13 @@ name = "futures_core"

[features]
default = ["std"]
std = ["either/use_std"]
std = ["alloc", "either/use_std", "alloc-shim/std"]
nightly = []
alloc = ["alloc-shim/alloc"]

[dependencies]
either = { version = "1.4", default-features = false, optional = true }
alloc-shim = { version = "0.3.0", features = ["futures"], optional = true }

[dev-dependencies]
futures-preview = { path = "../futures", version = "=0.3.0-alpha.12" }
7 changes: 4 additions & 3 deletions futures-core/src/future/future_obj.rs
Original file line number Diff line number Diff line change
@@ -185,10 +185,11 @@ where
unsafe fn drop(_ptr: *mut ()) {}
}

#[cfg(feature = "std")]
mod if_std {
#[cfg(feature = "alloc")]
mod if_alloc {
use super::*;
use std::mem;
use core::mem;
use alloc::boxed::Box;

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
where F: Future<Output = T> + 'a
7 changes: 5 additions & 2 deletions futures-core/src/future/mod.rs
Original file line number Diff line number Diff line change
@@ -33,9 +33,11 @@ impl<F: FusedFuture + ?Sized> FusedFuture for &mut F {
}
}

#[cfg(feature = "std")]
mod if_std {
#[cfg(feature = "alloc")]
mod if_alloc {
use alloc::boxed::Box;
use super::*;

impl<F: FusedFuture + ?Sized> FusedFuture for Box<F> {
fn is_terminated(&self) -> bool {
<F as FusedFuture>::is_terminated(&**self)
@@ -48,6 +50,7 @@ mod if_std {
}
}

#[cfg(feature = "std")]
impl<F: FusedFuture> FusedFuture for std::panic::AssertUnwindSafe<F> {
fn is_terminated(&self) -> bool {
<F as FusedFuture>::is_terminated(&**self)
4 changes: 4 additions & 0 deletions futures-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
#![feature(futures_api)]
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]

#![cfg_attr(not(feature = "std"), no_std)]

@@ -10,6 +11,9 @@

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures_core")]

#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))]
compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features");

pub mod future;
#[doc(hidden)] pub use self::future::{Future, FusedFuture, TryFuture};

9 changes: 5 additions & 4 deletions futures-core/src/stream/mod.rs
Original file line number Diff line number Diff line change
@@ -145,9 +145,9 @@ impl<S, T, E> TryStream for S
}
}

#[cfg(feature = "std")]
mod if_std {
use std::boxed::Box;
#[cfg(feature = "alloc")]
mod if_alloc {
use alloc::boxed::Box;
use super::*;

impl<S: ?Sized + Stream + Unpin> Stream for Box<S> {
@@ -161,6 +161,7 @@ mod if_std {
}
}

#[cfg(feature = "std")]
impl<S: Stream> Stream for ::std::panic::AssertUnwindSafe<S> {
type Item = S::Item;

@@ -172,7 +173,7 @@ mod if_std {
}
}

impl<T: Unpin> Stream for ::std::collections::VecDeque<T> {
impl<T: Unpin> Stream for ::alloc::collections::VecDeque<T> {
type Item = T;

fn poll_next(
8 changes: 4 additions & 4 deletions futures-core/src/stream/stream_obj.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ use super::Stream;
use crate::task::{LocalWaker, Poll};
use core::fmt;
use core::marker::PhantomData;
use core::mem;
use core::pin::Pin;

/// A custom trait object for polling streams, roughly akin to
@@ -188,10 +187,11 @@ where
unsafe fn drop(_ptr: *mut ()) {}
}

#[cfg(feature = "std")]
mod if_std {
use std::boxed::Box;
#[cfg(feature = "alloc")]
mod if_alloc {
use super::*;
use core::mem;
use alloc::boxed::Box;

unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for Box<F>
where F: Stream<Item = T> + 'a
4 changes: 2 additions & 2 deletions futures-core/src/task/mod.rs
Original file line number Diff line number Diff line change
@@ -6,5 +6,5 @@ pub mod __internal;
pub use self::spawn::{Spawn, LocalSpawn, SpawnError};

pub use core::task::{Poll, Waker, LocalWaker, UnsafeWake};
#[cfg(feature = "std")]
pub use std::task::{Wake, local_waker, local_waker_from_nonlocal};
#[cfg(feature = "alloc")]
pub use alloc::task::{Wake, local_waker, local_waker_from_nonlocal};
5 changes: 4 additions & 1 deletion futures-sink/Cargo.toml
Original file line number Diff line number Diff line change
@@ -15,10 +15,13 @@ The asynchronous `Sink` trait for the futures-rs library.
name = "futures_sink"

[features]
std = ["either/use_std", "futures-core-preview/std", "futures-channel-preview/std"]
std = ["alloc", "either/use_std", "futures-core-preview/std", "futures-channel-preview/std", "alloc-shim/std"]
default = ["std"]
nightly = ["futures-core-preview/nightly"]
alloc = ["futures-core-preview/alloc", "alloc-shim/alloc"]

[dependencies]
either = { version = "1.4", default-features = false, optional = true }
futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.12", default-features = false }
futures-channel-preview = { path = "../futures-channel", version = "=0.3.0-alpha.12", default-features = false }
alloc-shim = { version = "0.3.0", features = ["futures"], optional = true }
18 changes: 11 additions & 7 deletions futures-sink/src/lib.rs
Original file line number Diff line number Diff line change
@@ -8,6 +8,10 @@
#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures_sink")]

#![feature(futures_api)]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]

#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))]
compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features");

use futures_core::task::{LocalWaker, Poll};
use core::pin::Pin;
@@ -155,16 +159,16 @@ impl<'a, S: ?Sized + Sink> Sink for Pin<&'a mut S> {
#[cfg(feature = "std")]
mod channel_impls;

#[cfg(feature = "std")]
mod if_std {
#[cfg(feature = "alloc")]
mod if_alloc {
use super::*;

/// The error type for `Vec` and `VecDequeue` when used as `Sink`s.
/// Values of this type can never be created.
#[derive(Copy, Clone, Debug)]
pub enum VecSinkError {}

impl<T> Sink for ::std::vec::Vec<T> {
impl<T> Sink for ::alloc::vec::Vec<T> {
type SinkItem = T;
type SinkError = VecSinkError;

@@ -187,7 +191,7 @@ mod if_std {
}
}

impl<T> Sink for ::std::collections::VecDeque<T> {
impl<T> Sink for ::alloc::collections::VecDeque<T> {
type SinkItem = T;
type SinkError = VecSinkError;

@@ -210,7 +214,7 @@ mod if_std {
}
}

impl<S: ?Sized + Sink + Unpin> Sink for ::std::boxed::Box<S> {
impl<S: ?Sized + Sink + Unpin> Sink for ::alloc::boxed::Box<S> {
type SinkItem = S::SinkItem;
type SinkError = S::SinkError;

@@ -232,8 +236,8 @@ mod if_std {
}
}

#[cfg(feature = "std")]
pub use self::if_std::*;
#[cfg(feature = "alloc")]
pub use self::if_alloc::*;

#[cfg(feature = "either")]
use either::Either;
6 changes: 4 additions & 2 deletions futures-util/Cargo.toml
Original file line number Diff line number Diff line change
@@ -15,12 +15,13 @@ Common utilities and extension traits for the futures-rs library.
name = "futures_util"

[features]
std = ["futures-core-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-select-macro-preview/std", "either/use_std", "rand", "rand_core", "slab"]
std = ["alloc", "futures-core-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-select-macro-preview/std", "either/use_std", "rand", "rand_core", "slab", "alloc-shim/std"]
default = ["std", "futures-core-preview/either", "futures-sink-preview/either"]
compat = ["std", "futures_01"]
io-compat = ["compat", "tokio-io"]
bench = []
nightly = []
nightly = ["futures-core-preview/nightly", "futures-sink-preview/nightly"]
alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc", "alloc-shim/alloc"]

[dependencies]
futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.12", default-features = false }
@@ -37,6 +38,7 @@ slab = { version = "0.4", optional = true }
futures_01 = { version = "0.1.25", optional = true, package = "futures" }
tokio-io = { version = "0.1.9", optional = true }
pin-utils = "0.1.0-alpha.4"
alloc-shim = { version = "0.3.0", features = ["futures"], optional = true }

[dev-dependencies]
futures-preview = { path = "../futures", version = "=0.3.0-alpha.12" }
6 changes: 3 additions & 3 deletions futures-util/src/future/abortable.rs
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@ use crate::task::AtomicWaker;
use futures_core::future::Future;
use futures_core::task::{LocalWaker, Poll};
use pin_utils::unsafe_pinned;
use std::pin::Pin;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use core::pin::Pin;
use core::sync::atomic::{AtomicBool, Ordering};
use alloc::sync::Arc;

/// A future which can be remotely short-circuited using an `AbortHandle`.
#[derive(Debug, Clone)]
16 changes: 8 additions & 8 deletions futures-util/src/future/join_all.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.
use std::fmt;
use std::future::Future;
use std::iter::FromIterator;
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use std::task::Poll;
use core::fmt;
use core::future::Future;
use core::iter::FromIterator;
use core::mem;
use core::pin::Pin;
use alloc::prelude::*;
use alloc::task::Poll;

#[derive(Debug)]
enum ElemState<F>
@@ -129,7 +129,7 @@ where

fn poll(
mut self: Pin<&mut Self>,
lw: &::std::task::LocalWaker,
lw: &::alloc::task::LocalWaker,
) -> Poll<Self::Output> {
let mut all_done = true;

12 changes: 7 additions & 5 deletions futures-util/src/future/mod.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
#[cfg(feature = "alloc")]
use alloc::prelude::*;

// re-export for `select!`
#[doc(hidden)]
@@ -67,9 +69,9 @@ pub use self::unit_error::UnitError;
mod chain;
pub(crate) use self::chain::Chain;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod abortable;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::abortable::{abortable, Abortable, AbortHandle, AbortRegistration, Aborted};

#[cfg(feature = "std")]
@@ -82,10 +84,10 @@ mod remote_handle;
#[cfg(feature = "std")]
pub use self::remote_handle::{Remote, RemoteHandle};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod join_all;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::join_all::{join_all, JoinAll};

// #[cfg(feature = "std")]
@@ -653,7 +655,7 @@ pub trait FutureExt: Future {
}

/// Wrap the future in a Box, pinning it.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn boxed(self) -> Pin<Box<Self>>
where Self: Sized
{
6 changes: 5 additions & 1 deletion futures-util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -4,13 +4,17 @@
#![feature(futures_api, box_into_pin)]
#![cfg_attr(feature = "std", feature(async_await, await_macro))]
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]

#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs, missing_debug_implementations)]
#![deny(bare_trait_objects)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures_util")]

#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))]
compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features");

#[macro_use]
mod macros;

@@ -89,5 +93,5 @@ pub mod io;
#[cfg(feature = "std")]
#[doc(hidden)] pub use crate::io::{AsyncReadExt, AsyncWriteExt};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub mod lock;
21 changes: 12 additions & 9 deletions futures-util/src/lock/bilock.rs
Original file line number Diff line number Diff line change
@@ -3,17 +3,19 @@

use futures_core::future::Future;
use futures_core::task::{LocalWaker, Poll, Waker};
use core::cell::UnsafeCell;
use core::fmt;
use core::mem;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::SeqCst;
use alloc::boxed::Box;
use alloc::sync::Arc;
#[cfg(feature = "std")]
use std::any::Any;
use std::boxed::Box;
use std::cell::UnsafeCell;
#[cfg(feature = "std")]
use std::error::Error;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;

/// A type of futures-powered synchronization primitive which is a mutex between
/// two possible owners.
@@ -210,6 +212,7 @@ impl<T> fmt::Display for ReuniteError<T> {
}
}

#[cfg(feature = "std")]
impl<T: Any> Error for ReuniteError<T> {
fn description(&self) -> &str {
"tried to reunite two BiLocks that don't form a pair"
2 changes: 2 additions & 0 deletions futures-util/src/lock/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Futures-powered synchronization primitives.
#[cfg(feature = "std")]
mod mutex;
#[cfg(feature = "std")]
pub use self::mutex::{Mutex, MutexLockFuture, MutexGuard};

mod bilock;
4 changes: 2 additions & 2 deletions futures-util/src/sink/buffer.rs
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
use futures_sink::Sink;
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::collections::VecDeque;
use std::pin::Pin;
use core::pin::Pin;
use alloc::collections::VecDeque;

/// Sink for the `Sink::buffer` combinator, which buffers up to some fixed
/// number of values when the underlying sink is unable to accept them.
6 changes: 3 additions & 3 deletions futures-util/src/sink/mod.rs
Original file line number Diff line number Diff line change
@@ -41,9 +41,9 @@ pub use self::with::With;
mod with_flat_map;
pub use self::with_flat_map::WithFlatMap;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod buffer;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::buffer::Buffer;

impl<T: ?Sized> SinkExt for T where T: Sink {}
@@ -156,7 +156,7 @@ pub trait SinkExt: Sink {
///
/// This method is only available when the `std` feature of this
/// library is activated, and it is activated by default.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn buffer(self, capacity: usize) -> Buffer<Self>
where Self: Sized,
{
4 changes: 2 additions & 2 deletions futures-util/src/stream/buffer_unordered.rs
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ use futures_core::stream::{Stream, FusedStream};
use futures_core::task::{LocalWaker, Poll};
use futures_sink::Sink;
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::fmt;
use std::pin::Pin;
use core::fmt;
use core::pin::Pin;

/// An adaptor for a stream of futures to execute the futures concurrently, if
/// possible, delivering results as they become available.
4 changes: 2 additions & 2 deletions futures-util/src/stream/buffered.rs
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
use futures_sink::Sink;
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::fmt;
use std::pin::Pin;
use core::fmt;
use core::pin::Pin;

/// An adaptor for a stream of futures to execute the futures concurrently, if
/// possible.
6 changes: 3 additions & 3 deletions futures-util/src/stream/chunks.rs
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@ use crate::stream::Fuse;
use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use core::mem;
use core::pin::Pin;
use alloc::prelude::*;

/// An adaptor that chunks up elements in a vector.
///
10 changes: 5 additions & 5 deletions futures-util/src/stream/futures_ordered.rs
Original file line number Diff line number Diff line change
@@ -3,11 +3,11 @@ use futures_core::future::Future;
use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
use pin_utils::unsafe_pinned;
use std::cmp::{Eq, PartialEq, PartialOrd, Ord, Ordering};
use std::collections::binary_heap::{BinaryHeap, PeekMut};
use std::fmt::{self, Debug};
use std::iter::FromIterator;
use std::pin::Pin;
use core::cmp::{Eq, PartialEq, PartialOrd, Ord, Ordering};
use core::fmt::{self, Debug};
use core::iter::FromIterator;
use core::pin::Pin;
use alloc::collections::binary_heap::{BinaryHeap, PeekMut};

#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
4 changes: 2 additions & 2 deletions futures-util/src/stream/futures_unordered/iter.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::FuturesUnordered;
use super::task::Task;
use std::marker::PhantomData;
use std::pin::Pin;
use core::marker::PhantomData;
use core::pin::Pin;

#[derive(Debug)]
/// Mutable iterator over all futures in the unordered set.
22 changes: 11 additions & 11 deletions futures-util/src/stream/futures_unordered/mod.rs
Original file line number Diff line number Diff line change
@@ -4,17 +4,17 @@ use crate::task::AtomicWaker;
use futures_core::future::{Future, FutureObj, LocalFutureObj};
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{LocalWaker, Poll, Spawn, LocalSpawn, SpawnError};
use std::cell::UnsafeCell;
use std::fmt::{self, Debug};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::mem;
use std::pin::Pin;
use std::ptr;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::atomic::{AtomicPtr, AtomicBool};
use std::sync::{Arc, Weak};
use std::usize;
use core::cell::UnsafeCell;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem;
use core::pin::Pin;
use core::ptr;
use core::sync::atomic::Ordering::SeqCst;
use core::sync::atomic::{AtomicPtr, AtomicBool};
use core::usize;
use alloc::sync::{Arc, Weak};

mod abort;

10 changes: 5 additions & 5 deletions futures-util/src/stream/futures_unordered/ready_to_run_queue.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::task::AtomicWaker;
use std::cell::UnsafeCell;
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel};
use core::cell::UnsafeCell;
use core::ptr;
use core::sync::atomic::AtomicPtr;
use core::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel};
use alloc::sync::Arc;

use super::abort::abort;
use super::task::Task;
14 changes: 7 additions & 7 deletions futures-util/src/stream/futures_unordered/task.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem;
use std::ptr::{self, NonNull};
use std::sync::{Arc, Weak};
use std::sync::atomic::{AtomicPtr, AtomicBool};
use std::sync::atomic::Ordering::SeqCst;
use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::mem;
use core::ptr::{self, NonNull};
use core::sync::atomic::{AtomicPtr, AtomicBool};
use core::sync::atomic::Ordering::SeqCst;
use alloc::sync::{Arc, Weak};

use futures_core::task::{UnsafeWake, Waker, LocalWaker};

46 changes: 24 additions & 22 deletions futures-util/src/stream/mod.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ use futures_core::future::Future;
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{LocalWaker, Poll};
use futures_sink::Sink;
#[cfg(feature = "alloc")]
use alloc::prelude::*;

mod iter;
pub use self::iter::{iter, Iter};
@@ -100,49 +102,49 @@ pub use self::zip::Zip;
#[cfg(feature = "std")]
use std;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod buffer_unordered;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::buffer_unordered::BufferUnordered;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod buffered;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::buffered::Buffered;

#[cfg(feature = "std")]
mod catch_unwind;
#[cfg(feature = "std")]
pub use self::catch_unwind::CatchUnwind;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod chunks;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::chunks::Chunks;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod for_each_concurrent;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::for_each_concurrent::ForEachConcurrent;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod futures_ordered;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::futures_ordered::{futures_ordered, FuturesOrdered};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod futures_unordered;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::futures_unordered::{futures_unordered, FuturesUnordered};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod split;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::split::{SplitStream, SplitSink, ReuniteError};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod select_all;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::select_all::{select_all, SelectAll};

impl<T: ?Sized> StreamExt for T where T: Stream {}
@@ -614,7 +616,7 @@ pub trait StreamExt: Stream {
/// await!(fut);
/// # })
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn for_each_concurrent<Fut, F>(
self,
limit: impl Into<Option<usize>>,
@@ -791,7 +793,7 @@ pub trait StreamExt: Stream {
}

/// Wrap the stream in a Box, pinning it.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn boxed(self) -> Pin<Box<Self>>
where Self: Sized
{
@@ -810,7 +812,7 @@ pub trait StreamExt: Stream {
///
/// This method is only available when the `std` feature of this
/// library is activated, and it is activated by default.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn buffered(self, n: usize) -> Buffered<Self>
where Self::Item: Future,
Self: Sized
@@ -854,7 +856,7 @@ pub trait StreamExt: Stream {
/// assert_eq!(await!(buffered.next()), None);
/// # })
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn buffer_unordered(self, n: usize) -> BufferUnordered<Self>
where Self::Item: Future,
Self: Sized
@@ -945,7 +947,7 @@ pub trait StreamExt: Stream {
/// # Panics
///
/// This method will panic of `capacity` is zero.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn chunks(self, capacity: usize) -> Chunks<Self>
where Self: Sized
{
@@ -999,7 +1001,7 @@ pub trait StreamExt: Stream {
///
/// This method is only available when the `std` feature of this
/// library is activated, and it is activated by default.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn split(self) -> (SplitSink<Self>, SplitStream<Self>)
where Self: Sink + Sized
{
4 changes: 2 additions & 2 deletions futures-util/src/stream/select_all.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! An unbounded set of streams
use std::fmt::{self, Debug};
use std::pin::Pin;
use core::fmt::{self, Debug};
use core::pin::Pin;

use futures_core::{Poll, Stream, FusedStream};
use futures_core::task::LocalWaker;
7 changes: 5 additions & 2 deletions futures-util/src/stream/split.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use futures_core::stream::Stream;
use futures_core::task::{LocalWaker, Poll};
use futures_sink::Sink;
use core::fmt;
use core::pin::Pin;
#[cfg(feature = "std")]
use std::any::Any;
#[cfg(feature = "std")]
use std::error::Error;
use std::fmt;
use std::pin::Pin;

use crate::lock::BiLock;

@@ -139,6 +141,7 @@ impl<T: Sink> fmt::Display for ReuniteError<T> {
}
}

#[cfg(feature = "std")]
impl<T: Any + Sink> Error for ReuniteError<T> {
fn description(&self) -> &str {
"tried to reunite a SplitStream and SplitSink that don't form a pair"
10 changes: 5 additions & 5 deletions futures-util/src/task/local_waker_ref.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![allow(clippy::cast_ptr_alignment)] // clippy is too strict here

use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::NonNull;
use std::sync::Arc;
use std::task::{LocalWaker, Waker, Wake, UnsafeWake};
use core::marker::PhantomData;
use core::ops::Deref;
use core::ptr::NonNull;
use alloc::sync::Arc;
use alloc::task::{LocalWaker, Waker, Wake, UnsafeWake};

/// A [`LocalWaker`](::std::task::LocalWaker) that is only valid for a given lifetime.
///
4 changes: 2 additions & 2 deletions futures-util/src/task/mod.rs
Original file line number Diff line number Diff line change
@@ -6,9 +6,9 @@ pub use self::noop_waker::{noop_local_waker, noop_local_waker_ref};
mod spawn;
pub use self::spawn::{SpawnExt, LocalSpawnExt};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod local_waker_ref;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::local_waker_ref::{local_waker_ref, local_waker_ref_from_nonlocal, LocalWakerRef};

#[cfg_attr(
10 changes: 6 additions & 4 deletions futures-util/src/task/spawn.rs
Original file line number Diff line number Diff line change
@@ -4,10 +4,12 @@ use futures_core::task::{LocalSpawn, Spawn};

#[cfg(feature = "std")]
use crate::future::{FutureExt, RemoteHandle};
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
use futures_core::future::{Future, FutureObj, LocalFutureObj};
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
use futures_core::task::SpawnError;
#[cfg(feature = "alloc")]
use alloc::prelude::*;

impl<Sp: ?Sized> SpawnExt for Sp where Sp: Spawn {}
impl<Sp: ?Sized> LocalSpawnExt for Sp where Sp: LocalSpawn {}
@@ -39,7 +41,7 @@ pub trait SpawnExt: Spawn {
/// let future = async { /* ... */ };
/// executor.spawn(future).unwrap();
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn spawn<Fut>(&mut self, future: Fut) -> Result<(), SpawnError>
where
Fut: Future<Output = ()> + Send + 'static,
@@ -118,7 +120,7 @@ pub trait LocalSpawnExt: LocalSpawn {
/// let future = async { /* ... */ };
/// spawner.spawn_local(future).unwrap();
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn spawn_local<Fut>(&mut self, future: Fut) -> Result<(), SpawnError>
where
Fut: Future<Output = ()> + 'static,
4 changes: 2 additions & 2 deletions futures-util/src/try_future/mod.rs
Original file line number Diff line number Diff line change
@@ -54,10 +54,10 @@ pub use self::or_else::OrElse;
mod unwrap_or_else;
pub use self::unwrap_or_else::UnwrapOrElse;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod try_join_all;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::try_join_all::{try_join_all, TryJoinAll};

// Implementation details
16 changes: 8 additions & 8 deletions futures-util/src/try_future/try_join_all.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Definition of the `TryJoinAll` combinator, waiting for all of a list of
//! futures to finish with either success or error.
use std::fmt;
use std::future::Future;
use std::iter::FromIterator;
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use std::task::Poll;
use core::fmt;
use core::future::Future;
use core::iter::FromIterator;
use core::mem;
use core::pin::Pin;
use alloc::prelude::*;
use alloc::task::Poll;

use super::TryFuture;

@@ -139,7 +139,7 @@ where

fn poll(
mut self: Pin<&mut Self>,
lw: &::std::task::LocalWaker,
lw: &::alloc::task::LocalWaker,
) -> Poll<Self::Output> {
let mut state = FinalState::AllDone;

20 changes: 10 additions & 10 deletions futures-util/src/try_stream/mod.rs
Original file line number Diff line number Diff line change
@@ -41,21 +41,21 @@ pub use self::try_fold::TryFold;
mod try_skip_while;
pub use self::try_skip_while::TrySkipWhile;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod try_buffer_unordered;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::try_buffer_unordered::TryBufferUnordered;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod try_collect;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::try_collect::TryCollect;

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
mod try_for_each_concurrent;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use self::try_for_each_concurrent::TryForEachConcurrent;
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
use futures_core::future::Future;

#[cfg(feature = "std")]
@@ -312,7 +312,7 @@ pub trait TryStreamExt: TryStream {
/// assert_eq!(Err(oneshot::Canceled), await!(fut));
/// # })
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn try_for_each_concurrent<Fut, F>(
self,
limit: impl Into<Option<usize>>,
@@ -360,7 +360,7 @@ pub trait TryStreamExt: TryStream {
/// assert_eq!(output, Err(6));
/// # })
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn try_collect<C: Default + Extend<Self::Ok>>(self) -> TryCollect<Self, C>
where Self: Sized
{
@@ -548,7 +548,7 @@ pub trait TryStreamExt: TryStream {
/// assert_eq!(await!(buffered.next()), Some(Err("error in the stream")));
/// # })
/// ```
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered<Self>
where Self::Ok: TryFuture<Error = Self::Error>,
Self: Sized
2 changes: 1 addition & 1 deletion futures-util/src/try_stream/try_buffer_unordered.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ use futures_core::future::TryFuture;
use futures_core::stream::{Stream, TryStream};
use futures_core::task::{LocalWaker, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::pin::Pin;
use core::pin::Pin;

/// A stream returned by the
/// [`try_buffer_unordered`](super::TryStreamExt::try_buffer_unordered) method
5 changes: 2 additions & 3 deletions futures-util/src/try_stream/try_collect.rs
Original file line number Diff line number Diff line change
@@ -2,9 +2,8 @@ use futures_core::future::{FusedFuture, Future};
use futures_core::stream::{FusedStream, TryStream};
use futures_core::task::{LocalWaker, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use core::mem;
use core::pin::Pin;

/// A future which attempts to collect all of the values of a stream.
///
5 changes: 3 additions & 2 deletions futures/Cargo.toml
Original file line number Diff line number Diff line change
@@ -36,8 +36,9 @@ futures-test-preview = { path = "../futures-test", version = "=0.3.0-alpha.12" }
tokio = "0.1.11"

[features]
nightly = ["futures-util-preview/nightly", "futures-core-preview/nightly"]
std = ["futures-core-preview/std", "futures-executor-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-util-preview/std"]
nightly = ["futures-util-preview/nightly", "futures-core-preview/nightly", "futures-sink-preview/nightly"]
std = ["alloc", "futures-core-preview/std", "futures-executor-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-util-preview/std"]
default = ["std"]
compat = ["std", "futures-util-preview/compat"]
io-compat = ["compat", "futures-util-preview/io-compat"]
alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc", "futures-util-preview/alloc"]
32 changes: 22 additions & 10 deletions futures/src/lib.rs
Original file line number Diff line number Diff line change
@@ -31,6 +31,10 @@
#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]

#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))]
compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features");

#[doc(hidden)] pub use futures_util::core_reexport;

@@ -189,15 +193,18 @@ pub mod future {
Join5, Map, Then,
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_util::future::{
abortable, Abortable, AbortHandle, AbortRegistration, Aborted,

join_all, JoinAll,
};
#[cfg(feature = "std")]
pub use futures_util::future::{
Remote, RemoteHandle,
// For FutureExt:
CatchUnwind, Shared,

join_all, JoinAll,

// ToDo: SelectAll, SelectOk, select_all, select_ok
};

@@ -282,7 +289,7 @@ pub mod sink {
// WithFlatMap,
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_util::sink::Buffer;
}

@@ -319,18 +326,23 @@ pub mod stream {
Take, TakeWhile, Then, Zip
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_util::stream::{
futures_ordered, FuturesOrdered,
futures_unordered, FuturesUnordered,

// For StreamExt:
BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream,
SplitSink, ReuniteError,
BufferUnordered, Buffered, Chunks, Collect, SplitStream, SplitSink,

select_all, SelectAll,
};

#[cfg(feature = "std")]
pub use futures_util::stream::{
// For StreamExt:
CatchUnwind, ReuniteError,
};

pub use futures_util::try_stream::{
TryStreamExt,
TryNext, TryForEach, ErrInto,
@@ -339,7 +351,7 @@ pub mod stream {
// ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_util::try_stream::{
// For TryStreamExt:
TryCollect, TryBufferUnordered,
@@ -363,12 +375,12 @@ pub mod task {
Waker, LocalWaker, UnsafeWake,
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_core::task::{
Wake, local_waker, local_waker_from_nonlocal
};

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub use futures_util::task::{
LocalWakerRef, local_waker_ref, local_waker_ref_from_nonlocal,
SpawnExt, LocalSpawnExt,