次のようなコードを考えます。
rust
1struct S { 2 a: Box<i32>, 3 b: Box<i32>, 4} 5 6fn main() { 7 let s = S { 8 a: Box::new(1), 9 b: Box::new(2), 10 }; 11 let _closure = || { let _sa = s.a; }; // エラー 12}
このとき エラー
の行で
error[E0507]: cannot move out of captured outer variable in an `Fn` closure --> /home/dai/workspace/daily/2018/0301/junk03-51-57.rs:11:35 | 11 | let _closure = || { let _sa = s.a; }; | ^-- | | | cannot move out of captured outer variable in an `Fn` closure | help: consider using a reference instead: `&s.a` error: aborting due to previous error
とエラーになります。コンパイラは s
の借用で済むと判断して、クロージャに Fn まで実装したところ、 Fn クロージャの中で借用した値をムーブしようとしているためにエラーになっているようです。
しかし、 s.a
をムーブしようとした段階で s
のムーブが必要な (あるいは _sa
に相当する形で s.a
だけを部分的にムーブする必要がある) ことはコンパイラには分かると思います。そういう形で環境に所有権を移してしまって FnOnce 止まりに推論すればよい気がします。さらに不思議なことは、move
をつけて明示的にムーブを指示しても s
をムーブしてくれませんでした。
このクロージャを次のように明示的に s
を取るように書き換えると
rust
1let _closure = || { 2 let s = s; 3 let _sa = s.a; 4};
無事コンパイルが通るようになりました。
このような挙動になっているのは何故なのでしょうか。
s.a
だけをムーブしようとして、間違えて s
ごとムーブしてしまうことを防ぐため?
それを防ぐ意味も分かりませんが、だとすれば前述の通り部分的にムーブすることでも達成できると思います。
あるいは、このようにしなければ都合の悪いことがあるのでしょうか。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/01 00:10