Rust パターンマッチの変数束縛とコンストラクタ/定数の区別
パターンマッチを持つ言語では、変数束縛とコンストラクタ/定数が構文上曖昧である場合がある。Rustでは以下の規則に従っている。
- 以下のように、構文的にパスであるとわかる場合は、常にコンストラクタ/定数とみなす。
::
を含んでいる場合。 (::A
,self::A
,<T as Trait>::X
など){}
を後続する場合。 (A {}
など)()
を後続する場合。 (A()
など)..
/...
/..=
などの一部である場合。 (FOO_MIN .. FOO_MAX
など)!
を後続する場合。 (your_macro_expanding_to_a_pattern!()
など)
- 反駁不可文脈では常に変数束縛とみなす。反駁不可文脈かどうかは以下のように定義される。
match
,if let
,while let
のパターンは反駁可能でもよい。let
,for
, 関数の引数部のパターンは反駁不可でなければならない。
- asパターン (
ident @ pat
) の左辺は常に変数束縛とみなす。 ref ident
やmut ident
のように束縛モードが指定されていれば常に変数束縛とみなす。- 上記以外で、スコープ内のアイテム名と一致し、それらが以下のいずれかだった場合はコンストラクタ/定数とみなす。
const
定数static
静的変数- ユニット形式の
struct
(struct A;
のように宣言されるもの) enum
のバリアントでユニット形式のもの (例:use E::A; enum E { A; }
)
- 上記以外では、変数束縛とみなす。
また、上記の条件で変数束縛とみなされたが、アイテム名と一致するときはエラーとなる。
例えば以下のようになる。
struct A; fn main() { // let A = A; // Error let self::A = A; // OK match A { A => {}}; // OK // match A { ref A => {}}; // Error // match A { A @ A => {}}; // Error }