Error: returns a value referencing data owned by the current function

Hi,

How can solve this error

returns a value referencing data owned by the current function

Code

fn get_csrf_token(url: &str) -> Result<&str, Box<dyn std::error::Error>> {
    let body = reqwest::get(url)?.text()?;
    let re = Regex::new(r#"name="X-CSRF-Token" value="(.+?)""#)?;

    let caps = re.captures(&body).expect(&format!("csrf field not found for '{}'", url));

    Ok(&caps[1])
}

Correct if i am wrong, Here i am trying to return data that is referenced inside this function, and that data will be droped once the function return, so it will be nulled that's why the compiler does not allow it.

How can i return the data? if possible without cloning it?

Thank you

The text of the reqwest is created and destroyed in this fn, as you said - that’s what your capture is referencing, and thus cannot return a ref to.

Why are you opposed to cloning and getting a String? Alternatively, you can return the text to the caller and do the regex work there, keeping the request text alive for the duration.

@vitalyd i'am not against cloning, (which i don't know how to do btw, i tried .clone_into but it throws an error), but for my understanding why should the text be cloned.

given that i am new to rust and i am trying to wrap my head over rust concepts, this is how i picture the data inside that function

So when the function return all the green area will be deleted, that will leave a caps pointing to invalid data, but since that data is still in use, why does get removed, could just rust remove the area (only green) and leave the red area which i still need? am i wrong, if so how can i return a slice without clonning it into a new variable if possible? if not possible, how do i clone it?

Ok(caps[1].clone()) and change return type to Result<String, Box<dyn ...>>

text() returns a String, which basically just a Vec<u8> validated to have valid UTF. It owns the heap allocation storing its data; when it’s dropped, it frees that allocation.

Rust doesn’t have a GC so it doesn’t know that some area (slice) is still used, and therefore the entire allocation needs to be kept around. There are crates that provide reference counted buffers, where this type of thing is possible (eg bytes crate).

Speaking of GC, Java’s String::substring() used to do precisely what you described. That was changed because it was found to cause massive memory consumption since the large allocation was retained despite only a small slice being in use. Today the JDK creates a new allocation and copies the data when creating a substring.

2 Likes