about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-24 03:16:47 +0000
committerbors <bors@rust-lang.org>2019-04-24 03:16:47 +0000
commit8a44125f557706774b6e99912a585fa6a399c183 (patch)
tree72ba05ca46788988c1c644515dda05c7d24bab88 /src
parent0928511d3a11ecc9703c3c34f0fe36282dd9b171 (diff)
parent7304e969df1dddee7ea370df8c91b7dd1ee6d58c (diff)
downloadrust-8a44125f557706774b6e99912a585fa6a399c183.tar.gz
rust-8a44125f557706774b6e99912a585fa6a399c183.zip
Auto merge of #60224 - Centril:rollup-lfuhhsk, r=Centril
Rollup of 5 pull requests

Successful merges:

 - #56278 (Future-proof MIR for dedicated debuginfo.)
 - #59739 (Stabilize futures_api)
 - #59822 (Fix dark css rule)
 - #60186 (Temporarily accept [i|u][32|size] suffixes on a tuple index and warn)
 - #60190 (Don't generate unnecessary rmeta files.)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/boxed.rs2
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/libcore/future/future.rs9
-rw-r--r--src/libcore/future/mod.rs5
-rw-r--r--src/libcore/task/mod.rs6
-rw-r--r--src/libcore/task/poll.rs20
-rw-r--r--src/libcore/task/wake.rs36
-rw-r--r--src/librustc/ich/impls_syntax.rs1
-rw-r--r--src/librustc/middle/stability.rs1
-rw-r--r--src/librustc/mir/mod.rs31
-rw-r--r--src/librustc/mir/tcx.rs35
-rw-r--r--src/librustc/query/mod.rs2
-rw-r--r--src/librustc/ty/constness.rs7
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs19
-rw-r--r--src/librustc_codegen_ssa/back/write.rs11
-rw-r--r--src/librustc_codegen_ssa/base.rs28
-rw-r--r--src/librustc_codegen_ssa/lib.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs13
-rw-r--r--src/librustc_codegen_ssa/traits/debuginfo.rs2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs12
-rw-r--r--src/librustc_mir/borrow_check/mod.rs110
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs14
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs15
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs5
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs25
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs8
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs14
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs2
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs4
-rw-r--r--src/librustc_mir/build/matches/mod.rs5
-rw-r--r--src/librustc_mir/build/mod.rs35
-rw-r--r--src/librustc_mir/interpret/validity.rs28
-rw-r--r--src/librustc_mir/transform/generator.rs10
-rw-r--r--src/librustc_mir/transform/inline.rs6
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs8
-rw-r--r--src/librustc_mir/util/pretty.rs126
-rw-r--r--src/librustdoc/html/static/themes/dark.css4
-rw-r--r--src/librustdoc/html/static/themes/light.css2
-rw-r--r--src/libstd/future.rs1
-rw-r--r--src/libstd/lib.rs10
-rw-r--r--src/libstd/panic.rs2
-rw-r--r--src/libsyntax/attr/builtin.rs18
-rw-r--r--src/libsyntax/parse/parser.rs34
-rw-r--r--src/test/compile-fail/must_use-in-stdlib-traits.rs2
-rw-r--r--src/test/mir-opt/box_expr.rs9
-rw-r--r--src/test/mir-opt/issue-41110.rs21
-rw-r--r--src/test/mir-opt/issue-49232.rs10
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs4
-rw-r--r--src/test/mir-opt/packed-struct-drop-aligned.rs10
-rw-r--r--src/test/run-pass/async-await.rs2
-rw-r--r--src/test/run-pass/auxiliary/arc_wake.rs2
-rw-r--r--src/test/run-pass/futures-api.rs2
-rw-r--r--src/test/run-pass/issue-54716.rs2
-rw-r--r--src/test/run-pass/issue-55809.rs2
-rw-r--r--src/test/rustdoc/async-fn.rs2
-rw-r--r--src/test/ui/async-fn-multiple-lifetimes.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs10
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr12
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs11
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr12
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs18
-rw-r--r--src/test/ui/editions/edition-deny-async-fns-2015.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await.stderr12
-rw-r--r--src/test/ui/impl-trait/recursive-async-impl-trait-type.rs2
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type.rs2
-rw-r--r--src/test/ui/issues/issue-54974.rs2
-rw-r--r--src/test/ui/issues/issue-55324.rs2
-rw-r--r--src/test/ui/issues/issue-58885.rs2
-rw-r--r--src/test/ui/issues/issue-59001.rs2
-rw-r--r--src/test/ui/no-args-non-move-async-closure.rs2
-rw-r--r--src/test/ui/try-poll.rs1
77 files changed, 567 insertions, 354 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 8a3950718d7..207359ed696 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 63b3fbbdaef..eb673488170 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 e1ab67873a0..504330a023b 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 6693ecbac41..89ea4713cfd 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 29bae69ea83..ef090928392 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 ecf03afb88e..3db70d5e764 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 94e31054a58..b4e91249832 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 496ccc888b6..40cce8e77c0 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 ef1270d3045..8ce86f70a55 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/mir/mod.rs b/src/librustc/mir/mod.rs
index 555374a138c..bf2a1eaafd6 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -4,7 +4,7 @@
 
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
-use crate::hir::{self, HirId, InlineAsm as HirInlineAsm};
+use crate::hir::{self, InlineAsm as HirInlineAsm};
 use crate::mir::interpret::{ConstValue, InterpError, Scalar};
 use crate::mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
@@ -138,16 +138,20 @@ pub struct Mir<'tcx> {
     /// If this MIR was built for a constant, this will be 0.
     pub arg_count: usize,
 
-    /// Names and capture modes of all the closure upvars, assuming
-    /// the first argument is either the closure or a reference to it.
-    pub upvar_decls: Vec<UpvarDecl>,
-
     /// Mark an argument local (which must be a tuple) as getting passed as
     /// its individual components at the LLVM level.
     ///
     /// This is used for the "rust-call" ABI.
     pub spread_arg: Option<Local>,
 
+    /// Names and capture modes of all the closure upvars, assuming
+    /// the first argument is either the closure or a reference to it.
+    // NOTE(eddyb) This is *strictly* a temporary hack for codegen
+    // debuginfo generation, and will be removed at some point.
+    // Do **NOT** use it for anything else, upvar information should not be
+    // in the MIR, please rely on local crate HIR or other side-channels.
+    pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
+
     /// Mark this MIR of a const context other than const functions as having converted a `&&` or
     /// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
     /// this conversion from happening and use short circuiting, we will cause the following code
@@ -173,7 +177,7 @@ impl<'tcx> Mir<'tcx> {
         local_decls: LocalDecls<'tcx>,
         user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
         arg_count: usize,
-        upvar_decls: Vec<UpvarDecl>,
+        __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
         span: Span,
         control_flow_destroyed: Vec<(Span, String)>,
     ) -> Self {
@@ -197,7 +201,7 @@ impl<'tcx> Mir<'tcx> {
             local_decls,
             user_type_annotations,
             arg_count,
-            upvar_decls,
+            __upvar_debuginfo_codegen_only_do_not_use,
             spread_arg: None,
             span,
             cache: cache::Cache::new(),
@@ -431,7 +435,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
     local_decls,
     user_type_annotations,
     arg_count,
-    upvar_decls,
+    __upvar_debuginfo_codegen_only_do_not_use,
     spread_arg,
     control_flow_destroyed,
     span,
@@ -983,16 +987,11 @@ impl<'tcx> LocalDecl<'tcx> {
 
 /// A closure capture, with its name and mode.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UpvarDecl {
+pub struct UpvarDebuginfo {
     pub debug_name: Name,
 
-    /// `HirId` of the captured variable
-    pub var_hir_id: ClearCrossCrate<HirId>,
-
     /// If true, the capture is behind a reference.
     pub by_ref: bool,
-
-    pub mutability: Mutability,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -3156,7 +3155,7 @@ CloneTypeFoldableAndLiftImpls! {
     MirPhase,
     Mutability,
     SourceInfo,
-    UpvarDecl,
+    UpvarDebuginfo,
     FakeReadCause,
     RetagKind,
     SourceScope,
@@ -3178,7 +3177,7 @@ BraceStructTypeFoldableImpl! {
         local_decls,
         user_type_annotations,
         arg_count,
-        upvar_decls,
+        __upvar_debuginfo_codegen_only_do_not_use,
         spread_arg,
         control_flow_destroyed,
         span,
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 23be1bbf6c6..04b763f773d 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -133,41 +133,6 @@ impl<'tcx> Place<'tcx> {
                 proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
         }
     }
-
-    /// If this is a field projection, and the field is being projected from a closure type,
-    /// then returns the index of the field being projected. Note that this closure will always
-    /// be `self` in the current MIR, because that is the only time we directly access the fields
-    /// of a closure type.
-    pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
-                                                tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Field> {
-        let (place, by_ref) = if let Place::Projection(ref proj) = self {
-            if let ProjectionElem::Deref = proj.elem {
-                (&proj.base, true)
-            } else {
-                (self, false)
-            }
-        } else {
-            (self, false)
-        };
-
-        match place {
-            Place::Projection(ref proj) => match proj.elem {
-                ProjectionElem::Field(field, _ty) => {
-                    let base_ty = proj.base.ty(mir, *tcx).ty;
-
-                    if (base_ty.is_closure() || base_ty.is_generator()) &&
-                        (!by_ref || mir.upvar_decls[field.index()].by_ref)
-                    {
-                        Some(field)
-                    } else {
-                        None
-                    }
-                },
-                _ => None,
-            }
-            _ => None,
-        }
-    }
 }
 
 pub enum RvalueInitializationState {
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 8c1e345cdae..1861420b408 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 e33d0a74ea0..7298b548f31 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_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index ae498673c1d..cb00cca0f9c 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -542,7 +542,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         finalize(self)
     }
 
-    fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
+    fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
         unsafe {
             [llvm::LLVMRustDIBuilderCreateOpDeref(),
              llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 166234c83fc..fe703ff4d25 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -83,14 +83,16 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
         for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
             remove(sess, obj);
         }
-        if let Some(ref obj) = codegen_results.metadata_module.object {
-            remove(sess, obj);
-        }
-        if let Some(ref allocator) = codegen_results.allocator_module {
-            if let Some(ref obj) = allocator.object {
+        if let Some(ref metadata_module) = codegen_results.metadata_module {
+            if let Some(ref obj) = metadata_module.object {
+                remove(sess, obj);
+            }
+         }
+        if let Some(ref allocator_module) = codegen_results.allocator_module {
+            if let Some(ref obj) = allocator_module.object {
                 remove(sess, obj);
             }
-            if let Some(ref bc) = allocator.bytecode_compressed {
+            if let Some(ref bc) = allocator_module.bytecode_compressed {
                 remove(sess, bc);
             }
         }
@@ -1067,7 +1069,10 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
     // object file, so we link that in here.
     if crate_type == config::CrateType::Dylib ||
        crate_type == config::CrateType::ProcMacro {
-        if let Some(obj) = codegen_results.metadata_module.object.as_ref() {
+        let obj = codegen_results.metadata_module
+            .as_ref()
+            .and_then(|m| m.object.as_ref());
+        if let Some(obj) = obj {
             cmd.add_object(obj);
         }
     }
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 4b02425d40d..88a5e5a1aec 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -350,7 +350,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
 
 pub struct CompiledModules {
     pub modules: Vec<CompiledModule>,
-    pub metadata_module: CompiledModule,
+    pub metadata_module: Option<CompiledModule>,
     pub allocator_module: Option<CompiledModule>,
 }
 
@@ -682,8 +682,10 @@ fn produce_final_output_artifacts(sess: &Session,
         }
 
         if !user_wants_bitcode {
-            if let Some(ref path) = compiled_modules.metadata_module.bytecode {
-                remove(sess, &path);
+            if let Some(ref metadata_module) = compiled_modules.metadata_module {
+                if let Some(ref path) = metadata_module.bytecode {
+                    remove(sess, &path);
+                }
             }
 
             if let Some(ref allocator_module) = compiled_modules.allocator_module {
@@ -1564,9 +1566,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
         // out deterministic results.
         compiled_modules.sort_by(|a, b| a.name.cmp(&b.name));
 
-        let compiled_metadata_module = compiled_metadata_module
-            .expect("Metadata module not compiled?");
-
         Ok(CompiledModules {
             modules: compiled_modules,
             metadata_module: compiled_metadata_module,
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 6cb54831a07..3046c069981 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -25,7 +25,7 @@ use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
-use rustc::session::config::{self, EntryFnType, Lto};
+use rustc::session::config::{self, CrateType, EntryFnType, Lto};
 use rustc::session::Session;
 use rustc_mir::monomorphize::item::DefPathBasedNames;
 use rustc_mir::monomorphize::Instance;
@@ -550,12 +550,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     });
     tcx.sess.profiler(|p| p.end_activity("codegen crate metadata"));
 
-    let metadata_module = ModuleCodegen {
-        name: metadata_cgu_name,
-        module_llvm: metadata_llvm_module,
-        kind: ModuleKind::Metadata,
-    };
-
     // Skip crate items and just output metadata in -Z no-codegen mode.
     if tcx.sess.opts.debugging_opts.no_codegen ||
        !tcx.sess.opts.output_types.should_codegen() {
@@ -566,7 +560,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
             rx,
             1);
 
-        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
         ongoing_codegen.codegen_finished(tcx);
 
         assert_and_save_dep_graph(tcx);
@@ -639,7 +632,24 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
     }
 
-    ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
+    let needs_metadata_module = tcx.sess.crate_types.borrow().iter().any(|ct| {
+        match *ct {
+            CrateType::Dylib |
+            CrateType::ProcMacro => true,
+            CrateType::Executable |
+            CrateType::Rlib |
+            CrateType::Staticlib |
+            CrateType::Cdylib => false,
+        }
+    });
+    if needs_metadata_module {
+        let metadata_module = ModuleCodegen {
+            name: metadata_cgu_name,
+            module_llvm: metadata_llvm_module,
+            kind: ModuleKind::Metadata,
+        };
+        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
+    }
 
     // We sort the codegen units by size. This way we can schedule work for LLVM
     // a bit more efficiently.
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 9d3d6ef8549..4d7af7a643b 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -154,7 +154,7 @@ pub struct CodegenResults {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
     pub allocator_module: Option<CompiledModule>,
-    pub metadata_module: CompiledModule,
+    pub metadata_module: Option<CompiledModule>,
     pub crate_hash: Svh,
     pub metadata: rustc::middle::cstore::EncodedMetadata,
     pub windows_subsystem: Option<String>,
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 91aa9bcc780..621c4e5d448 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -598,9 +598,10 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 tmp
             }
         };
+        let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
         arg_scope.map(|scope| {
             // Is this a regular argument?
-            if arg_index > 0 || mir.upvar_decls.is_empty() {
+            if arg_index > 0 || upvar_debuginfo.is_empty() {
                 // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
                 // need to insert a deref here, but the C ABI uses a pointer and a copy using the
                 // byval attribute, for which LLVM always does the deref itself,
@@ -638,16 +639,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             let (def_id, upvar_substs) = match closure_layout.ty.sty {
                 ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
                 ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
-                _ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
+                _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
             };
             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
 
             let extra_locals = {
-                let upvars = mir.upvar_decls
+                let upvars = upvar_debuginfo
                     .iter()
                     .zip(upvar_tys)
                     .enumerate()
-                    .map(|(i, (decl, ty))| (i, decl.debug_name, decl.by_ref, ty));
+                    .map(|(i, (upvar, ty))| (i, upvar.debug_name, upvar.by_ref, ty));
 
                 let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
                     let (def_id, gen_substs) = match closure_layout.ty.sty {
@@ -656,7 +657,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                     };
                     let state_tys = gen_substs.state_tys(def_id, tcx);
 
-                    let upvar_count = mir.upvar_decls.len();
+                    let upvar_count = upvar_debuginfo.len();
                     generator_layout.fields
                         .iter()
                         .zip(state_tys)
@@ -673,7 +674,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             for (field, name, by_ref, ty) in extra_locals {
                 let byte_offset_of_var_in_env = closure_layout.fields.offset(field).bytes();
 
-                let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
+                let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
 
                 // The environment and the capture can each be indirect.
                 let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index a0b53fde09c..aadffc5932b 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -37,7 +37,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
         defining_crate: CrateNum,
     ) -> Self::DIScope;
     fn debuginfo_finalize(&self);
-    fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
+    fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
 }
 
 pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 3ab0996d3a1..12dcea7bd59 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1088,7 +1088,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         | LocalKind::Temp => bug!("temporary or return pointer with a name"),
                         LocalKind::Var => "local variable ",
                         LocalKind::Arg
-                        if !self.mir.upvar_decls.is_empty()
+                        if !self.upvars.is_empty()
                             && local == Local::new(1) => {
                             "variable captured by `move` "
                         }
@@ -1632,11 +1632,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 match proj.elem {
                     ProjectionElem::Deref => {
                         let upvar_field_projection =
-                            place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
+                            self.is_upvar_field_projection(place);
                         if let Some(field) = upvar_field_projection {
                             let var_index = field.index();
-                            let name = self.mir.upvar_decls[var_index].debug_name.to_string();
-                            if self.mir.upvar_decls[var_index].by_ref {
+                            let name = self.upvars[var_index].name.to_string();
+                            if self.upvars[var_index].by_ref {
                                 buf.push_str(&name);
                             } else {
                                 buf.push_str(&format!("*{}", &name));
@@ -1694,10 +1694,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         autoderef = true;
 
                         let upvar_field_projection =
-                            place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
+                            self.is_upvar_field_projection(place);
                         if let Some(field) = upvar_field_projection {
                             let var_index = field.index();
-                            let name = self.mir.upvar_decls[var_index].debug_name.to_string();
+                            let name = self.upvars[var_index].name.to_string();
                             buf.push_str(&name);
                         } else {
                             let field_name = self.describe_field(&proj.base, field);
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4a3159d8a9d..14cafdef67d 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1,7 +1,7 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
-use rustc::hir;
+use rustc::hir::{self, HirId};
 use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
@@ -27,6 +27,7 @@ use std::collections::BTreeMap;
 use std::mem;
 use std::rc::Rc;
 
+use syntax::ast::Name;
 use syntax_pos::{Span, DUMMY_SP};
 
 use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
@@ -63,6 +64,19 @@ mod used_muts;
 
 pub(crate) mod nll;
 
+// FIXME(eddyb) perhaps move this somewhere more centrally.
+#[derive(Debug)]
+crate struct Upvar {
+    name: Name,
+
+    var_hir_id: HirId,
+
+    /// If true, the capture is behind a reference.
+    by_ref: bool,
+
+    mutability: Mutability,
+}
+
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
         mir_borrowck,
@@ -126,6 +140,36 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         .as_local_hir_id(def_id)
         .expect("do_mir_borrowck: non-local DefId");
 
+    // Gather the upvars of a closure, if any.
+    let tables = tcx.typeck_tables_of(def_id);
+    let upvars: Vec<_> = tables
+        .upvar_list
+        .get(&def_id)
+        .into_iter()
+        .flatten()
+        .map(|upvar_id| {
+            let var_hir_id = upvar_id.var_path.hir_id;
+            let var_node_id = tcx.hir().hir_to_node_id(var_hir_id);
+            let capture = tables.upvar_capture(*upvar_id);
+            let by_ref = match capture {
+                ty::UpvarCapture::ByValue => false,
+                ty::UpvarCapture::ByRef(..) => true,
+            };
+            let mut upvar = Upvar {
+                name: tcx.hir().name(var_node_id),
+                var_hir_id,
+                by_ref,
+                mutability: Mutability::Not,
+            };
+            let bm = *tables.pat_binding_modes().get(var_hir_id)
+                .expect("missing binding mode");
+            if bm == ty::BindByValue(hir::MutMutable) {
+                upvar.mutability = Mutability::Mut;
+            }
+            upvar
+        })
+        .collect();
+
     // Replace all regions with fresh inference variables. This
     // requires first making our own copy of the MIR. This copy will
     // be modified (in place) to contain non-lexical lifetimes. It
@@ -168,6 +212,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         def_id,
         free_regions,
         mir,
+        &upvars,
         location_table,
         param_env,
         &mut flow_inits,
@@ -240,6 +285,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         used_mut_upvars: SmallVec::new(),
         borrow_set,
         dominators,
+        upvars,
     };
 
     let mut state = Flows::new(
@@ -475,6 +521,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
 
     /// Dominators for MIR
     dominators: Dominators<BasicBlock>,
+
+    /// Information about upvars not necessarily preserved in types or MIR
+    upvars: Vec<Upvar>,
 }
 
 // Check that:
@@ -1287,8 +1336,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
             match *place {
                 Place::Projection { .. } => {
-                    if let Some(field) = place.is_upvar_field_projection(
-                            this.mir, &this.infcx.tcx) {
+                    if let Some(field) = this.is_upvar_field_projection(place) {
                         this.used_mut_upvars.push(field);
                     }
                 }
@@ -2057,7 +2105,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 place: place @ Place::Projection(_),
                 is_local_mutation_allowed: _,
             } => {
-                if let Some(field) = place.is_upvar_field_projection(self.mir, &self.infcx.tcx) {
+                if let Some(field) = self.is_upvar_field_projection(place) {
                     self.used_mut_upvars.push(field);
                 }
             }
@@ -2127,13 +2175,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                     // Mutably borrowed data is mutable, but only if we have a
                                     // unique path to the `&mut`
                                     hir::MutMutable => {
-                                        let mode = match place.is_upvar_field_projection(
-                                            self.mir, &self.infcx.tcx)
-                                        {
+                                        let mode = match self.is_upvar_field_projection(place) {
                                             Some(field)
-                                                if {
-                                                    self.mir.upvar_decls[field.index()].by_ref
-                                                } =>
+                                                if self.upvars[field.index()].by_ref =>
                                             {
                                                 is_local_mutation_allowed
                                             }
@@ -2173,15 +2217,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. }
                     | ProjectionElem::Downcast(..) => {
-                        let upvar_field_projection = place.is_upvar_field_projection(
-                            self.mir, &self.infcx.tcx);
+                        let upvar_field_projection = self.is_upvar_field_projection(place);
                         if let Some(field) = upvar_field_projection {
-                            let decl = &self.mir.upvar_decls[field.index()];
+                            let upvar = &self.upvars[field.index()];
                             debug!(
-                                "decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
-                                decl, is_local_mutation_allowed, place
+                                "upvar.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
+                                upvar, is_local_mutation_allowed, place
                             );
-                            match (decl.mutability, is_local_mutation_allowed) {
+                            match (upvar.mutability, is_local_mutation_allowed) {
                                 (Mutability::Not, LocalMutationIsAllowed::No)
                                 | (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) => {
                                     Err(place)
@@ -2229,6 +2272,41 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             }
         }
     }
+
+    /// If `place` is a field projection, and the field is being projected from a closure type,
+    /// then returns the index of the field being projected. Note that this closure will always
+    /// be `self` in the current MIR, because that is the only time we directly access the fields
+    /// of a closure type.
+    pub fn is_upvar_field_projection(&self, place: &Place<'tcx>) -> Option<Field> {
+        let (place, by_ref) = if let Place::Projection(ref proj) = place {
+            if let ProjectionElem::Deref = proj.elem {
+                (&proj.base, true)
+            } else {
+                (place, false)
+            }
+        } else {
+            (place, false)
+        };
+
+        match place {
+            Place::Projection(ref proj) => match proj.elem {
+                ProjectionElem::Field(field, _ty) => {
+                    let tcx = self.infcx.tcx;
+                    let base_ty = proj.base.ty(self.mir, tcx).ty;
+
+                    if (base_ty.is_closure() || base_ty.is_generator()) &&
+                        (!by_ref || self.upvars[field.index()].by_ref)
+                    {
+                        Some(field)
+                    } else {
+                        None
+                    }
+                },
+                _ => None,
+            }
+            _ => None,
+        }
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 7efe1d83c2e..a7bad44c42c 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             let origin = Origin::Mir;
             debug!("report: original_path={:?} span={:?}, kind={:?} \
                    original_path.is_upvar_field_projection={:?}", original_path, span, kind,
-                   original_path.is_upvar_field_projection(self.mir, &self.infcx.tcx));
+                   self.is_upvar_field_projection(original_path));
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
@@ -269,8 +269,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         let ty = place.ty(self.mir, self.infcx.tcx).ty;
                         let is_upvar_field_projection =
                             self.prefixes(&original_path, PrefixSet::All)
-                            .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
-                                 .is_some());
+                            .any(|p| self.is_upvar_field_projection(p).is_some());
                         debug!("report: ty={:?}", ty);
                         match ty.sty {
                             ty::Array(..) | ty::Slice(..) =>
@@ -278,7 +277,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                                     span, ty, None, origin
                                 ),
                             ty::Closure(def_id, closure_substs)
-                                if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
+                                if def_id == self.mir_def_id && is_upvar_field_projection
                             => {
                                 let closure_kind_ty =
                                     closure_substs.closure_kind_ty(def_id, self.infcx.tcx);
@@ -303,11 +302,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                                     span, place_description, origin);
 
                                 for prefix in self.prefixes(&original_path, PrefixSet::All) {
-                                    if let Some(field) = prefix.is_upvar_field_projection(
-                                            self.mir, &self.infcx.tcx) {
-                                        let upvar_decl = &self.mir.upvar_decls[field.index()];
-                                        let upvar_hir_id =
-                                            upvar_decl.var_hir_id.assert_crate_local();
+                                    if let Some(field) = self.is_upvar_field_projection(prefix) {
+                                        let upvar_hir_id = self.upvars[field.index()].var_hir_id;
                                         let upvar_span = self.infcx.tcx.hir().span_by_hir_id(
                                             upvar_hir_id);
                                         diag.span_label(upvar_span, "captured outer variable");
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index b780511315d..c5ad2b18c23 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -68,10 +68,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if access_place.is_upvar_field_projection(self.mir, &self.infcx.tcx).is_some() {
+                if self.is_upvar_field_projection(access_place).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
-                    let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
+                    let name = self.upvars[upvar_index.index()].name;
                     reason = format!(", as `{}` is not declared as mutable", name);
                 }
             }
@@ -81,15 +81,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 elem: ProjectionElem::Deref,
             }) => {
                 if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
-                    !self.mir.upvar_decls.is_empty() {
+                    !self.upvars.is_empty() {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
                         the_place_err.ty(self.mir, self.infcx.tcx).ty
                     ));
 
-                    reason = if access_place.is_upvar_field_projection(self.mir,
-                                                                       &self.infcx.tcx).is_some() {
+                    reason = if self.is_upvar_field_projection(access_place).is_some() {
                         ", as it is a captured variable in a `Fn` closure".to_string()
                     } else {
                         ", as `Fn` closures cannot mutate their captured variables".to_string()
@@ -309,9 +308,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
-                let upvar_hir_id = self.mir.upvar_decls[upvar_index.index()]
-                    .var_hir_id
-                    .assert_crate_local();
+                let upvar_hir_id = self.upvars[upvar_index.index()].var_hir_id;
                 let upvar_node_id = self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id);
                 if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_node_id) {
                     if let hir::PatKind::Binding(
@@ -452,7 +449,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 base,
                 elem: ProjectionElem::Deref,
             }) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
-                  !self.mir.upvar_decls.is_empty() =>
+                  !self.upvars.is_empty() =>
             {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.span_help(
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 5ad54080c5a..89f85a941d3 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -273,11 +273,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 if mir.local_decls[local].name.is_some() {
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
                         if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
-                            let dropped_local_scope = mir.local_decls[local].visibility_scope;
-                            let borrowed_local_scope =
-                                mir.local_decls[*borrowed_local].visibility_scope;
-
-                            if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope)
+                             if mir.local_decls[*borrowed_local].name.is_some()
                                 && local != *borrowed_local
                             {
                                 should_note_order = true;
@@ -298,6 +294,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     let (category, from_closure, span, region_name) =
                         self.nonlexical_regioncx.free_region_constraint_info(
                             self.mir,
+                        &self.upvars,
                             self.mir_def_id,
                             self.infcx,
                             borrow_region_vid,
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 3e1b93fb417..ad43c8ef66f 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -8,6 +8,7 @@ use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::FlowAtLocation;
 use crate::dataflow::MaybeInitializedPlaces;
 use crate::transform::MirSource;
+use crate::borrow_check::Upvar;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
@@ -72,6 +73,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     def_id: DefId,
     universal_regions: UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
+    upvars: &[Upvar],
     location_table: &LocationTable,
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
@@ -187,7 +189,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     });
 
     // Solve the region constraints.
-    let closure_region_requirements = regioncx.solve(infcx, &mir, def_id, errors_buffer);
+    let closure_region_requirements =
+        regioncx.solve(infcx, &mir, upvars, def_id, errors_buffer);
 
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests, as well as helping with debugging.
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 917e383cae8..abb30d042ca 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -4,6 +4,7 @@ use crate::borrow_check::nll::type_check::Locations;
 use crate::borrow_check::nll::universal_regions::DefiningTy;
 use crate::borrow_check::nll::ConstraintDescription;
 use crate::util::borrowck_errors::{BorrowckErrors, Origin};
+use crate::borrow_check::Upvar;
 use rustc::hir::def_id::DefId;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
@@ -237,6 +238,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(super) fn report_error(
         &self,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
@@ -273,6 +275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
                 self.report_fnmut_error(
                     mir,
+                    upvars,
                     infcx,
                     mir_def_id,
                     fr,
@@ -284,6 +287,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             (ConstraintCategory::Assignment, true, false)
             | (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
                 mir,
+                upvars,
                 infcx,
                 mir_def_id,
                 fr,
@@ -294,6 +298,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             ),
             _ => self.report_general_error(
                 mir,
+                upvars,
                 infcx,
                 mir_def_id,
                 fr,
@@ -353,6 +358,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn report_fnmut_error(
         &self,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
         _fr: RegionVid,
@@ -377,7 +383,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         diag.span_label(span, message);
 
-        match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source {
+        match self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, &mut 1)
+            .unwrap().source
+        {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -415,6 +423,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn report_escaping_data_error(
         &self,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
@@ -423,9 +432,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         span: Span,
         errors_buffer: &mut Vec<Diagnostic>,
     ) {
-        let fr_name_and_span = self.get_var_name_and_span_for_region(infcx.tcx, mir, fr);
+        let fr_name_and_span =
+            self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, fr);
         let outlived_fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr);
+            self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, outlived_fr);
 
         let escapes_from = match self.universal_regions.defining_ty {
             DefiningTy::Closure(..) => "closure",
@@ -442,6 +452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         {
             return self.report_general_error(
                 mir,
+                upvars,
                 infcx,
                 mir_def_id,
                 fr,
@@ -504,6 +515,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn report_general_error(
         &self,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
@@ -520,10 +532,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         );
 
         let counter = &mut 1;
-        let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap();
+        let fr_name = self.give_region_a_name(infcx, mir, upvars, mir_def_id, fr, counter).unwrap();
         fr_name.highlight_region_name(&mut diag);
         let outlived_fr_name =
-            self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap();
+            self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, counter).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
         let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
@@ -656,6 +668,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn free_region_constraint_info(
         &self,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         infcx: &InferCtxt<'_, '_, 'tcx>,
         borrow_region: RegionVid,
@@ -664,7 +677,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let (category, from_closure, span) =
             self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
         let outlived_fr_name =
-            self.give_region_a_name(infcx, mir, mir_def_id, outlived_region, &mut 1);
+            self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_region, &mut 1);
         (category, from_closure, span, outlived_fr_name)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 362214d3257..680e7ce576a 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -2,6 +2,7 @@ use std::fmt::{self, Display};
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use crate::borrow_check::nll::universal_regions::DefiningTy;
 use crate::borrow_check::nll::ToRegionVid;
+use crate::borrow_check::Upvar;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
@@ -144,6 +145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
@@ -160,7 +162,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_upvars(
-                    infcx.tcx, mir, fr, counter,
+                    infcx.tcx, upvars, fr, counter,
                 )
             })
             .or_else(|| {
@@ -639,13 +641,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_anonymous_region_appears_in_upvars(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         fr: RegionVid,
         counter: &mut usize,
     ) -> Option<RegionName> {
         let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
         let (upvar_name, upvar_span) =
-            self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index);
+            self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
         let region_name = self.synthesize_region_name(counter);
 
         Some(RegionName {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
index f6bbaf2db03..d8f34233839 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
@@ -1,5 +1,6 @@
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use crate::borrow_check::nll::ToRegionVid;
+use crate::borrow_check::Upvar;
 use rustc::mir::{Local, Mir};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
@@ -11,6 +12,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         fr: RegionVid,
     ) -> Option<(Option<Symbol>, Span)> {
         debug!("get_var_name_and_span_for_region(fr={:?})", fr);
@@ -19,7 +21,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!("get_var_name_and_span_for_region: attempting upvar");
         self.get_upvar_index_for_region(tcx, fr)
             .map(|index| {
-                let (name, span) = self.get_upvar_name_and_span_for_region(tcx, mir, index);
+                let (name, span) =
+                    self.get_upvar_name_and_span_for_region(tcx, upvars, index);
                 (Some(name), span)
             })
             .or_else(|| {
@@ -67,10 +70,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn get_upvar_name_and_span_for_region(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         upvar_index: usize,
     ) -> (Symbol, Span) {
-        let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local();
+        let upvar_hir_id = upvars[upvar_index].var_hir_id;
         debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
 
         let upvar_name = tcx.hir().name_by_hir_id(upvar_hir_id);
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index ac10683598a..9dd18ab76a5 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -4,6 +4,7 @@ use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, O
 use crate::borrow_check::nll::region_infer::values::{
     PlaceholderIndices, RegionElement, ToElementIndex
 };
+use crate::borrow_check::Upvar;
 use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
 use crate::borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
@@ -400,6 +401,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &mut self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         errors_buffer: &mut Vec<Diagnostic>,
     ) -> Option<ClosureRegionRequirements<'gcx>> {
@@ -407,7 +409,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             infcx.tcx.sess.time_extended(),
             Some(infcx.tcx.sess),
             &format!("solve_nll_region_constraints({:?})", mir_def_id),
-            || self.solve_inner(infcx, mir, mir_def_id, errors_buffer),
+            || self.solve_inner(infcx, mir, upvars, mir_def_id, errors_buffer),
         )
     }
 
@@ -415,6 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &mut self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         errors_buffer: &mut Vec<Diagnostic>,
     ) -> Option<ClosureRegionRequirements<'gcx>> {
@@ -442,6 +445,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.check_universal_regions(
             infcx,
             mir,
+            upvars,
             mir_def_id,
             outlives_requirements.as_mut(),
             errors_buffer,
@@ -1102,6 +1106,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
@@ -1115,6 +1120,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     self.check_universal_region(
                         infcx,
                         mir,
+                        upvars,
                         mir_def_id,
                         fr,
                         &mut propagated_outlives_requirements,
@@ -1145,6 +1151,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@@ -1177,6 +1184,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 representative,
                 infcx,
                 mir,
+                upvars,
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
@@ -1192,6 +1200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 shorter_fr,
                 infcx,
                 mir,
+                upvars,
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
@@ -1208,6 +1217,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         shorter_fr: RegionVid,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
+        upvars: &[Upvar],
         mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
@@ -1265,7 +1275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         //
         // Note: in this case, we use the unapproximated regions to report the
         // error. This gives better error messages in some cases.
-        self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
+        self.report_error(mir, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
         Some(ErrorReported)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index ae8dfa8144f..d3cef46b402 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -105,7 +105,7 @@ impl<'tcx> DefiningTy<'tcx> {
     /// Returns a list of all the upvar types for this MIR. If this is
     /// not a closure or generator, there are no upvars, and hence it
     /// will be an empty list. The order of types in this list will
-    /// match up with the `upvar_decls` field of `Mir`.
+    /// match up with the upvar order in the HIR, typesystem, and MIR.
     pub fn upvar_tys(self, tcx: TyCtxt<'_, '_, 'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         match self {
             DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)),
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index b9fec22da63..c58b570d8fc 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -556,10 +556,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 );
                 // Not in a closure
                 debug_assert!(
-                    this.upvar_decls.len() > upvar_index.index(),
+                    this.upvar_mutbls.len() > upvar_index.index(),
                     "Unexpected capture place"
                 );
-                this.upvar_decls[upvar_index.index()].mutability
+                this.upvar_mutbls[upvar_index.index()]
             }
             _ => bug!("Unexpected capture place"),
         };
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index b5b2d78f1bd..5e15d98e246 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -505,14 +505,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             UserTypeProjections::none(),
             &mut |this, mutability, name, mode, var, span, ty, user_ty| {
                 if visibility_scope.is_none() {
-                    visibility_scope =
-                        Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
                     // If we have lints, create a new source scope
                     // that marks the lints for the locals. See the comment
                     // on the `source_info` field for why this is needed.
                     if lint_level.is_explicit() {
                         scope = this.new_source_scope(scope_span, lint_level, None);
                     }
+                visibility_scope = Some(this.new_source_scope(scope_span,
+                                                           LintLevel::Inherited,
+                                                           None));
                 }
                 let source_info = SourceInfo { span, scope };
                 let visibility_scope = visibility_scope.unwrap();
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 7fe86d11c9e..79e1d5daae1 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -375,7 +375,8 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     var_indices: HirIdMap<LocalsForNode>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
     canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
-    upvar_decls: Vec<UpvarDecl>,
+    __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
+    upvar_mutbls: Vec<Mutability>,
     unit_temp: Option<Place<'tcx>>,
 
     /// Cached block with the `RESUME` terminator; this is created
@@ -625,11 +626,12 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let fn_def_id = tcx_hir.local_def_id_from_hir_id(fn_id);
 
     // Gather the upvars of a closure, if any.
+    let mut upvar_mutbls = vec![];
     // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
     // closure and we stored in a map called upvar_list in TypeckTables indexed
     // with the closure's DefId. Here, we run through that vec of UpvarIds for
     // the given closure and use the necessary information to create UpvarDecl.
-    let upvar_decls: Vec<_> = hir_tables
+    let upvar_debuginfo: Vec<_> = hir_tables
         .upvar_list
         .get(&fn_def_id)
         .into_iter()
@@ -642,27 +644,27 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                 ty::UpvarCapture::ByValue => false,
                 ty::UpvarCapture::ByRef(..) => true,
             };
-            let mut decl = UpvarDecl {
+            let mut debuginfo = UpvarDebuginfo {
                 debug_name: keywords::Invalid.name(),
-                var_hir_id: ClearCrossCrate::Set(var_hir_id),
                 by_ref,
-                mutability: Mutability::Not,
             };
+            let mut mutability = Mutability::Not;
             if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
                 if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
-                    decl.debug_name = ident.name;
+                    debuginfo.debug_name = ident.name;
                     if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
                         if bm == ty::BindByValue(hir::MutMutable) {
-                            decl.mutability = Mutability::Mut;
+                            mutability = Mutability::Mut;
                         } else {
-                            decl.mutability = Mutability::Not;
+                            mutability = Mutability::Not;
                         }
                     } else {
                         tcx.sess.delay_span_bug(pat.span, "missing binding mode");
                     }
                 }
             }
-            decl
+            upvar_mutbls.push(mutability);
+            debuginfo
         })
         .collect();
 
@@ -672,7 +674,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         safety,
         return_ty,
         return_ty_span,
-        upvar_decls);
+        upvar_debuginfo,
+        upvar_mutbls);
 
     let call_site_scope = region::Scope {
         id: body.value.hir_id.local_id,
@@ -734,7 +737,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
     let owner_id = tcx.hir().body_owner(body_id);
     let span = tcx.hir().span(owner_id);
-    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span,vec![]);
+    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span, vec![], vec![]);
 
     let mut block = START_BLOCK;
     let expr = builder.hir.mirror(ast_expr);
@@ -762,7 +765,7 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     let owner_id = hir.tcx().hir().body_owner(body_id);
     let span = hir.tcx().hir().span(owner_id);
     let ty = hir.tcx().types.err;
-    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]);
+    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![], vec![]);
     let source_info = builder.source_info(span);
     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
     builder.finish(None)
@@ -775,7 +778,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
            safety: Safety,
            return_ty: Ty<'tcx>,
            return_span: Span,
-           upvar_decls: Vec<UpvarDecl>)
+           __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
+           upvar_mutbls: Vec<Mutability>)
            -> Builder<'a, 'gcx, 'tcx> {
         let lint_level = LintLevel::Explicit(hir.root_lint_level);
         let mut builder = Builder {
@@ -797,7 +801,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 1,
             ),
             canonical_user_type_annotations: IndexVec::new(),
-            upvar_decls,
+            __upvar_debuginfo_codegen_only_do_not_use,
+            upvar_mutbls,
             var_indices: Default::default(),
             unit_temp: None,
             cached_resume_block: None,
@@ -832,7 +837,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             self.local_decls,
             self.canonical_user_type_annotations,
             self.arg_count,
-            self.upvar_decls,
+            self.__upvar_debuginfo_codegen_only_do_not_use,
             self.fn_span,
             self.hir.control_flow_destroyed(),
         )
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 11e4ffe19da..bd6f005e873 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -3,6 +3,7 @@ use std::hash::Hash;
 use std::ops::RangeInclusive;
 
 use syntax_pos::symbol::Symbol;
+use rustc::hir;
 use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
@@ -165,13 +166,28 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, '
         match layout.ty.sty {
             // generators and closures.
             ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
-                if let Some(upvar) = self.ecx.tcx.optimized_mir(def_id).upvar_decls.get(field) {
-                    PathElem::ClosureVar(upvar.debug_name)
-                } else {
-                    // Sometimes the index is beyond the number of freevars (seen
-                    // for a generator).
-                    PathElem::ClosureVar(Symbol::intern(&field.to_string()))
+                let mut name = None;
+                if def_id.is_local() {
+                    let tables = self.ecx.tcx.typeck_tables_of(def_id);
+                    if let Some(upvars) = tables.upvar_list.get(&def_id) {
+                        // Sometimes the index is beyond the number of freevars (seen
+                        // for a generator).
+                        if let Some(upvar_id) = upvars.get(field) {
+                            let var_hir_id = upvar_id.var_path.hir_id;
+                            let var_node_id = self.ecx.tcx.hir().hir_to_node_id(var_hir_id);
+                            if let hir::Node::Binding(pat) = self.ecx.tcx.hir().get(var_node_id) {
+                                if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
+                                    name = Some(ident.name);
+                                }
+                            }
+                        }
+                    }
                 }
+
+                PathElem::ClosureVar(name.unwrap_or_else(|| {
+                    // Fall back to showing the field index.
+                    Symbol::intern(&field.to_string())
+                }))
             }
 
             // tuples
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index e63c1899fe5..2b909feb960 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -490,7 +490,7 @@ fn locals_live_across_suspend_points(
 
 fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             source: MirSource<'tcx>,
-                            upvars: Vec<Ty<'tcx>>,
+                            upvars: &Vec<Ty<'tcx>>,
                             interior: Ty<'tcx>,
                             movable: bool,
                             mir: &mut Mir<'tcx>)
@@ -505,7 +505,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                             movable);
     // Erase regions from the types passed in from typeck so we can compare them with
     // MIR types
-    let allowed_upvars = tcx.erase_regions(&upvars);
+    let allowed_upvars = tcx.erase_regions(upvars);
     let allowed = match interior.sty {
         ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
         _ => bug!(),
@@ -528,7 +528,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    let upvar_len = mir.upvar_decls.len();
+    let upvar_len = upvars.len();
     let dummy_local = LocalDecl::new_internal(tcx.mk_unit(), mir.span);
 
     // Gather live locals and their indices replacing values in mir.local_decls with a dummy
@@ -917,12 +917,12 @@ impl MirPass for StateTransform {
         let (remap, layout, storage_liveness) = compute_layout(
             tcx,
             source,
-            upvars,
+            &upvars,
             interior,
             movable,
             mir);
 
-        let state_field = mir.upvar_decls.len();
+        let state_field = upvars.len();
 
         // Run the transformation which converts Places from Local to generator struct
         // accesses for locals in `remap`.
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 027ae70b06a..e96a40ad2f0 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -222,10 +222,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         debug!("should_inline({:?})", callsite);
         let tcx = self.tcx;
 
-        // Don't inline closures that have captures
+        // Don't inline closures that have capture debuginfo
         // FIXME: Handle closures better
-        if callee_mir.upvar_decls.len() > 0 {
-            debug!("    upvar decls present - not inlining");
+        if callee_mir.__upvar_debuginfo_codegen_only_do_not_use.len() > 0 {
+            debug!("    upvar debuginfo present - not inlining");
             return false;
         }
 
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 776985ab798..d5f04ca64e4 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/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index efae1e56f4d..1f55a728f9c 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -461,9 +461,7 @@ fn comment(tcx: TyCtxt<'_, '_, '_>, SourceInfo { span, scope }: SourceInfo) -> S
     )
 }
 
-/// Prints user-defined variables in a scope tree.
-///
-/// Returns the total number of variables printed.
+/// Prints local variables in a scope tree.
 fn write_scope_tree(
     tcx: TyCtxt<'_, '_, '_>,
     mir: &Mir<'_>,
@@ -474,57 +472,64 @@ fn write_scope_tree(
 ) -> io::Result<()> {
     let indent = depth * INDENT.len();
 
+    // Local variable types (including the user's name in a comment).
+    for (local, local_decl) in mir.local_decls.iter_enumerated() {
+        if (1..mir.arg_count+1).contains(&local.index()) {
+            // Skip over argument locals, they're printed in the signature.
+            continue;
+        }
+
+        if local_decl.source_info.scope != parent {
+            // Not declared in this scope.
+            continue;
+        }
+
+        let mut_str = if local_decl.mutability == Mutability::Mut {
+            "mut "
+        } else {
+            ""
+        };
+
+        let mut indented_decl = format!(
+            "{0:1$}let {2}{3:?}: {4:?}",
+            INDENT,
+            indent,
+            mut_str,
+            local,
+            local_decl.ty
+        );
+        for user_ty in local_decl.user_ty.projections() {
+            write!(indented_decl, " as {:?}", user_ty).unwrap();
+        }
+        indented_decl.push_str(";");
+
+        let local_name = if local == RETURN_PLACE {
+            format!(" return place")
+        } else if let Some(name) = local_decl.name {
+            format!(" \"{}\"", name)
+        } else {
+            String::new()
+        };
+
+        writeln!(
+            w,
+            "{0:1$} //{2} in {3}",
+            indented_decl,
+            ALIGN,
+            local_name,
+            comment(tcx, local_decl.source_info),
+        )?;
+    }
+
     let children = match scope_tree.get(&parent) {
-        Some(children) => children,
+        Some(childs) => childs,
         None => return Ok(()),
     };
 
     for &child in children {
-        let data = &mir.source_scopes[child];
-        assert_eq!(data.parent_scope, Some(parent));
+        assert_eq!(mir.source_scopes[child].parent_scope, Some(parent));
         writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
-
-        // User variable types (including the user's name in a comment).
-        for local in mir.vars_iter() {
-            let var = &mir.local_decls[local];
-            let (name, source_info) = if var.source_info.scope == child {
-                (var.name.unwrap(), var.source_info)
-            } else {
-                // Not a variable or not declared in this scope.
-                continue;
-            };
-
-            let mut_str = if var.mutability == Mutability::Mut {
-                "mut "
-            } else {
-                ""
-            };
-
-            let indent = indent + INDENT.len();
-            let mut indented_var = format!(
-                "{0:1$}let {2}{3:?}: {4:?}",
-                INDENT,
-                indent,
-                mut_str,
-                local,
-                var.ty
-            );
-            for user_ty in var.user_ty.projections() {
-                write!(indented_var, " as {:?}", user_ty).unwrap();
-            }
-            indented_var.push_str(";");
-            writeln!(
-                w,
-                "{0:1$} // \"{2}\" in {3}",
-                indented_var,
-                ALIGN,
-                name,
-                comment(tcx, source_info)
-            )?;
-        }
-
         write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
-
         writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
     }
 
@@ -556,19 +561,8 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
         }
     }
 
-    // Print return place
-    let indented_retptr = format!("{}let mut {:?}: {};",
-                                  INDENT,
-                                  RETURN_PLACE,
-                                  mir.local_decls[RETURN_PLACE].ty);
-    writeln!(w, "{0:1$} // return place",
-             indented_retptr,
-             ALIGN)?;
-
     write_scope_tree(tcx, mir, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?;
 
-    write_temp_decls(mir, w)?;
-
     // Add an empty line before the first block is printed.
     writeln!(w, "")?;
 
@@ -632,22 +626,6 @@ fn write_mir_sig(
     Ok(())
 }
 
-fn write_temp_decls(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
-    // Compiler-introduced temporary types.
-    for temp in mir.temps_iter() {
-        writeln!(
-            w,
-            "{}let {}{:?}: {};",
-            INDENT,
-            if mir.local_decls[temp].mutability == Mutability::Mut {"mut "} else {""},
-            temp,
-            mir.local_decls[temp].ty
-        )?;
-    }
-
-    Ok(())
-}
-
 fn write_user_type_annotations(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
     if !mir.user_type_annotations.is_empty() {
         writeln!(w, "| User Type Annotations")?;
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index e3bb41ae672..f1255f52247 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -184,12 +184,12 @@ a.test-arrow {
 	color: #ddd;
 }
 
-.stab.unstable {background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
 .stab.internal { background: #FFB9B3; border-color: #B71C1C; color: #2f2f2f; }
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
 
-.stab > code {
+.stab.portability > code {
 	color: #ddd;
 }
 
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index dd4d028c6c9..c052e6b37ad 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -190,7 +190,7 @@ a.test-arrow {
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
 
-.stab > code {
+.stab.portability > code {
 	color: #000;
 }
 
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 898387cb9f5..c18a314116b 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 62bc1991cc9..bdec0c347f5 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 5a8101e2301..7a3b5d30500 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 74c952b076c..db821f4e536 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/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 53dab510ac3..75d687be280 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1145,9 +1145,34 @@ impl<'a> Parser<'a> {
                 if text.is_empty() {
                     self.span_bug(sp, "found empty literal suffix in Some")
                 }
-                self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
-                    .span_label(sp, format!("invalid suffix `{}`", text))
-                    .emit();
+                let mut err = if kind == "a tuple index" &&
+                    ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str())
+                {
+                    // #59553: warn instead of reject out of hand to allow the fix to percolate
+                    // through the ecosystem when people fix their macros
+                    let mut err = self.struct_span_warn(
+                        sp,
+                        &format!("suffixes on {} are invalid", kind),
+                    );
+                    err.note(&format!(
+                        "`{}` is *temporarily* accepted on tuple index fields as it was \
+                         incorrectly accepted on stable for a few releases",
+                        text,
+                    ));
+                    err.help(
+                        "on proc macros, you'll want to use `syn::Index::from` or \
+                         `proc_macro::Literal::*_unsuffixed` for code that will desugar \
+                         to tuple field access",
+                    );
+                    err.note(
+                        "for more context, see https://github.com/rust-lang/rust/issues/60210",
+                    );
+                    err
+                } else {
+                    self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
+                };
+                err.span_label(sp, format!("invalid suffix `{}`", text));
+                err.emit();
             }
         }
     }
@@ -1455,6 +1480,9 @@ impl<'a> Parser<'a> {
     fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
         self.sess.span_diagnostic.struct_span_err(sp, m)
     }
+    fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
+        self.sess.span_diagnostic.struct_span_warn(sp, m)
+    }
     crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
         self.sess.span_diagnostic.span_bug(sp, m)
     }
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 503b39e181a..39472ae11fb 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/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index 14d302f0eea..d4852db6d47 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -22,15 +22,14 @@ impl Drop for S {
 // END RUST SOURCE
 // START rustc.main.ElaborateDrops.before.mir
 //     let mut _0: ();
+//     let mut _2: std::boxed::Box<S>;
+//     let mut _3: ();
+//     let mut _4: std::boxed::Box<S>;
 //     scope 1 {
+//         let _1: std::boxed::Box<S>;
 //     }
 //     scope 2 {
-//         let _1: std::boxed::Box<S>;
 //     }
-//     let mut _2: std::boxed::Box<S>;
-//     let mut _3: ();
-//     let mut _4: std::boxed::Box<S>;
-//
 //     bb0: {
 //         StorageLive(_1);
 //         StorageLive(_2);
diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs
index 31ad1ebd9ff..023440af0eb 100644
--- a/src/test/mir-opt/issue-41110.rs
+++ b/src/test/mir-opt/issue-41110.rs
@@ -29,27 +29,28 @@ impl S {
 // END RUST SOURCE
 // START rustc.main.ElaborateDrops.after.mir
 //    let mut _0: ();
-//    scope 1 {
-//    }
-//    scope 2 {
-//        let _1: ();
-//    }
 //    let mut _2: S;
 //    let mut _3: S;
 //    let mut _4: S;
 //    let mut _5: bool;
+//    scope 1 {
+//        let _1: ();
+//    }
+//    scope 2 {
+//    }
+//    ...
 //    bb0: {
 // END rustc.main.ElaborateDrops.after.mir
 // START rustc.test.ElaborateDrops.after.mir
 //    let mut _0: ();
-//    ...
-//    let mut _2: S;
-//    ...
-//    let _1: S;
-//    ...
 //    let mut _3: ();
 //    let mut _4: S;
 //    let mut _5: S;
 //    let mut _6: bool;
+//    ...
+//    let _1: S;
+//    ...
+//    let mut _2: S;
+//    ...
 //    bb0: {
 // END rustc.test.ElaborateDrops.after.mir
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index 5f4f4ab82af..29446d2ecc2 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -17,16 +17,16 @@ fn main() {
 // START rustc.main.mir_map.0.mir
 // fn main() -> (){
 //     let mut _0: ();
-//     scope 1 {
-//     }
-//     scope 2 {
-//         let _2: i32;
-//     }
 //     let mut _1: ();
 //     let mut _3: bool;
 //     let mut _4: !;
 //     let mut _5: ();
 //     let mut _6: &i32;
+//     scope 1 {
+//         let _2: i32;
+//     }
+//     scope 2 {
+//     }
 //     bb0: {
 //         goto -> bb1;
 //     }
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index c2dda680b73..bb27461bb1e 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -27,10 +27,10 @@ fn main() {
 // | '_#4r    | U0 | {bb2[4..=5], bb3[0..=1]}
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
-// let _6: &'_#4r usize;
-// ...
 // let _2: &'_#3r usize;
 // ...
+// let _6: &'_#4r usize;
+// ...
 // _2 = &'_#2r _1[_3];
 // ...
 // _6 = _2;
diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs
index 167a6eb349e..7e8c58e64c2 100644
--- a/src/test/mir-opt/packed-struct-drop-aligned.rs
+++ b/src/test/mir-opt/packed-struct-drop-aligned.rs
@@ -18,16 +18,16 @@ impl Drop for Droppy {
 // START rustc.main.EraseRegions.before.mir
 // fn main() -> () {
 //     let mut _0: ();
-//     scope 1 {
-//     }
-//     scope 2 {
-//         let mut _1: Packed;
-//     }
 //     let mut _2: Aligned;
 //     let mut _3: Droppy;
 //     let mut _4: Aligned;
 //     let mut _5: Droppy;
 //     let mut _6: Aligned;
+//     scope 1 {
+//         let mut _1: Packed;
+//     }
+//     scope 2 {
+//     }
 //
 //     bb0: {
 //         StorageLive(_1);
diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs
index 518452aefc1..e1b4328debd 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 93e074e7ee5..c21886f26f4 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 6094f15569b..ee77053fd5b 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 ea4f5e076b0..961c412f5ec 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 86b0977bebe..12be6582a21 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 ba4997a7f9b..7384f7027d1 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 fccc4fdb917..e3ac817b15c 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 00000000000..3992607c387
--- /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 00000000000..e6e1ced6592
--- /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 00000000000..0395795ef7b
--- /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 00000000000..c934307e918
--- /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 00000000000..1d8b95ab1a2
--- /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 2105aa5835d..e1111f9e0e4 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 b6ab8ae0a9b..801aeb82aa2 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 cec211fef13..b419f1232df 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 1fdaec75e9d..9cfefef4129 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 1fa21f52045..43e41b45458 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 40642523be2..a4e08011934 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 869876dc6a8..2428b560b70 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 b2624ec92a1..d6f18875c9e 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 6160fbabd96..4572e543f22 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 559899194fb..99d87b2273c 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 a310653fbce..c758244002f 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 4f5b2ea3783..345f19b0623 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 3d7115c5223..f63950ad5e9 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;