我有一个trait,它有一个返回Box<dyn Iterator<...>>
的函数,根据我的理解,根据定义,这个返回的迭代器的生命周期需要匹配trait对象的生命周期,但是在一个函数中,如果在末尾同时删除了这两个参数,我会得到一个生命周期错误,这里是一个最小的例子,并添加了一些假设作为注解:
trait Foo<'a> {
// The returned iterator's lifetime should match self's
fn bar(&'a self) -> Box<dyn Iterator<Item = usize> + 'a>;
}
struct FooImpl {
values: Vec<usize>
}
impl<'a> Foo<'a> for FooImpl {
fn bar(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
Box::new(self.values.iter().cloned())
}
}
fn foo_bar_caller<'a>(foo: Box<dyn Foo<'a>>) {
// `foo` is moved into this fn
let _iter = foo.bar();
// `_iter` and `foo` should drop
}
fn main() {
let foo = FooImpl { values: vec![1, 2, 3, 4, 5] };
foo_bar_caller(Box::new(foo));
}
(代码为rust playground。)运行此命令会出现以下生存期错误:
error[E0597]: `*foo` does not live long enough
--> src/main.rs:17:17
|
16 | fn foo_bar_caller<'a>(foo: Box<dyn Foo<'a>>) {
| -- lifetime `'a` defined here
17 | let _iter = foo.bar();
| ^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `*foo` is borrowed for `'a`
18 | // `_iter` and `foo` should drop
19 | }
| - `*foo` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error
1条答案
按热度按时间eanckbw91#
你可能想让 function
Foo::bar
在引用生存期内成为泛型,而不是traitFoo
:通过将生存期放在trait
Foo
上,您不必(至少在本上下文中)限制可以用于特定Foo::<'_>::bar
实现的引用的生存期。(在X1 M6 N1 X是X1 M7 N1 X的上下文中的X1 M5 N1 X)调用只能采用具有生存期X1 M8 N1 X的引用,但正如@MaximilianBurszley在评论中指出的,您实际传递给它的是一个临时借用,它 * 不 * 具有相同的生存期'a
。Playground
注意,如果你让函数接受一个具有相同生存期的引用,你可以让
foo_bar_caller
work with your existing code(traitFoo
在生存期内是泛型的):或者,您可以使用higher-ranked trait bound(HRTB)来指定
foo_bar_caller
必须接受一个值,该值在'b
的 * 所有 * 生存期内实现Foo<'b>
:这允许值
foo
的Foo<'_>
实现在foo.bar()
调用期间创建的临时借用的生存期内有效(因为它在 * 所有 * 生存期内实现Foo<'_>
)。Playground for HRTB version