Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add help on pattern guard #33260

Merged
merged 1 commit into from
May 11, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions src/librustc_const_eval/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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##"
Expand Down