1

I am trying to use the builder pattern in Rust, however I am getting a compilation error.

pub struct DynamicParams {
    port: Option<u16>,
} 

impl DynamicParams {
    pub fn new() -> Self {
        DynamicParams { port: None }
    }

    pub fn port(&mut self, port: u16) -> &mut Self {
        self.port = Some(port);
        self
    }
}

fn main() {
    let params = DynamicParams::new().port(1);
}

It's available on play.rust-lang.org.

Error:

error: borrowed value does not live long enough
  --> <anon>:17:18
   |>
17 |>     let params = DynamicParams::new().port(1);
   |>                  ^^^^^^^^^^^^^^^^^^^^ does not live long enough
note: reference must be valid for the block suffix following statement 0 at 17:46...
  --> <anon>:17:47
   |>
17 |>     let params = DynamicParams::new().port(1);
   |>                                               ^
note: ...but borrowed value is only valid for the statement at 17:4
  --> <anon>:17:5
   |>
17 |>     let params = DynamicParams::new().port(1);
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
   --> <anon>:17:5
   |>
17 |>     let params = DynamicParams::new().port(1);
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

However as near as I can see, this is very similar to the builder pattern, as described in the Rust book. What's going on? What am I doing wrong?

I'm using Rust 1.11.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Amandasaurus
  • 58,203
  • 71
  • 188
  • 248
  • I asked a concise Question for this common rust error `error[E0716]` [error E0716: temporary value dropped while borrowed (rust)](https://stackoverflow.com/questions/71626083/error-e0716-temporary-value-dropped-while-borrowed-rust). It links back to this Question. – JamesThomasMoon Mar 26 '22 at 07:23

1 Answers1

3

You seem to be missing a finalizing method returning an owned object, like:

pub fn finalize(&self) -> DynamicParams {
    DynamicParams { port: self.port }
}

When you have it you can do the following:

let params = DynamicParams::new().port(1).finalize();

Which works, because the right hand expression does not return a reference, but an owned object. port() only returns a mutable reference; the object created by new() would have to be introduced by an earlier let binding in order for a reference to it to be valid.

ljedrz
  • 20,316
  • 4
  • 69
  • 97
  • Thanks! I've changed my getter methods to work on owned objects, and return that. Not references. Then I don't need the `.finalize()` – Amandasaurus Sep 15 '16 at 13:55