|
| 1 | +#### Note: this error code is no longer emitted by the compiler. |
| 2 | + |
| 3 | +Names bound in match arms retain their type in pattern guards. As such, if a |
| 4 | +name is bound by move in a pattern, it should also be moved to wherever it is |
| 5 | +referenced in the pattern guard code. Doing so however would prevent the name |
| 6 | +from being available in the body of the match arm. Consider the following: |
| 7 | + |
| 8 | +``` |
| 9 | +match Some("hi".to_string()) { |
| 10 | + Some(s) if s.len() == 0 => {}, // use s. |
| 11 | + _ => {}, |
| 12 | +} |
| 13 | +``` |
| 14 | + |
| 15 | +The variable `s` has type `String`, and its use in the guard is as a variable of |
| 16 | +type `String`. The guard code effectively executes in a separate scope to the |
| 17 | +body of the arm, so the value would be moved into this anonymous scope and |
| 18 | +therefore becomes unavailable in the body of the arm. |
| 19 | +The problem above can be solved by using the `ref` keyword. |
| 20 | + |
| 21 | +``` |
| 22 | +match Some("hi".to_string()) { |
| 23 | + Some(ref s) if s.len() == 0 => {}, |
| 24 | + _ => {}, |
| 25 | +} |
| 26 | +``` |
| 27 | + |
| 28 | +Though this example seems innocuous and easy to solve, the problem becomes clear |
| 29 | +when it encounters functions which consume the value: |
| 30 | + |
| 31 | +```compile_fail,E0507 |
| 32 | +struct A {} |
| 33 | +
|
| 34 | +impl A { |
| 35 | + fn consume(self) -> usize { |
| 36 | + 0 |
| 37 | + } |
| 38 | +} |
| 39 | +
|
| 40 | +fn main() { |
| 41 | + let a = Some(A{}); |
| 42 | + match a { |
| 43 | + Some(y) if y.consume() > 0 => {} |
| 44 | + _ => {} |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +In this situation, even the `ref` keyword cannot solve it, since borrowed |
| 50 | +content cannot be moved. This problem cannot be solved generally. If the value |
| 51 | +can be cloned, here is a not-so-specific solution: |
| 52 | + |
| 53 | +``` |
| 54 | +#[derive(Clone)] |
| 55 | +struct A {} |
| 56 | +
|
| 57 | +impl A { |
| 58 | + fn consume(self) -> usize { |
| 59 | + 0 |
| 60 | + } |
| 61 | +} |
| 62 | +
|
| 63 | +fn main() { |
| 64 | + let a = Some(A{}); |
| 65 | + match a{ |
| 66 | + Some(ref y) if y.clone().consume() > 0 => {} |
| 67 | + _ => {} |
| 68 | + } |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +If the value will be consumed in the pattern guard, using its clone will not |
| 73 | +move its ownership, so the code works. |
0 commit comments