ちょっとはまったのでメモ
struct A {
foo: Vec<i32>,
bar: Vec<bool>,
}
こんな構造体があったとする。
普通、A
の所有権を分解して foo
と bar
にしたいときは
fn xxx(x: A) -> (Vec<i32>, Vec<bool>) {
let A { foo, bar } = x;
(foo, bar)
}
とやれば良い(この例だともっと簡単に書ける気もするけど)
一方、Box<A>
から foo
と bar
に分解したい場合は話が変わってくる。
fn error1(x: Box<A>) -> (Vec<i32>, Vec<bool>) {
(x.foo, x.bar)
}
fn error2(x: Box<A>) -> (Vec<i32>, Vec<bool>) {
let A { foo, bar } = *x;
(foo, bar)
}
これらは両方共コンパイルできない。
人間から見ると,Box<A>
は A
の所有権を持っているのだから、A
-> foo/bar
に分解できるなら Box<A>
も同様にできる気がする。
実際にはこのようにするとコンパイルが通る。
fn success(x: Box<A>) -> (Vec<i32>, Vec<bool>) {
let x = *x;
let A { foo, bar } = x;
(foo, bar)
}
うーん、エラーになるケースだと Deref
トレイトの機能を経由している感じになるのかな?
Deref
経由で foo
の所有権をとるとその時点で Box<A>
の所有権は奪われちゃうから bar
の所有権が取れないということなのだと想像した。
success
のようなコードが突然出てきたら混乱しそうだ。