使用生命周期参数为类型实现索引
Implementing Index for type with a lifetime parameter
我有一些这样的类型,它们每个都有一个生命周期参数。
use std::marker::PhantomData;
use std::ops::Index;
pub struct Foo<'ctx> {
bars: Vec<Bar<'ctx>>,
phantom: PhantomData<&'ctx ()>,
}
impl Foo<'_> {
pub fn get_bar(&self, index: usize) -> Option<&Bar> {
self.bars.get(index)
}
}
pub struct Bar<'ctx> {
// pretend we are using a context here
phantom: PhantomData<&'ctx ()>,
}
我想为 Foo
实现 Index
,但编译器不喜欢它:
impl <'ctx> Index<usize> for Foo<'ctx> {
type Output = Bar<'ctx>;
fn index(&self, _index: usize) -> &Self::Output {
self.get_bar(_index).unwrap()
}
}
我收到这个错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/ir/foo.rs:24:14
|
24 | self.get_bar(_index).unwrap()
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/ir/foo.rs:23:14
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/ir/foo.rs:24:9
|
24 | self.get_bar(_index).unwrap()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'ctx` as defined here...
--> src/ir/foo.rs:20:7
|
20 | impl <'ctx> Index<usize> for Foo<'ctx> {
| ^^^^
note: ...so that the types are compatible
--> src/ir/foo.rs:23:53
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| _____________________________________________________^
24 | | self.get_bar(_index).unwrap()
25 | | }
| |_____^
= note: expected `<Foo<'ctx> as Index<usize>>`
found `<Foo<'_> as Index<usize>>`
(我在 SO 上看到了一些类似的问题,但它们在细节上似乎都不同,即输出类型具有生命周期参数)。
这是因为当存在多个省略的生命周期时,rust 编译器无法推断出正确的生命周期。 Rust 编译器只能将省略的生命周期视为相同的生命周期 '_
.
函数get_bar
的推断签名实际上是:
pub fn get_bar<'_>(self: &'_ Foo<'_>, index: usize) -> Option<&'_ Bar<'_>>
注意所有的'_
指的是同一个生命周期,这显然不是我们需要的,因为我们不必在整个生命周期中一直借用某些Bar
的值'ctx
.
并且,函数 index
的推断签名是:
fn index<'_>(self: &'_ Foo<'ctx>, _index: usize) -> &'_ Bar<'ctx>
它比 get_bar
的签名更通用,因为它允许 '_
的生命周期参数比 'ctx
短,因此您不能在内部调用 get_bar
index
的正文
要使其正常工作,您必须明确指定 'ctx
,因为省略的生命周期 '_
必须是借用的生命周期 self
。
impl<'ctx> Foo<'ctx> {
pub fn get_bar(&self, index: usize) -> Option<&Bar<'ctx>> {
self.bars.get(index)
}
}
get_bar
的签名现在变为:
pub fn get_bar<'_>(self: &'_ Foo<'ctx>, index: usize) -> Option<&'_ Bar<'ctx>>
那么 index
中的生命周期可以匹配 get_bar
中的生命周期
我有一些这样的类型,它们每个都有一个生命周期参数。
use std::marker::PhantomData;
use std::ops::Index;
pub struct Foo<'ctx> {
bars: Vec<Bar<'ctx>>,
phantom: PhantomData<&'ctx ()>,
}
impl Foo<'_> {
pub fn get_bar(&self, index: usize) -> Option<&Bar> {
self.bars.get(index)
}
}
pub struct Bar<'ctx> {
// pretend we are using a context here
phantom: PhantomData<&'ctx ()>,
}
我想为 Foo
实现 Index
,但编译器不喜欢它:
impl <'ctx> Index<usize> for Foo<'ctx> {
type Output = Bar<'ctx>;
fn index(&self, _index: usize) -> &Self::Output {
self.get_bar(_index).unwrap()
}
}
我收到这个错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/ir/foo.rs:24:14
|
24 | self.get_bar(_index).unwrap()
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/ir/foo.rs:23:14
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/ir/foo.rs:24:9
|
24 | self.get_bar(_index).unwrap()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'ctx` as defined here...
--> src/ir/foo.rs:20:7
|
20 | impl <'ctx> Index<usize> for Foo<'ctx> {
| ^^^^
note: ...so that the types are compatible
--> src/ir/foo.rs:23:53
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| _____________________________________________________^
24 | | self.get_bar(_index).unwrap()
25 | | }
| |_____^
= note: expected `<Foo<'ctx> as Index<usize>>`
found `<Foo<'_> as Index<usize>>`
(我在 SO 上看到了一些类似的问题,但它们在细节上似乎都不同,即输出类型具有生命周期参数)。
这是因为当存在多个省略的生命周期时,rust 编译器无法推断出正确的生命周期。 Rust 编译器只能将省略的生命周期视为相同的生命周期 '_
.
函数get_bar
的推断签名实际上是:
pub fn get_bar<'_>(self: &'_ Foo<'_>, index: usize) -> Option<&'_ Bar<'_>>
注意所有的'_
指的是同一个生命周期,这显然不是我们需要的,因为我们不必在整个生命周期中一直借用某些Bar
的值'ctx
.
并且,函数 index
的推断签名是:
fn index<'_>(self: &'_ Foo<'ctx>, _index: usize) -> &'_ Bar<'ctx>
它比 get_bar
的签名更通用,因为它允许 '_
的生命周期参数比 'ctx
短,因此您不能在内部调用 get_bar
index
要使其正常工作,您必须明确指定 'ctx
,因为省略的生命周期 '_
必须是借用的生命周期 self
。
impl<'ctx> Foo<'ctx> {
pub fn get_bar(&self, index: usize) -> Option<&Bar<'ctx>> {
self.bars.get(index)
}
}
get_bar
的签名现在变为:
pub fn get_bar<'_>(self: &'_ Foo<'ctx>, index: usize) -> Option<&'_ Bar<'ctx>>
那么 index
中的生命周期可以匹配 get_bar