Summary

Rust currently forbids pattern guards on match

一致する、マッチさせる
arms with move-bound variables.
変数、ストレージ
Allowing
許可する、可能にする
them would increase the applicability of pattern guards.

Motivation

Currently, if you attempt to use guards on a match

一致する、マッチさせる
arm with a move-bound variable,
変数、ストレージ
e.g.

#![allow(unused)] fn main() { struct A { a: Box<int> } fn foo(n: int) { let x = A { a: box n }; let y = match x { A { a: v } if *v == 42 => v, _ => box 0 }; } }

you get an error:

test.rs:6:16: 6:17 error: cannot bind by-move into a pattern guard test.rs:6 A { a: v } if *v == 42 => v, ^

This should be permitted

許す
in cases where the guard only accesses the moved value by reference
参照
or copies out of derived paths.

This allows

許可する、可能にする
for succinct code with less pattern matching
一致する、マッチさせる
duplication and a minimum
最小の
number of copies at runtime. The lack of this feature was encountered
出会う
by @kmcallister when developing Servo's new HTML 5 parser.

Detailed design
設計(する)

This change requires all occurrences of move-bound pattern variables

変数、ストレージ
in the guard to be treated
取り扱う
as paths to the values being matched before they are moved, rather than the moved values themselves. Any moves of matched values into the bound
制限する、結び付けられて
variables
変数、ストレージ
would occur
起こる
on the control
制御する
flow edge between the guard and the arm's expression.
There would be no changes to the handling of reference-bound pattern variables.
変数、ストレージ

The arm would be treated

取り扱う
as its own nested scope with respect to borrows, so that pattern-bound variables
変数、ストレージ
would be able to be borrowed and dereferenced freely in the guard, but these borrows would not be in scope in the arm's expression.
Since the guard dominates the expression
and the move into the pattern-bound variable,
変数、ストレージ
moves of either the match's head expression
or any pattern-bound variables
変数、ストレージ
in the guard would trigger
引き起こす
an error.

The following examples would be accepted:

受け付ける、受理する

#![allow(unused)] fn main() { struct A { a: Box<int> } impl A { fn get(&self) -> int { *self.a } } fn foo(n: int) { let x = A { a: box n }; let y = match x { A { a: v } if *v == 42 => v, _ => box 0 }; } fn bar(n: int) { let x = A { a: box n }; let y = match x { A { a: v } if x.get() == 42 => v, _ => box 0 }; } fn baz(n: int) { let x = A { a: box n }; let y = match x { A { a: v } if *v.clone() == 42 => v, _ => box 0 }; } }

This example would be rejected, due to a double

2倍にする
move of v:

#![allow(unused)] fn main() { struct A { a: Box<int> } fn foo(n: int) { let x = A { a: box n }; let y = match x { A { a: v } if { drop(v); true } => v, _ => box 0 }; } }

This example would also be rejected, even though there is no use of the move-bound variable

変数、ストレージ
in the first arm's expression,
since the move into the bound
制限する、結び付けられて
variable
変数、ストレージ
would be moving the same value a second time:

#![allow(unused)] fn main() { enum VecWrapper { A(Vec<int>) } fn foo(x: VecWrapper) -> uint { match x { A(v) if { drop(v); false } => 1, A(v) => v.len() } } }

There are issues with mutation of the bound

制限する、結び付けられて
values, but that is true without the changes proposed by this RFC, e.g. Rust issue #14684. The general
一般
approach to resolving that issue should also work with these proposed changes.

This would be implemented

実装する
behind a feature(bind_by_move_pattern_guards) gate until we have enough experience with the feature to remove the feature gate.

Drawbacks

The current error message makes it more clear what the user is doing wrong, but if this change is made the error message for an invalid use of this feature (even if it were accidental) would indicate

指し示す
a use of a moved value, which might be more confusing.

This might be moderately difficult to implement

実装する
in rustc.

Alternatives
代わりのもの、選択肢

As far as I am aware, the only workarounds for the lack of this feature are to manually expand the control

制御する
flow of the guard (which can quickly get messy) or use unnecessary copies.

Unresolved questions

This has nontrivial interaction with guards in arbitrary

任意の
patterns as proposed in #99.