Rust:参数要求 `[VARIABLE]` 是为 `'static` 借用的

Rust: argument requires that `[VARIABLE]` is borrowed for `'static`

我收到这条无用的错误消息:

error[E0597]: `msg` does not live long enough
  --> src/main.rs:25:23
   |
25 |         let msg_str = msg.as_str();
   |                       ^^^^^^^^^^^^
   |                       |
   |                       borrowed value does not live long enough
   |                       argument requires that `msg` is borrowed for `'static`
...
51 |     }
   |     - `msg` dropped here while still borrowed

来自以下 Rust 代码:

    for msg in rx {
        let msg_str = msg.as_str();
        let msg_type = get_msg_type(exchange, &msg_str);

        println!("{}", &msg_str);

        let join_handle = spawn_blocking(move || { parse_trade(exchange, market_type, &msg_str) });
        match join_handle.await {
            Ok(trade) => {
                let t = &trade.unwrap()[0];
            },
            Err(error) => panic!("Problem joining: {:?}", error),
        }
    }

但它没有告诉我在这种情况下如何 static 借用 msg

什么是可行的解决方案?

None 以下提出的重复问题等同于此问题:

问题是 msg 是您从迭代中获得的一个变量,因此仅在一个迭代步骤中有效。它在迭代步骤结束时不再存在,因此编译器消息 - msg dropped here while still borrowed 在循环结束时。

这是一个问题的原因是因为你通过 move || 将引用 msg_str 移动到闭包中,而 Rust 编译器无法推断 spawn_blocking 在结束之前将其删除的循环。 (它不能推断它,因为它是不正确的;join_handle.await 可能会被取消,这不会取消生成的任务并会导致 &msg_str 成为悬空引用)


But it doesn't tell me how to do a static borrow of msg in this case.

您不能从时间变量静态借用。这就是'static借用的定义,它不会在一段时间后不复存在。


遗憾的是,在不知道变量/函数参数类型的情况下,我无法给您任何解决此问题的建议。您可能想在某处引入一个克隆,但在不知道类型的情况下很难说出确切位置。


猜解

我试图从您的问题中推断出一个最小的可重现示例。 我假设类型如下:

use tokio::task::spawn_blocking;

fn parse_trade(_msg: &str) -> Result<Vec<u32>, String> {
    Ok(vec![1, 2, 3])
}

#[tokio::main]
async fn main() {
    let rx = vec!["a".to_string(), "b".to_string()];

    for msg in rx {
        let msg_str = msg.as_str();

        println!("{}", &msg_str);

        let join_handle = spawn_blocking(move || parse_trade(&msg_str));
        match join_handle.await {
            Ok(trade) => {
                let t = &trade.unwrap()[0];
            }
            Err(error) => panic!("Problem joining: {:?}", error),
        }
    }
}

显示以下错误消息:

error[E0597]: `msg` does not live long enough
  --> src/main.rs:12:23
   |
12 |         let msg_str = msg.as_str();
   |                       ^^^^^^^^^^^^
   |                       |
   |                       borrowed value does not live long enough
   |                       argument requires that `msg` is borrowed for `'static`
...
23 |     }
   |     - `msg` dropped here while still borrowed

这是一个可能的解决方案:

use tokio::task::spawn_blocking;

fn parse_trade(_msg: &str) -> Result<Vec<u32>, String> {
    Ok(vec![1, 2, 3])
}

#[tokio::main]
async fn main() {
    let rx = vec!["a".to_string(), "b".to_string()];

    for msg in rx {
        let msg_str = msg.as_str();
        let msg_clone = msg.clone();

        println!("{}", &msg_str);

        let join_handle = spawn_blocking(move || parse_trade(msg_clone.as_str()));
        match join_handle.await {
            Ok(trade) => {
                let t = &trade.unwrap()[0];
            }
            Err(error) => panic!("Problem joining: {:?}", error),
        }
    }
}

您创建了一个 msg.clone() 并将这个移到闭包中。它将克隆字符串的所有权带入闭包,因此它不再依赖于 msg 变量。