diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml
index 1e49cc00921cd..ca32888b74c34 100644
--- a/.azure-pipelines/steps/run.yml
+++ b/.azure-pipelines/steps/run.yml
@@ -62,17 +62,6 @@ steps:
 - template: install-sccache.yml
 - template: install-clang.yml
 
-# Install some dependencies needed to build LLDB/Clang, currently only needed
-# during the `dist` target
-- bash: |
-    set -e
-    brew update
-    brew install xz
-    brew install swig@3
-    brew link --force swig@3
-  displayName: Install build dependencies (OSX)
-  condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['SCRIPT'],'./x.py dist'))
-
 # Switch to XCode 9.3 on OSX since it seems to be the last version that supports
 # i686-apple-darwin. We'll eventually want to upgrade this and it will probably
 # force us to drop i686-apple-darwin, but let's keep the wheels turning for now.
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index b197516403f78..c5198ca39fedf 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -1108,6 +1108,16 @@ fn test_iterator_last() {
     assert_eq!(it.last(), Some('m'));
 }
 
+#[test]
+fn test_chars_debug() {
+    let s = "ศไทย中华Việt Nam";
+    let c = s.chars();
+    assert_eq!(
+        format!("{:?}", c),
+        r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
+    );
+}
+
 #[test]
 fn test_bytesator() {
     let s = "ศไทย中华Việt Nam";
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 70a87cfe5a78a..7713e5761d4bd 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -8,7 +8,7 @@
 //! * Initial values
 //! * Return values for functions that are not defined
 //!   over their entire input range (partial functions)
-//! * Return value for otherwise reporting simple errors, where `None` is
+//! * Return value for otherwise reporting simple errors, where [`None`] is
 //!   returned on error
 //! * Optional struct fields
 //! * Struct fields that can be loaned or "taken"
@@ -752,7 +752,7 @@ impl<T> Option<T> {
         }
     }
 
-    /// Returns [`Some`] if exactly one of `self`, `optb` is [`Some`], otherwise returns `None`.
+    /// Returns [`Some`] if exactly one of `self`, `optb` is [`Some`], otherwise returns [`None`].
     ///
     /// [`Some`]: #variant.Some
     /// [`None`]: #variant.None
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index a7f6926de4263..a1f96905dc99b 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1609,7 +1609,7 @@ impl<T: ?Sized> *const T {
     /// `usize::max_value()`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
-    /// used with the `offset` or `offset_to` methods.
+    /// used with the `add` method.
     ///
     /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
@@ -2410,7 +2410,7 @@ impl<T: ?Sized> *mut T {
     /// `usize::max_value()`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
-    /// used with the `offset` or `offset_to` methods.
+    /// used with the `add` method.
     ///
     /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 4ecaa37460c66..4faf9ff4d2ee2 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -464,7 +464,7 @@ Section: Iterators
 ///
 /// [`chars`]: ../../std/primitive.str.html#method.chars
 /// [`str`]: ../../std/primitive.str.html
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chars<'a> {
     iter: slice::Iter<'a, u8>
@@ -600,6 +600,16 @@ impl<'a> Iterator for Chars<'a> {
     }
 }
 
+#[stable(feature = "chars_debug_impl", since = "1.38.0")]
+impl fmt::Debug for Chars<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Chars(")?;
+        f.debug_list().entries(self.clone()).finish()?;
+        write!(f, ")")?;
+        Ok(())
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for Chars<'a> {
     #[inline]
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 5acc3fd2fbcfd..73a76ebcb74f4 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -1189,11 +1189,7 @@ pub fn may_define_existential_type(
     opaque_hir_id: hir::HirId,
 ) -> bool {
     let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    trace!(
-        "may_define_existential_type(def={:?}, opaque_node={:?})",
-        tcx.hir().get(hir_id),
-        tcx.hir().get(opaque_hir_id)
-    );
+
 
     // Named existential types can be defined by any siblings or children of siblings.
     let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope");
@@ -1202,5 +1198,12 @@ pub fn may_define_existential_type(
         hir_id = tcx.hir().get_parent_item(hir_id);
     }
     // Syntactically, we are allowed to define the concrete type if:
-    hir_id == scope
+    let res = hir_id == scope;
+    trace!(
+        "may_define_existential_type(def={:?}, opaque_node={:?}) = {}",
+        tcx.hir().get(hir_id),
+        tcx.hir().get(opaque_hir_id),
+        res
+    );
+    res
 }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index e2b1b54cef39f..f6c62d191fa62 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2568,7 +2568,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let lifetimes: Vec<_> = params
             .iter()
             .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some((param, param.name)),
+                GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())),
                 _ => None,
             })
             .collect();
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 67fc3520745dd..5ab1b90642a6a 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -461,7 +461,7 @@ rustc_queries! {
     }
 
     TypeChecking {
-        query check_match(key: DefId) -> () {
+        query check_match(key: DefId) -> SignalledError {
             cache_on_disk_if { key.is_local() }
         }
 
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index f4b99ca368874..fb2ad2aa54d7a 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -4,7 +4,7 @@ use crate::hir::def::{DefKind, Export};
 use crate::hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs};
 use crate::infer::canonical::{self, Canonical};
 use crate::lint;
-use crate::middle::borrowck::BorrowCheckResult;
+use crate::middle::borrowck::{BorrowCheckResult, SignalledError};
 use crate::middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule};
 use crate::middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
 use crate::middle::privacy::AccessLevels;
diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs
index f8ad8baa5974d..3bbd7ae5c352f 100644
--- a/src/librustc_ast_borrowck/borrowck/mod.rs
+++ b/src/librustc_ast_borrowck/borrowck/mod.rs
@@ -66,6 +66,13 @@ fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult {
 
     debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
 
+    let signalled_error = tcx.check_match(owner_def_id);
+    if let SignalledError::SawSomeError = signalled_error {
+        return tcx.arena.alloc(BorrowCheckResult {
+            signalled_any_error: SignalledError::SawSomeError,
+        })
+    }
+
     let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap();
 
     match tcx.hir().get(owner_id) {
diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs
index a5e44a1933c9d..2afffd71fe206 100644
--- a/src/librustc_mir/error_codes.rs
+++ b/src/librustc_mir/error_codes.rs
@@ -1989,7 +1989,7 @@ When matching on a variable it cannot be mutated in the match guards, as this
 could cause the match to be non-exhaustive:
 
 ```compile_fail,E0510
-#![feature(nll, bind_by_move_pattern_guards)]
+#![feature(bind_by_move_pattern_guards)]
 let mut x = Some(0);
 match x {
     None => (),
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 32a8c5cd3bb28..17fd9377a1629 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -4,6 +4,7 @@ use super::_match::WitnessPreference::*;
 
 use super::{Pattern, PatternContext, PatternError, PatternKind};
 
+use rustc::middle::borrowck::SignalledError;
 use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
 use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
 use rustc::middle::expr_use_visitor as euv;
@@ -26,21 +27,24 @@ use std::slice;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 
-pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
+crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError {
     let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) {
         tcx.hir().body_owned_by(id)
     } else {
-        return;
+        return SignalledError::NoErrorsSeen;
     };
 
-    MatchVisitor {
+    let mut visitor = MatchVisitor {
         tcx,
         body_owner: def_id,
         tables: tcx.body_tables(body_id),
         region_scope_tree: &tcx.region_scope_tree(def_id),
         param_env: tcx.param_env(def_id),
         identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
-    }.visit_body(tcx.hir().body(body_id));
+        signalled_error: SignalledError::NoErrorsSeen,
+    };
+    visitor.visit_body(tcx.hir().body(body_id));
+    visitor.signalled_error
 }
 
 fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> {
@@ -54,6 +58,7 @@ struct MatchVisitor<'a, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
     identity_substs: SubstsRef<'tcx>,
     region_scope_tree: &'a region::ScopeTree,
+    signalled_error: SignalledError,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
@@ -64,11 +69,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
         intravisit::walk_expr(self, ex);
 
-        match ex.node {
-            hir::ExprKind::Match(ref scrut, ref arms, source) => {
-                self.check_match(scrut, arms, source);
-            }
-            _ => {}
+        if let hir::ExprKind::Match(ref scrut, ref arms, source) = ex.node {
+            self.check_match(scrut, arms, source);
         }
     }
 
@@ -130,7 +132,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
-    fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
+    fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
         check_legality_of_move_bindings(self, has_guard, pats);
         for pat in pats {
             check_legality_of_bindings_in_at_patterns(self, pat);
@@ -138,11 +140,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
     }
 
     fn check_match(
-        &self,
+        &mut self,
         scrut: &hir::Expr,
         arms: &'tcx [hir::Arm],
-        source: hir::MatchSource)
-    {
+        source: hir::MatchSource
+    ) {
         for arm in arms {
             // First, check legality of move bindings.
             self.check_patterns(arm.guard.is_some(), &arm.pats);
@@ -150,6 +152,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             // Second, if there is a guard on each arm, make sure it isn't
             // assigning or borrowing anything mutably.
             if let Some(ref guard) = arm.guard {
+                self.signalled_error = SignalledError::SawSomeError;
                 if !self.tcx.features().bind_by_move_pattern_guards {
                     check_for_mutation_in_guard(self, &guard);
                 }
@@ -548,7 +551,7 @@ fn maybe_point_at_variant(
 
 // Legality of move bindings checking
 fn check_legality_of_move_bindings(
-    cx: &MatchVisitor<'_, '_>,
+    cx: &mut MatchVisitor<'_, '_>,
     has_guard: bool,
     pats: &[P<Pat>],
 ) {
@@ -565,7 +568,12 @@ fn check_legality_of_move_bindings(
         })
     }
     let span_vec = &mut Vec::new();
-    let check_move = |p: &Pat, sub: Option<&Pat>, span_vec: &mut Vec<Span>| {
+    let check_move = |
+        cx: &mut MatchVisitor<'_, '_>,
+        p: &Pat,
+        sub: Option<&Pat>,
+        span_vec: &mut Vec<Span>,
+    | {
         // check legality of moving out of the enum
 
         // x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -574,15 +582,17 @@ fn check_legality_of_move_bindings(
                              "cannot bind by-move with sub-bindings")
                 .span_label(p.span, "binds an already bound by-move value by moving it")
                 .emit();
-        } else if has_guard && !cx.tcx.features().bind_by_move_pattern_guards {
-            let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
-                                           "cannot bind by-move into a pattern guard");
-            err.span_label(p.span, "moves value into pattern guard");
-            if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
-                err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
-                          crate attributes to enable");
+        } else if has_guard {
+            if !cx.tcx.features().bind_by_move_pattern_guards {
+                let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
+                                            "cannot bind by-move into a pattern guard");
+                err.span_label(p.span, "moves value into pattern guard");
+                if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
+                    err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
+                            crate attributes to enable");
+                }
+                err.emit();
             }
-            err.emit();
         } else if let Some(_by_ref_span) = by_ref_span {
             span_vec.push(p.span);
         }
@@ -596,7 +606,7 @@ fn check_legality_of_move_bindings(
                         ty::BindByValue(..) => {
                             let pat_ty = cx.tables.node_type(p.hir_id);
                             if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) {
-                                check_move(p, sub.as_ref().map(|p| &**p), span_vec);
+                                check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec);
                             }
                         }
                         _ => {}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index bc5898fe78da7..c8dd8282fd0f9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -869,8 +869,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         debug!("(resolving function) entering function");
         let rib_kind = match function_kind {
             FnKind::ItemFn(..) => FnItemRibKind,
-            FnKind::Method(..) => AssocItemRibKind,
-            FnKind::Closure(_) => NormalRibKind,
+            FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind,
         };
 
         // Create a value rib for the function.
@@ -2307,21 +2306,32 @@ impl<'a> Resolver<'a> {
         if ident.name == kw::Invalid {
             return Some(LexicalScopeBinding::Res(Res::Err));
         }
-        ident.span = if ident.name == kw::SelfUpper {
+        let (general_span, modern_span) = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
-            ident.span.with_ctxt(SyntaxContext::empty())
+            let empty_span = ident.span.with_ctxt(SyntaxContext::empty());
+            (empty_span, empty_span)
         } else if ns == TypeNS {
-            ident.span.modern()
+            let modern_span = ident.span.modern();
+            (modern_span, modern_span)
         } else {
-            ident.span.modern_and_legacy()
+            (ident.span.modern_and_legacy(), ident.span.modern())
         };
+        ident.span = general_span;
+        let modern_ident = Ident { span: modern_span, ..ident };
 
         // Walk backwards up the ribs in scope.
         let record_used = record_used_id.is_some();
         let mut module = self.graph_root;
         for i in (0 .. self.ribs[ns].len()).rev() {
             debug!("walk rib\n{:?}", self.ribs[ns][i].bindings);
-            if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() {
+            // Use the rib kind to determine whether we are resolving parameters
+            // (modern hygiene) or local variables (legacy hygiene).
+            let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind {
+                modern_ident
+            } else {
+                ident
+            };
+            if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(
                     self.validate_res_from_ribs(ns, i, res, record_used, path_span),
@@ -2357,7 +2367,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        ident.span = ident.span.modern();
+        ident = modern_ident;
         let mut poisoned = None;
         loop {
             let opt_module = if let Some(node_id) = record_used_id {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 053ef1f8f8297..395e266ae46aa 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1664,6 +1664,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             intravisit::NestedVisitorMap::All(&self.tcx.hir())
         }
         fn visit_item(&mut self, it: &'tcx Item) {
+            debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The existential type itself or its children are not within its reveal scope.
             if def_id != self.def_id {
@@ -1672,6 +1673,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
         }
         fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
+            debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The existential type itself or its children are not within its reveal scope.
             if def_id != self.def_id {
@@ -1680,6 +1682,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
         }
         fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
+            debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             self.check(def_id);
             intravisit::walk_trait_item(self, it);
@@ -1703,9 +1706,23 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     } else {
         debug!("find_existential_constraints: scope={:?}", tcx.hir().get(scope));
         match tcx.hir().get(scope) {
-            Node::Item(ref it) => intravisit::walk_item(&mut locator, it),
-            Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it),
-            Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it),
+            // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
+            // This allows our visitor to process the defining item itself, causing
+            // it to pick up any 'sibling' defining uses.
+            //
+            // For example, this code:
+            // ```
+            // fn foo() {
+            //     existential type Blah: Debug;
+            //     let my_closure = || -> Blah { true };
+            // }
+            // ```
+            //
+            // requires us to explicitly process `foo()` in order
+            // to notice the defining usage of `Blah`.
+            Node::Item(ref it) => locator.visit_item(it),
+            Node::ImplItem(ref it) => locator.visit_impl_item(it),
+            Node::TraitItem(ref it) => locator.visit_trait_item(it),
             other => bug!(
                 "{:?} is not a valid scope for an existential type item",
                 other
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index d41b3a3a1233f..f7c32a5c20d3d 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -3316,11 +3316,11 @@ mod tests {
         fs::create_dir_all(&d).unwrap();
         File::create(&f).unwrap();
         if cfg!(not(windows)) {
-            symlink_dir("../d/e", &c).unwrap();
+            symlink_file("../d/e", &c).unwrap();
             symlink_file("../f", &e).unwrap();
         }
         if cfg!(windows) {
-            symlink_dir(r"..\d\e", &c).unwrap();
+            symlink_file(r"..\d\e", &c).unwrap();
             symlink_file(r"..\f", &e).unwrap();
         }
 
diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs
index 4eb185c4d57ac..d537d2258fda7 100644
--- a/src/libstd/sys/vxworks/fs.rs
+++ b/src/libstd/sys/vxworks/fs.rs
@@ -287,22 +287,7 @@ impl File {
         let fd = cvt_r(|| unsafe {
             open(path.as_ptr(), flags, opts.mode as c_int)
         })?;
-        let fd = FileDesc::new(fd);
-        // Currently the standard library supports Linux 2.6.18 which did not
-        // have the O_CLOEXEC flag (passed above). If we're running on an older
-        // Linux kernel then the flag is just ignored by the OS. After we open
-        // the first file, we check whether it has CLOEXEC set. If it doesn't,
-        // we will explicitly ask for a CLOEXEC fd for every further file we
-        // open, if it does, we will skip that step.
-        //
-        // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc
-        // that we support, so we only do this on Linux currently.
-        fn ensure_cloexec(_: &FileDesc) -> io::Result<()> {
-            Ok(())
-        }
-
-        ensure_cloexec(&fd)?;
-        Ok(File(fd))
+        Ok(File(FileDesc::new(fd)))
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs
index aa6b93c860069..56962e11dcf95 100644
--- a/src/libstd/sys/vxworks/net.rs
+++ b/src/libstd/sys/vxworks/net.rs
@@ -141,10 +141,6 @@ impl Socket {
 
     pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t)
                   -> io::Result<Socket> {
-        // Unfortunately the only known way right now to accept a socket and
-        // atomically set the CLOEXEC flag is to use the `accept4` syscall on
-        // Linux. This was added in 2.6.28, however, and because we support
-        // 2.6.18 we must detect this support dynamically.
         let fd = cvt_r(|| unsafe {
             libc::accept(self.0.raw(), storage, len)
         })?;
diff --git a/src/libstd/sys/vxworks/pipe.rs b/src/libstd/sys/vxworks/pipe.rs
index 83637832ff327..e09dbe6e99ba8 100644
--- a/src/libstd/sys/vxworks/pipe.rs
+++ b/src/libstd/sys/vxworks/pipe.rs
@@ -11,11 +11,6 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
     static INVALID: AtomicBool = AtomicBool::new(false);
 
     let mut fds = [0; 2];
-
-    // Unfortunately the only known way right now to create atomically set the
-    // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
-    // 2.6.27, however, and because we support 2.6.18 we must detect this
-    // support dynamically.
     cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
 
     let fd0 = FileDesc::new(fds[0]);
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 39cb5042fbc11..9eb6aa303b06b 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -14,7 +14,7 @@ use crate::ThinVec;
 use crate::util::parser::AssocOp;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_data_structures::fx::FxHashSet;
-use syntax_pos::{Span, DUMMY_SP, MultiSpan};
+use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
 use log::{debug, trace};
 use std::mem;
 
@@ -199,6 +199,10 @@ impl<'a> Parser<'a> {
         &self.sess.span_diagnostic
     }
 
+    crate fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
+        self.sess.source_map().span_to_snippet(span)
+    }
+
     crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
         let mut err = self.struct_span_err(
             self.token.span,
@@ -549,8 +553,10 @@ impl<'a> Parser<'a> {
             ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
                 // respan to include both operators
                 let op_span = op.span.to(self.token.span);
-                let mut err = self.diagnostic().struct_span_err(op_span,
-                    "chained comparison operators require parentheses");
+                let mut err = self.struct_span_err(
+                    op_span,
+                    "chained comparison operators require parentheses",
+                );
                 if op.node == BinOpKind::Lt &&
                     *outer_op == AssocOp::Less ||  // Include `<` to provide this recommendation
                     *outer_op == AssocOp::Greater  // even in a case like the following:
@@ -717,8 +723,6 @@ impl<'a> Parser<'a> {
         path.span = ty_span.to(self.prev_span);
 
         let ty_str = self
-            .sess
-            .source_map()
             .span_to_snippet(ty_span)
             .unwrap_or_else(|_| pprust::ty_to_string(&ty));
         self.diagnostic()
@@ -889,7 +893,7 @@ impl<'a> Parser<'a> {
             err.span_label(await_sp, "while parsing this incorrect await expression");
             err
         })?;
-        let expr_str = self.sess.source_map().span_to_snippet(expr.span)
+        let expr_str = self.span_to_snippet(expr.span)
             .unwrap_or_else(|_| pprust::expr_to_string(&expr));
         let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
         let sp = lo.to(expr.span);
@@ -923,6 +927,48 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Recover a situation like `for ( $pat in $expr )`
+    /// and suggest writing `for $pat in $expr` instead.
+    ///
+    /// This should be called before parsing the `$block`.
+    crate fn recover_parens_around_for_head(
+        &mut self,
+        pat: P<Pat>,
+        expr: &Expr,
+        begin_paren: Option<Span>,
+    ) -> P<Pat> {
+        match (&self.token.kind, begin_paren) {
+            (token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
+                self.bump();
+
+                let pat_str = self
+                    // Remove the `(` from the span of the pattern:
+                    .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
+                    .unwrap_or_else(|_| pprust::pat_to_string(&pat));
+
+                self.struct_span_err(self.prev_span, "unexpected closing `)`")
+                    .span_label(begin_par_sp, "opening `(`")
+                    .span_suggestion(
+                        begin_par_sp.to(self.prev_span),
+                        "remove parenthesis in `for` loop",
+                        format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
+                        // With e.g. `for (x) in y)` this would replace `(x) in y)`
+                        // with `x) in y)` which is syntactically invalid.
+                        // However, this is prevented before we get here.
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
+
+                // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
+                pat.and_then(|pat| match pat.node {
+                    PatKind::Paren(pat) => pat,
+                    _ => P(pat),
+                })
+            }
+            _ => pat,
+        }
+    }
+
     crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
         self.token.is_ident() &&
             if let ast::ExprKind::Path(..) = node { true } else { false } &&
@@ -1105,17 +1151,14 @@ impl<'a> Parser<'a> {
     crate fn check_for_for_in_in_typo(&mut self, in_span: Span) {
         if self.eat_keyword(kw::In) {
             // a common typo: `for _ in in bar {}`
-            let mut err = self.sess.span_diagnostic.struct_span_err(
-                self.prev_span,
-                "expected iterable, found keyword `in`",
-            );
-            err.span_suggestion_short(
-                in_span.until(self.prev_span),
-                "remove the duplicated `in`",
-                String::new(),
-                Applicability::MachineApplicable,
-            );
-            err.emit();
+            self.struct_span_err(self.prev_span, "expected iterable, found keyword `in`")
+                .span_suggestion_short(
+                    in_span.until(self.prev_span),
+                    "remove the duplicated `in`",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
         }
     }
 
@@ -1128,12 +1171,12 @@ impl<'a> Parser<'a> {
 
     crate fn eat_incorrect_doc_comment_for_arg_type(&mut self) {
         if let token::DocComment(_) = self.token.kind {
-            let mut err = self.diagnostic().struct_span_err(
+            self.struct_span_err(
                 self.token.span,
                 "documentation comments cannot be applied to a function parameter's type",
-            );
-            err.span_label(self.token.span, "doc comments are not allowed here");
-            err.emit();
+            )
+            .span_label(self.token.span, "doc comments are not allowed here")
+            .emit();
             self.bump();
         } else if self.token == token::Pound && self.look_ahead(1, |t| {
             *t == token::OpenDelim(token::Bracket)
@@ -1145,12 +1188,12 @@ impl<'a> Parser<'a> {
             }
             let sp = lo.to(self.token.span);
             self.bump();
-            let mut err = self.diagnostic().struct_span_err(
+            self.struct_span_err(
                 sp,
                 "attributes cannot be applied to a function parameter's type",
-            );
-            err.span_label(sp, "attributes are not allowed here");
-            err.emit();
+            )
+            .span_label(sp, "attributes are not allowed here")
+            .emit();
         }
     }
 
@@ -1206,18 +1249,19 @@ impl<'a> Parser<'a> {
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
-        let mut err = self.diagnostic().struct_span_err_with_code(
-            pat.span,
-            "patterns aren't allowed in methods without bodies",
-            DiagnosticId::Error("E0642".into()),
-        );
-        err.span_suggestion_short(
-            pat.span,
-            "give this argument a name or use an underscore to ignore it",
-            "_".to_owned(),
-            Applicability::MachineApplicable,
-        );
-        err.emit();
+        self.diagnostic()
+            .struct_span_err_with_code(
+                pat.span,
+                "patterns aren't allowed in methods without bodies",
+                DiagnosticId::Error("E0642".into()),
+            )
+            .span_suggestion_short(
+                pat.span,
+                "give this argument a name or use an underscore to ignore it",
+                "_".to_owned(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
 
         // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
         let pat = P(Pat {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 6cb965bf817d1..fb5ff7e8f9862 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2329,19 +2329,19 @@ impl<'a> Parser<'a> {
             // This is a struct literal, but we don't can't accept them here
             let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
             if let (Ok(expr), false) = (&expr, struct_allowed) {
-                let mut err = self.diagnostic().struct_span_err(
+                self.struct_span_err(
                     expr.span,
                     "struct literals are not allowed here",
-                );
-                err.multipart_suggestion(
+                )
+                .multipart_suggestion(
                     "surround the struct literal with parentheses",
                     vec![
                         (lo.shrink_to_lo(), "(".to_string()),
                         (expr.span.shrink_to_hi(), ")".to_string()),
                     ],
                     Applicability::MachineApplicable,
-                );
-                err.emit();
+                )
+                .emit();
             }
             return Some(expr);
         }
@@ -2370,18 +2370,18 @@ impl<'a> Parser<'a> {
                     }
                 }
                 if self.token == token::Comma {
-                    let mut err = self.sess.span_diagnostic.mut_span_err(
+                    self.struct_span_err(
                         exp_span.to(self.prev_span),
                         "cannot use a comma after the base struct",
-                    );
-                    err.span_suggestion_short(
+                    )
+                    .span_suggestion_short(
                         self.token.span,
                         "remove this comma",
                         String::new(),
                         Applicability::MachineApplicable
-                    );
-                    err.note("the base struct must always be the last field");
-                    err.emit();
+                    )
+                    .note("the base struct must always be the last field")
+                    .emit();
                     self.recover_stmt();
                 }
                 break;
@@ -2736,15 +2736,14 @@ impl<'a> Parser<'a> {
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 let span_of_tilde = lo;
-                let mut err = self.diagnostic()
-                    .struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator");
-                err.span_suggestion_short(
-                    span_of_tilde,
-                    "use `!` to perform bitwise negation",
-                    "!".to_owned(),
-                    Applicability::MachineApplicable
-                );
-                err.emit();
+                self.struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator")
+                    .span_suggestion_short(
+                        span_of_tilde,
+                        "use `!` to perform bitwise negation",
+                        "!".to_owned(),
+                        Applicability::MachineApplicable
+                    )
+                    .emit();
                 (lo.to(span), self.mk_unary(UnOp::Not, e))
             }
             token::BinOp(token::Minus) => {
@@ -2792,21 +2791,20 @@ impl<'a> Parser<'a> {
                 if cannot_continue_expr {
                     self.bump();
                     // Emit the error ...
-                    let mut err = self.diagnostic()
-                        .struct_span_err(self.token.span,
-                                         &format!("unexpected {} after identifier",
-                                                  self.this_token_descr()));
-                    // span the `not` plus trailing whitespace to avoid
-                    // trailing whitespace after the `!` in our suggestion
-                    let to_replace = self.sess.source_map()
-                        .span_until_non_whitespace(lo.to(self.token.span));
-                    err.span_suggestion_short(
-                        to_replace,
+                    self.struct_span_err(
+                        self.token.span,
+                        &format!("unexpected {} after identifier",self.this_token_descr())
+                    )
+                    .span_suggestion_short(
+                        // Span the `not` plus trailing whitespace to avoid
+                        // trailing whitespace after the `!` in our suggestion
+                        self.sess.source_map()
+                            .span_until_non_whitespace(lo.to(self.token.span)),
                         "use `!` to perform logical negation",
                         "!".to_owned(),
                         Applicability::MachineApplicable
-                    );
-                    err.emit();
+                    )
+                    .emit();
                     // —and recover! (just as if we were in the block
                     // for the `token::Not` arm)
                     let e = self.parse_prefix_expr(None);
@@ -2884,7 +2882,7 @@ impl<'a> Parser<'a> {
                 // We've found an expression that would be parsed as a statement, but the next
                 // token implies this should be parsed as an expression.
                 // For example: `if let Some(x) = x { x } else { 0 } / 2`
-                let mut err = self.sess.span_diagnostic.struct_span_err(self.token.span, &format!(
+                let mut err = self.struct_span_err(self.token.span, &format!(
                     "expected expression, found `{}`",
                     pprust::token_to_string(&self.token),
                 ));
@@ -3072,28 +3070,29 @@ impl<'a> Parser<'a> {
                         // in AST and continue parsing.
                         let msg = format!("`<` is interpreted as a start of generic \
                                            arguments for `{}`, not a {}", path, op_noun);
-                        let mut err =
-                            self.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
                         let span_after_type = parser_snapshot_after_type.token.span;
-                        err.span_label(self.look_ahead(1, |t| t.span).to(span_after_type),
-                                       "interpreted as generic arguments");
-                        err.span_label(self.token.span, format!("not interpreted as {}", op_noun));
-
                         let expr = mk_expr(self, P(Ty {
                             span: path.span,
                             node: TyKind::Path(None, path),
                             id: ast::DUMMY_NODE_ID
                         }));
 
-                        let expr_str = self.sess.source_map().span_to_snippet(expr.span)
-                                                .unwrap_or_else(|_| pprust::expr_to_string(&expr));
-                        err.span_suggestion(
-                            expr.span,
-                            &format!("try {} the cast value", op_verb),
-                            format!("({})", expr_str),
-                            Applicability::MachineApplicable
-                        );
-                        err.emit();
+                        let expr_str = self.span_to_snippet(expr.span)
+                            .unwrap_or_else(|_| pprust::expr_to_string(&expr));
+
+                        self.struct_span_err(self.token.span, &msg)
+                            .span_label(
+                                self.look_ahead(1, |t| t.span).to(span_after_type),
+                                "interpreted as generic arguments"
+                            )
+                            .span_label(self.token.span, format!("not interpreted as {}", op_noun))
+                            .span_suggestion(
+                                expr.span,
+                                &format!("try {} the cast value", op_verb),
+                                format!("({})", expr_str),
+                                Applicability::MachineApplicable
+                            )
+                            .emit();
 
                         Ok(expr)
                     }
@@ -3276,26 +3275,40 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a 'for' .. 'in' expression ('for' token already eaten)
-    fn parse_for_expr(&mut self, opt_label: Option<Label>,
-                          span_lo: Span,
-                          mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_for_expr(
+        &mut self,
+        opt_label: Option<Label>,
+        span_lo: Span,
+        mut attrs: ThinVec<Attribute>
+    ) -> PResult<'a, P<Expr>> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
+        // Record whether we are about to parse `for (`.
+        // This is used below for recovery in case of `for ( $stuff ) $block`
+        // in which case we will suggest `for $stuff $block`.
+        let begin_paren = match self.token.kind {
+            token::OpenDelim(token::Paren) => Some(self.token.span),
+            _ => None,
+        };
+
         let pat = self.parse_top_level_pat()?;
         if !self.eat_keyword(kw::In) {
             let in_span = self.prev_span.between(self.token.span);
-            let mut err = self.sess.span_diagnostic
-                .struct_span_err(in_span, "missing `in` in `for` loop");
-            err.span_suggestion_short(
-                in_span, "try adding `in` here", " in ".into(),
-                // has been misleading, at least in the past (closed Issue #48492)
-                Applicability::MaybeIncorrect
-            );
-            err.emit();
+            self.struct_span_err(in_span, "missing `in` in `for` loop")
+                .span_suggestion_short(
+                    in_span,
+                    "try adding `in` here", " in ".into(),
+                    // has been misleading, at least in the past (closed Issue #48492)
+                    Applicability::MaybeIncorrect
+                )
+                .emit();
         }
         let in_span = self.prev_span;
         self.check_for_for_in_in_typo(in_span);
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
+
+        let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);
+
         let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
 
@@ -3522,15 +3535,14 @@ impl<'a> Parser<'a> {
             pats.push(self.parse_top_level_pat()?);
 
             if self.token == token::OrOr {
-                let mut err = self.struct_span_err(self.token.span,
-                                                   "unexpected token `||` after pattern");
-                err.span_suggestion(
-                    self.token.span,
-                    "use a single `|` to specify multiple patterns",
-                    "|".to_owned(),
-                    Applicability::MachineApplicable
-                );
-                err.emit();
+                self.struct_span_err(self.token.span, "unexpected token `||` after pattern")
+                    .span_suggestion(
+                        self.token.span,
+                        "use a single `|` to specify multiple patterns",
+                        "|".to_owned(),
+                        Applicability::MachineApplicable
+                    )
+                    .emit();
                 self.bump();
             } else if self.eat(&token::BinOp(token::Or)) {
                 // This is a No-op. Continue the loop to parse the next
@@ -3627,15 +3639,14 @@ impl<'a> Parser<'a> {
 
                 if self.token == token::DotDotDot { // Issue #46718
                     // Accept `...` as if it were `..` to avoid further errors
-                    let mut err = self.struct_span_err(self.token.span,
-                                                       "expected field pattern, found `...`");
-                    err.span_suggestion(
-                        self.token.span,
-                        "to omit remaining fields, use one fewer `.`",
-                        "..".to_owned(),
-                        Applicability::MachineApplicable
-                    );
-                    err.emit();
+                    self.struct_span_err(self.token.span, "expected field pattern, found `...`")
+                        .span_suggestion(
+                            self.token.span,
+                            "to omit remaining fields, use one fewer `.`",
+                            "..".to_owned(),
+                            Applicability::MachineApplicable
+                        )
+                        .emit();
                 }
                 self.bump();  // `..` || `...`
 
@@ -3788,7 +3799,7 @@ impl<'a> Parser<'a> {
             let seq_span = pat.span.to(self.prev_span);
             let mut err = self.struct_span_err(comma_span,
                                                "unexpected `,` in pattern");
-            if let Ok(seq_snippet) = self.sess.source_map().span_to_snippet(seq_span) {
+            if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
                 err.span_suggestion(
                     seq_span,
                     "try adding parentheses to match on a tuple..",
@@ -4137,7 +4148,7 @@ impl<'a> Parser<'a> {
                     let parser_snapshot_after_type = self.clone();
                     mem::replace(self, parser_snapshot_before_type);
 
-                    let snippet = self.sess.source_map().span_to_snippet(pat.span).unwrap();
+                    let snippet = self.span_to_snippet(pat.span).unwrap();
                     err.span_label(pat.span, format!("while parsing the type for `{}`", snippet));
                     (Some((parser_snapshot_after_type, colon_sp, err)), None)
                 }
@@ -4557,7 +4568,7 @@ impl<'a> Parser<'a> {
                     if self.eat(&token::Semi) {
                         stmt_span = stmt_span.with_hi(self.prev_span.hi());
                     }
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(stmt_span) {
+                    if let Ok(snippet) = self.span_to_snippet(stmt_span) {
                         e.span_suggestion(
                             stmt_span,
                             "try placing this code inside a block",
@@ -4730,7 +4741,7 @@ impl<'a> Parser<'a> {
                             lo.to(self.prev_span),
                             "parenthesized lifetime bounds are not supported"
                         );
-                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(inner_span) {
+                        if let Ok(snippet) = self.span_to_snippet(inner_span) {
                             err.span_suggestion_short(
                                 lo.to(self.prev_span),
                                 "remove the parentheses",
@@ -4788,7 +4799,7 @@ impl<'a> Parser<'a> {
                 let mut new_bound_list = String::new();
                 if !bounds.is_empty() {
                     let mut snippets = bounds.iter().map(|bound| bound.span())
-                        .map(|span| self.sess.source_map().span_to_snippet(span));
+                        .map(|span| self.span_to_snippet(span));
                     while let Some(Ok(snippet)) = snippets.next() {
                         new_bound_list.push_str(" + ");
                         new_bound_list.push_str(&snippet);
@@ -5853,15 +5864,16 @@ impl<'a> Parser<'a> {
                 if let token::DocComment(_) = self.token.kind {
                     if self.look_ahead(1,
                     |tok| tok == &token::CloseDelim(token::Brace)) {
-                        let mut err = self.diagnostic().struct_span_err_with_code(
+                        self.diagnostic().struct_span_err_with_code(
                             self.token.span,
                             "found a documentation comment that doesn't document anything",
                             DiagnosticId::Error("E0584".into()),
-                        );
-                        err.help("doc comments must come before what they document, maybe a \
+                        )
+                        .help(
+                            "doc comments must come before what they document, maybe a \
                             comment was intended with `//`?",
-                        );
-                        err.emit();
+                        )
+                        .emit();
                         self.bump();
                         continue;
                     }
@@ -6305,12 +6317,15 @@ impl<'a> Parser<'a> {
                 let sp = path.span;
                 let help_msg = format!("make this visible only to module `{}` with `in`", path);
                 self.expect(&token::CloseDelim(token::Paren))?;  // `)`
-                let mut err = struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg);
-                err.help(suggestion);
-                err.span_suggestion(
-                    sp, &help_msg, format!("in {}", path), Applicability::MachineApplicable
-                );
-                err.emit();  // emit diagnostic, but continue with public visibility
+                struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg)
+                    .help(suggestion)
+                    .span_suggestion(
+                        sp,
+                        &help_msg,
+                        format!("in {}", path),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();  // emit diagnostic, but continue with public visibility
             }
         }
 
@@ -6744,14 +6759,10 @@ impl<'a> Parser<'a> {
             }
             ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
 
-            let mut err = self.struct_span_err(fixed_name_sp, error_msg);
-            err.span_label(fixed_name_sp, "dash-separated idents are not valid");
-            err.multipart_suggestion(
-                suggestion_msg,
-                replacement,
-                Applicability::MachineApplicable,
-            );
-            err.emit();
+            self.struct_span_err(fixed_name_sp, error_msg)
+                .span_label(fixed_name_sp, "dash-separated idents are not valid")
+                .multipart_suggestion(suggestion_msg, replacement, Applicability::MachineApplicable)
+                .emit();
         }
         Ok(ident)
     }
@@ -6906,14 +6917,14 @@ impl<'a> Parser<'a> {
             if !self.eat(&token::Comma) {
                 if self.token.is_ident() && !self.token.is_reserved_ident() {
                     let sp = self.sess.source_map().next_point(self.prev_span);
-                    let mut err = self.struct_span_err(sp, "missing comma");
-                    err.span_suggestion_short(
-                        sp,
-                        "missing comma",
-                        ",".to_owned(),
-                        Applicability::MaybeIncorrect,
-                    );
-                    err.emit();
+                    self.struct_span_err(sp, "missing comma")
+                        .span_suggestion_short(
+                            sp,
+                            "missing comma",
+                            ",".to_owned(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                 } else {
                     break;
                 }
@@ -6952,15 +6963,16 @@ impl<'a> Parser<'a> {
                     Some(abi) => Ok(Some(abi)),
                     None => {
                         let prev_span = self.prev_span;
-                        let mut err = struct_span_err!(
+                        struct_span_err!(
                             self.sess.span_diagnostic,
                             prev_span,
                             E0703,
                             "invalid ABI: found `{}`",
-                            symbol);
-                        err.span_label(prev_span, "invalid ABI");
-                        err.help(&format!("valid ABIs: {}", abi::all_names().join(", ")));
-                        err.emit();
+                            symbol
+                        )
+                        .span_label(prev_span, "invalid ABI")
+                        .help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
+                        .emit();
                         Ok(None)
                     }
                 }
@@ -7130,16 +7142,15 @@ impl<'a> Parser<'a> {
             // CONST ITEM
             if self.eat_keyword(kw::Mut) {
                 let prev_span = self.prev_span;
-                let mut err = self.diagnostic()
-                    .struct_span_err(prev_span, "const globals cannot be mutable");
-                err.span_label(prev_span, "cannot be mutable");
-                err.span_suggestion(
-                    const_span,
-                    "you might want to declare a static instead",
-                    "static".to_owned(),
-                    Applicability::MaybeIncorrect,
-                );
-                err.emit();
+                self.struct_span_err(prev_span, "const globals cannot be mutable")
+                    .span_label(prev_span, "cannot be mutable")
+                    .span_suggestion(
+                        const_span,
+                        "you might want to declare a static instead",
+                        "static".to_owned(),
+                        Applicability::MaybeIncorrect,
+                    )
+                    .emit();
             }
             let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
             let prev_span = self.prev_span;
@@ -7407,7 +7418,7 @@ impl<'a> Parser<'a> {
                         sp, &suggestion, format!(" {} ", kw), Applicability::MachineApplicable
                     );
                 } else {
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(ident_sp) {
+                    if let Ok(snippet) = self.span_to_snippet(ident_sp) {
                         err.span_suggestion(
                             full_sp,
                             "if you meant to call a macro, try",
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.toml b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
index 499553304c681..73fdee71f0c0b 100644
--- a/src/test/run-make/thumb-none-qemu/example/Cargo.toml
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
@@ -2,7 +2,7 @@
 name = "example"
 version = "0.1.0"
 authors = ["Hideki Sekine <sekineh@me.com>"]
-# edition = "2018"
+edition = "2018"
 
 [dependencies]
 cortex-m = "0.5.4"
diff --git a/src/test/run-make/thumb-none-qemu/example/src/main.rs b/src/test/run-make/thumb-none-qemu/example/src/main.rs
index d88a327ef08b4..4a08419a07e14 100644
--- a/src/test/run-make/thumb-none-qemu/example/src/main.rs
+++ b/src/test/run-make/thumb-none-qemu/example/src/main.rs
@@ -1,16 +1,14 @@
 // #![feature(stdsimd)]
 #![no_main]
 #![no_std]
-
-extern crate cortex_m;
-
-extern crate cortex_m_rt as rt;
-extern crate cortex_m_semihosting as semihosting;
-extern crate panic_halt;
-
 use core::fmt::Write;
 use cortex_m::asm;
-use rt::entry;
+use cortex_m_rt::entry;
+use cortex_m_semihosting as semihosting;
+
+//FIXME: This imports the provided #[panic_handler].
+#[allow(rust_2018_idioms)]
+extern crate panic_halt;
 
 entry!(main);
 
@@ -22,7 +20,7 @@ fn main() -> ! {
 
         // write something through semihosting interface
         let mut hstdout = semihosting::hio::hstdout().unwrap();
-        write!(hstdout, "x = {}\n", x);
+        let _ = write!(hstdout, "x = {}\n", x);
 
         // exit from qemu
         semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS);
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
index d97883ad47a50..a33a1d00a5786 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
@@ -1,14 +1,14 @@
-warning[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/borrowck-migrate-to-nll.rs:26:18
+warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-migrate-to-nll.rs:28:21
    |
-LL |                 (|| { let bar = foo; bar.take() })();
-   |                  ^^             ---
-   |                  |              |
-   |                  |              move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait
-   |                  |              move occurs due to use in closure
-   |                  move out of `foo` occurs here
+LL |     let x = &mut block;
+   |             ---------- mutable borrow occurs here
+LL |     let p: &'a u8 = &*block.current;
+   |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
+LL |     // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
+LL |     drop(x);
+   |          - mutable borrow later used here
    |
-   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
    = note: for more information, try `rustc --explain E0729`
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
index a64df9df25948..6dda317e57efe 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
@@ -1,4 +1,4 @@
-// This is a test of the borrowck migrate mode. It leverages #27282, a
+// This is a test of the borrowck migrate mode. It leverages #38899, a
 // bug that is fixed by NLL: this code is (unsoundly) accepted by
 // AST-borrowck, but is correctly rejected by the NLL borrowck.
 //
@@ -18,15 +18,17 @@
 //[zflag] run-pass
 //[edition] run-pass
 
-fn main() {
-    match Some(&4) {
-        None => {},
-        ref mut foo
-            if {
-                (|| { let bar = foo; bar.take() })();
-                false
-            } => {},
-        Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
-        _ => println!("Here is some supposedly unreachable code."),
-    }
+pub struct Block<'a> {
+    current: &'a u8,
+    unrelated: &'a u8,
 }
+
+fn bump<'a>(mut block: &mut Block<'a>) {
+    let x = &mut block;
+    let p: &'a u8 = &*block.current;
+    // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
+    drop(x);
+    drop(p);
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
index d97883ad47a50..a33a1d00a5786 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
@@ -1,14 +1,14 @@
-warning[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/borrowck-migrate-to-nll.rs:26:18
+warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-migrate-to-nll.rs:28:21
    |
-LL |                 (|| { let bar = foo; bar.take() })();
-   |                  ^^             ---
-   |                  |              |
-   |                  |              move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait
-   |                  |              move occurs due to use in closure
-   |                  move out of `foo` occurs here
+LL |     let x = &mut block;
+   |             ---------- mutable borrow occurs here
+LL |     let p: &'a u8 = &*block.current;
+   |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
+LL |     // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
+LL |     drop(x);
+   |          - mutable borrow later used here
    |
-   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
    = note: for more information, try `rustc --explain E0729`
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
deleted file mode 100644
index 43b578e9f1eaf..0000000000000
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
+++ /dev/null
@@ -1,41 +0,0 @@
-error[E0302]: cannot assign in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:10:25
-   |
-LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
-   |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
-
-error[E0301]: cannot mutably borrow in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:38
-   |
-LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-   |                                      ^ borrowed mutably in pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error[E0302]: cannot assign in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:41
-   |
-LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-   |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
-
-error[E0510]: cannot assign `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:10:25
-   |
-LL |     match x {
-   |           - value is immutable in match guard
-LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
-   |                         ^^^^^^^^^^^^^^^^^^ cannot assign
-
-error[E0510]: cannot mutably borrow `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:33
-   |
-LL |     match x {
-   |           - value is immutable in match guard
-...
-LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-   |                                 ^^^^^^ cannot mutably borrow
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0301, E0302, E0510.
-For more information about an error, try `rustc --explain E0301`.
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
index 9ea5e5cd145a0..5b6aa7a979be5 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
@@ -9,15 +9,11 @@ fn foo() -> isize {
     match x {
         Enum::A(_) if { x = Enum::B(false); false } => 1,
         //~^ ERROR cannot assign in a pattern guard
-        //~| WARN cannot assign `x` in match guard
-        //~| WARN this error has been downgraded to a warning for backwards compatibility
-        //~| WARN this represents potential undefined behavior in your code and this warning will
+        //~| ERROR cannot assign `x` in match guard
         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
         //~^ ERROR cannot mutably borrow in a pattern guard
         //~| ERROR cannot assign in a pattern guard
-        //~| WARN cannot mutably borrow `x` in match guard
-        //~| WARN this error has been downgraded to a warning for backwards compatibility
-        //~| WARN this represents potential undefined behavior in your code and this warning will
+        //~| ERROR cannot mutably borrow `x` in match guard
         Enum::A(p) => *p,
         Enum::B(_) => 2,
     }
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
index d39f535d8e2f7..674f137dbb043 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -5,7 +5,7 @@ LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
    |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
 
 error[E0301]: cannot mutably borrow in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:38
+  --> $DIR/borrowck-mutate-in-guard.rs:13:38
    |
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                      ^ borrowed mutably in pattern guard
@@ -13,37 +13,29 @@ LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error[E0302]: cannot assign in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:41
+  --> $DIR/borrowck-mutate-in-guard.rs:13:41
    |
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
 
-warning[E0510]: cannot assign `x` in match guard
+error[E0510]: cannot assign `x` in match guard
   --> $DIR/borrowck-mutate-in-guard.rs:10:25
    |
 LL |     match x {
    |           - value is immutable in match guard
 LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
    |                         ^^^^^^^^^^^^^^^^^^ cannot assign
-   |
-   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
-   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
-   = note: for more information, try `rustc --explain E0729`
 
-warning[E0510]: cannot mutably borrow `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:15:33
+error[E0510]: cannot mutably borrow `x` in match guard
+  --> $DIR/borrowck-mutate-in-guard.rs:13:33
    |
 LL |     match x {
    |           - value is immutable in match guard
 ...
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                 ^^^^^^ cannot mutably borrow
-   |
-   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
-   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
-   = note: for more information, try `rustc --explain E0729`
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0301, E0302, E0510.
 For more information about an error, try `rustc --explain E0301`.
diff --git a/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs b/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs
new file mode 100644
index 0000000000000..395c7d214d0ce
--- /dev/null
+++ b/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs
@@ -0,0 +1,13 @@
+fn main() {
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if {
+                (|| { let bar = foo; bar.take() })();
+                //~^ ERROR cannot move out of `foo` in pattern guard
+                false
+            } => {},
+        Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
+        _ => println!("Here is some supposedly unreachable code."),
+    }
+}
diff --git a/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr b/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr
new file mode 100644
index 0000000000000..ea7df7d5a7b61
--- /dev/null
+++ b/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of `foo` in pattern guard
+  --> $DIR/issue-27282-mutation-in-guard.rs:6:18
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                  ^^             ---
+   |                  |              |
+   |                  |              move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait
+   |                  |              move occurs due to use in closure
+   |                  move out of `foo` occurs here
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs
new file mode 100644
index 0000000000000..07125b98a1f7d
--- /dev/null
+++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let a = Some("...".to_owned());
+    let b = match a {
+        Some(_) if { drop(a); false } => None,
+        x => x, //~ ERROR use of moved value: `a`
+    };
+    println!("{:?}", b);
+}
diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
new file mode 100644
index 0000000000000..85c83ec4d70ed
--- /dev/null
+++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/issue-31287-drop-in-guard.rs:5:9
+   |
+LL |     let a = Some("...".to_owned());
+   |         - move occurs because `a` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
+LL |     let b = match a {
+LL |         Some(_) if { drop(a); false } => None,
+   |                           - value moved here
+LL |         x => x,
+   |         ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.rs b/src/test/ui/existential-type/issue-52843-closure-constrain.rs
new file mode 100644
index 0000000000000..b2bbc1f154998
--- /dev/null
+++ b/src/test/ui/existential-type/issue-52843-closure-constrain.rs
@@ -0,0 +1,12 @@
+// Checks to ensure that we properly detect when a closure constrains an existential type
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {
+    existential type Existential: Debug;
+    fn _unused() -> Existential { String::new() }
+    //~^ ERROR: concrete type differs from previous defining existential type use
+    let null = || -> Existential { 0 };
+    println!("{:?}", null());
+}
diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.stderr b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr
new file mode 100644
index 0000000000000..424d65a193c92
--- /dev/null
+++ b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr
@@ -0,0 +1,20 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/issue-52843-closure-constrain.rs:8:5
+   |
+LL |     fn _unused() -> Existential { String::new() }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String`
+   |
+note: previous use here
+  --> $DIR/issue-52843-closure-constrain.rs:6:1
+   |
+LL | / fn main() {
+LL | |     existential type Existential: Debug;
+LL | |     fn _unused() -> Existential { String::new() }
+LL | |
+LL | |     let null = || -> Existential { 0 };
+LL | |     println!("{:?}", null());
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_type.rs b/src/test/ui/existential_types/existential_type-pass.rs
similarity index 100%
rename from src/test/ui/existential_type.rs
rename to src/test/ui/existential_types/existential_type-pass.rs
diff --git a/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs
new file mode 100644
index 0000000000000..d964f2b74ff69
--- /dev/null
+++ b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(const_fn, generators, generator_trait, existential_type)]
+
+use std::ops::Generator;
+
+existential type GenOnce<Y, R>: Generator<Yield = Y, Return = R>;
+
+const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
+    move || {
+        yield yielding;
+
+        return returning;
+    }
+}
+
+const FOO: GenOnce<usize, usize> = const_generator(10, 100);
+
+fn main() {}
diff --git a/src/test/ui/existential-type/issue-58887.rs b/src/test/ui/existential_types/issue-58887.rs
similarity index 100%
rename from src/test/ui/existential-type/issue-58887.rs
rename to src/test/ui/existential_types/issue-58887.rs
diff --git a/src/test/ui/existential-type/issue-58887.stderr b/src/test/ui/existential_types/issue-58887.stderr
similarity index 100%
rename from src/test/ui/existential-type/issue-58887.stderr
rename to src/test/ui/existential_types/issue-58887.stderr
diff --git a/src/test/ui/existential-type/issue-60371.rs b/src/test/ui/existential_types/issue-60371.rs
similarity index 100%
rename from src/test/ui/existential-type/issue-60371.rs
rename to src/test/ui/existential_types/issue-60371.rs
diff --git a/src/test/ui/existential-type/issue-60371.stderr b/src/test/ui/existential_types/issue-60371.stderr
similarity index 100%
rename from src/test/ui/existential-type/issue-60371.stderr
rename to src/test/ui/existential_types/issue-60371.stderr
diff --git a/src/test/ui/existential_types/issue-60407.rs b/src/test/ui/existential_types/issue-60407.rs
new file mode 100644
index 0000000000000..52162c491b5c8
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60407.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(existential_type)]
+
+existential type Debuggable: core::fmt::Debug;
+
+static mut TEST: Option<Debuggable> = None;
+
+fn main() {
+    unsafe { TEST = Some(foo()) }
+}
+
+fn foo() -> Debuggable {
+    0u32
+}
diff --git a/src/test/ui/existential_types/issue-60564.rs b/src/test/ui/existential_types/issue-60564.rs
new file mode 100644
index 0000000000000..cb3914ddd1deb
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60564.rs
@@ -0,0 +1,26 @@
+#![feature(existential_type)]
+
+trait IterBits {
+    type BitsIter: Iterator<Item = u8>;
+    fn iter_bits(self, n: u8) -> Self::BitsIter;
+}
+
+existential type IterBitsIter<T, E, I>: std::iter::Iterator<Item = I>;
+//~^ ERROR could not find defining uses
+
+impl<T, E> IterBits for T
+where
+    T: std::ops::Shr<Output = T>
+        + std::ops::BitAnd<T, Output = T>
+        + std::convert::From<u8>
+        + std::convert::TryInto<u8, Error = E>,
+    E: std::fmt::Debug,
+{
+    type BitsIter = IterBitsIter<T, E, u8>;
+    fn iter_bits(self, n: u8) -> Self::BitsIter {
+    //~^ ERROR type parameter `E` is part of concrete type but not used
+        (0u8..n)
+            .rev()
+            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+    }
+}
diff --git a/src/test/ui/existential_types/issue-60564.stderr b/src/test/ui/existential_types/issue-60564.stderr
new file mode 100644
index 0000000000000..d8480b521570a
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60564.stderr
@@ -0,0 +1,25 @@
+error[E0601]: `main` function not found in crate `issue_60564`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-60564.rs`
+
+error: type parameter `E` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-60564.rs:20:49
+   |
+LL |       fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |  _________________________________________________^
+LL | |
+LL | |         (0u8..n)
+LL | |             .rev()
+LL | |             .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+LL | |     }
+   | |_____^
+
+error: could not find defining uses
+  --> $DIR/issue-60564.rs:8:1
+   |
+LL | existential type IterBitsIter<T, E, I>: std::iter::Iterator<Item = I>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/hygiene/duplicate_lifetimes.rs b/src/test/ui/hygiene/duplicate_lifetimes.rs
new file mode 100644
index 0000000000000..e7312b51dbcb8
--- /dev/null
+++ b/src/test/ui/hygiene/duplicate_lifetimes.rs
@@ -0,0 +1,19 @@
+// Ensure that lifetime parameter names are modernized before we check for
+// duplicates.
+
+#![feature(decl_macro, rustc_attrs)]
+
+#[rustc_macro_transparency = "semitransparent"]
+macro m($a:lifetime) {
+    fn g<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
+}
+
+#[rustc_macro_transparency = "transparent"]
+macro n($a:lifetime) {
+    fn h<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
+}
+
+m!('a);
+n!('a);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/duplicate_lifetimes.stderr b/src/test/ui/hygiene/duplicate_lifetimes.stderr
new file mode 100644
index 0000000000000..7aaea6ff24e39
--- /dev/null
+++ b/src/test/ui/hygiene/duplicate_lifetimes.stderr
@@ -0,0 +1,27 @@
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/duplicate_lifetimes.rs:8:14
+   |
+LL |     fn g<$a, 'a>() {}
+   |              ^^ declared twice
+...
+LL | m!('a);
+   | -------
+   | |  |
+   | |  previous declaration here
+   | in this macro invocation
+
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/duplicate_lifetimes.rs:13:14
+   |
+LL |     fn h<$a, 'a>() {}
+   |              ^^ declared twice
+...
+LL | n!('a);
+   | -------
+   | |  |
+   | |  previous declaration here
+   | in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0263`.
diff --git a/src/test/ui/hygiene/generic_params.rs b/src/test/ui/hygiene/generic_params.rs
new file mode 100644
index 0000000000000..9dc5adfce478a
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.rs
@@ -0,0 +1,104 @@
+// Ensure that generic parameters always have modern hygiene.
+
+// check-pass
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro, rustc_attrs, const_generics)]
+
+mod type_params {
+    macro m($T:ident) {
+        fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
+            (t1.clone(), t2 == t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($T:ident) {
+        fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($T:ident) {
+        fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    m!(T);
+    n!(T);
+    p!(T);
+}
+
+mod lifetime_params {
+    macro m($a:lifetime) {
+        fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($a:lifetime) {
+        fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($a:lifetime) {
+        fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    m!('a);
+    n!('a);
+    p!('a);
+}
+
+mod const_params {
+    macro m($C:ident) {
+        fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($C:ident) {
+        fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($C:ident) {
+        fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    m!(C);
+    n!(C);
+    p!(C);
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr
new file mode 100644
index 0000000000000..ecd228a5db5c8
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/generic_params.rs:6:37
+   |
+LL | #![feature(decl_macro, rustc_attrs, const_generics)]
+   |                                     ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.rs b/src/test/ui/hygiene/issue-61574-const-parameters.rs
new file mode 100644
index 0000000000000..dcfb42287d5cb
--- /dev/null
+++ b/src/test/ui/hygiene/issue-61574-const-parameters.rs
@@ -0,0 +1,32 @@
+// A more comprehensive test that const parameters have correctly implemented
+// hygiene
+
+// check-pass
+
+#![feature(const_generics)]
+
+use std::ops::Add;
+
+struct VectorLike<T, const SIZE: usize>([T; {SIZE}]);
+
+macro_rules! impl_operator_overload {
+    ($trait_ident:ident, $method_ident:ident) => {
+
+        impl<T, const SIZE: usize> $trait_ident for VectorLike<T, {SIZE}>
+        where
+            T: $trait_ident,
+        {
+            type Output = VectorLike<T, {SIZE}>;
+
+            fn $method_ident(self, _: VectorLike<T, {SIZE}>) -> VectorLike<T, {SIZE}> {
+                let _ = SIZE;
+                unimplemented!()
+            }
+        }
+
+    }
+}
+
+impl_operator_overload!(Add, add);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr
new file mode 100644
index 0000000000000..302b5fde8879c
--- /dev/null
+++ b/src/test/ui/hygiene/issue-61574-const-parameters.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61574-const-parameters.rs:6:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/hygiene/ty_params.rs b/src/test/ui/hygiene/ty_params.rs
deleted file mode 100644
index b296bfe598887..0000000000000
--- a/src/test/ui/hygiene/ty_params.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// ignore-pretty pretty-printing is unhygienic
-
-#![feature(decl_macro)]
-
-macro m($T:ident) {
-    fn f<T, $T>(t: T, t2: $T) -> (T, $T) {
-        (t, t2)
-    }
-}
-
-m!(T);
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
index c79b1873241c8..1ffb7f6fd4acd 100644
--- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
@@ -5,9 +5,7 @@
 // reject it. But I want to make sure that we continue to reject it
 // (under NLL) even when that conservaive check goes away.
 
-
 #![feature(bind_by_move_pattern_guards)]
-#![feature(nll)]
 
 fn main() {
     let mut b = &mut true;
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
index 3a10928981c8b..a8eb78b7cc007 100644
--- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
-  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:16:25
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25
    |
 LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
    |                         ^^                   - mutable borrow occurs due to use of `r` in closure
diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs
index 795a3fc210f6a..49e0dfaa3eb84 100644
--- a/src/test/ui/match/match-ref-mut-stability.rs
+++ b/src/test/ui/match/match-ref-mut-stability.rs
@@ -3,7 +3,7 @@
 
 // run-pass
 
-#![feature(nll, bind_by_move_pattern_guards)]
+#![feature(bind_by_move_pattern_guards)]
 
 // Test that z always point to the same temporary.
 fn referent_stability() {
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
index a3add8856dfa1..94e4a763866f6 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.rs
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -1,7 +1,7 @@
 // Test that we have enough false edges to avoid exposing the exact matching
 // algorithm in borrow checking.
 
-#![feature(nll, bind_by_move_pattern_guards)]
+#![feature(bind_by_move_pattern_guards)]
 
 fn guard_always_precedes_arm(y: i32) {
     let mut x;
@@ -41,18 +41,4 @@ fn guard_may_be_taken(y: bool) {
     };
 }
 
-fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
-    let r = &mut y.1;
-    // We don't actually test y.1 to select the second arm, but we don't want
-    // borrowck results to be based on the order we match patterns.
-    match y {
-        (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
-        (true, _) => {
-            r;
-            2
-        }
-        (false, _) => 3,
-    };
-}
-
 fn main() {}
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index d37c52444ac0d..b1e0fa739769a 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -16,19 +16,7 @@ LL |         true => {
 LL |             x;
    |             ^ value used here after move
 
-error[E0503]: cannot use `y.1` because it was mutably borrowed
-  --> $DIR/match-cfg-fake-edges.rs:49:17
-   |
-LL |     let r = &mut y.1;
-   |             -------- borrow of `y.1` occurs here
-...
-LL |         (false, true) => 1,
-   |                 ^^^^ use of borrowed `y.1`
-LL |         (true, _) => {
-LL |             r;
-   |             - borrow later used here
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0381, E0382, E0503.
+Some errors have detailed explanations: E0381, E0382.
 For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/match-cfg-fake-edges2.rs b/src/test/ui/nll/match-cfg-fake-edges2.rs
new file mode 100644
index 0000000000000..84c0dec2fe5cd
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges2.rs
@@ -0,0 +1,20 @@
+// Test that we have enough false edges to avoid exposing the exact matching
+// algorithm in borrow checking.
+
+#![feature(nll)]
+
+fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
+    let r = &mut y.1;
+    // We don't actually test y.1 to select the second arm, but we don't want
+    // borrowck results to be based on the order we match patterns.
+    match y {
+        (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
+        (true, _) => {
+            r;
+            2
+        }
+        (false, _) => 3,
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/match-cfg-fake-edges2.stderr b/src/test/ui/nll/match-cfg-fake-edges2.stderr
new file mode 100644
index 0000000000000..eab89658e79be
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges2.stderr
@@ -0,0 +1,15 @@
+error[E0503]: cannot use `y.1` because it was mutably borrowed
+  --> $DIR/match-cfg-fake-edges2.rs:11:17
+   |
+LL |     let r = &mut y.1;
+   |             -------- borrow of `y.1` occurs here
+...
+LL |         (false, true) => 1,
+   |                 ^^^^ use of borrowed `y.1`
+LL |         (true, _) => {
+LL |             r;
+   |             - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs
index 6e158713146f1..601c46ff86cc7 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.rs
+++ b/src/test/ui/nll/match-guards-partially-borrow.rs
@@ -5,9 +5,7 @@
 // Test that we don't allow mutating the value being matched on in a way that
 // changes which patterns it matches, until we have chosen an arm.
 
-
 #![feature(bind_by_move_pattern_guards)]
-#![feature(nll)]
 
 fn ok_mutation_in_guard(mut q: i32) {
     match q {
diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr
index 3d9b67b4ea660..b2951fd339da4 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.stderr
+++ b/src/test/ui/nll/match-guards-partially-borrow.stderr
@@ -1,5 +1,5 @@
 error[E0510]: cannot assign `q` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:59:13
+  --> $DIR/match-guards-partially-borrow.rs:57:13
    |
 LL |     match q {
    |           - value is immutable in match guard
@@ -8,7 +8,7 @@ LL |             q = true;
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `r` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:71:13
+  --> $DIR/match-guards-partially-borrow.rs:69:13
    |
 LL |     match r {
    |           - value is immutable in match guard
@@ -17,7 +17,7 @@ LL |             r = true;
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `t` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:95:13
+  --> $DIR/match-guards-partially-borrow.rs:93:13
    |
 LL |     match t {
    |           - value is immutable in match guard
@@ -26,7 +26,7 @@ LL |             t = true;
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot mutably borrow `x.0` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:109:22
+  --> $DIR/match-guards-partially-borrow.rs:107:22
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -35,7 +35,7 @@ LL |                 Some(ref mut r) => *r = None,
    |                      ^^^^^^^^^ cannot mutably borrow
 
 error[E0506]: cannot assign to `t` because it is borrowed
-  --> $DIR/match-guards-partially-borrow.rs:121:13
+  --> $DIR/match-guards-partially-borrow.rs:119:13
    |
 LL |         s if {
    |         - borrow of `t` occurs here
@@ -46,7 +46,7 @@ LL |         } => (), // What value should `s` have in the arm?
    |         - borrow later used here
 
 error[E0510]: cannot assign `y` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:132:13
+  --> $DIR/match-guards-partially-borrow.rs:130:13
    |
 LL |     match *y {
    |           -- value is immutable in match guard
@@ -55,7 +55,7 @@ LL |             y = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `z` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:143:13
+  --> $DIR/match-guards-partially-borrow.rs:141:13
    |
 LL |     match z {
    |           - value is immutable in match guard
@@ -64,7 +64,7 @@ LL |             z = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `a` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:155:13
+  --> $DIR/match-guards-partially-borrow.rs:153:13
    |
 LL |     match a {
    |           - value is immutable in match guard
@@ -73,7 +73,7 @@ LL |             a = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `b` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:166:13
+  --> $DIR/match-guards-partially-borrow.rs:164:13
    |
 LL |     match b {
    |           - value is immutable in match guard
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
new file mode 100644
index 0000000000000..e6c59fcf22dea
--- /dev/null
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
@@ -0,0 +1,15 @@
+// Here we test that the parser is able to recover in a situation like
+// `for ( $pat in $expr )` since that is familiar syntax in other languages.
+// Instead we suggest that the user writes `for $pat in $expr`.
+
+#![deny(unused)] // Make sure we don't trigger `unused_parens`.
+
+fn main() {
+    let vec = vec![1, 2, 3];
+
+    for ( elem in vec ) {
+        //~^ ERROR expected one of `)`, `,`, or `@`, found `in`
+        //~| ERROR unexpected closing `)`
+        const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
new file mode 100644
index 0000000000000..c160e646c28b3
--- /dev/null
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
@@ -0,0 +1,27 @@
+error: expected one of `)`, `,`, or `@`, found `in`
+  --> $DIR/recover-for-loop-parens-around-head.rs:10:16
+   |
+LL |     for ( elem in vec ) {
+   |                ^^ expected one of `)`, `,`, or `@` here
+
+error: unexpected closing `)`
+  --> $DIR/recover-for-loop-parens-around-head.rs:10:23
+   |
+LL |     for ( elem in vec ) {
+   |         --------------^
+   |         |
+   |         opening `(`
+   |         help: remove parenthesis in `for` loop: `elem in vec`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-for-loop-parens-around-head.rs:13:38
+   |
+LL |         const RECOVERY_WITNESS: () = 0;
+   |                                      ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
index 6e75977b5900e..e43c8541e6d6d 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
@@ -2,7 +2,7 @@
 // rust-lang/rust#2329), that starts passing with this feature in
 // place.
 
-// build-pass (FIXME(62277): could be check-pass?)
+// run-pass
 
 #![feature(bind_by_move_pattern_guards)]
 
@@ -12,6 +12,7 @@ fn main() {
     let (tx, rx) = channel();
     let x = Some(rx);
     tx.send(false);
+    tx.send(false);
     match x {
         Some(z) if z.recv().unwrap() => { panic!() },
         Some(z) => { assert!(!z.recv().unwrap()); },
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
index 34e8b0e14399e..fe1f699074735 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
@@ -1,5 +1,5 @@
 error: compilation successful
-  --> $DIR/feature-gate.rs:41:1
+  --> $DIR/feature-gate.rs:36:1
    |
 LL | / fn main() {
 LL | |     foo(107)
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
index 34e8b0e14399e..fe1f699074735 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
@@ -1,5 +1,5 @@
 error: compilation successful
-  --> $DIR/feature-gate.rs:41:1
+  --> $DIR/feature-gate.rs:36:1
    |
 LL | / fn main() {
 LL | |     foo(107)
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
index c2f6edee05fa6..7a7b1c253528f 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
@@ -1,5 +1,5 @@
 error[E0008]: cannot bind by-move into a pattern guard
-  --> $DIR/feature-gate.rs:33:16
+  --> $DIR/feature-gate.rs:28:16
    |
 LL |         A { a: v } if *v == 42 => v,
    |                ^ moves value into pattern guard
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
index 97f90f7762a41..69fce0bc775f7 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
@@ -6,7 +6,7 @@
 
 // gate-test-bind_by_move_pattern_guards
 
-// revisions: no_gate gate_and_2015 gate_and_2018 gate_and_znll gate_and_feature_nll
+// revisions: no_gate gate_and_2015 gate_and_2018
 
 // (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.)
 // ignore-compare-mode-nll
@@ -15,14 +15,9 @@
 
 #![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))]
 #![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))]
-#![cfg_attr(gate_and_znll, feature(bind_by_move_pattern_guards))]
-#![cfg_attr(gate_and_feature_nll, feature(bind_by_move_pattern_guards))]
-
-#![cfg_attr(gate_and_feature_nll, feature(nll))]
 
 //[gate_and_2015] edition:2015
 //[gate_and_2018] edition:2018
-//[gate_and_znll] compile-flags: -Z borrowck=mir
 
 struct A { a: Box<i32> }
 
@@ -43,5 +38,3 @@ fn main() {
 }
 //[gate_and_2015]~^^^ ERROR compilation successful
 //[gate_and_2018]~^^^^ ERROR compilation successful
-//[gate_and_znll]~^^^^^ ERROR compilation successful
-//[gate_and_feature_nll]~^^^^^^ ERROR compilation successful
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
index 40588ca331eba..eccb4e417b694 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
@@ -1,6 +1,6 @@
 #![feature(bind_by_move_pattern_guards)]
 
-// build-pass (FIXME(62277): could be check-pass?)
+// run-pass
 
 struct A { a: Box<i32> }
 
@@ -8,32 +8,38 @@ impl A {
     fn get(&self) -> i32 { *self.a }
 }
 
-fn foo(n: i32) {
+fn foo(n: i32) -> i32 {
     let x = A { a: Box::new(n) };
     let y = match x {
         A { a: v } if *v == 42 => v,
         _ => Box::new(0),
     };
+    *y
 }
 
-fn bar(n: i32) {
+fn bar(n: i32) -> i32 {
     let x = A { a: Box::new(n) };
     let y = match x {
         A { a: v } if x.get() == 42 => v,
         _ => Box::new(0),
     };
+    *y
 }
 
-fn baz(n: i32) {
+fn baz(n: i32) -> i32 {
     let x = A { a: Box::new(n) };
     let y = match x {
         A { a: v } if *v.clone() == 42 => v,
         _ => Box::new(0),
     };
+    *y
 }
 
 fn main() {
-    foo(107);
-    bar(107);
-    baz(107);
+    assert_eq!(foo(107), 0);
+    assert_eq!(foo(42), 42);
+    assert_eq!(bar(107), 0);
+    assert_eq!(bar(42), 42);
+    assert_eq!(baz(107), 0);
+    assert_eq!(baz(42), 42);
 }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
index bf387d01b6b2e..602a8e15cb180 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
@@ -1,4 +1,3 @@
-#![feature(nll)]
 #![feature(bind_by_move_pattern_guards)]
 
 enum VecWrapper { A(Vec<i32>) }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
index f6e4e5bd49bf8..c9e8fc8ee532b 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-across-arms.rs:8:36
+  --> $DIR/rfc-reject-double-move-across-arms.rs:7:36
    |
 LL |         VecWrapper::A(v) if { drop(v); false } => 1,
    |                                    ^ move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
index ba999e9b3a4a3..77252a1ce1569 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
@@ -1,4 +1,3 @@
-#![feature(nll)]
 #![feature(bind_by_move_pattern_guards)]
 
 struct A { a: Box<i32> }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
index ec133b028e8f8..a345022cee7c5 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-in-first-arm.rs:9:30
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30
    |
 LL |         A { a: v } if { drop(v); true } => v,
    |                              ^ move occurs because `v` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
diff --git a/src/tools/rustc-std-workspace-alloc/Cargo.toml b/src/tools/rustc-std-workspace-alloc/Cargo.toml
index 05df1fddc7f1c..ef7dc812af9d4 100644
--- a/src/tools/rustc-std-workspace-alloc/Cargo.toml
+++ b/src/tools/rustc-std-workspace-alloc/Cargo.toml
@@ -6,6 +6,7 @@ license = 'MIT OR Apache-2.0'
 description = """
 Hack for the compiler's own build system
 """
+edition = "2018"
 
 [lib]
 path = "lib.rs"
diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs
new file mode 100644
index 0000000000000..4a2e49fd1c3c7
--- /dev/null
+++ b/src/tools/tidy/src/edition.rs
@@ -0,0 +1,45 @@
+//! Tidy check to ensure that crate `edition` is '2018'
+//!
+
+use std::path::Path;
+
+fn filter_dirs(path: &Path) -> bool {
+    // FIXME: just use super::filter_dirs after the submodules are updated.
+    if super::filter_dirs(path) {
+        return true;
+    }
+    let skip = [
+        "src/doc/book/second-edition",
+        "src/doc/book/2018-edition",
+        "src/doc/book/ci/stable-check",
+        "src/doc/reference/stable-check",
+    ];
+    skip.iter().any(|p| path.ends_with(p))
+}
+
+fn is_edition_2018(mut line: &str) -> bool {
+    line = line.trim();
+    line == "edition = \"2018\"" || line == "edition = \'2018\'"
+}
+
+pub fn check(path: &Path, bad: &mut bool) {
+    super::walk(
+        path,
+        &mut |path| filter_dirs(path) || path.ends_with("src/test"),
+        &mut |entry, contents| {
+            let file = entry.path();
+            let filename = file.file_name().unwrap();
+            if filename != "Cargo.toml" {
+                return;
+            }
+            let has_edition = contents.lines().any(is_edition_2018);
+            if !has_edition {
+                tidy_error!(
+                    bad,
+                    "{} doesn't have `edition = \"2018\"` on a separate line",
+                    file.display()
+                );
+            }
+        },
+    );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index eca8001a9d2a1..e01184e3658b5 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -34,6 +34,7 @@ pub mod style;
 pub mod errors;
 pub mod features;
 pub mod cargo;
+pub mod edition;
 pub mod pal;
 pub mod deps;
 pub mod extdeps;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 3acb50547daf0..5deac52f08b5e 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -22,6 +22,7 @@ fn main() {
     style::check(&path, &mut bad);
     errors::check(&path, &mut bad);
     cargo::check(&path, &mut bad);
+    edition::check(&path, &mut bad);
     let collected = features::check(&path, &mut bad, verbose);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, collected, &mut bad);