将字符串传递给"恐慌!"时,参数的生存时间不够长

Tey*_*tix 3 vector rust

参数ln活不够久,我似乎无法找到它的原因.我试图把它和我给它的值作为输入静态,但这只是引起了其他问题.

pub fn CompileLine(ln: &str) -> std::vec::Vec<u8> {
    let mut out = std::vec::Vec::new();
    let splitLn: Vec<&str> = ln.split_whitespace().collect();
    match splitLn[0] {
        "exit" => out.push(0),
        "reg" => out.push(0x1),
        "rem" => out.push(0x2),
        "set" => out.push(0x3),
        "sum" => out.push(0x4),
        "jmp" => out.push(0x5),
        _ => panic!(splitLn[0]),
    }
    return out;
}
Run Code Online (Sandbox Code Playgroud)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
 --> src/main.rs:3:33
  |
3 |     let splitLn: Vec<&str> = ln.split_whitespace().collect();
  |                                 ^^^^^^^^^^^^^^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 1:1...
 --> src/main.rs:1:1
  |
1 | / pub fn CompileLine(ln: &str) -> std::vec::Vec<u8> {
2 | |     let mut out = std::vec::Vec::new();
3 | |     let splitLn: Vec<&str> = ln.split_whitespace().collect();
4 | |     match splitLn[0] {
... |
13| |     return out;
14| | }
  | |_^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:3:30
  |
3 |     let splitLn: Vec<&str> = ln.split_whitespace().collect();
  |                              ^^
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&str` will meet its required lifetime bounds
 --> src/main.rs:11:14
  |
11|         _ => panic!(splitLn[0]),
  |              ^^^^^^^^^^^^^^^^^^
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)

She*_*ter 5

panic!将字符串文字作为其第一个参数1.字符串文字是a &'static str,但你的字符串切片不是'static.

相反,将字符串作为格式化程序参数传递:

panic!("{}", split_ln[0]),
Run Code Online (Sandbox Code Playgroud)

值得指出的是:

  1. Rust使用的变量和函数snake_case.
  2. 没有理由将结果收集split_whitespace到向量中,除非你计划迭代两次(甚至可能不是那时).
  3. 不要循环遍历迭代器以进入a Vec,你可以mapcollect.
  4. 没有必要使用return,只需让最后一个表达式成为值.
pub fn compile_line(ln: &str) -> std::vec::Vec<u8> {
    ln.split_whitespace()
        .map(|p| match p {
            "exit" => 0,
            "reg" => 0x1,
            "rem" => 0x2,
            "set" => 0x3,
            "sum" => 0x4,
            "jmp" => 0x5,
            _ => panic!("Unknown mnemonic {}", p),
        })
        .collect()
}
Run Code Online (Sandbox Code Playgroud)

也可以看看:


1这是我用过的一个肮脏的谎言,因为它更容易理解.如果你看一下定义panic!,你会发现这个调用实际上是在调用hidden/internal函数::rt::begin_panic:

pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

因此,第一个参数panic!实际上可以是实现Any特征的任何东西.该Any特征要求实现它的任何类型必须是'static:

pub trait Any: 'static { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

此时,同样的逻辑适用:你正在传递一个&str和一个任意&str不符合特征的界限'static.

  • 从技术上讲,"恐慌!"的单参数版本需要任何"Any + Send".当然,"Any"意味着"静态".这意味着它意味着`&str:'static`,从而导致编译器的生命周期扣除错误. (2认同)