捕捉時の型推論

Rustはたいていの場合、型アノテーションなしでも変数を捕捉する方法を臨機応変に選択してくれますが、関数を書く場合にはこの曖昧さは許されません。引数のパラメータとしてクロージャを取る場合、そのクロージャの完全な型はいくつかのtraitsの中の1つを使って明示されなければなりません。どれが使われるかは、捕捉された値でクロージャが何をするかによって決まります。制限の少ない順に並べると、下記の通りです。

  • Fn:参照(&T)によって捕捉するクロージャ
  • FnMut:ミュータブルな参照(&mut T)によって捕捉するクロージャ
  • FnOnce:値(T)によって捕捉するクロージャ

変数ごとに、コンパイラは可能な限り制約の少ない方法でその変数を捕捉します。

例えば、FnOnceというアノテーションの付けられたパラメータを考えてみましょう。これはそのクロージャが&T&mut TもしくはTどれか で捕捉することを指定するものですが、コンパイラは捕捉した変数がそのクロージャの中でどのように使用されるかに基づき、最終的に捕捉する方法を選択することになります。

これは、もし移動が可能であれば、いずれの種類の借用であっても同様に可能だからです。その逆は正しくないことに注意してください。パラメータがFnとしてアノテーションされている場合、変数を&mut TTで捕捉することは許可されません。しかし&Tは許可されます。

以下の例で、FnFnMut、およびFnOnceを入れ替えて、何が起こるのかを見てみましょう。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

参照

std::mem::drop, Fn, FnMut, ジェネリクス, where, FnOnce