-1

I have the following code

pub struct Something {
    value: usize,
}

impl Something {
    pub fn get_and_increment(&mut self) -> &[u8] {
        let res = self.get();
        self.value += 1;

        res
    }

    pub fn get(&self) -> &[u8] {
        &[3; 2]
    }
}

When I try to compile this I get this error:

error[E0506]: cannot assign to `self.value` because it is borrowed
 --> src/main.rs:8:9
  |
7 |         let res = self.get();
  |                   ---- borrow of `self.value` occurs here
8 |         self.value += 1;
  |         ^^^^^^^^^^^^^^^ assignment to borrowed `self.value` occurs here

If I change the return type of each function to u8 rather than &[u8] it compiles just fine:

pub struct Something {
    value: usize,
}

impl Something {
    pub fn get_and_increment(&mut self) -> u8 {
        let res = self.get();
        self.value += 1;

        res
    }

    pub fn get(&self) -> u8 {
        3
    }
}

Why is it that Rust doesn't let me use the value property of Something in the get_and_increment function after self.get is called but only when both functions return &[u8]?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
linuxuser
  • 121
  • 7

1 Answers1

2

I highly recommend going back and re-reading The Rust Programming Language, specifically the chapter about references and borrowing.

Why does returning a &[u8] rather than u8 from a function in Rust borrow self?

You are essentially asking

why does returning «something that is borrowed» rather than «something that is not borrowed» from a function «require a borrow»?

The contrite answer is: because a u8 is not borrowed while a &[u8] is borrowed.

Why is it that Rust doesn't let me use the value property

Because the compiler doesn't know what values of self are returned as part of get when checking the body of get_and_increment. It's entirely possible that your implementation of get returns a reference to value, or it might in the future, so the compiler has to take the conservative route and disallow it.

but only when both functions return &[u8]?

This is not accurate. The return type of get_and_increment has no impact on the error. The return type of get only matters in that it contains a reference.


There's no obvious reason for you to return a reference, however:

pub fn get(&self) -> [u8; 2] {
    [3; 2]
}

If you wanted to return a reference for some reason, it doesn't need to be tied to the lifetime of self (which your code does due to lifetime elision):

pub fn get(&self) -> &'static [u8] {
    &[3; 2]
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366