变量的寿命不足以通过通道发送

Variable does not live long enough to send over channel

我正在尝试通过频道发送包含 Cow<[u8]> 的消息。但是,终身规则不允许我通过它。

use std::borrow::Cow;
use std::sync::mpsc;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct PlayerAction<'a> {
    pub data: Cow<'a, [u8]>,
}

#[derive(Debug, Clone)]
pub enum NetworkMessage<'a> {
    PlayerActionMessage(PlayerAction<'a>),
}

pub struct ConnectionsManager<'a> {
    channel: mpsc::Sender<NetworkMessage<'a>>,
}

pub struct MessageHandler<'a> {
    pub connection_manager: ConnectionsManager<'a>,
}

fn read_message<'a>(bytes: &'a Vec<u8>) -> NetworkMessage {
    NetworkMessage::PlayerActionMessage(PlayerAction {
        data: Cow::Borrowed(&bytes),
    })
}

impl<'a> MessageHandler<'a> {
    fn on_message(&mut self, msg: Vec<u8>) {
        let readm = read_message(&msg);
        self.connection_manager.channel.send(readm);
    }
}

fn main() {}

Playground

error[E0597]: `msg` does not live long enough
  --> src/main.rs:30:35
   |
30 |         let readm = read_message(&msg);
   |                                   ^^^ borrowed value does not live long enough
31 |         self.connection_manager.channel.send(readm);
32 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 28:1...
  --> src/main.rs:28:1
   |
28 | impl<'a> MessageHandler<'a> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

MessageHandlerVec<u8> 长,但我不知道如何以其他方式传递它。

有没有什么办法可以通过Vec<u8>让它比on_message函数活得更久?

您可以通过以下一行更改来使此代码正确:

fn on_message(&mut self, msg: &'a [u8])

不是按值获取 Vec<u8>,而是获取对已保证至少与 'a 一样长的切片的引用。这使得 调用者 有责任确保您传递给 on_message 的任何内容都将存在足够长的时间以通过通道发送。


但也许你不能那样做。要么调用者有同样的问题,你不能再往上推,要么 Vec<u8>on_message 签名的必需部分。如果是这样的话,你将不得不改变read_message。这是一种可能性:

fn read_message<'b>(bytes: Vec<u8>) -> NetworkMessage<'b> {
    NetworkMessage::PlayerActionMessage(PlayerAction {
        data: Cow::Owned(bytes),
    })
}

impl<'a> MessageHandler<'a> {
    fn on_message(&mut self, msg: Vec<u8>) {
        let readm = read_message(msg);
        self.connection_manager.channel.send(readm);
    }
}

msg 移动到 read_message 后,编译器可以自由选择 'b 的任何生命周期。在 on_message 中,它可以只选择 'a 来编译代码。这种方法的缺点是,如果您需要在将它发送到频道后再次使用它,您可能必须 .clone() Vec