Skip to content

Commit f9966df

Browse files
committed
Rollup merge of rust-lang#33260 - mrmiywj:help-on-pattern-guard, r=guillaumegomez
add help on pattern guard
2 parents 04308ce + 201d9ed commit f9966df

File tree

1 file changed

+51
-10
lines changed

1 file changed

+51
-10
lines changed

src/librustc_const_eval/diagnostics.rs

+51-10
Original file line numberDiff line numberDiff line change
@@ -215,22 +215,63 @@ match Some("hi".to_string()) {
215215
The variable `s` has type `String`, and its use in the guard is as a variable of
216216
type `String`. The guard code effectively executes in a separate scope to the
217217
body of the arm, so the value would be moved into this anonymous scope and
218-
therefore become unavailable in the body of the arm. Although this example seems
219-
innocuous, the problem is most clear when considering functions that take their
220-
argument by value.
218+
therefore becomes unavailable in the body of the arm.
221219
222-
```compile_fail
220+
The problem above can be solved by using the `ref` keyword.
221+
222+
```
223223
match Some("hi".to_string()) {
224-
Some(s) if { drop(s); false } => (),
225-
Some(s) => {}, // use s.
224+
Some(ref s) if s.len() == 0 => {},
226225
_ => {},
227226
}
228227
```
229228
230-
The value would be dropped in the guard then become unavailable not only in the
231-
body of that arm but also in all subsequent arms! The solution is to bind by
232-
reference when using guards or refactor the entire expression, perhaps by
233-
putting the condition inside the body of the arm.
229+
Though this example seems innocuous and easy to solve, the problem becomes clear
230+
when it encounters functions which consume the value:
231+
232+
```compile_fail
233+
struct A{}
234+
235+
impl A {
236+
fn consume(self) -> usize {
237+
0
238+
}
239+
}
240+
241+
fn main() {
242+
let a = Some(A{});
243+
match a {
244+
Some(y) if y.consume() > 0 => {}
245+
_ => {}
246+
}
247+
}
248+
```
249+
250+
In this situation, even the `ref` keyword cannot solve it, since borrowed
251+
content cannot be moved. This problem cannot be solved generally. If the value
252+
can be cloned, here is a not-so-specific solution:
253+
254+
```
255+
#[derive(Clone)]
256+
struct A{}
257+
258+
impl A {
259+
fn consume(self) -> usize {
260+
0
261+
}
262+
}
263+
264+
fn main() {
265+
let a = Some(A{});
266+
match a{
267+
Some(ref y) if y.clone().consume() > 0 => {}
268+
_ => {}
269+
}
270+
}
271+
```
272+
273+
If the value will be consumed in the pattern guard, using its clone will not
274+
move its ownership, so the code works.
234275
"##,
235276

236277
E0009: r##"

0 commit comments

Comments
 (0)