Rollup merge of #33260 - mrmiywj:help-on-pattern-guard, r=guillaumegomez
add help on pattern guard
This commit is contained in:
commit
82c4f5915b
1 changed files with 51 additions and 10 deletions
|
@ -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
|
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
|
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
|
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
|
therefore becomes unavailable in the body of the arm.
|
||||||
innocuous, the problem is most clear when considering functions that take their
|
|
||||||
argument by value.
|
|
||||||
|
|
||||||
```compile_fail
|
The problem above can be solved by using the `ref` keyword.
|
||||||
|
|
||||||
|
```
|
||||||
match Some("hi".to_string()) {
|
match Some("hi".to_string()) {
|
||||||
Some(s) if { drop(s); false } => (),
|
Some(ref s) if s.len() == 0 => {},
|
||||||
Some(s) => {}, // use s.
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The value would be dropped in the guard then become unavailable not only in the
|
Though this example seems innocuous and easy to solve, the problem becomes clear
|
||||||
body of that arm but also in all subsequent arms! The solution is to bind by
|
when it encounters functions which consume the value:
|
||||||
reference when using guards or refactor the entire expression, perhaps by
|
|
||||||
putting the condition inside the body of the arm.
|
```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##"
|
E0009: r##"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue