Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with "borrowed value does not live long enough" within for loops [duplicate]

Tags:

rust

ownership

A site I am scraping requires me to query the title tag of an HTML page as well as a few other elements to see if I can discern the title of the article.

I create a HashMap<&str, u8> and immediately .insert(title_tag_text, 1), query for the header elements and then I am hoping to insert the header tags' text into the hash map similarly but I get the error borrowed value does not live long enough.

I'm not sure I understand since I thought I was properly dereferencing the std::string::String into a &str which should implement the Copy trait? Unfortunately, I suspect the next code I plan to implement has a similar issue.

let mut title_candidates: HashMap<&str, u8> = HashMap::new();

let title_tag_text: String = Selector::parse("title")
    .ok()
    .and_then(|selector| html_document.select(&selector).next())
    .map(|elem| elem.inner_html())?;

title_candidates.insert(&*title_tag_text, 1);

Selector::parse("h1, h2, h3, .title")
    .ok()
    .as_ref()
    .map(|selector| html_document.select(selector))?
    .map(|elem| elem.inner_html()) // std::string::String
    .for_each(|title| {
        *title_candidates.entry(&*title).or_insert(0) += 1;
        // if title_tag_text.contains(&*title.as_str()) {
        //     *title_candidates.entry(&*title_tag_text) += 1;
        // }
    });

error[E0597]: `title` does not live long enough
   --> src/main.rs:140:39
    |
125 |     let mut title_candidates: HashMap<&str, u8> = HashMap::new();
    |         -------------------- lifetime `'1` appears in the type of `title_candidates`
...
140 |             *title_candidates.entry(&*title).or_insert(0) += 1;
    |              -------------------------^^^^^-
    |              |                        |
    |              |                        borrowed value does not live long enough
    |              argument requires that `title` is borrowed for `'1`
...
144 |         });
    |         - `title` dropped here while still borrowed
like image 804
Miranda Abbasi Avatar asked Oct 29 '25 08:10

Miranda Abbasi


1 Answers

Your HashMap's keys are of type &str. This means that the HashMap only holds a reference to a str and not the str itself. Therefore, for the data in the HashMap to be valid, the reference to the str should live at least as long as the HashMap. Now the issue is, the String is being created in .map(|elem| elem.inner_html()) and therefore it gets dropped after that statement is completed.

Instead, create a HashMap which uses owned Strings instead of references. Below is a simplified example that you can adapt for your case:

fn main() {
    let mut data: HashMap<String, i32> = HashMap::new();

    (0..20)
        .map(|i| (i % 10).to_string())
        .for_each(|text| {
            *data.entry(text).or_insert(0) += 1;
        });
}

Here, .map(|i| (i % 10).to_string()) creates a String whose ownership is then passed to the HashMap in data.entry(text) thus avoiding any mismatches in the lifetimes of references.

Rust Playground

like image 113
sshashank124 Avatar answered Oct 30 '25 23:10

sshashank124



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!