Trying to borrow variable binding from outside of loop in Rust

569 Views Asked by At
    // I want to use this...
    let group = svg::node::element::Group::new();

    for (index, character) in label_string.char_indices() {

        let character = svg::node::Text::new(character);

        let text = svg::node::element::Text::new()
        .set("x", 0 + 16 * index)
        .set("y", 20)
        .set("font-family", "Hack")
        .set("font-size", 16)
        .set("fill", color::color(foreground_color))
        .add(character);

        // ...inside this for loop.
        group.add(text);

    }

But I am told use of moved value: group because value moved here, in previous iteration of loop.

Which makes sense. But I can't figure out how to just borrow group instead. The for syntax doesn't give me any way do this, and these haven't work either:

    for (index, character) in label_string.char_indices() {
        ...
        let group_ref = &group;
        group_ref.add(text);
    }
    let group_ref = &group;
    for (index, character) in label_string.char_indices() {
        ...
        group_ref.add(text);
    }

Note: Trying to borrow variable binding from outside of loop doesn't answer this question.

2

There are 2 best solutions below

2
Frxstrem On BEST ANSWER

svg::node::element::Group::add has the following signature:

impl Group {
    pub fn add<T>(self, node: T) -> Self
    where
        T: Node,
    { /* ... */ }
}

From this signature we can see that the method takes self by value (not by reference, like &self or &mut self), which means that when you call group.add(text) from within your loop, you move the value out of the group variable (since the add method needs to take ownership). By the next time iteration of the loop, there is no value in the variable, so the compiler will complain.

However, we can also see that the method returns Self, which indicates that we get a new value that we can just re-assign to group. That way, by the end of the iteration (and beginning of the next) we will have a value in the group variable that has not been moved out:

// note that we need this to be mut now, since we're reassigning within the loop
let mut group = svg::node::element::Group::new();

for (index, character) in label_string.char_indices() {
    // ...

    // since `group.add()` takes ownership of `group`, but returns a new value,
    // we can just reassign to `group`, so that it is present for the next iteration
    group = group.add(text);

}
0
jongguk.jo On

svg::node::element::Group::add function takes first argument as self and return Self.

Code can be fixed as

let mut group = svg::node::element::Group::new();
    ^^^
//...

// in for loop
group = group.add(text);
^^^^^^^