rust - 关于 Rust 生命周期的问题

标签 rust lifetime

我正在尝试基于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

最佳答案

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

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/

相关文章:

c - 不含数组的结构体的生命周期

pointers - 如何使用指针算法获取向量中元素的索引?

rust - Rust 中的内置对象

rust - 在两个 HashMap 之间交换特征

Rust 从可变 self 函数调用可变 self 函数

azure - 如何修复 AzureADPreview Windows PowerShell 中的 'Policy operations on v2 application are disabled'

asp.net-mvc - Autofac 生命周期管理

c++ - 可以延长初始化列表中对象的生命周期吗?

serialization - 我们如何编写一个通用函数来检查 Serde 序列化和反序列化?

rust - 如何使用具有 doctests 的 Rust 项目实现条件编译?