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/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/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/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/cargotest/main.rs b/src/tools/cargotest/main.rs
index 729287faeb628..f6aaaa5c6eadb 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -50,7 +50,7 @@ const TEST_REPOS: &'static [Test] = &[
     Test {
         name: "servo",
         repo: "https://github.com/servo/servo",
-        sha: "987e376ca7a4245dbc3e0c06e963278ee1ac92d1",
+        sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
         lock: None,
         // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
         // This takes much less time to build than all of Servo and supports stable Rust.