about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteve Klabnik <steve@steveklabnik.com>2016-05-11 09:27:42 -0400
committerSteve Klabnik <steve@steveklabnik.com>2016-05-11 09:27:42 -0400
commit82c4f5915bfb330db596d06b74eb406d21845f9e (patch)
tree67172938ee476ca5630b4a81d94b5d0cbe542890
parentc5e0099a2085e3c3de68242d8550970d2ba88f12 (diff)
parent201d9ed0bbf05a8cc7015165a8f36bb87ef79a60 (diff)
downloadrust-82c4f5915bfb330db596d06b74eb406d21845f9e.tar.gz
rust-82c4f5915bfb330db596d06b74eb406d21845f9e.zip
Rollup merge of #33260 - mrmiywj:help-on-pattern-guard, r=guillaumegomez
add help on pattern guard
-rw-r--r--src/librustc_const_eval/diagnostics.rs61
1 files changed, 51 insertions, 10 deletions
diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs
index 4f5176f6b0b..c86c22b1e0f 100644
--- a/src/librustc_const_eval/diagnostics.rs
+++ b/src/librustc_const_eval/diagnostics.rs
@@ -215,22 +215,63 @@ match Some("hi".to_string()) {
 The variable `s` has type `String`, and its use in the guard is as a variable of
 type `String`. The guard code effectively executes in a separate scope to the
 body of the arm, so the value would be moved into this anonymous scope and
-therefore become unavailable in the body of the arm. Although this example seems
-innocuous, the problem is most clear when considering functions that take their
-argument by value.
+therefore becomes unavailable in the body of the arm.
 
-```compile_fail
+The problem above can be solved by using the `ref` keyword.
+
+```
 match Some("hi".to_string()) {
-    Some(s) if { drop(s); false } => (),
-    Some(s) => {}, // use s.
+    Some(ref s) if s.len() == 0 => {},
     _ => {},
 }
 ```
 
-The value would be dropped in the guard then become unavailable not only in the
-body of that arm but also in all subsequent arms! The solution is to bind by
-reference when using guards or refactor the entire expression, perhaps by
-putting the condition inside the body of the arm.
+Though this example seems innocuous and easy to solve, the problem becomes clear
+when it encounters functions which consume the value:
+
+```compile_fail
+struct A{}
+
+impl A {
+    fn consume(self) -> usize {
+        0
+    }
+}
+
+fn main() {
+    let a = Some(A{});
+    match a {
+        Some(y) if y.consume() > 0 => {}
+        _ => {}
+    }
+}
+```
+
+In this situation, even the `ref` keyword cannot solve it, since borrowed
+content cannot be moved. This problem cannot be solved generally. If the value
+can be cloned, here is a not-so-specific solution:
+
+```
+#[derive(Clone)]
+struct A{}
+
+impl A {
+    fn consume(self) -> usize {
+        0
+    }
+}
+
+fn main() {
+    let a = Some(A{});
+    match a{
+        Some(ref y) if y.clone().consume() > 0 => {}
+        _ => {}
+    }
+}
+```
+
+If the value will be consumed in the pattern guard, using its clone will not
+move its ownership, so the code works.
 "##,
 
 E0009: r##"