感谢您纠正我提问的方式。我做了几个修改以使代码可编译。
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()
方法旨在通过取消Foo
和brace
来使用buz
的实例。它调用brace.transform()
使brace
成为Devil
。它通过用buz.unwrap()
喂养魔鬼来加强魔鬼。
问题是,调用let weapon = buz.into();
是合法的,而调用devil = devil.arm(buz);
会导致生命周期问题。
似乎这个问题与生命周期有很大关系。如果没有魔鬼,那么所有这些问题都会消失。
答案 0 :(得分:0)
编辑:我之前的回答并没有很好地解释这个问题。这是另一种尝试。
您遇到此问题是因为transform
存在缺陷。为了找出原因,让我们看看编译器为transform
推断的生命周期:
fn transform<'a>(&'a self, n: i32) -> Devil<'a>
我们可以看到编译器决定给返回的Devil
提供与传递给函数的self
的引用相同的生命周期。
现在,让我们看一下Devil
:
struct Devil<'a> {
hp: i32,
weapon: Option<Bar<'a>>,
}
我们可以看到Devil
的生命周期参数与其weapon
相关联。
回顾transform
,但是......
fn transform<'a>(&'a self, n: i32) -> Devil<'a> {
Devil {
hp: self.x + n,
weapon: None,
}
}
...很明显,weapon
是Devil
的生命周期参数的唯一目的,与self
的引用无关,所以&self
和Devil
的生命周期应该彼此无关。
这会在以后为Devil
分配实际武器时导致问题,因为我们可能希望Devil
weapon
具有不同的生命周期,并且没有理由我们不应该这样做。
此外,transform
的当前实施禁止返回的Devil
超过对self
的引用,并且不一定是这种情况。
要解决此问题,请明确注释transform
以明确&self
并且返回的Devil
具有无关的生命周期:
fn transform<'a, 'b>(&'a self, n: i32) -> Devil<'b>