[SOLVED] Is correct solution with borrowed value does not live long enough error


#1

I’m learning Rust, and I wrote the following code to extract useful data from HTML documents with the select.rs crate.

let document = Document::from(&*html);
for node in document.find(Name("a")).iter() {
    let anchor = node.text().trim();
    match node.attr("href") {
        Some(href) => {
            if anchor.len() > 0 {
                println!("Anchor: {}, Link: ({:?})", anchor, href);
            } else {
                println!("Anchor: [No anchor], Link: ({:?})", href);
            }
        }
        None => (),
    }
}

src\main.rs:29:38: 29:49 error: borrowed value does not live long enough
src\main.rs:29 let anchor = node.text().trim();

This confuses me. Is it text() or trim() that doesn’t live long enough?
I do this:

for node in document.find(Name("a")).iter() {
    let anchor = node.text();
    let anchor = anchor.trim();

This worked fine, but is it good hint?


#2

The text method returns a String value, which owns a copy of the string on the heap. (No documentation linked to crates.io, so have a source code reference instead.)

Since you didn’t assign the String to a variable, Rust by default assumes that you want to destroy the string at the end of the current statement. But that’s a problem, because trim() doesn’t copy the string — it returns a pointer and length into the middle, as a &str — and that pointer would not remain valid long enough to use, if the string returned by text() were to be immediately destroyed.

Your fix is correct; assigning values to let-bindings is how you tell Rust that you want those values to stick around (until the end of the current block).

Something else you could do in cases like this is to add .to_owned() to the line; that would immediately copy the text a second time, so the first copy could safely be deleted. The type of anchor would then change from &str to String, indicating that it stands alone rather than referencing another value. In this case you don’t want to do that because the second copy is unnecessary, but this would be useful if you needed anchor to last longer than the current block.


#3

Thanks, this brings the question on the use of String vs &str :confused:


#4

https://www.rust-lang.org/en-US/faq.html#what-are-the-differences-between-str-and-string

https://doc.rust-lang.org/book/strings.html

(I have checked the last one and it is still accurate)

Basically — are you handling a string that needs to be able to survive on its own for a long time, or is this a short-lived reference to a string that “someone else” is managing?