diff --git a/.travis.yml b/.travis.yml
index 24028c3452..af161349f2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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:
@@ -74,6 +82,10 @@ matrix:
             --target thumbv6m-none-eabi
             --no-default-features
             --features nightly,cfg-target-has-atomic
+        - cargo build --manifest-path futures/Cargo.toml
+            --target thumbv6m-none-eabi
+            --no-default-features
+            --features nightly,alloc,cfg-target-has-atomic
 
     - name: cargo build --target=thumbv7m-none-eabi
       rust: nightly
@@ -84,6 +96,10 @@ matrix:
         - cargo build --manifest-path futures/Cargo.toml
             --target thumbv7m-none-eabi
             --no-default-features
+        - cargo build --manifest-path futures/Cargo.toml
+            --target thumbv7m-none-eabi
+            --no-default-features
+            --features nightly,alloc
 
     - name: cargo doc
       rust: nightly
diff --git a/futures-core/Cargo.toml b/futures-core/Cargo.toml
index e5c9905eb7..7cb4e5df7e 100644
--- a/futures-core/Cargo.toml
+++ b/futures-core/Cargo.toml
@@ -16,9 +16,10 @@ name = "futures_core"
 
 [features]
 default = ["std"]
-std = ["either/use_std"]
+std = ["alloc", "either/use_std"]
 nightly = []
 cfg-target-has-atomic = []
+alloc = []
 
 [dependencies]
 either = { version = "1.4", default-features = false, optional = true }
diff --git a/futures-core/src/future/future_obj.rs b/futures-core/src/future/future_obj.rs
index 94c76981b5..d765cabcf5 100644
--- a/futures-core/src/future/future_obj.rs
+++ b/futures-core/src/future/future_obj.rs
@@ -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
diff --git a/futures-core/src/future/mod.rs b/futures-core/src/future/mod.rs
index efdca7524d..0d539b3876 100644
--- a/futures-core/src/future/mod.rs
+++ b/futures-core/src/future/mod.rs
@@ -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)
diff --git a/futures-core/src/lib.rs b/futures-core/src/lib.rs
index 3e2639d861..daf2d3982d 100644
--- a/futures-core/src/lib.rs
+++ b/futures-core/src/lib.rs
@@ -2,6 +2,7 @@
 
 #![feature(futures_api)]
 #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]
+#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
@@ -12,6 +13,14 @@
 #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
 compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");
 
+#[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");
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std as alloc;
+
 pub mod future;
 #[doc(hidden)] pub use self::future::{Future, FusedFuture, TryFuture};
 
diff --git a/futures-core/src/stream/mod.rs b/futures-core/src/stream/mod.rs
index 72e813f8d8..cddc11e150 100644
--- a/futures-core/src/stream/mod.rs
+++ b/futures-core/src/stream/mod.rs
@@ -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(
diff --git a/futures-core/src/stream/stream_obj.rs b/futures-core/src/stream/stream_obj.rs
index dae033e398..70559ecffd 100644
--- a/futures-core/src/stream/stream_obj.rs
+++ b/futures-core/src/stream/stream_obj.rs
@@ -187,11 +187,11 @@ where
     unsafe fn drop(_ptr: *mut ()) {}
 }
 
-#[cfg(feature = "std")]
-mod if_std {
-    use std::boxed::Box;
-    use std::mem;
+#[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
diff --git a/futures-sink/Cargo.toml b/futures-sink/Cargo.toml
index fc615a8826..fd4396735b 100644
--- a/futures-sink/Cargo.toml
+++ b/futures-sink/Cargo.toml
@@ -15,8 +15,10 @@ 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"]
 default = ["std"]
+nightly = ["futures-core-preview/nightly"]
+alloc = ["futures-core-preview/alloc"]
 
 [dependencies]
 either = { version = "1.4", default-features = false, optional = true }
diff --git a/futures-sink/src/lib.rs b/futures-sink/src/lib.rs
index e7fd141095..973cb3d61f 100644
--- a/futures-sink/src/lib.rs
+++ b/futures-sink/src/lib.rs
@@ -8,6 +8,15 @@
 #![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/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");
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std as alloc;
 
 use futures_core::task::{Waker, Poll};
 use core::pin::Pin;
@@ -155,8 +164,8 @@ 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.
@@ -164,7 +173,7 @@ mod if_std {
     #[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 +196,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 +219,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 +241,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;
diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml
index 51be739f89..f7bdbc2482 100644
--- a/futures-util/Cargo.toml
+++ b/futures-util/Cargo.toml
@@ -15,13 +15,14 @@ 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"]
 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"]
 cfg-target-has-atomic = []
+alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc"]
 
 [dependencies]
 futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.13", default-features = false }
diff --git a/futures-util/src/future/abortable.rs b/futures-util/src/future/abortable.rs
index cfb51d55be..98e8d6fa2e 100644
--- a/futures-util/src/future/abortable.rs
+++ b/futures-util/src/future/abortable.rs
@@ -2,9 +2,9 @@ use crate::task::AtomicWaker;
 use futures_core::future::Future;
 use futures_core::task::{Waker, 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)]
diff --git a/futures-util/src/future/join_all.rs b/futures-util/src/future/join_all.rs
index 86c9e91d1c..398f054f2c 100644
--- a/futures-util/src/future/join_all.rs
+++ b/futures-util/src/future/join_all.rs
@@ -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 core::task::{Poll, Waker};
+use alloc::prelude::v1::*;
 
 #[derive(Debug)]
 enum ElemState<F>
@@ -127,10 +127,7 @@ where
 {
     type Output = Vec<F::Output>;
 
-    fn poll(
-        mut self: Pin<&mut Self>,
-        waker: &::std::task::Waker,
-    ) -> Poll<Self::Output> {
+    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
         let mut all_done = true;
 
         for mut elem in iter_pin_mut(self.elems.as_mut()) {
diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs
index 419cca8426..1605a41d23 100644
--- a/futures-util/src/future/mod.rs
+++ b/futures-util/src/future/mod.rs
@@ -7,6 +7,8 @@ use core::pin::Pin;
 use futures_core::future::Future;
 use futures_core::stream::Stream;
 use futures_core::task::{Waker, Poll};
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
 
 // re-export for `select!`
 #[doc(hidden)]
@@ -67,10 +69,17 @@ pub use self::unit_error::UnitError;
 mod chain;
 pub(crate) use self::chain::Chain;
 
-#[cfg(feature = "std")]
-mod abortable;
-#[cfg(feature = "std")]
-pub use self::abortable::{abortable, Abortable, AbortHandle, AbortRegistration, Aborted};
+#[cfg(feature = "alloc")]
+mod join_all;
+#[cfg(feature = "alloc")]
+pub use self::join_all::{join_all, JoinAll};
+
+cfg_target_has_atomic! {
+    #[cfg(feature = "alloc")]
+    mod abortable;
+    #[cfg(feature = "alloc")]
+    pub use self::abortable::{abortable, Abortable, AbortHandle, AbortRegistration, Aborted};
+}
 
 #[cfg(feature = "std")]
 mod catch_unwind;
@@ -82,12 +91,6 @@ mod remote_handle;
 #[cfg(feature = "std")]
 pub use self::remote_handle::{Remote, RemoteHandle};
 
-#[cfg(feature = "std")]
-mod join_all;
-
-#[cfg(feature = "std")]
-pub use self::join_all::{join_all, JoinAll};
-
 // #[cfg(feature = "std")]
 // mod select_all;
 // #[cfg(feature = "std")]
@@ -653,7 +656,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
     {
diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs
index c528d96070..d01bf36ea6 100644
--- a/futures-util/src/lib.rs
+++ b/futures-util/src/lib.rs
@@ -2,8 +2,10 @@
 //! and the `AsyncRead` and `AsyncWrite` traits.
 
 #![feature(futures_api)]
-#![cfg_attr(feature = "std", feature(async_await, await_macro, box_into_pin))]
+#![cfg_attr(feature = "alloc", feature(box_into_pin))]
+#![cfg_attr(feature = "std", feature(async_await, await_macro))]
 #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]
+#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc, alloc_prelude))]
 
 #![cfg_attr(not(feature = "std"), no_std)]
 #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
@@ -13,6 +15,14 @@
 #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
 compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");
 
+#[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");
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std as alloc;
+
 #[macro_use]
 mod macros;
 
@@ -91,5 +101,7 @@ pub mod io;
 #[cfg(feature = "std")]
 #[doc(hidden)] pub use crate::io::{AsyncReadExt, AsyncWriteExt};
 
-#[cfg(feature = "std")]
-pub mod lock;
+cfg_target_has_atomic! {
+    #[cfg(feature = "alloc")]
+    pub mod lock;
+}
diff --git a/futures-util/src/lock/bilock.rs b/futures-util/src/lock/bilock.rs
index a8c9676695..8ac3483063 100644
--- a/futures-util/src/lock/bilock.rs
+++ b/futures-util/src/lock/bilock.rs
@@ -3,17 +3,19 @@
 
 use futures_core::future::Future;
 use futures_core::task::{Waker, Poll};
+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"
diff --git a/futures-util/src/lock/mod.rs b/futures-util/src/lock/mod.rs
index e768c22332..38a5537724 100644
--- a/futures-util/src/lock/mod.rs
+++ b/futures-util/src/lock/mod.rs
@@ -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;
diff --git a/futures-util/src/macros/mod.rs b/futures-util/src/macros/mod.rs
index f0e9f05edc..0a9ac422c1 100644
--- a/futures-util/src/macros/mod.rs
+++ b/futures-util/src/macros/mod.rs
@@ -1,2 +1,12 @@
 #[macro_use]
 mod poll;
+
+macro_rules! cfg_target_has_atomic {
+    ($($item:item)*) => {$(
+        #[cfg_attr(
+            feature = "cfg-target-has-atomic",
+            cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+        )]
+        $item
+    )*};
+}
diff --git a/futures-util/src/sink/buffer.rs b/futures-util/src/sink/buffer.rs
index e61c1f1a69..4100c184d3 100644
--- a/futures-util/src/sink/buffer.rs
+++ b/futures-util/src/sink/buffer.rs
@@ -2,8 +2,8 @@ use futures_core::stream::Stream;
 use futures_core::task::{Waker, 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.
diff --git a/futures-util/src/sink/mod.rs b/futures-util/src/sink/mod.rs
index bde6d241d6..684735898b 100644
--- a/futures-util/src/sink/mod.rs
+++ b/futures-util/src/sink/mod.rs
@@ -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,
     {
diff --git a/futures-util/src/stream/buffer_unordered.rs b/futures-util/src/stream/buffer_unordered.rs
index f42f977fad..34c5252b08 100644
--- a/futures-util/src/stream/buffer_unordered.rs
+++ b/futures-util/src/stream/buffer_unordered.rs
@@ -4,8 +4,8 @@ use futures_core::stream::{Stream, FusedStream};
 use futures_core::task::{Waker, 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.
diff --git a/futures-util/src/stream/buffered.rs b/futures-util/src/stream/buffered.rs
index e8b1b128d1..cafa5f3a98 100644
--- a/futures-util/src/stream/buffered.rs
+++ b/futures-util/src/stream/buffered.rs
@@ -4,8 +4,8 @@ use futures_core::stream::Stream;
 use futures_core::task::{Waker, 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.
diff --git a/futures-util/src/stream/chunks.rs b/futures-util/src/stream/chunks.rs
index ae54ae60bd..6c0e631320 100644
--- a/futures-util/src/stream/chunks.rs
+++ b/futures-util/src/stream/chunks.rs
@@ -2,9 +2,9 @@ use crate::stream::Fuse;
 use futures_core::stream::Stream;
 use futures_core::task::{Waker, 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::v1::*;
 
 /// An adaptor that chunks up elements in a vector.
 ///
diff --git a/futures-util/src/stream/futures_ordered.rs b/futures-util/src/stream/futures_ordered.rs
index 443b434337..4f85b91723 100644
--- a/futures-util/src/stream/futures_ordered.rs
+++ b/futures-util/src/stream/futures_ordered.rs
@@ -3,11 +3,11 @@ use futures_core::future::Future;
 use futures_core::stream::Stream;
 use futures_core::task::{Waker, 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)]
diff --git a/futures-util/src/stream/futures_unordered/iter.rs b/futures-util/src/stream/futures_unordered/iter.rs
index 1eef3e5265..b03e10bb2d 100644
--- a/futures-util/src/stream/futures_unordered/iter.rs
+++ b/futures-util/src/stream/futures_unordered/iter.rs
@@ -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.
diff --git a/futures-util/src/stream/futures_unordered/mod.rs b/futures-util/src/stream/futures_unordered/mod.rs
index 29f891c28b..c9431ccc13 100644
--- a/futures-util/src/stream/futures_unordered/mod.rs
+++ b/futures-util/src/stream/futures_unordered/mod.rs
@@ -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::{Waker, 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;
 
diff --git a/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs b/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs
index f71b8ff877..210519585e 100644
--- a/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs
+++ b/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs
@@ -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;
diff --git a/futures-util/src/stream/futures_unordered/task.rs b/futures-util/src/stream/futures_unordered/task.rs
index 069c750e61..cbfec0c7ea 100644
--- a/futures-util/src/stream/futures_unordered/task.rs
+++ b/futures-util/src/stream/futures_unordered/task.rs
@@ -1,7 +1,7 @@
-use std::cell::UnsafeCell;
-use std::sync::{Arc, Weak};
-use std::sync::atomic::{AtomicPtr, AtomicBool};
-use std::sync::atomic::Ordering::SeqCst;
+use core::cell::UnsafeCell;
+use core::sync::atomic::{AtomicPtr, AtomicBool};
+use core::sync::atomic::Ordering::SeqCst;
+use alloc::sync::{Arc, Weak};
 
 use crate::task::{ArcWake, WakerRef, waker_ref};
 use super::ReadyToRunQueue;
diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs
index c3eafdcfc5..3b734dad8e 100644
--- a/futures-util/src/stream/mod.rs
+++ b/futures-util/src/stream/mod.rs
@@ -9,6 +9,8 @@ use futures_core::future::Future;
 use futures_core::stream::{FusedStream, Stream};
 use futures_core::task::{Waker, Poll};
 use futures_sink::Sink;
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
 
 mod iter;
 pub use self::iter::{iter, Iter};
@@ -97,53 +99,52 @@ pub use self::unfold::{unfold, Unfold};
 mod zip;
 pub use self::zip::Zip;
 
-#[cfg(feature = "std")]
-use std;
-
-#[cfg(feature = "std")]
-mod buffer_unordered;
-#[cfg(feature = "std")]
-pub use self::buffer_unordered::BufferUnordered;
-
-#[cfg(feature = "std")]
-mod buffered;
-#[cfg(feature = "std")]
-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")]
-mod for_each_concurrent;
-#[cfg(feature = "std")]
-pub use self::for_each_concurrent::ForEachConcurrent;
-
-#[cfg(feature = "std")]
-mod futures_ordered;
-#[cfg(feature = "std")]
-pub use self::futures_ordered::{futures_ordered, FuturesOrdered};
-
-#[cfg(feature = "std")]
-mod futures_unordered;
-#[cfg(feature = "std")]
-pub use self::futures_unordered::{futures_unordered, FuturesUnordered};
-
-#[cfg(feature = "std")]
-mod split;
-#[cfg(feature = "std")]
-pub use self::split::{SplitStream, SplitSink, ReuniteError};
+cfg_target_has_atomic! {
+    #[cfg(feature = "alloc")]
+    mod buffer_unordered;
+    #[cfg(feature = "alloc")]
+    pub use self::buffer_unordered::BufferUnordered;
+
+    #[cfg(feature = "alloc")]
+    mod buffered;
+    #[cfg(feature = "alloc")]
+    pub use self::buffered::Buffered;
+
+    #[cfg(feature = "alloc")]
+    mod for_each_concurrent;
+    #[cfg(feature = "alloc")]
+    pub use self::for_each_concurrent::ForEachConcurrent;
+
+    #[cfg(feature = "alloc")]
+    mod futures_ordered;
+    #[cfg(feature = "alloc")]
+    pub use self::futures_ordered::{futures_ordered, FuturesOrdered};
+
+    #[cfg(feature = "alloc")]
+    mod futures_unordered;
+    #[cfg(feature = "alloc")]
+    pub use self::futures_unordered::{futures_unordered, FuturesUnordered};
+
+    #[cfg(feature = "alloc")]
+    mod split;
+    #[cfg(feature = "alloc")]
+    pub use self::split::{SplitStream, SplitSink, ReuniteError};
+
+    #[cfg(feature = "alloc")]
+    mod select_all;
+    #[cfg(feature = "alloc")]
+    pub use self::select_all::{select_all, SelectAll};
+}
 
 #[cfg(feature = "std")]
-mod select_all;
+mod catch_unwind;
 #[cfg(feature = "std")]
-pub use self::select_all::{select_all, SelectAll};
+pub use self::catch_unwind::CatchUnwind;
 
 impl<T: ?Sized> StreamExt for T where T: Stream {}
 
@@ -614,7 +615,11 @@ pub trait StreamExt: Stream {
     /// await!(fut);
     /// # })
     /// ```
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn for_each_concurrent<Fut, F>(
         self,
         limit: impl Into<Option<usize>>,
@@ -791,7 +796,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 +815,11 @@ 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_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn buffered(self, n: usize) -> Buffered<Self>
         where Self::Item: Future,
               Self: Sized
@@ -854,7 +863,11 @@ pub trait StreamExt: Stream {
     /// assert_eq!(await!(buffered.next()), None);
     /// # })
     /// ```
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn buffer_unordered(self, n: usize) -> BufferUnordered<Self>
         where Self::Item: Future,
               Self: Sized
@@ -945,7 +958,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
     {
@@ -993,7 +1006,11 @@ 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_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn split(self) -> (SplitSink<Self>, SplitStream<Self>)
         where Self: Sink + Sized
     {
diff --git a/futures-util/src/stream/select_all.rs b/futures-util/src/stream/select_all.rs
index 31039c2011..d48542df5c 100644
--- a/futures-util/src/stream/select_all.rs
+++ b/futures-util/src/stream/select_all.rs
@@ -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::Waker;
diff --git a/futures-util/src/stream/split.rs b/futures-util/src/stream/split.rs
index 472b820c03..fea598275c 100644
--- a/futures-util/src/stream/split.rs
+++ b/futures-util/src/stream/split.rs
@@ -1,10 +1,12 @@
 use futures_core::stream::Stream;
 use futures_core::task::{Waker, 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"
diff --git a/futures-util/src/task/arc_wake.rs b/futures-util/src/task/arc_wake.rs
index aee4285986..f7333e06b6 100644
--- a/futures-util/src/task/arc_wake.rs
+++ b/futures-util/src/task/arc_wake.rs
@@ -1,6 +1,6 @@
-use std::mem;
-use std::sync::Arc;
-use std::task::{Waker, RawWaker, RawWakerVTable};
+use core::mem;
+use core::task::{Waker, RawWaker, RawWakerVTable};
+use alloc::sync::Arc;
 
 /// A way of waking up a specific task.
 ///
diff --git a/futures-util/src/task/mod.rs b/futures-util/src/task/mod.rs
index 580b0e12c8..d686272124 100644
--- a/futures-util/src/task/mod.rs
+++ b/futures-util/src/task/mod.rs
@@ -1,21 +1,31 @@
 //! Task notification
 
-/// A macro for creating a `RawWaker` vtable for a type that implements
-/// the `ArcWake` trait.
-macro_rules! waker_vtable {
-    ($ty:ident) => {
-        &RawWakerVTable {
-            clone: clone_arc_raw::<$ty>,
-            drop: drop_arc_raw::<$ty>,
-            wake: wake_arc_raw::<$ty>,
-        }
-    };
-}
+cfg_target_has_atomic! {
+    /// A macro for creating a `RawWaker` vtable for a type that implements
+    /// the `ArcWake` trait.
+    #[cfg(feature = "alloc")]
+    macro_rules! waker_vtable {
+        ($ty:ident) => {
+            &RawWakerVTable {
+                clone: clone_arc_raw::<$ty>,
+                drop: drop_arc_raw::<$ty>,
+                wake: wake_arc_raw::<$ty>,
+            }
+        };
+    }
 
-#[cfg(feature = "std")]
-mod arc_wake;
-#[cfg(feature = "std")]
-pub use self::arc_wake::ArcWake;
+    #[cfg(feature = "alloc")]
+    mod arc_wake;
+    #[cfg(feature = "alloc")]
+    pub use self::arc_wake::ArcWake;
+
+    #[cfg(feature = "alloc")]
+    mod waker_ref;
+    #[cfg(feature = "alloc")]
+    pub use self::waker_ref::{waker_ref, WakerRef};
+
+    pub use futures_core::task::__internal::AtomicWaker;
+}
 
 mod noop_waker;
 pub use self::noop_waker::noop_waker;
@@ -25,17 +35,6 @@ pub use self::noop_waker::noop_waker_ref;
 mod spawn;
 pub use self::spawn::{SpawnExt, LocalSpawnExt};
 
-#[cfg(feature = "std")]
-mod waker_ref;
-#[cfg(feature = "std")]
-pub use self::waker_ref::{waker_ref, WakerRef};
-
-#[cfg_attr(
-    feature = "cfg-target-has-atomic",
-    cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
-)]
-pub use futures_core::task::__internal::AtomicWaker;
-
 // re-export for `select!`
 #[doc(hidden)]
 pub use futures_core::task::{Waker, Poll};
diff --git a/futures-util/src/task/spawn.rs b/futures-util/src/task/spawn.rs
index 58fd89bec7..e414dccf74 100644
--- a/futures-util/src/task/spawn.rs
+++ b/futures-util/src/task/spawn.rs
@@ -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::boxed::Box;
 
 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,
diff --git a/futures-util/src/task/waker_ref.rs b/futures-util/src/task/waker_ref.rs
index 9608831b6f..cd5c39dc06 100644
--- a/futures-util/src/task/waker_ref.rs
+++ b/futures-util/src/task/waker_ref.rs
@@ -1,10 +1,10 @@
 #![allow(clippy::cast_ptr_alignment)] // clippy is too strict here
 
 use super::arc_wake::{ArcWake, clone_arc_raw, wake_arc_raw};
-use std::marker::PhantomData;
-use std::ops::Deref;
-use std::sync::Arc;
-use std::task::{Waker, RawWaker, RawWakerVTable};
+use alloc::sync::Arc;
+use core::marker::PhantomData;
+use core::ops::Deref;
+use core::task::{Waker, RawWaker, RawWakerVTable};
 
 /// A [`Waker`](::std::task::Waker) that is only valid for a given lifetime.
 ///
diff --git a/futures-util/src/try_future/mod.rs b/futures-util/src/try_future/mod.rs
index add19f88d0..3dcce7d4c6 100644
--- a/futures-util/src/try_future/mod.rs
+++ b/futures-util/src/try_future/mod.rs
@@ -54,10 +54,9 @@ 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
diff --git a/futures-util/src/try_future/try_join_all.rs b/futures-util/src/try_future/try_join_all.rs
index f26625c9cb..d387e0a164 100644
--- a/futures-util/src/try_future/try_join_all.rs
+++ b/futures-util/src/try_future/try_join_all.rs
@@ -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 core::task::{Poll, Waker};
+use alloc::prelude::v1::*;
 
 use super::TryFuture;
 
@@ -137,10 +137,7 @@ where
 {
     type Output = Result<Vec<F::Ok>, F::Error>;
 
-    fn poll(
-        mut self: Pin<&mut Self>,
-        waker: &::std::task::Waker,
-    ) -> Poll<Self::Output> {
+    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
         let mut state = FinalState::AllDone;
 
         for mut elem in iter_pin_mut(self.elems.as_mut()) {
diff --git a/futures-util/src/try_stream/mod.rs b/futures-util/src/try_stream/mod.rs
index 488a6f8750..a71798bd07 100644
--- a/futures-util/src/try_stream/mod.rs
+++ b/futures-util/src/try_stream/mod.rs
@@ -44,17 +44,19 @@ pub use self::try_fold::TryFold;
 mod try_skip_while;
 pub use self::try_skip_while::TrySkipWhile;
 
-#[cfg(feature = "std")]
-mod try_buffer_unordered;
-#[cfg(feature = "std")]
-pub use self::try_buffer_unordered::TryBufferUnordered;
-
-#[cfg(feature = "std")]
-mod try_for_each_concurrent;
-#[cfg(feature = "std")]
-pub use self::try_for_each_concurrent::TryForEachConcurrent;
-#[cfg(feature = "std")]
-use futures_core::future::Future;
+cfg_target_has_atomic! {
+    #[cfg(feature = "alloc")]
+    mod try_buffer_unordered;
+    #[cfg(feature = "alloc")]
+    pub use self::try_buffer_unordered::TryBufferUnordered;
+
+    #[cfg(feature = "alloc")]
+    mod try_for_each_concurrent;
+    #[cfg(feature = "alloc")]
+    pub use self::try_for_each_concurrent::TryForEachConcurrent;
+    #[cfg(feature = "alloc")]
+    use futures_core::future::Future;
+}
 
 #[cfg(feature = "std")]
 mod into_async_read;
@@ -310,7 +312,11 @@ pub trait TryStreamExt: TryStream {
     /// assert_eq!(Err(oneshot::Canceled), await!(fut));
     /// # })
     /// ```
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn try_for_each_concurrent<Fut, F>(
         self,
         limit: impl Into<Option<usize>>,
@@ -542,7 +548,11 @@ pub trait TryStreamExt: TryStream {
     /// assert_eq!(await!(buffered.next()), Some(Err("error in the stream")));
     /// # })
     /// ```
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered<Self>
         where Self::Ok: TryFuture<Error = Self::Error>,
               Self: Sized
diff --git a/futures-util/src/try_stream/try_buffer_unordered.rs b/futures-util/src/try_stream/try_buffer_unordered.rs
index 6b1f3e5bfa..3cbaad5c9d 100644
--- a/futures-util/src/try_stream/try_buffer_unordered.rs
+++ b/futures-util/src/try_stream/try_buffer_unordered.rs
@@ -5,7 +5,7 @@ use futures_core::future::TryFuture;
 use futures_core::stream::{Stream, TryStream};
 use futures_core::task::{Waker, 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
diff --git a/futures/Cargo.toml b/futures/Cargo.toml
index b97190e69b..70d8b3ba72 100644
--- a/futures/Cargo.toml
+++ b/futures/Cargo.toml
@@ -36,9 +36,10 @@ futures-test-preview = { path = "../futures-test", version = "=0.3.0-alpha.13" }
 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-core-preview/nightly", "futures-sink-preview/nightly", "futures-util-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"]
 cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic", "futures-util-preview/cfg-target-has-atomic"]
+alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc", "futures-util-preview/alloc"]
diff --git a/futures/src/lib.rs b/futures/src/lib.rs
index 8fb7dea1da..96ba9661c8 100644
--- a/futures/src/lib.rs
+++ b/futures/src/lib.rs
@@ -23,6 +23,7 @@
 
 #![feature(futures_api)]
 #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]
+#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
@@ -33,6 +34,9 @@
 #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
 compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");
 
+#[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;
 
 #[doc(hidden)] pub use futures_core::future::Future;
@@ -198,15 +202,24 @@ pub mod future {
         Join5, Map, Then,
     };
 
-    #[cfg(feature = "std")]
+    #[cfg(feature = "alloc")]
+    pub use futures_util::future::{join_all, JoinAll};
+
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     pub use futures_util::future::{
         abortable, Abortable, AbortHandle, AbortRegistration, Aborted,
+    };
+
+    #[cfg(feature = "std")]
+    pub use futures_util::future::{
         Remote, RemoteHandle,
         // For FutureExt:
         CatchUnwind, Shared,
 
-        join_all, JoinAll,
-
         // ToDo: SelectAll, SelectOk, select_all, select_ok
     };
 
@@ -217,7 +230,7 @@ pub mod future {
         TryJoin, TryJoin3, TryJoin4, TryJoin5,
     };
 
-    #[cfg(feature = "std")]
+    #[cfg(feature = "alloc")]
     pub use futures_util::try_future::{
         try_join_all, TryJoinAll,
     };
@@ -295,7 +308,7 @@ pub mod sink {
         // WithFlatMap,
     };
 
-    #[cfg(feature = "std")]
+    #[cfg(feature = "alloc")]
     pub use futures_util::sink::Buffer;
 }
 
@@ -327,23 +340,38 @@ pub mod stream {
         unfold, Unfold,
 
         StreamExt,
-        Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
+        Chain, Collect, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
         StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile,
         Take, TakeWhile, Then, Zip
     };
 
-    #[cfg(feature = "std")]
+    #[cfg(feature = "alloc")]
+    pub use futures_util::stream::{
+        // For StreamExt:
+        Chunks,
+    };
+
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[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, 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,
@@ -352,7 +380,11 @@ pub mod stream {
         // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
     };
 
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     pub use futures_util::try_stream::{
         // For TryStreamExt:
         TryBufferUnordered,
@@ -378,13 +410,19 @@ pub mod task {
 
     pub use futures_util::task::noop_waker;
 
-    #[cfg(feature = "std")]
+    #[cfg_attr(
+        feature = "cfg-target-has-atomic",
+        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+    )]
+    #[cfg(feature = "alloc")]
     pub use futures_util::task::{
         WakerRef, waker_ref, ArcWake,
         SpawnExt, LocalSpawnExt,
-        noop_waker_ref,
     };
 
+    #[cfg(feature = "std")]
+    pub use futures_util::task::noop_waker_ref;
+
     #[cfg_attr(
         feature = "cfg-target-has-atomic",
         cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))