Why this error occurred: cannot return value referencing local variable `v`

Viewed 347
match base64::decode(text) {
    Ok(v) => str::from_utf8(&v).ok(),
    _ => None
}

With this program, the following error occurs.
I would like someone to explain what this means and what should I do.

cannot return value referencing local variable `v`
returns a value referencing data owned by the current function
`v` is borrowed here
1 Answers

According to base64::decode documentation, its signature looks like this:

pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError>

Your input is taken as reference &[u8]. The output of the function is an owned type Result<Vec<u8>, DecodeError>. So far so good.

You move the result of base64::decode(text) function into the match expression. In the Ok branch, you move the Vec<u8> into v variable. Understand, that now the owner of decoded Vec<u8> is v. Inside this branch, you borrow the vector using &v. However str::from_utf8 function has a signature:

pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>

Meaning that the return value of it is not owned, it still borrows the input value. By doing

Ok(v) => str::from_utf8(&v).ok()

you try to return this borrowed value, however remember that the owner of Vec<u8> is v. After match expression is finished, the owner v is destroyed, the data of Vec<u8> is destroyed.

The error you get notifies you, that match tries to return borrowed data, that will no longer be valid after match is finished.


The easiest way to fix it is to use String type, instead of &str type like this:

let decoded = match base64::decode("aGVsbG8gd29ybGQ=") {
    Ok(v) => String::from_utf8(v).ok(),
    _ => None
};
println!("{:?}", decoded);
// Some("hello world")

Hopefully you won't waste any memory, because in documentation of String::from_utf8 it's said that

This method will take care to not copy the vector, for efficiency’s sake.

Related