私の質問方法を訂正してくれてありがとう。コードをコンパイル可能にするためにいくつかの改訂を行いました。`Into`ジェネリックを扱うときの寿命の問題
use std::marker::PhantomData;
struct Brace {
x: i32,
}
impl Brace {
fn transform(&self, n: i32) -> Devil {
Devil {
hp: self.x + n,
weapon: None,
}
}
}
struct Bar<'a> {
tasty: &'a str,
}
struct Foo<'a, B>
where B: 'a + Into<Bar<'a>>
{
brace: Brace,
buz: Option<B>, // buz is of generic type B, and is able to be turned into bar.
phantom: PhantomData<&'a B>, // A marker that is used to resolve 'unused lifetime parameter a'
}
impl<'a, B: Into<Bar<'a>>> Foo<'a, B> {
fn transform_and_arm(self) {
// line B
let brace1: Brace = self.brace;
let mut devil: Devil = brace1.transform(12345); // line A
let buz = self.buz.unwrap();
// Before this line, it passes the compiler.
// Uncommenting the following line causes compiler to argue that the brace1 at line A doesn't live long enough. It says that borrowed value must be valid for the lifetime 'a as defined on the body at line B, but the borrowed value only lives until line C.
// devil = devil.arm(buz);
// Although adding the above line fails, making the weapon directly won't cause the compiler to complain.
// Uncommenting the following line passes compiler.
// let weapon = buz.into();
// The compiler stops the devil from arming itself before I even try to write the following line.
// devil.slay_the_world();
} // line C
}
struct Devil<'a> {
hp: i32,
weapon: Option<Bar<'a>>,
}
impl<'a> Devil<'a> {
fn arm<B: Into<Bar<'a>>>(mut self, biu: B) -> Devil<'a> {
self.weapon = Some(biu.into());
self
}
fn slay_the_world(self) {
unimplemented!()
}
}
transform_and_arm()
方法はbrace
とbuz
を奪うことによってFoo
のインスタンスを消費するように設計されています。 brace.transform()
を呼び出してbrace
をDevil
にします。それはbuz.unwrap()
と悪魔を与えることによって悪魔を強化します。
問題は、let weapon = buz.into();
を呼び出すことは合法ですが、devil = devil.arm(buz);
を呼び出すと生涯の問題が発生することです。
問題は生涯に関係しているようです。悪魔のためのものがなければ、これらの問題はすべて消滅するでしょう。
ありがとうございました!それは明らか
&self
と返さDevil
は無関係な寿命を有することを確認するためにtransform
に注釈を付け、明示的に、問題を解決するためにテストコードで同じ変更を行った後でコンパイルされ、問題の原因を理解し始めます。しかし、実際の状況は、 'transform()'がサードパーティライブラリ(実際にはhyper :: client :: Client :: get())として提供される関数であるということです。私は 'transform_and_arm(self)'がなぜうまくいかないのか不思議です。悪ふざけはC行まで生きているので、FooはC行の後に消費されるので、中途半端に残っていたり、Fooが残っているわけではありません。 –
もう一つの関連する観察は、 'devil.slay_the_world();'エラーは表示されますが、 'devil.arm(buz);のコメントは解除されます。私は 'transform_and_arm(self)'でFooのすべてのフィールドを消費したいだけです。 –