Why passing a Bytes to a function leads to lifetime error, even though it's guaranteed to complete before drop? and how to fix?

huangapple go评论61阅读模式
英文:

Why passing a Bytes to a function leads to lifetime error, even though it's guaranteed to complete before drop? and how to fix?

问题

Explanation:
The error you're encountering is related to the lifetime of the text_owned variable in your code. The text_owned variable is created by cloning the text field from the msg.content in the if let block. However, when you try to create a Bytes instance from text_owned.as_bytes(), the compiler is indicating that text_owned does not live long enough for this operation.

The issue arises because the Bytes::from function expects its argument to have a 'static lifetime, which means it should live for the entire duration of the program. In your case, text_owned is a temporary value that only lives within the scope of the if let block, and it goes out of scope when the block ends.

How to Fix:
To fix this issue, you need to ensure that the data you're using to create the Bytes instance lives for a 'static lifetime. One way to do this is by cloning the text into a Vec<u8> and then creating the Bytes instance from the Vec. Here's how you can modify your code:

if let Content::Text(ref text) = msg.content {
    let text_vec = text.clone().into_bytes(); // Convert String to Vec<u8>
    let text_byte = Bytes::from(text_vec);
    let mut online_users = online_users.lock().await;
    online_users.send_to_user(target_user, text_byte).await; 
}

In this code, text_vec is a Vec<u8> created from the cloned text, and it can be used to create the Bytes instance without lifetime issues.

This modification ensures that the data used to create text_byte lives long enough for the Bytes instance.

英文:

My current code using bytes crate:

pub async fn send_msg(online_users: Arc&lt;Mutex&lt;OnlineUsers&gt;&gt;, msg: &amp;Message, from: &amp;str) -&gt; io::Result&lt;()&gt; {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_owned = text.clone();
        let text_byte = Bytes::from(text_owned.as_bytes());
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await; 
    }
    Ok(())
}

The error occurs at the call of send_to_user(), the definition of it is:

pub async fn send_to_user(&amp;mut self, name: &amp;str, content: Bytes) -&gt; io::Result&lt;()&gt; {
    let target_user = self
        .list
        .get_mut(name)
        .ok_or(io::Error::new(io::ErrorKind::NotConnected, name.clone()))?;
    target_user.send(content).await?;
    Ok(())
}

Error message below:

error[E0597]: `text_owned` does not live long enough
  --&gt; server/src/handler.rs:28:37
   |
28 |         let text_byte = Bytes::from(text_owned.as_bytes());
   |                         ------------^^^^^^^^^^^^^^^^^^^^^-
   |                         |           |
   |                         |           borrowed value does not live long enough
   |                         argument requires that `text_owned` is borrowed for `&#39;static`
...
31 |     }
   |     - `text_owned` dropped here while still borrowed

I do not understand why it does not live long enough. Since I called .await on an send_to_user(), it must complete before send_msg() reaches its end and drop all variables.
I want:

  1. explanation why this happens.
  2. how am I able to fix this?

答案1

得分: 1

Bytes::from 适用于 &amp;&#39;static [u8],而 String::as_bytes 不提供静态引用。您必须提供一些拥有的数据结构给 Bytes::from。我建议直接传递您的 text_owned 变量,因为 Bytes 实现了 From&lt;String&gt;:

pub async fn send_msg(online_users: Arc&lt;Mutex&lt;OnlineUsers&gt;&gt;, msg: &amp;Message, from: &amp;str) -&gt; io::Result&lt;()&gt; {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_owned = text.clone();
        let text_byte = Bytes::from(text_owned);
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await; 
    }
    Ok(())
}
英文:

Bytes::from is implemented for &amp;&#39;static [u8], whereas String::as_bytes does not give you a static reference. You must provide some owned data structure to Bytes::from. I'd opt for passing your text_owned variable directly, as Bytes implements From&lt;String&gt;:

pub async fn send_msg(online_users: Arc&lt;Mutex&lt;OnlineUsers&gt;&gt;, msg: &amp;Message, from: &amp;str) -&gt; io::Result&lt;()&gt; {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_owned = text.clone();
        let text_byte = Bytes::from(text_owned);
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await; 
    }
    Ok(())
}

huangapple
  • 本文由 发表于 2023年2月23日 20:32:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定