有关Rust寿命的问题 [英] Questions about Rust lifetime

查看:88
本文介绍了有关Rust寿命的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试基于TypedArena实现一个内存池.这是我原始代码的简化版本:

I'm trying to implement a memory pool based on TypedArena. Here's a simplified version of my original code:

#![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);:

However, the compiler complains about the line: 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.

  1. Why data does not have lifetime 'a? I'm thinking that since pool has lifetime a and consume returns the same lifetime as self, it should have lifetime 'a.

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

What's the best way to make this code work as intended? Basically I want to allocate new bytes and adjust their lifetime to be the same as the memory pool. I know I can use TypedArena directly since alloc does not take a mut reference. However I really want to track other information such as bytes_allocated.

推荐答案

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

Let's tackle this step by step:

cannot infer an appropriate lifetime for autoref

"autoref"描述了为方法的self自变量构建正确引用的过程.编译器无法找到具有正确生命周期的引用来调用consume().为什么不能呢?

"autoref" describes the process of building the right reference for the self argument of a method. The compiler is unable to find a reference with the right lifetime to call consume(). Why is it unable?

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自变量的生存期比实际寿命更长.

The "anonymous lifetime #1" refers to the lifetime of &mut self. This note is just saying: we can't pass a reference with a lifetime greater than the lifetime of self into consume(): then consume() would think that its self argument lives longer than it actually does.

note: but, the lifetime must be valid for the lifetime 'a

这是您已经预期要应用的规则.但是现在问题出在哪里呢?好吧:&mut self的生存期(匿名生命周期#1)可能比'a生存期短 !就这样!而且我们可以很容易地解决它:

This is the rule you already expected to be applied. But where is the problem now? Well: the lifetime of &mut self (anonymous lifetime #1) could life shorter than 'a! That's all! And we can fix it quite easily:

impl<'a> S<'a> {
    pub fn write<'b: 'a>(&'b mut self, buffer: &mut ByteArray<'a>) {
        //      ^^^^^^^^  ^^
        ...
    }
}

在这里,我们仅将先前的匿名生存期命名为#1以便绑定它,说它必须 outlive 'a(生存期长于'a).

Here we just name the previously anonymous lifetime #1 to be able to bound it, saying that it has to outlive 'a (live longer than 'a).

这篇关于有关Rust寿命的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆