0

I'm new to rust and have not got the lifetime specifier things yet. In order to separate different concerns into different stucts, I try to do something similar to the decorator pattern. However, the following code does not compile:

trait T {
    fn foo(self) -> u64;
}

struct Inner {}

impl T for Inner {
    fn foo(self) -> u64 {
        42
    }
}

struct Outer<'a> {
    delegate: &'a T,
}

impl<'a> T for Outer<'a> {
    fn foo(self) -> u64 {
        self.delegate.foo()
    }
}

pub fn dec_test() {
    let inner = &Inner {};
    let outer = Outer{delegate:inner};

    println!("Meaning of life: {}", outer.foo());
}

I get the following error

error[E0161]: cannot move a value of type dyn T: the size of dyn T cannot be statically determined
  --> src/lib.rs:19:9
   |
19 |         self.delegate.foo()
   |         ^^^^^^^^^^^^^

error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:19:9
   |
19 |         self.delegate.foo()
   |         ^^^^^^^^^^^^^ cannot move out of borrowed content

error: aborting due to 2 previous errors
hellow
  • 9,446
  • 5
  • 41
  • 61
Jockbert
  • 47
  • 5
  • Possible duplicate of [Cannot move out of borrowed content](https://stackoverflow.com/questions/28158738/cannot-move-out-of-borrowed-content) – timotree Feb 20 '19 at 05:21

1 Answers1

2

Ignoring the first error about unsized types, both of the second two errors are about the same problem: "cannot move out of borrowed content"

This smaller example triggers the same error:

struct Inner {}

impl Inner {
    // consumes self. requires ownership
    fn foo(self) -> u64 {
        42
    }
}

fn main() {
    let my_inner = Inner {};
    let borrow = &my_inner;
    let answer = borrow.foo(); // oops! we are using a borrowed version that we don't own
    println!("meaning of life {}", answer);
}

For more information see this answer, specifically the part about ownership or see chapter four of the rust book.

With your problem specifically, one fix is to change trait T so that it only borrows its argument:

trait T {
    fn foo(&self) -> u64; // notice the change: `self` -> `&self`
}

// ...

impl T for Inner {
    fn foo(&self) -> u64 { // notice the change: `self` -> `&self`
        42
    }
}

// ...

impl<'a> T for Outer<'a> {
    fn foo(&self) -> u64 { // notice the change: `self` -> `&self`
        self.delegate.foo()
    }
}

// ...
timotree
  • 765
  • 3
  • 23