0
votes

I have a struct with a field containing references to other structs (that I did not define)

struct HtmlHandlebars {
    user_helpers: Vec<(String, Box<HelperDef + 'static>)>,
}

And HtmlHandlebars has to implement a function

fn render(&self, ...) -> &self

And in that function I would need to move the Box to another function. Something like this:

fn render(&self, ...) -> &self {
    let mut handlebars = Handlebars::new();
    for (name, helper) in self.user_helpers {
        handlebars.register_helper(&name, helper);
    }
}

But I am kind of stuck because:

  • I can't move the Box references because I am borrowing self
  • I can't copy the Box references because that struct does not implement copy
  • I can't modify &self to &mut self because that causes other problems...

Maybe I am doing it completely wrong.. Is there something else I can do? What are my options?

If you need a more complete overview of the code, you can find it here

PS: I had no idea how to describe the situation in the title, feel free to change it

1
I would guess you're doing it completely wrong. You can't pass a borrowed value to something that takes ownership - that's the whole point of the borrow checker. - Veedrac
Yeah I know that ;) But I am not sure how I could accomplish it. I have no problem recoding it completely if it is going to make my code better. But I have no clue how I could organize my code for it to work. - Mathieu David

1 Answers

0
votes

The code you've written is trying to consume the Vec and its elements. In general, you can iterate over &self.user_helpers which will give you references to the elements rather than consuming them. That is (modulo silly typos in the pattern):

for &(ref name, ref helper) in self.user_helpers {
    handlebars.register_helper(name, helper);
}

See also: The Rust Programming Language on iterating vectors.

There is a problem with that though: Handlebars needs ownership of the helpers. It may very well be that you have to create a new Handlebars object every time you render, but in that case you also need to be able to create all the helpers every time you create a new Handlebars. There is no way to take ownership of the boxes without taking at least a &mut reference to the Vec. You need at least mutable access to take the handlers out of the struct. And if you did that, you wouldn't have the handlers around for the next time render() is called. Depending on how configurable the set of handlers is, you could have a function that constructs the Vec<Box<HelperDef + 'static>> out of thin air when you need it, or you could maintain a list of callbacks that construct Box<HelperDef + 'static> for you.