3

The parameter ln doesn't live long enough, and I couldn't seem to find a reason why it does. I tried to make it and the value I was giving it as input static, but that just caused other problems.

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)
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Teytix
  • 85
  • 1
  • 4
  • 10

1 Answers1

5

panic! takes a string literal as its first argument1. A string literal is a &'static str, but your string slices are not 'static.

Instead, pass the string as a formatter argument:

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

It's also worth pointing out:

  1. Variables and functions in Rust use snake_case.
  2. There's no reason to collect the result of split_whitespace into a vector unless you plan on iterating over it twice (and maybe not even then).
  3. Don't loop over an iterator to push into a Vec, you can just map and collect.
  4. There's no need to use return, just let the last expression be the value.
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()
}

See also:


1 This is a dirty lie that I've used because it's easier to understand. If you look at the definition of panic!, you'll see that this invocation is actually calling the hidden / internal function ::rt::begin_panic:

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

Thus the first argument to panic! can actually be anything that implements the Any trait. The Any trait requires that any type that implements it must be 'static:

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

At this point, the same logic applies: you are passing a &str and an arbitrary &str does not meet the trait bound 'static.

mcarton
  • 27,633
  • 5
  • 85
  • 95
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    Technically, the single-argument version of `panic!` takes anything that is `Any + Send`. Of course, `Any` implies `'static`. Which means it implies `&str: 'static`, thus leading to the compiler's confusing lifetime deduction error. – Sebastian Redl Mar 22 '18 at 19:20
  • `panic!` also takes arbitrary values (not just strings), but the value must be valid forever (because may be shown to the user after all the functions have finished). What `panic!("{}", splitLn[0])` does is it copies `splitLn[0]` into a fresh `String` that can be passed around. Remember the `ln: &str` argument isn't actually a string, it just points to a string that may disappear sometime after the function finishes. – Bram Geron Mar 22 '18 at 19:21
  • 1
    @SebastianRedl I didn't really want to get into those details because this is likely going to be a problem that people new to Rust will experience, but now I suppose I need to muddle it up. – Shepmaster Mar 22 '18 at 19:21