0

Here what I want to achieve:

trait Foo {
    fn readonly(&self) -> i32;
    fn modify(&mut self, val: i32);
}

struct FooWrapper<'a> {
    foo: &'a Foo,
}

impl<'a> FooWrapper<'a> {
    fn readonly(&self) -> i32 {
        self.foo.readonly()
    }

    fn modify(&mut self, val: i32) {
        self.foo.modify(val);//!!!
    }
}

As input I got &Foo and &mut Foo, like: fn func(a: &Foo, b: &mut Foo).

I want then wrap them inside FooWraper, and use it's methods to work with Foo.

But as you see compiler not allow code marked with //!!!.

Any way to fix this without code duplication like:

struct FooWrapper<'a> {
    foo: &'a Foo,
}
struct FooWrapperMut<'a> {
    foo: &'a mut Foo,
}
impl<'a> FooWrapper<'a>..
impl<'a> FooWrapperMut<'a>..

?

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
user1244932
  • 7,352
  • 5
  • 46
  • 103
  • *But as you see compiler not allow code* — you need to include the complete compiler error. It is not acceptable to simply state that an error occurs. – Shepmaster Jun 09 '17 at 12:43

1 Answers1

2

Just make foo a mutable reference. Then it can be borrowed either mutably or immutably.

struct FooWrapper<'a> {
    foo: &'a mut Foo,
}

A &mut T reference can always be coerced to a &T.

If you wanted to provide minimal functionality for an immutable reference and some additional methods if you able to get a mutable reference, you could maybe split it out with type parameter:

trait Foo {
    fn readonly(&self) -> i32;
    fn modify(&mut self, val: i32);
}

struct FooWrapper<T> {
    foo: T,
}

impl <'a> FooWrapper<&'a Foo> {
    fn readonly(&self) -> i32 {
        self.foo.readonly()
    }
}

impl <'a> FooWrapper<&'a mut Foo> {
    fn modify(&mut self, val: i32) {
        self.foo.modify(val); //
    }
}

Now you can supply the type parameter to be either &mut Foo or just &Foo, depending on what you have.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • "Just make foo a mutable reference" I cann't, if I get `&Foo` as input how can I construct `&mut Foo` from it? See `func` as example. – user1244932 Jun 09 '17 at 12:12
  • 1
    You probably need to include more code in order to explain your problem, and to show that it is different from the duplicate (if it is). – Peter Hall Jun 09 '17 at 15:11