gpt4 book ai didi

rust - 如何防止移入功能的 impl Trait 在借用时被删除?

转载 作者:行者123 更新时间:2023-12-03 11:26:33 25 4
gpt4 key购买 nike

我想定义一个特征 Holder ,它可以通过 items 方法迭代一些。我不想从此方法返回特征对象,因为如果可能的话,我想坚持使用静态分派(dispatch)和堆栈分配。我的系统工作正常,但在某种令人惊讶的情况下出现故障。

代码如下:

pub trait Holder<'a, N: 'a> {
type Items: Iterator<Item=&'a N>;

fn items(&'a self) -> Self::Items;
}

struct Impl<N> {
items: Vec<N>
}

impl<'a, N: 'a> Holder<'a, N> for Impl<N> {
type Items = std::slice::Iter<'a, N>;

fn items(&'a self) -> Self::Items {
self.items.iter()
}
}

fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
// COMPILE ERROR
for item in holder.items() {

}
}

这是错误:

error[E0309]: the parameter type `impl Holder<'a, N>` may not live long enough
--> src/graph/test.rs:20:17
|
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
| ------------------ help: consider adding an explicit lifetime bound...: `impl Holder<'a, N> + 'a`
20 | for item in holder.items() {
| ^^^^^^
|
note: ...so that the type `impl Holder<'a, N>` is not borrowed for too long
--> src/graph/test.rs:20:17
|
20 | for item in holder.items() {
| ^^^^^^

error[E0309]: the parameter type `impl Holder<'a, N>` may not live long enough
--> src/graph/test.rs:20:24
|
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
| ------------------ help: consider adding an explicit lifetime bound...: `impl Holder<'a, N> + 'a`
20 | for item in holder.items() {
| ^^^^^
|
note: ...so that the reference type `&'a impl Holder<'a, N>` does not outlive the data it points at
--> src/graph/test.rs:20:24
|
20 | for item in holder.items() {
| ^^^^^

error: aborting due to 2 previous errors; 4 warnings emitted

For more information about this error, try `rustc --explain E0309`.

我遵循编译器的建议并添加显式生命周期:

pub trait Holder<'a, N: 'a> {
type Items: Iterator<Item=&'a N>;

fn items(&'a self) -> Self::Items;
}

struct Impl<N> {
items: Vec<N>
}

impl<'a, N: 'a> Holder<'a, N> for Impl<N> {
type Items = std::slice::Iter<'a, N>;

fn items(&'a self) -> Self::Items {
self.items.iter()
}
}

fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N> + 'a) {
for item in holder.items() {

}
}

这给出了错误:

error[E0597]: `holder` does not live long enough
--> src/graph/test.rs:20:17
|
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N> + 'a) {
| -- lifetime `'a` defined here
20 | for item in holder.items() {
| ^^^^^^--------
| |
| borrowed value does not live long enough
| argument requires that `holder` is borrowed for `'a`
...
23 | }
| - `holder` dropped here while still borrowed

我看过 this question以及其他几个与此问题无关的问题,但无法理解如何前进。

除了从 Hoder#items 返回一个 trait 对象之外,我还有哪些选择可以让 use_hodler 中的循环正常工作?

最佳答案

这实际上非常困难 - 生命周期和关联类型似乎是 Rust 中那些奇怪的角落案例之一,(还)没有得到很好的支持。如果我说我正确地理解了错误的原因,那我就是在撒谎,但是我已经设法让它工作 对于这个特定的例子 使用 Higher Ranked Trait Bounds .

你只需要改变一行:

fn use_holder<N>(holder: impl for<'a> Holder<'a, N>) {

请注意,生命周期参数已移至 for<'a> .这意味着 holder参数实现Holder<'a, N>每一个可能的生命'a , 而不是特定的 'a至少与功能一样长。

您需要使用 for<'a> ... 大多数地方你都使用了这个特性,所以它很快就会变得凌乱。更高等级的特征界限不是一个常用的特征:它非常小众并且在最常见的情况下被忽略了,所以它不会有助于提高易读性或可维护性。

我建议您更改您的架构,尽可能避免这种构造。

关于rust - 如何防止移入功能的 impl Trait 在借用时被删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62605059/

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