'How to prevent move in non-consuming builder pattern?

I am trying to create a struct with non-consuming builder pattern like this:

#[derive(Default)]
struct Person {
    first_name: String,
    last_name: String,
}

impl<'a> Person {
    pub fn first_name(&'a mut self, name: &str) -> &'a mut Self {
        self.first_name = name.to_owned();
        self
    }
    pub fn last_name(&'a mut self, name: &str) -> &'a mut Self {
        self.last_name = name.to_owned();
        self
    }

    pub fn greet(&self) -> String {
        format!("{:?} {:?}", self.first_name, self.last_name)
    }

    pub fn build(self) -> Self {
        self
    }
}

fn main() {
    let person = Person::default()
        .first_name("John")
        .last_name("Doe")
        .build();

    let name = person.greet();
}

But when I use build() to get the value back, I get a move error like this:


error[E0507]: cannot move out of a mutable reference
  --> builder/src/main.rs:27:18
   |
27 |       let person = Person::default()
   |  __________________^
28 | |         .first_name("John")
29 | |         .last_name("Doe")
30 | |         .build();
   | |________________^ move occurs because value has type `Person`, which does not implement the `Copy` trait

How can I use a non-consuming builder pattern while ensuring my code can work in multiple lines? Should I ditch the build() method?



Solution 1:[1]

I think you should use two struct, a PersonBuilder, and a Person. The PersonBuilder can collect the applicable info and its build method can check whether a complete Person can be built, and if so return a Person by moving its info into a new Person.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hkBst