これは私が実行しようとしているコードです:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
if arg1.is_none() {
return 0;
}
let integer = arg1.unwrap();
*integer
}
fn main() {
let integer = 42;
my_fn(&Some(Box::new(integer)));
}
( Rust遊び場 )
以前のバージョンのRustで次のエラーが発生します。
error[E0507]: cannot move out of borrowed content
--> src/main.rs:5:19
|
5 | let integer = arg1.unwrap();
| ^^^^ cannot move out of borrowed content
そして、より現代的なバージョンでは:
error[E0507]: cannot move out of `*arg1` which is behind a shared reference
--> src/main.rs:5:19
|
5 | let integer = arg1.unwrap();
| ^^^^
| |
| move occurs because `*arg1` has type `std::option::Option<std::boxed::Box<i32>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `arg1.as_ref()`
ボローチェッカーの問題に関するドキュメントはすでにたくさんあるようですが、それを読んだ後でも、問題を理解することはできません。
なぜこれがエラーなのですか、どうすれば解決できますか?
Option::unwrap()
オプションを消費します。つまり、値でオプションを受け入れます。ただし、値はなく、参照のみがあります。それがエラーの原因です。
あなたのコードは慣用的に次のように書かれるべきです:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
match arg1 {
Some(b) => **b,
None => 0,
}
}
fn main() {
let integer = 42;
my_fn(&Some(Box::new(integer)));
}
( Rust遊び場 )
または、 Option::as_ref
または Option::as_mut
と組み合わせて Option::map_or
のようなOption
コンビネータを使用できます。 =、Shepmasterが提案したように:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
arg1.as_ref().map_or(0, |n| **n)
}
このコードは、i32
が自動的にコピー可能であるという事実を使用しています。 Box
内の型がCopy
でない場合、値ごとに内部値を取得することはできません。クローンを作成するか、を返すことしかできません。たとえば、次のような参照:
fn my_fn2(arg1: &Option<Box<i32>>) -> &i32 {
arg1.as_ref().map_or(&0, |n| n)
}
オプションへの不変の参照しかないため、その内容への不変の参照のみを返すことができます。 Rustは、リテラル0
を静的な値に昇格させて、入力値がない場合にそれを返すことができるようにするのに十分賢いです。