【Rust】クロージャのOption型でNoneを作る場合の型指定

最近Rustを触り始めて、クロージャをOption型にした時の扱い方で詰まったので、その辺りを色々といじくり回してみました。
おそらく、今後Rustを扱う場合にも同様のことで詰まりそうなので、残しておきます。
今回の投稿は、クロージャの型についての調査です。Rustの用語周りについて正確に把握していなため、変な部分があるかもしれません。
※Rustのバージョンは1.24.0 (stable)です。
# クロージャの型指定
このような関数にクロージャを渡すことを考えます。

```rust
fn exec_opt_fnonce<T, U, F>(a: T, opt: Option<F>) -> U
where U: Default, F: FnOnce(T) -> U {
    match opt {
        Some(f) => f(a),
        None => Default::default()
    }
}
```

上記の関数は、`Some`の場合は、引数aをクロージャの引数に渡して、クロージャの戻り値をそのまま返し、`None`の場合は初期値を返す関数です。
※Defaultトレイトは`Default::default()`で初期値を返せるトレイトです。
[std::default::Default - Rust](https://doc.rust-lang.org/std/default/trait.Default.html "std::default::Default - Rust")

## 実装してみる
この関数を実行するコードを作成します。

```rust
println!("exec_opt_fnonce Some : {}", exec_opt_fnonce(1, Some(|i| i + 1)));
```

実行結果は

```
exec_opt_fnonce Some : 2
```

問題なく動きます。では、`Some`ではなく`None`を渡す場合はどうでしょう。

```rust
println!("exec_opt_fnonce None : {}", exec_opt_fnonce(1, None));
```

コンパイルが通りません。「型がわからねえよ！」と怒られます。
では、適当にキャストします。

```rust
println!("exec_opt_fnonce None : {}", exec_opt_fnonce(1, None as Option<FnOnce(i32) -> i32>));
```

コンパイルが通りません。「サイズがわからねえよ！」と怒られます。変数や引数はサイズが決まっていないといけないようです。
[サイズ不定形](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/unsized-types.html "サイズ不定形")
実際にクロージャを作るわけではないのに、どうやってサイズを決められるのでしょうか？
ここが詰まったポイントだったのですが、「サイズ不定型でも、その参照はサイズが決まっている」ということで、クロージャを参照にしてみます。

```rust
println!("exec_opt_fnonce None : {}", exec_opt_fnonce(1, None as Option<&FnOnce(i32) -> i32>));
```

進展が有りましたが、まだコンパイルは通りません。以下のエラーメッセージが表示されます。

```
error[E0277]: the trait bound `std::ops::FnOnce(i32) -> i32: std::ops::Fn<(i32,)>` is not satisfied
```

指定すべき型は、`FnOnce`ではなく`Fn`なのでしょうか？

```rust
println!("exec_opt_fnonce None : {}", exec_opt_fnonce(1, None as Option<&Fn(i32) -> i32>));
```

無事に通りました。実行結果も想定どおり初期値が返ってきています。

```
exec_opt_fnonce None : 0
```

どうやら、`Fn`の参照を指定すると良いようです。

## 疑問点
無事想定通りの動作となりましたが、いくつか疑問も残っています。

1. ジェネリックの境界で`FnOnce`を指定しているのに、なぜ`Fn`を渡さなければいけないのか。
2. ジェネリックの境界で参照を指定してないのに、なぜ参照(`&Fn(i32) -> i32`)を渡せるのか。

1の疑問については、下記のリンクを参考に推測してみました。
[トレイトオブジェクト](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/trait-objects.html "トレイトオブジェクト")
[Rustのクロージャ3種を作って理解する | κeenのHappy Hacκing Blog](http://keens.github.io/blog/2016/10/10/rustnokuro_ja3tanewotsukutterikaisuru/ "Rustのクロージャ3種を作って理解する")
~~`FnOnce`はトレイトのメソッドで`Self`を使用しているため、トレイトオブジェクトになれない。
`Fn`はトレイトのメソッドで`&Self`を使用しているため、トレイトオブジェクトになれる。
`FnOnce`と`Fn`は、`FnOnce`⊃`Fn`の関係なので、`&Fn`なら`FnOnce`の条件でも渡せる…ということなのでしょうか？
これに関してはただの推測なので、鵜呑みにしないでください。~~

2の疑問については、追加で実験してみました。

```rust
let f = |i:i32| i;
//let a: Option<&Fn(i32) -> i32> = Some(f); // エラー Some(&f)ならOK
let b: Option<&Fn(i32) -> i32> = None; // OK
exec_opt_fnonce(1, Some(&f)); // OK
exec_opt_fnonce(1, Some(f)); // OK
exec_opt_fnonce(1, b); // OK
```

上の結果を見るに、`&Fn`と`Fn`は別の型だが、境界条件の`FnOnce`は`Fn`も`&Fn`も通すということみたいですね。（境界条件`FnMut`、`Fn`も同様）

これ以上追うと泥沼にはまりそうなので、ひとまず「そういうもの」として納得しておくことにします。

### 疑問の解答　※追記（2018/02/19）
コメントで疑問に答えていただきましたので、追記します。
[Trait std::ops::FnOnce - Rust](https://doc.rust-lang.org/beta/std/ops/trait.FnOnce.html#implementors "Trait std::ops::FnOnce - Rust")

```rust
impl<'a, A, F> FnOnce<A> for &'a F where
    F: Fn<A> + ?Sized,   type Output = <F as FnOnce<A>>::Output;
```

`FnOnce`トレイトが上記のように`&Fn`に対して実装されているため、`&Fn`は指定できる、`&FnOnce`に対しては無いため指定できないという理由みたいです。
ちなみに、`FnOnce`は`&mut FnMut`に対しても実装があるため

```rust
exec_opt_fnonce(1, None as Option<&mut FnMut(i32) -> i32>)
```

でもエラーにはならないですね。

## `Option<&F>`、`Option<&mut F>`の場合
クロージャの参照やミュータブルな参照が要求されている場合も同様に

```rust
// Option<&F> where F : Fn(i32) -> i32
None as Option<&&Fn(i32) -> i32>

// Option<&mut F> where F : FnMut(i32) -> i32
None as Option<&mut &Fn(i32) -> i32>
```

のように、参照の参照にすることでNoneを作ることができます。
おそらく、Option以外の列挙型に関しても同様でしょう。

## プリミティブ型 `fn`　※追記（2018/02/20）
コメントで教えていただいたことを追記します。
~~クロージャ（関数ポインタ）のプロミティブ型は`fn`とのことです。~~

[Primitive Type fn - Rust](https://doc.rust-lang.org/beta/std/primitive.fn.html "Primitive Type fn - Rust")

関数ポインタのプロミティブ型`fn`は、_unsafeではない場合は_`Fn``FnMut``FnOnce`を実装しているので、以下のように書いても問題ないです。

```rust
exec_opt_fnonce(1, None as Option<fn(i32) -> i32>);
```

~~クロージャのプリミティブ型がわかっていれば、難しく考えなくてもよかったですね…。こちらのほうが型を指定するだけなので、考え方がシンプルです。~~
考え方は前述の`&Fn`の例と同じでした。今回挙げた例のように型はとりえあずなんでもいい場合は、`&Fn`か`fn`を指定すれば問題なさそうです。
また、以下の書き方も出来ます。


```rust
exec_opt_fnonce(1, None::<fn(i32) -> i32>); // Option::None::<fn(i32) -> i32>
```

わからなかったのでキャストで書いていたのですが、ジェネリックの型もこう指定できるのですね。
勉強になりました。