about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2018-09-07 17:52:27 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2018-09-17 13:46:50 +0200
commit7d844e871c2b6d3c86adff53792fc36fdd338eb2 (patch)
treeb0a1c602705c20ee6689f2c4a6051e1666ccfcea
parentf1aefb48d2ec7ac38a66c964396a5aec729b7a28 (diff)
downloadrust-7d844e871c2b6d3c86adff53792fc36fdd338eb2.tar.gz
rust-7d844e871c2b6d3c86adff53792fc36fdd338eb2.zip
Add `feature(bind_by_move_pattern_guards)`.
Note it requires MIR-borrowck to be enabled to actually do anything.

Note also that it implicitly turns off our AST-based check for
mutation in guards.
-rw-r--r--src/librustc/ty/context.rs29
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs2
-rw-r--r--src/libsyntax/feature_gate.rs6
3 files changed, 35 insertions, 2 deletions
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6738267b5b8..43bd82118c6 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1436,10 +1436,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.queries.on_disk_cache.serialize(self.global_tcx(), encoder)
     }
 
+    /// This checks whether one is allowed to have pattern bindings
+    /// that bind-by-move on a match arm that has a guard, e.g.:
+    ///
+    /// ```rust
+    /// match foo { A(inner) if { /* something */ } => ..., ... }
+    /// ```
+    ///
+    /// It is separate from check_for_mutation_in_guard_via_ast_walk,
+    /// because that method has a narrower effect that can be toggled
+    /// off via a separate `-Z` flag, at least for the short term.
+    pub fn allow_bind_by_move_patterns_with_guards(self) -> bool {
+        self.features().bind_by_move_pattern_guards && self.use_mir_borrowck()
+    }
+
     /// If true, we should use a naive AST walk to determine if match
     /// guard could perform bad mutations (or mutable-borrows).
     pub fn check_for_mutation_in_guard_via_ast_walk(self) -> bool {
-        !self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard
+        // If someone passes the `-Z` flag, they're asking for the footgun.
+        if self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard {
+            return false;
+        }
+
+        // If someone requests the feature, then be a little more
+        // careful and ensure that MIR-borrowck is enabled (which can
+        // happen via edition selection, via `feature(nll)`, or via an
+        // appropriate `-Z` flag) before disabling the mutation check.
+        if self.allow_bind_by_move_patterns_with_guards() {
+            return false;
+        }
+
+        return true;
     }
 
     /// If true, we should use the AST-based borrowck (we may *also* use
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index bf878145e1f..507019559fc 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -537,7 +537,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                              "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 {
+        } else if has_guard && !cx.tcx.allow_bind_by_move_patterns_with_guards() {
             struct_span_err!(cx.tcx.sess, p.span, E0008,
                       "cannot bind by-move into a pattern guard")
                 .span_label(p.span, "moves value into pattern guard")
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 7266d807d3b..922e773f144 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -515,6 +515,12 @@ declare_features! (
 
     // Self struct constructor  (RFC 2302)
     (active, self_struct_ctor, "1.31.0", Some(51994), None),
+
+    // allow mixing of bind-by-move in patterns and references to
+    // those identifiers in guards, *if* we are using MIR-borrowck
+    // (aka NLL). Essentially this means you need to be on
+    // edition:2018 or later.
+    (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None),
 );
 
 declare_features! (