回答編集履歴
1
説明を少し追加しました
answer
CHANGED
@@ -25,7 +25,7 @@
|
|
25
25
|
|
26
26
|
関連関数`new()`の戻り値型は`Self`(`Worker<F>`)ですので、ジェネリクスの型パラメータ`F`を含んでます。そして`F`の具体的な型は`new()`を呼び出す側で決まります。つまり、`new()`は呼び出し側が求める、どんな`Worker<何かの型>`でも返せなければなりません。
|
27
27
|
|
28
|
-
一方、`|x| func_a(x)`は具体的な型を持ちます。もしこれがコンパイルできたとすると、`new()`の戻り値は`Worker<具体的な一つの型>`になり、`Self`と矛盾してしまいます。
|
28
|
+
一方、`|x| func_a(x)`は具体的な型を持ちます。もしこれがコンパイルできたとすると、`new()`の戻り値は`Worker<具体的な一つの型>`になり、`Self`と矛盾してしまいます。そのため型不一致のエラーE0308になるわけです。
|
29
29
|
|
30
30
|
解決法としては2つあると思います。
|
31
31
|
1. クロージャを`new()`の外側から与える
|
@@ -49,6 +49,8 @@
|
|
49
49
|
|
50
50
|
## 2. `Worker.func`を具体的な型にする
|
51
51
|
|
52
|
+
`Worker`構造体の`func`フィールドの型を、ジェネリクスの型パラメータではなく、具体的な型にします。
|
53
|
+
|
52
54
|
`|x| func_a(x)`は具体的な型を持ちますが、コンパイラが内部的に作成する匿名型なので、ソースコードで型を指定することはできません。
|
53
55
|
|
54
56
|
しかし、このクロージャをよく見ると自由変数がありません(外側にある変数を環境にキャプチャしていません) こういうクロージャは普通の関数と同じように扱えますので、関数ポインタ型`fn(&[u8]) -> Vec<u8>`へと型強制できます。
|
@@ -63,7 +65,7 @@
|
|
63
65
|
impl Worker {
|
64
66
|
fn new() -> Self {
|
65
67
|
Self {
|
66
|
-
// 自由変数を持たないクロージャは関数ポインタ型に型強制できる
|
68
|
+
// 自由変数を持たないクロージャは関数ポインタ型に型強制できる
|
67
69
|
func: |x| func_a(x),
|
68
70
|
}
|
69
71
|
}
|