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

时间:2018-03-22 19:08:38

标签: vector rust

参数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; } 的寿命不够长,我似乎无法找到原因。我试图把它和我给它的值作为输入静态,但这只会引起其他问题。

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)
raw_data = [
        {
            "Company":123,
            "Person":{
                "First Name":123,
                "Last Name":323
            }
        },
        {
            "Company":13,
            "Person":{
                "First Name":123,
                "Last Name":323
            }
        },
        {
            "Company":123,
            "Person":{
                "First Name":122,
                "Last Name":133
            }
        }
    ]

unique = []
for company in raw_data:
    if all(unique_comp["Person"] != company["Person"] for unique_comp in unique):
        unique.append(company)

print(unique)

#>>> [{'Company': 123, 'Person': {'First Name': 123, 'Last Name': 323}}, {'Company': 123, 'Person': {'First Name': 122, 'Last Name': 133}}]

1 个答案:

答案 0 :(得分:5)

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

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

panic!("{}", split_ln[0]),

值得指出的是:

  1. Rust中的变量和函数使用snake_case
  2. 没有理由将split_whitespace的结果收集到一个向量中,除非你计划迭代两次(甚至可能不是)。
  3. 不要遍历迭代器以推入Vec,您可以mapcollect
  4. 无需使用return,只需将最后一个表达式作为值。
  5. 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()
    }
    

    另见:

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

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

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

    pub trait Any: 'static { /* ... */ }
    

    此时,同样的逻辑适用:您传递&str且任意&str不符合特征限制'static