Rust lifetimes
Errors I encounter learning lifetimes and how to resolve them.
<'a>
Syntax used to declare and use a lifetime parameter named 'a
Zero-Copy Parser Example
We can think of 'a kind of like a variable, similar to x=5. But instead of a value it holds the duration of time (scope).
<'a>: We are saying "This struct cannot exist on its own, it is dependent on some data that lives for a duration we call'a."&'a str: This tells use that this holds a reference to a string, that must live at least as long as'a.
The Highlight struct is essentially signing a contract with the compiler stating
I, the struct
Highlight, promise that I will never outlive the data insidecontent. If the string data goes out of scope, I must go out of scope too.
Parser Function
let raw_data = Stringfrom;
let highlight = find_important_part;
My initial confusion here was here:
Highlight
Setting content to parts[1].trim() looked like we were just "getting" a lifetime reference from nowhere, because I had stated the struct Highlight is defined needing content: &'a str,. Digging a little deeper I found Rust's Lifetime Elision rules. Which means although the trim() function in the std written as pub fn trim(&self) -> &str is expanded to fn trim<'b>(&'b self) -> &'b str. Which satisfies our definition.
Variables Sharing Lifetimes
When multiple variables share the same lifetime, Rust will also scope it to the smallest time frame.
Longest String Example
Here we have an example of both x and y using the same lifetime 'a, this code works fine because both s1 and s2 live with the main() scope, so they both end at the same time. But what if we changed to scope of one of them?
let s1 = Stringfrom;
let result;
// s2 dies here, so 'a ends here.
// even if 'result' actually points to 's1' at runtime!
println!;
}
// Error: `s2 does not live long enough
// Error: borrowed value does not live long enough
The solution here is to deal with the ownership of the string. Instead of &'a str we can change the return to String. The con here is we are taking a small performance hit, this is probably still an acceptable solution unless you are writing some high performance code or working with embeded systems.
The Embeded systems way which has higher performance would be create a type that can hold either type.
// Can hold EITHER a reference to 'a OR a reference to 'b