This question already has answers here:
“borrowed value does not live long enough” seems to blame the wrong thing
(2 answers)
Why is it legal to borrow a temporary?
(3 answers)
Why does the compiler tell me to consider using a `let` binding" when I already am?
(2 answers)
Closed last year.
I'm trying to scrape a webpage using the Select crate:
let document = Document::from_read(response).unwrap();
for node in document.find(Class("lia-list-row")) {
let title = node.find(Class("page-link")).next().unwrap();
let title_text = title.text().trim();
println!("{}\n", title_text);
}
Which results in following error:
let title_text = title.text().trim();
^^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
creates a temporary which is freed while still in use
println!("{} - {}\n", i, title_text);
---------- borrow used here, in later iteration of loop
I solved it by separating the .text()
and .trim()
let title_text = title.text();
let trim_text = title_text.trim();
What is the difference? Why did the first attempt fail?
This one seems convoluted at first, but remember that String
and &str
are different beasts.
String
can live and be used on its own, but &str
is just a reference to part of String
. So, &str
can live as long as referenced String
lives. Lets see how it should work on return signatures.
let title_text = title .text() .trim();
// ^ ^ ^
// Node String <- &str
Here, title
is a select::Node
.
Node::text
returns a String
, but nothing binds it to context.
String::trim
, in turn, returns a &str
which is a reference to part of String
itself.
In the end, the borrow checker just doesn't understand how it should process a reference to String
that will not live long enough in context, as it is a temporary value (non-bound).