How to pass a mutable link to the builder, but only an immutable link to the constructed object?

When building, FooBuilderI want to provide &mut Bar. When I build Foo, I want to provide &Bar, but I Foohave to call methods &selffrom Bar. In other words, volatile borrowing should exist only throughout life FooBuilder.

struct FooBuilder<'a> {
    bar: &'a mut Bar,
}
impl<'a> FooBuilder<'a> {
    fn new(bar: &'a mut Bar) -> Self {
        FooBuilder { bar: bar }
    }
    fn build(&'a self) -> Foo<'a> {
        Foo { bar: &self.bar }
    }
}

struct Foo<'a> {
    bar: &'a Bar,
}

struct Bar;
impl Bar {
    fn bar(&self) {}
}

fn main() {
    let mut bar = Bar;
    let foo = FooBuilder::new(&mut bar).build();
    bar.bar();
}

This code has an error:

error: borrowed value does not live long enough
  --> <anon>:24:15
   |
24 |     let foo = FooBuilder::new(&mut bar).build();
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long     enough
   |
note: reference must be valid for the block suffix following     statement 1 at 24:48...
  --> <anon>:24:49
   |
24 |     let foo = FooBuilder::new(&mut bar).build();
   |                                                 ^
note: ...but borrowed value is only valid for the statement at 24:4
  --> <anon>:24:5
   |
24 |     let foo = FooBuilder::new(&mut bar).build();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
  --> <anon>:24:5
   |
24 |     let foo = FooBuilder::new(&mut bar).build();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0502]: cannot borrow `bar` as immutable because it is also     borrowed as mutable
  --> <anon>:25:5
   |
24 |     let foo = FooBuilder::new(&mut bar).build();
   |                                    --- mutable borrow occurs     here
25 |     bar.bar();
   |     ^^^ immutable borrow occurs here
26 | }
   | - mutable borrow ends here

error: aborting due to 2 previous errors
+4
source share
2 answers

The first step is to fix it build.

To convert a &mut Tto &Tyou need to consume &mut T(otherwise you will have smoothing and volatility). It means:

  • builder consumes without referring to it
  • ,

, :

fn build(&'a self) -> Foo<'a> {
    Foo { bar: &self.bar }
}

fn build(self) -> Foo<'a> {
    Foo { bar: self.bar }
}

:

error: cannot borrow `bar` as immutable because it is also borrowed as mutable [--explain E0502]
  --> <anon>:25:5
24 |>     let foo = FooBuilder::new(&mut bar).build();
   |>                                    --- mutable borrow occurs here
25 |>     bar.bar();
   |>     ^^^ immutable borrow occurs here
26 |>     //foo.bar.bar();
27 |> }
   |> - mutable borrow ends here

, bar . , foo .

: bar bar foo. , , :

fn main() {
    let mut bar = Bar;
    {
        let foo = FooBuilder::new(&mut bar).build();
        // `bar` currently borrow (mutably) by `foo`, cannot use it directly
        foo.bar.bar();
    }
    // `bar` no longer borrowed, use at your heart content
    bar.bar();
}
+2

- , bar Rc. , Rc, &mut . ; &mut & , ( ) "" .

use std::rc::Rc;

struct FooBuilder<'a> {
    bar: &'a mut Rc<Bar>,
}
impl<'a> FooBuilder<'a> {
    fn new(bar: &'a mut Rc<Bar>) -> Self {
        FooBuilder { bar: bar }
    }
    fn f(mut self) -> Self {
        Rc::get_mut(self.bar).unwrap().mut_method();
        self
    }
    fn build(&'a self) -> Foo {
        Foo { bar: self.bar.clone() }
    }
}

struct Foo {
    bar: Rc<Bar>,
}

struct Bar;
impl Bar {
    fn bar(&self) {}
    fn mut_method(&mut self) {}
}

fn main() {
    let mut bar = Rc::new(Bar);
    let foo = FooBuilder::new(&mut bar).f().build();
    bar.bar();
}

Foo Rc, , mut (, , None Rc::get_mut()).

, ; FooBuilder Foo bar, , - , &mut T.

, , , , .

+1

Source: https://habr.com/ru/post/1649446/


All Articles