diff options
| author | Steve Klabnik <steve@steveklabnik.com> | 2016-05-11 09:27:42 -0400 |
|---|---|---|
| committer | Steve Klabnik <steve@steveklabnik.com> | 2016-05-11 09:27:42 -0400 |
| commit | 82c4f5915bfb330db596d06b74eb406d21845f9e (patch) | |
| tree | 67172938ee476ca5630b4a81d94b5d0cbe542890 | |
| parent | c5e0099a2085e3c3de68242d8550970d2ba88f12 (diff) | |
| parent | 201d9ed0bbf05a8cc7015165a8f36bb87ef79a60 (diff) | |
| download | rust-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.rs | 61 |
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##" |
