关于Rust生命周期的问题

rust lifetime

173 观看

1回复

327 作者的声誉

我正在尝试实现基于的内存池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);
   |            ^^^^^^^^

我的问题是:

  1. 为什么data没有终身'a?我认为既然pool有生命,a并且consume返回相同的生命周期self,它应该有生命'a

  2. 使此代码按预期工作的最佳方法是什么?基本上我想分配新字节并将其生命周期调整为与内存池相同。我知道我可以TypedArena直接使用,因为alloc没有mut参考。但是我真的想跟踪其他信息,例如bytes_allocated

作者: Chao Sun 的来源 发布者: 2017 年 4 月 5 日

回应 1


0

32348 作者的声誉

决定

让我们一步一步解决这个问题:

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。本说明只是说:我们不能用一生比的寿命大于传递引用selfconsume():然后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能够约束它,说它有活得比 'a(活长于'a)。

作者: Lukas Kalbertodt 发布者: 2017 年 4 月 5 日
32x32