-1

I am trying to implement the builder pattern in Rust, but am running into some issues. I am new to the ownership paradigm that Rust follows, so maybe some knowledge gap there has resulted in the issue, where dereferencing and movement of structs is not happening properly.

Here is the code for my Builder:

pub(crate) struct Builder {
    member1 : String,
    /* other members */
}

impl Builder {

    pub fn new() -> Builder {
        return Builder {
            member1 : "".to_string(),
            /* other members */
        };
    }

    pub fn member1(mut self, member1 : &String) -> Builder {
        self.member1 = member1.clone();
        return self;
    }

    /* other setters */

    pub fn build(&self) -> Target {
        return Target {
            member1 : self.member1.clone(),
            /* other members */
        }
    }

}


I have tried interacting with this builder in two different ways, and getting an error both times.

First method : Creating a variable Builder and trying to use it.

let mem1 : &String = &"sample".to_owned();
let builder : Builder = Builder::new();
builder.member1(some_str);
builder.build();

Here, the error : borrow of moved value : 'builder'


Second method : Creating a reference to the builder, and trying to interact with it

let mem1 : &String = &"sample".to_owned();
let builder : &Builder = &Builder::new();
builder.member1(some_str);
builder.build();

Here, the error : cannot move out of *builder which is behind a shared reference


If I use * to dereference, it tells me to implement Deref trait, and once I do that, it is still unable to dereference because of recursion limit which I set very high, but still no luck.

Please give me any ideas on how to proceed.

1 Answers1

1

Your member1 method takes ownership of self and returns it again, but you don't store it anywhere. So you could just do that:

let mem1 = &"sample".to_owned();
let builder = Builder::new();
let builder = builder.member1(some_str);
builder.build();

Or since you only change the object, not it's type, you don't really need ownership of it so you could instead only take a mutable reference:

// …

    pub fn member1(&mut self, member1 : &String) {
        self.member1 = member1.clone();
    }

// …

let mem1 = &"sample".to_owned();
let mut builder = Builder::new();
builder.member1(some_str);
builder.build();

A couple of notes:

  • the akward &"sample".to_owned() is precisely why you shouldn't take &String as arguments
  • usually in Rust if you can leave off the type information off a let binding especially if it's as redundant as in let builder : Builder = Builder::new(); where the type information is right there.
cafce25
  • 15,907
  • 4
  • 25
  • 31