Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument requires that _ is borrowed for 'static - how do I work round this?

Tags:

rust

I have a lifetime/borrowing error from the Rust compiler that I can't get my head around. The problem seems to be that Rust assumes that when an argument is passed to a function that returns a reference to a static value, the argument reference must also be static.

#[derive(Debug)]
struct TestThingy<'a> {
    label: &'a str,
}

const TEST_VALUES: [TestThingy; 3] = [
    TestThingy { label: "one" },
    TestThingy { label: "two" },
    TestThingy { label: "three" },
];

pub fn value_for_num(num: &str) -> Option<&'static TestThingy> {
    TEST_VALUES.iter().find(|value| value.label == num)
}

pub fn test_out_thingy() {
    let tmp_val = String::from("two");
    if let Some(test_thingy) = value_for_num(&tmp_val) {
        println!("test_thingy: {:?}", test_thingy);
    }
}

fn main() {
    test_out_thingy();
}

Rust errors with: error[E0597]: `tmp_val` does not live long enough - E0597 refers to when a value gets dropped whilst its still borrowed, which isn't happening here - I don't know how to convince Rust of that though.

The idea behind this code, for more context, is it's a lookup mechanism for compile-time/static config (in my codebase they are Syntax values, matched on the basis of a provided filename &str). So the provided argument genuinely does not live as long as the static config, but I don't understand why that's a problem. The returned value doesn't/can't contain the argument as a reference, so I'm super unclear why this borrowing error is happening.

like image 870
William Roe Avatar asked Oct 17 '19 16:10

William Roe


1 Answers

The problem lies in the function signature of value_for_num.

You indicate that you return a static reference to a TestThingy but have no indication what kind of references that TestThingy<'x> might hold. Thus the compiler assumes that the unspecified input reference lifetime may be tied to the unspecified output lifetime of references inside the TestThingy.

i.e. the compiler sees this:

pub fn value_for_num<'a>(num: &'a str) -> Option<&'static TestThingy<'a>>

If you change the signature to specify that the contained references are also static then it compiles.

pub fn value_for_num(num: &str) -> Option<&'static TestThingy<'static>>
like image 90
turbulencetoo Avatar answered Sep 20 '22 10:09

turbulencetoo