diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 8a3950718d7d2..207359ed6968f 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -911,7 +911,7 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
 
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 63b3fbbdaefe1..eb673488170b6 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -85,7 +85,6 @@
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(fundamental)]
-#![feature(futures_api)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(needs_allocator)]
diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index e1ab67873a025..504330a023b31 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -1,6 +1,4 @@
-#![unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+#![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::marker::Unpin;
 use crate::ops;
@@ -26,8 +24,10 @@ use crate::task::{Context, Poll};
 /// `await!` the value.
 #[doc(spotlight)]
 #[must_use = "futures do nothing unless polled"]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub trait Future {
     /// The type of value produced on completion.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     type Output;
 
     /// Attempt to resolve the future to a final value, registering
@@ -92,9 +92,11 @@ pub trait Future {
     /// [`Context`]: ../task/struct.Context.html
     /// [`Waker`]: ../task/struct.Waker.html
     /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
+    #[stable(feature = "futures_api", since = "1.36.0")]
     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<F: ?Sized + Future + Unpin> Future for &mut F {
     type Output = F::Output;
 
@@ -103,6 +105,7 @@ impl<F: ?Sized + Future + Unpin> Future for &mut F {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<P> Future for Pin<P>
 where
     P: Unpin + ops::DerefMut,
diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs
index 6693ecbac41fa..89ea4713cfdaa 100644
--- a/src/libcore/future/mod.rs
+++ b/src/libcore/future/mod.rs
@@ -1,8 +1,7 @@
-#![unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+#![stable(feature = "futures_api", since = "1.36.0")]
 
 //! Asynchronous values.
 
 mod future;
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::future::Future;
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 29bae69ea83c1..ef090928392cd 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -1,11 +1,11 @@
-#![unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+#![stable(feature = "futures_api", since = "1.36.0")]
 
 //! Types and Traits for working with asynchronous tasks.
 
 mod poll;
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::poll::Poll;
 
 mod wake;
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::wake::{Context, Waker, RawWaker, RawWakerVTable};
diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs
index ecf03afb88e2a..3db70d5e7645f 100644
--- a/src/libcore/task/poll.rs
+++ b/src/libcore/task/poll.rs
@@ -1,6 +1,4 @@
-#![unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+#![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::ops::Try;
 use crate::result::Result;
@@ -9,20 +7,27 @@ use crate::result::Result;
 /// scheduled to receive a wakeup instead.
 #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub enum Poll<T> {
     /// Represents that a value is immediately ready.
-    Ready(T),
+    #[stable(feature = "futures_api", since = "1.36.0")]
+    Ready(
+        #[stable(feature = "futures_api", since = "1.36.0")]
+        T
+    ),
 
     /// Represents that a value is not ready yet.
     ///
     /// When a function returns `Pending`, the function *must* also
     /// ensure that the current task is scheduled to be awoken when
     /// progress can be made.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     Pending,
 }
 
 impl<T> Poll<T> {
     /// Changes the ready value of this `Poll` with the closure provided.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map<U, F>(self, f: F) -> Poll<U>
         where F: FnOnce(T) -> U
     {
@@ -34,6 +39,7 @@ impl<T> Poll<T> {
 
     /// Returns `true` if this is `Poll::Ready`
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn is_ready(&self) -> bool {
         match *self {
             Poll::Ready(_) => true,
@@ -43,6 +49,7 @@ impl<T> Poll<T> {
 
     /// Returns `true` if this is `Poll::Pending`
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn is_pending(&self) -> bool {
         !self.is_ready()
     }
@@ -50,6 +57,7 @@ impl<T> Poll<T> {
 
 impl<T, E> Poll<Result<T, E>> {
     /// Changes the success value of this `Poll` with the closure provided.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
         where F: FnOnce(T) -> U
     {
@@ -61,6 +69,7 @@ impl<T, E> Poll<Result<T, E>> {
     }
 
     /// Changes the error value of this `Poll` with the closure provided.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
         where F: FnOnce(E) -> U
     {
@@ -72,12 +81,14 @@ impl<T, E> Poll<Result<T, E>> {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<T> From<T> for Poll<T> {
     fn from(t: T) -> Poll<T> {
         Poll::Ready(t)
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<T, E> Try for Poll<Result<T, E>> {
     type Ok = Poll<T>;
     type Error = E;
@@ -102,6 +113,7 @@ impl<T, E> Try for Poll<Result<T, E>> {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<T, E> Try for Poll<Option<Result<T, E>>> {
     type Ok = Poll<Option<T>>;
     type Error = E;
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index 94e31054a5812..b4e9124983205 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -1,6 +1,4 @@
-#![unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+#![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::fmt;
 use crate::marker::{PhantomData, Unpin};
@@ -13,6 +11,7 @@ use crate::marker::{PhantomData, Unpin};
 /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that
 /// customizes the behavior of the `RawWaker`.
 #[derive(PartialEq, Debug)]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub struct RawWaker {
     /// A data pointer, which can be used to store arbitrary data as required
     /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
@@ -37,9 +36,7 @@ impl RawWaker {
     /// from a `RawWaker`. For each operation on the `Waker`, the associated
     /// function in the `vtable` of the underlying `RawWaker` will be called.
     #[rustc_promotable]
-    #[unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
         RawWaker {
             data,
@@ -58,6 +55,7 @@ impl RawWaker {
 /// pointer of a properly constructed [`RawWaker`] object from inside the
 /// [`RawWaker`] implementation. Calling one of the contained functions using
 /// any other `data` pointer will cause undefined behavior.
+#[stable(feature = "futures_api", since = "1.36.0")]
 #[derive(PartialEq, Copy, Clone, Debug)]
 pub struct RawWakerVTable {
     /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
@@ -131,9 +129,14 @@ impl RawWakerVTable {
     /// resources that are associated with this instance of a [`RawWaker`] and
     /// associated task.
     #[rustc_promotable]
-    #[unstable(feature = "futures_api",
-            reason = "futures in libcore are unstable",
-            issue = "50547")]
+    #[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))]
+    #[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))]
+    // `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else
+    // without first consulting with T-Lang.
+    //
+    // FIXME: remove whenever we have a stable way to accept fn pointers from const fn
+    // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062)
+    #[cfg_attr(not(stage0), rustc_allow_const_fn_ptr)]
     pub const fn new(
         clone: unsafe fn(*const ()) -> RawWaker,
         wake: unsafe fn(*const ()),
@@ -153,6 +156,7 @@ impl RawWakerVTable {
 ///
 /// Currently, `Context` only serves to provide access to a `&Waker`
 /// which can be used to wake the current task.
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Context<'a> {
     waker: &'a Waker,
     // Ensure we future-proof against variance changes by forcing
@@ -164,6 +168,7 @@ pub struct Context<'a> {
 
 impl<'a> Context<'a> {
     /// Create a new `Context` from a `&Waker`.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     #[inline]
     pub fn from_waker(waker: &'a Waker) -> Self {
         Context {
@@ -173,12 +178,14 @@ impl<'a> Context<'a> {
     }
 
     /// Returns a reference to the `Waker` for the current task.
+    #[stable(feature = "futures_api", since = "1.36.0")]
     #[inline]
     pub fn waker(&self) -> &'a Waker {
         &self.waker
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl fmt::Debug for Context<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Context")
@@ -195,17 +202,22 @@ impl fmt::Debug for Context<'_> {
 ///
 /// Implements [`Clone`], [`Send`], and [`Sync`].
 #[repr(transparent)]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
     waker: RawWaker,
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl Unpin for Waker {}
+#[stable(feature = "futures_api", since = "1.36.0")]
 unsafe impl Send for Waker {}
+#[stable(feature = "futures_api", since = "1.36.0")]
 unsafe impl Sync for Waker {}
 
 impl Waker {
     /// Wake up the task associated with this `Waker`.
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn wake(self) {
         // The actual wakeup call is delegated through a virtual function call
         // to the implementation which is defined by the executor.
@@ -227,6 +239,7 @@ impl Waker {
     /// where an owned `Waker` is available. This method should be preferred to
     /// calling `waker.clone().wake()`.
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn wake_by_ref(&self) {
         // The actual wakeup call is delegated through a virtual function call
         // to the implementation which is defined by the executor.
@@ -243,6 +256,7 @@ impl Waker {
     ///
     /// This function is primarily used for optimization purposes.
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn will_wake(&self, other: &Waker) -> bool {
         self.waker == other.waker
     }
@@ -253,6 +267,7 @@ impl Waker {
     /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
     /// Therefore this method is unsafe.
     #[inline]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub unsafe fn from_raw(waker: RawWaker) -> Waker {
         Waker {
             waker,
@@ -260,6 +275,7 @@ impl Waker {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl Clone for Waker {
     #[inline]
     fn clone(&self) -> Self {
@@ -272,6 +288,7 @@ impl Clone for Waker {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl Drop for Waker {
     #[inline]
     fn drop(&mut self) {
@@ -282,6 +299,7 @@ impl Drop for Waker {
     }
 }
 
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl fmt::Debug for Waker {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 496ccc888b61a..40cce8e77c0e0 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -121,6 +121,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
     feature,
     rustc_depr,
     promotable,
+    allow_const_fn_ptr,
     const_stability
 });
 
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index ef1270d304523..8ce86f70a551f 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -441,6 +441,7 @@ impl<'a, 'tcx> Index<'tcx> {
                     rustc_depr: None,
                     const_stability: None,
                     promotable: false,
+                    allow_const_fn_ptr: false,
                 });
                 annotator.parent_stab = Some(stability);
             }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 8c1e345cdaec5..1861420b408b6 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -235,6 +235,8 @@ rustc_queries! {
         /// constructor function).
         query is_promotable_const_fn(_: DefId) -> bool {}
 
+        query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {}
+
         /// True if this is a foreign item (i.e., linked via `extern { ... }`).
         query is_foreign_item(_: DefId) -> bool {}
 
diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
index e33d0a74ea013..7298b548f3197 100644
--- a/src/librustc/ty/constness.rs
+++ b/src/librustc/ty/constness.rs
@@ -95,9 +95,16 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
         }
     }
 
+    fn const_fn_is_allowed_fn_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
+        tcx.is_const_fn(def_id) &&
+            tcx.lookup_stability(def_id)
+                .map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
+    }
+
     *providers = Providers {
         is_const_fn_raw,
         is_promotable_const_fn,
+        const_fn_is_allowed_fn_ptr,
         ..*providers
     };
 }
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 776985ab79802..d5f04ca64e4c4 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -60,13 +60,14 @@ pub fn is_min_const_fn(
     }
 
     for local in &mir.local_decls {
-        check_ty(tcx, local.ty, local.source_info.span)?;
+        check_ty(tcx, local.ty, local.source_info.span, def_id)?;
     }
     // impl trait is gone in MIR, so check the return type manually
     check_ty(
         tcx,
         tcx.fn_sig(def_id).output().skip_binder(),
         mir.local_decls.iter().next().unwrap().source_info.span,
+        def_id,
     )?;
 
     for bb in mir.basic_blocks() {
@@ -82,6 +83,7 @@ fn check_ty(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ty: ty::Ty<'tcx>,
     span: Span,
+    fn_def_id: DefId,
 ) -> McfResult {
     for ty in ty.walk() {
         match ty.sty {
@@ -91,7 +93,9 @@ fn check_ty(
             )),
             ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
-                return Err((span, "function pointers in const fn are unstable".into()))
+                if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
+                    return Err((span, "function pointers in const fn are unstable".into()))
+                }
             }
             ty::Dynamic(preds, _) => {
                 for pred in preds.iter() {
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 898387cb9f56d..c18a314116bf0 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -9,6 +9,7 @@ use core::task::{Context, Poll};
 use core::ops::{Drop, Generator, GeneratorState};
 
 #[doc(inline)]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub use core::future::*;
 
 /// Wrap a generator in a future.
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 62bc1991cc93c..bdec0c347f546 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -263,7 +263,6 @@
 #![feature(fixed_size_array)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
-#![feature(futures_api)]
 #![feature(generator_trait)]
 #![feature(hash_raw_entry)]
 #![feature(hashmap_internals)]
@@ -458,18 +457,15 @@ pub mod process;
 pub mod sync;
 pub mod time;
 
-#[unstable(feature = "futures_api",
-           reason = "futures in libcore are unstable",
-           issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub mod task {
     //! Types and Traits for working with asynchronous tasks.
     #[doc(inline)]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub use core::task::*;
 }
 
-#[unstable(feature = "futures_api",
-           reason = "futures in libcore are unstable",
-           issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub mod future;
 
 // Platform-abstraction modules
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 5a8101e230119..7a3b5d30500a9 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -319,7 +319,7 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<F: Future> Future for AssertUnwindSafe<F> {
     type Output = F::Output;
 
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 74c952b076cd7..db821f4e5369d 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -114,6 +114,8 @@ pub struct Stability {
     pub const_stability: Option<Symbol>,
     /// whether the function has a `#[rustc_promotable]` attribute
     pub promotable: bool,
+    /// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
+    pub allow_const_fn_ptr: bool,
 }
 
 /// The available stability levels.
@@ -178,6 +180,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
     let mut rustc_depr: Option<RustcDeprecation> = None;
     let mut rustc_const_unstable: Option<Symbol> = None;
     let mut promotable = false;
+    let mut allow_const_fn_ptr = false;
     let diagnostic = &sess.span_diagnostic;
 
     'outer: for attr in attrs_iter {
@@ -187,6 +190,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
             "unstable",
             "stable",
             "rustc_promotable",
+            "rustc_allow_const_fn_ptr",
         ].iter().any(|&s| attr.path == s) {
             continue // not a stability level
         }
@@ -198,6 +202,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
         if attr.path == "rustc_promotable" {
             promotable = true;
         }
+        if attr.path == "rustc_allow_const_fn_ptr" {
+            allow_const_fn_ptr = true;
+        }
         // attributes with data
         else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
             let meta = meta.as_ref().unwrap();
@@ -354,6 +361,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
                                 rustc_depr: None,
                                 const_stability: None,
                                 promotable: false,
+                                allow_const_fn_ptr: false,
                             })
                         }
                         (None, _, _) => {
@@ -418,6 +426,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
                                 rustc_depr: None,
                                 const_stability: None,
                                 promotable: false,
+                                allow_const_fn_ptr: false,
                             })
                         }
                         (None, _) => {
@@ -458,13 +467,14 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
     }
 
     // Merge the const-unstable info into the stability info
-    if promotable {
+    if promotable || allow_const_fn_ptr {
         if let Some(ref mut stab) = stab {
-            stab.promotable = true;
+            stab.promotable = promotable;
+            stab.allow_const_fn_ptr = allow_const_fn_ptr;
         } else {
             span_err!(diagnostic, item_sp, E0717,
-                      "rustc_promotable attribute must be paired with \
-                       either stable or unstable attribute");
+                      "rustc_promotable and rustc_allow_const_fn_ptr attributes \
+                      must be paired with either stable or unstable attribute");
         }
     }
 
diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs
index 503b39e181ab7..39472ae11fbc5 100644
--- a/src/test/compile-fail/must_use-in-stdlib-traits.rs
+++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs
@@ -1,5 +1,5 @@
 #![deny(unused_must_use)]
-#![feature(arbitrary_self_types, futures_api)]
+#![feature(arbitrary_self_types)]
 
 use std::iter::Iterator;
 use std::future::Future;
diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs
index 518452aefc152..e1b4328debd9a 100644
--- a/src/test/run-pass/async-await.rs
+++ b/src/test/run-pass/async-await.rs
@@ -1,7 +1,7 @@
 // edition:2018
 // aux-build:arc_wake.rs
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 extern crate arc_wake;
 
diff --git a/src/test/run-pass/auxiliary/arc_wake.rs b/src/test/run-pass/auxiliary/arc_wake.rs
index 93e074e7ee55c..c21886f26f467 100644
--- a/src/test/run-pass/auxiliary/arc_wake.rs
+++ b/src/test/run-pass/auxiliary/arc_wake.rs
@@ -1,7 +1,5 @@
 // edition:2018
 
-#![feature(futures_api)]
-
 use std::sync::Arc;
 use std::task::{
     Waker, RawWaker, RawWakerVTable,
diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs
index 6094f15569bb6..ee77053fd5b6a 100644
--- a/src/test/run-pass/futures-api.rs
+++ b/src/test/run-pass/futures-api.rs
@@ -1,7 +1,5 @@
 // aux-build:arc_wake.rs
 
-#![feature(futures_api)]
-
 extern crate arc_wake;
 
 use std::future::Future;
diff --git a/src/test/run-pass/issue-54716.rs b/src/test/run-pass/issue-54716.rs
index ea4f5e076b005..961c412f5ecb2 100644
--- a/src/test/run-pass/issue-54716.rs
+++ b/src/test/run-pass/issue-54716.rs
@@ -3,7 +3,7 @@
 // run-pass
 
 #![allow(unused_variables)]
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 extern crate arc_wake;
 
diff --git a/src/test/run-pass/issue-55809.rs b/src/test/run-pass/issue-55809.rs
index 86b0977bebe1d..12be6582a21e8 100644
--- a/src/test/run-pass/issue-55809.rs
+++ b/src/test/run-pass/issue-55809.rs
@@ -1,7 +1,7 @@
 // edition:2018
 // run-pass
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 trait Foo { }
 
diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs
index ba4997a7f9b5b..7384f7027d185 100644
--- a/src/test/rustdoc/async-fn.rs
+++ b/src/test/rustdoc/async-fn.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(async_await, futures_api)]
+#![feature(async_await)]
 
 // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
 pub async fn foo() -> Option<Foo> {
diff --git a/src/test/ui/async-fn-multiple-lifetimes.rs b/src/test/ui/async-fn-multiple-lifetimes.rs
index fccc4fdb91725..e3ac817b15ca5 100644
--- a/src/test/ui/async-fn-multiple-lifetimes.rs
+++ b/src/test/ui/async-fn-multiple-lifetimes.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+#![feature(arbitrary_self_types, async_await, await_macro, pin)]
 
 use std::ops::Add;
 
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
new file mode 100644
index 0000000000000..3992607c387e1
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
@@ -0,0 +1,10 @@
+#![feature(rustc_attrs, staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_allow_const_fn_ptr]
+const fn compiles(_: fn()) {}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
new file mode 100644
index 0000000000000..e6e1ced6592a2
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
@@ -0,0 +1,12 @@
+error[E0723]: function pointers in const fn are unstable
+  --> $DIR/allow_const_fn_ptr.rs:4:16
+   |
+LL | const fn error(_: fn()) {}
+   |                ^
+   |
+   = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs
new file mode 100644
index 0000000000000..0395795ef7bfe
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs
@@ -0,0 +1,11 @@
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+const fn error(_: fn()) {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_allow_const_fn_ptr]
+//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+const fn compiles(_: fn()) {}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr
new file mode 100644
index 0000000000000..c934307e918b9
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr
@@ -0,0 +1,12 @@
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
+  --> $DIR/allow_const_fn_ptr_feature_gate.rs:7:3
+   |
+LL | #[rustc_allow_const_fn_ptr]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs
new file mode 100644
index 0000000000000..1d8b95ab1a2fd
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#![feature(rustc_attrs, staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_allow_const_fn_ptr]
+const fn takes_fn_ptr(_: fn()) {}
+
+const FN: fn() = || ();
+
+const fn gives_fn_ptr() {
+    takes_fn_ptr(FN)
+}
+
+fn main() {
+    gives_fn_ptr();
+}
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/editions/edition-deny-async-fns-2015.rs
index 2105aa5835d0d..e1111f9e0e4b9 100644
--- a/src/test/ui/editions/edition-deny-async-fns-2015.rs
+++ b/src/test/ui/editions/edition-deny-async-fns-2015.rs
@@ -1,6 +1,6 @@
 // edition:2015
 
-#![feature(futures_api, async_await)]
+#![feature(async_await)]
 
 async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
 
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
index b6ab8ae0a9bc7..801aeb82aa266 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
@@ -1,7 +1,5 @@
 // edition:2015
 
-#![feature(futures_api)]
-
 async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
                   //~^ ERROR async fn is unstable
 
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
index cec211fef1351..b419f1232dfab 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
@@ -1,23 +1,23 @@
 error[E0670]: `async fn` is not permitted in the 2015 edition
-  --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+  --> $DIR/feature-gate-async-await-2015-edition.rs:3:1
    |
 LL | async fn foo() {}
    | ^^^^^
 
 error[E0422]: cannot find struct, variant or union type `async` in this scope
-  --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
+  --> $DIR/feature-gate-async-await-2015-edition.rs:7:13
    |
 LL |     let _ = async {};
    |             ^^^^^ not found in this scope
 
 error[E0425]: cannot find value `async` in this scope
-  --> $DIR/feature-gate-async-await-2015-edition.rs:10:13
+  --> $DIR/feature-gate-async-await-2015-edition.rs:8:13
    |
 LL |     let _ = async || { true };
    |             ^^^^^ not found in this scope
 
 error[E0658]: async fn is unstable
-  --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+  --> $DIR/feature-gate-async-await-2015-edition.rs:3:1
    |
 LL | async fn foo() {}
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs
index 1fdaec75e9d5a..9cfefef4129de 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await.rs
+++ b/src/test/ui/feature-gates/feature-gate-async-await.rs
@@ -1,7 +1,5 @@
 // edition:2018
 
-#![feature(futures_api)]
-
 struct S;
 
 impl S {
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr
index 1fa21f52045fc..43e41b4545869 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr
@@ -1,11 +1,11 @@
 error[E0706]: trait fns cannot be declared `async`
-  --> $DIR/feature-gate-async-await.rs:12:5
+  --> $DIR/feature-gate-async-await.rs:10:5
    |
 LL |     async fn foo();
    |     ^^^^^^^^^^^^^^^
 
 error[E0658]: async fn is unstable
-  --> $DIR/feature-gate-async-await.rs:8:5
+  --> $DIR/feature-gate-async-await.rs:6:5
    |
 LL |     async fn foo() {}
    |     ^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL |     async fn foo() {}
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error[E0658]: async fn is unstable
-  --> $DIR/feature-gate-async-await.rs:12:5
+  --> $DIR/feature-gate-async-await.rs:10:5
    |
 LL |     async fn foo();
    |     ^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     async fn foo();
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error[E0658]: async fn is unstable
-  --> $DIR/feature-gate-async-await.rs:16:1
+  --> $DIR/feature-gate-async-await.rs:14:1
    |
 LL | async fn foo() {}
    | ^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL | async fn foo() {}
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error[E0658]: async blocks are unstable
-  --> $DIR/feature-gate-async-await.rs:19:13
+  --> $DIR/feature-gate-async-await.rs:17:13
    |
 LL |     let _ = async {};
    |             ^^^^^^^^
@@ -41,7 +41,7 @@ LL |     let _ = async {};
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error[E0658]: async closures are unstable
-  --> $DIR/feature-gate-async-await.rs:20:13
+  --> $DIR/feature-gate-async-await.rs:18:13
    |
 LL |     let _ = async || {};
    |             ^^^^^^^^^^^
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
index 40642523be255..a4e080119345e 100644
--- a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
+++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
@@ -2,7 +2,7 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden when using `async` and `await`.
 
-#![feature(await_macro, async_await, futures_api, generators)]
+#![feature(await_macro, async_await, generators)]
 
 async fn recursive_async_function() -> () { //~ ERROR
     await!(recursive_async_function());
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
index 869876dc6a88a..2428b560b7001 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
@@ -1,7 +1,7 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden.
 
-#![feature(futures_api, generators)]
+#![feature(generators)]
 
 fn option(i: i32) -> impl Sized { //~ ERROR
     if i < 0 {
diff --git a/src/test/ui/issues/issue-54974.rs b/src/test/ui/issues/issue-54974.rs
index b2624ec92a184..d6f18875c9e3a 100644
--- a/src/test/ui/issues/issue-54974.rs
+++ b/src/test/ui/issues/issue-54974.rs
@@ -1,7 +1,7 @@
 // compile-pass
 // edition:2018
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 use std::sync::Arc;
 
diff --git a/src/test/ui/issues/issue-55324.rs b/src/test/ui/issues/issue-55324.rs
index 6160fbabd96d7..4572e543f22de 100644
--- a/src/test/ui/issues/issue-55324.rs
+++ b/src/test/ui/issues/issue-55324.rs
@@ -1,7 +1,7 @@
 // compile-pass
 // edition:2018
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 use std::future::Future;
 
diff --git a/src/test/ui/issues/issue-58885.rs b/src/test/ui/issues/issue-58885.rs
index 559899194fbe7..99d87b2273c2f 100644
--- a/src/test/ui/issues/issue-58885.rs
+++ b/src/test/ui/issues/issue-58885.rs
@@ -1,7 +1,7 @@
 // compile-pass
 // edition:2018
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 struct Xyz {
     a: u64,
diff --git a/src/test/ui/issues/issue-59001.rs b/src/test/ui/issues/issue-59001.rs
index a310653fbce48..c758244002ff6 100644
--- a/src/test/ui/issues/issue-59001.rs
+++ b/src/test/ui/issues/issue-59001.rs
@@ -1,7 +1,7 @@
 // compile-pass
 // edition:2018
 
-#![feature(async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro)]
 
 use std::future::Future;
 
diff --git a/src/test/ui/no-args-non-move-async-closure.rs b/src/test/ui/no-args-non-move-async-closure.rs
index 4f5b2ea3783aa..345f19b06233b 100644
--- a/src/test/ui/no-args-non-move-async-closure.rs
+++ b/src/test/ui/no-args-non-move-async-closure.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+#![feature(async_await, await_macro)]
 
 fn main() {
     let _ = async |x: u8| {};
diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-poll.rs
index 3d7115c522346..f63950ad5e905 100644
--- a/src/test/ui/try-poll.rs
+++ b/src/test/ui/try-poll.rs
@@ -1,7 +1,6 @@
 // compile-pass
 
 #![allow(dead_code, unused)]
-#![feature(futures_api)]
 
 use std::task::Poll;