TonyLEE
TonyLEE

Reputation: 1

Rust lifetime issue

pub fn get_header_authorization() -> (&str, &str) {
    dotenv().ok();
    let str = std::env::var("HEADER_AUTHORIZATION").expect("HEADER AUTHORIZATION must be set!");
    let header:Vec<&str> = str.split('&').collect();
    let (a, b) = (header[0], header[1]);
    (a, b)
}
#[test]
fn test() {
    let authorization = get_header_authorization();
    assert_eq!(authorization.0, "Authorization")
}
error[E0106]: missing lifetime specifier
   --> src\json_function.rs:173:45
    |
173 | pub fn get_header_authorization() -> (&str, &str) {
    |                                             ^ expected named lifetime parameter
    |

Upvotes: 0

Views: 345

Answers (2)

Henry Obiaraije
Henry Obiaraije

Reputation: 448

 let (a, b) = (header[0], header[1]);
 (a, b)

These are the 2 last lines of the function.

As pointed out in the answer by @isaactfa, you are returning references that could go out of scope at any time and cause issues.

The best way to understand how Rust asks for a lifetime is to first understand the Lifetime Elission Rule in Rust. There are 3 rules that rust uses to implicitly assign lifetime parameters to the function's input parameters and the return value of the function, but all of this will depend on the input parameters. In your case, the function does not have any concrete input parameter by reference, so Rust could not automatically assign the lifetimes.

Solution

Return String Objects in the tuple instead by doing it as pointed out by @issactfa above or this way

pub fn get_header_authorization() -> (String, String) {
    // dotenv().ok();
    let str = std::env::var("HEADER_AUTHORIZATION").expect("HEADER AUTHORIZATION must be set!");
    let header: Vec<&str> = str.split('&').collect();
    let (a, b) = (header[0], header[1]);
    (a.to_string(), b.to_string())
}

Pay attention to the return value (a.to_string(), b.to_string())

If you still need help, familiarize yourself with both the ownership rules in Rust and, the concept of Lifetime in Rust and the Lifetime Elision Rules or you can take a look at this detailed 3 series video where I explained Lifetimes in Rust and also explained the 3 Lifetime Elision Rules with Examples.

Upvotes: 0

isaactfa
isaactfa

Reputation: 6651

Rust can only infer the lifetimes of return types if you have a reference in the arguments, in which case it'll infer that the lifetimes of the parameters and return types has to be the same. This is why you get this particular error. That isn't the problem with the code, though.

The problem is that std::env::var returns a Result<String, VarError>, so the type of str is String and that String is owned by the function. You then try to return a reference to that String from the function. But when the function returns the String it owns will go out of scope and get dropped and all references to it will become invalid. Rust doesn't allow this. To get around this, you can just return the Strings directly:

pub fn get_header_authorization() -> (String, String) {
    dotenv().ok();
    let str = std::env::var("HEADER_AUTHORIZATION").expect("HEADER AUTHORIZATION must be set!");
    let mut header = str.split('&').map(str::to_owned);
    
    let (a, b) = (header.next().unwrap(), header.next().unwrap());
    (a, b)
}

Upvotes: 1

Related Questions