我正在尝试基于TypedArena
实现一个内存池。这是我的原始代码的简化版本:
#![feature(rustc_private)]
extern crate arena;
use arena::TypedArena;
pub struct MemoryPool {
arena: TypedArena<Vec<u8>>,
bytes_allocated: usize,
}
impl MemoryPool {
pub fn consume(&mut self, buf: Vec<u8>) -> &[u8] {
self.bytes_allocated += buf.capacity();
self.arena.alloc(buf)
}
}
pub struct ByteArray<'a> {
data: &'a [u8],
}
impl<'a> ByteArray<'a> {
pub fn set_data(&mut self, data: &'a [u8]) {
self.data = data;
}
}
pub struct S<'a> {
pool: &'a mut MemoryPool,
}
impl<'a> S<'a> {
pub fn write(&mut self, buffer: &mut ByteArray<'a>) {
let v = vec!();
let data = self.pool.consume(v);
buffer.set_data(data);
}
}
但是,编译器会提示以下行:let data = self.pool.consume(v);
:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> <anon>:34:26
|
34 | let data = self.pool.consume(v);
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 32:54...
--> <anon>:32:55
|
32 | pub fn write(&mut self, buffer: &mut ByteArray<'a>) {
| _______________________________________________________^ starting here...
33 | | let v = vec!();
34 | | let data = self.pool.consume(v);
35 | | buffer.set_data(data);
36 | | }
| |___^ ...ending here
note: ...so that reference does not outlive borrowed content
--> <anon>:34:16
|
34 | let data = self.pool.consume(v);
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 32:54...
--> <anon>:32:55
|
32 | pub fn write(&mut self, buffer: &mut ByteArray<'a>) {
| _______________________________________________________^ starting here...
33 | | let v = vec!();
34 | | let data = self.pool.consume(v);
35 | | buffer.set_data(data);
36 | | }
| |___^ ...ending here
note: ...so that types are compatible (expected &mut ByteArray<'_>, found &mut ByteArray<'a>)
--> <anon>:35:12
|
35 | buffer.set_data(data);
| ^^^^^^^^
我的问题是:
为什么
data
没有生命周期'a
?我在想,既然pool
有生命周期a
并且consume
返回与self
相同的生命周期,它应该有生命周期'a
.使这段代码按预期工作的最佳方法是什么?基本上我想分配新字节并将它们的生命周期调整为与内存池相同。我知道我可以直接使用
TypedArena
,因为alloc
不采用mut
引用。但是我真的很想跟踪其他信息,例如bytes_allocated
。
最佳答案
让我们逐步解决这个问题:
cannot infer an appropriate lifetime for autoref
“autoref”描述了为方法的 self
参数构建正确引用的过程。编译器无法找到具有正确生命周期的引用来调用 consume()
。为什么不能呢?
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 32:54...
--> <anon>:32:55
|
32 | pub fn write(&mut self, buffer: &mut ByteArray<'a>) {
| _______________________________________________________^ starting here...
33 | | let v = vec!();
34 | | let data = self.pool.consume(v);
35 | | buffer.set_data(data);
36 | | }
| |___^ ...ending here
note: ...so that reference does not outlive borrowed content
--> <anon>:34:16
|
34 | let data = self.pool.consume(v);
| ^^^^^^^^^
“匿名生命周期#1”指的是&mut self
的生命周期。这个注释只是说:我们不能将生命周期大于 self
生命周期的引用传递给 consume()
:然后 consume()
会认为它的 self
参数比它实际存在的时间更长。
note: but, the lifetime must be valid for the lifetime 'a
这是您已经期望应用的规则。但是现在问题出在哪里呢?好吧:&mut self
的生命周期(匿名生命周期 #1)可能比 'a
的生命周期更短!就这样!我们可以很容易地修复它:
impl<'a> S<'a> {
pub fn write<'b: 'a>(&'b mut self, buffer: &mut ByteArray<'a>) {
// ^^^^^^^^ ^^
...
}
}
这里我们只是将之前的匿名生命周期命名为 #1 以便能够绑定(bind)它,表示它必须outlive 'a
(比 ' 长一个
).
关于rust - 关于 Rust 生命周期的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43223497/