gpt4 book ai didi

generics - 处理 `Into` 泛型时的 Rust 生命周期问题

转载 作者:行者123 更新时间:2023-11-29 08:33:10 24 4
gpt4 key购买 nike

感谢您纠正我提问的方式。我进行了多次修改以使代码可编译。

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() 方法旨在通过移除 bracebuz 来使用 Foo 的实例.它调用 brace.transform() 使 brace 成为 Devil。它通过用 buz.unwrap() 喂养魔鬼来强化魔鬼。

问题在于,调用 let weapon = buz.into(); 是合法的,而调用 devil = devil.arm(buz); 会导致终身问题.

看来这个问题与生命周期有很大关系。如果没有'a for Devil,那么所有这些问题都会烟消云散。

最佳答案

编辑:我之前的回答没有很好地解释问题。这是另一种尝试。

你遇到这个问题是因为 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>

关于generics - 处理 `Into` 泛型时的 Rust 生命周期问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44164826/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com