Search code examples
rusttype-conversionclonemoveborrow-checker

Can I reuse a struct field during type conversion without calling .clone()?


I currently have two similar structs, and I need to implement the From trait to convert one to the other. However, I'm getting an error that says:

error[E0382]: borrow of moved value: `item.my_first_string`
  --> src/lib.rs:14:30
   |
13 |             my_second_string: item.my_first_string,
   |                               -------------------- value moved here
14 |             string_is_empty: item.my_first_string.is_empty(),
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
   |
   = note: move occurs because `item.my_first_string` has type `String`, which does not implement the `Copy` trait

Here's what my code looks like:

struct Foo {
    my_first_string: String,
}

struct Bar {
    my_second_string: String,
    string_is_empty: bool,
}

impl From<Foo> for Bar {
    fn from(item: Foo) -> Self {
        Bar {
            my_second_string: item.my_first_string,
            string_is_empty: item.my_first_string.is_empty(),
        }
    }
}

I'm aware that I could just call .clone on my_first_string to satisfy the borrow checker, but this seems like it may be unnecessary. Is there a way to use this field twice without .clone()?


Solution

  • Just store the result of is_empty() is a variable before moving the string:

    impl From<Foo> for Bar {
        fn from(item: Foo) -> Self {
            let string_is_empty = item.my_first_string.is_empty();
            Bar {
                my_second_string: item.my_first_string,
                string_is_empty,
            }
        }
    }
    

    Or just inverse the order:

    impl From<Foo> for Bar {
        fn from(item: Foo) -> Self {
            Bar {
                string_is_empty: item.my_first_string.is_empty(),
                my_second_string: item.my_first_string,
            }
        }
    }