Cannot return reference to temporary value

Hi! I'm trying to use kuchikiki to parse and replace text nodes in html fragments, but I keep getting this error;

error[E0515]: cannot return reference to temporary value
  --> src\main.rs:27:71
   |
27 |         text_node = NodeDataRef::new(text_node.as_node().clone(), |_| &RefCell::new(new_text[index].clone()));
   |                                                                       ^-------------------------------------
   |                                                                       ||
   |                                                                       |temporary value created here
   |                                                                       returns a reference to data owned by the current function

Here's a reproducible example:

let html = "<p>woo<em>hoo</em></p>";
let document = kuchikiki::parse_html().one(html);

let text_list = vec!["hoo".to_string(), "woo".to_string()];

    for (index, mut text_node) in document.select("p").unwrap().next().expect("").as_node().descendants().text_nodes().enumerate() {
        text_node = NodeDataRef::new(text_node.as_node().clone(), |_| &RefCell::new(text_list[index].clone()));
        println!("{:?}", text_node);
    }

I can't find any solution that works, so any help will be appreciated. Thanks!

Indeed, you can't return references to local variables from a closure (or function), because the local variables drop (or are otherwise moved) by the end of the closure/function.

The signature of the closure you pass to new is FnOnce(&Node) -> &T, which basically means the T has to already exist in the Node (or is static, or is leaked (which you practically never want)).

1 Like

Does this just mean it's not possible? Is there another way to do this?

You can't create a RefCell in a closure and return a reference to it (without leaking it).

But I can't really answer your question, because I don't understand what you're actually trying to accomplish (nor do I know kuchikiki outside of what I go look up on the fly).

After clicking around the docs awhile, you may be able to do something like...

let iter = document.select("p"). ... .text_nodes();
for (text_node, replacement) in iter.zip(text_list.iter()) {
    let data = text_node.data(); // or text_node.as_node().data() maybe
    if let NodeData::Text(cell) = data {
        *cell.borrow_mut() = replacement.clone();
    }
}

Untested.

The idea is you want to find a way to get ahold of a reference to this data structure, at which point you can overwrite the text contents via the RefCells.

Solved. I used text_node.replace(text_list[index].clone())

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.