windwarrior
windwarrior

Reputation: 456

Multiple uses of self in same function

I have an argument with the borrow checker. My problem is a little more complex, but for this case I am using a buffer like structure. My buffer has a function safe_write_to_slot that first retrieves the first empty element (returning a result that is either Ok(location) or an Err(error message)) and then writes a value to that retrieved location. The problem however is that when I assign the location that was retrieved to a value rust complains that I am reusing self again a few lines later. How do I first call a (self) function that returns a result, and then move on with self to do some action?

use std::result::Result;

struct Elems {
    pub elems : Vec<int>,
}

impl Elems {
    pub fn new() -> Elems {
        Elems{elems: vec![0,0,0,0,0,0]}
    }

    pub fn safe_write_to_slot(&mut self, elem : uint) -> Result<(), &str> {
        let loc = try!(self.get_slot());

        self.unsafe_write_to_slot(loc);

        Ok(())
    }

    pub fn get_slot(&self) -> Result<uint, &str>{
        let mut loc = -1i;

        for x in range(0, self.elems.len()) {
            if *self.elems.get(x) == 0 {
                loc = x as int;
            }
        }

        if loc != -1 { Ok(loc as uint) } else { Err("No free slots") }
    }

    fn unsafe_write_to_slot(&mut self, elem : uint) {
        self.elems[elem] = 1;
    }
}

The error that I get is:

   Compiling borrow v0.0.1 (file:///borrow)
main.rs:19:9: 19:13 error: cannot borrow `*self` as mutable because it is also borrowed as immutable
main.rs:19         self.unsafe_write_to_slot(loc);
                   ^~~~
main.rs:17:24: 17:28 note: previous borrow of `*self` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*self` until the borrow ends
main.rs:17         let loc = try!(self.get_slot());
                                  ^~~~
/main.rs:17:19: 17:41 note: expansion site
main.rs:22:6: 22:6 note: previous borrow ends here
main.rs:16     pub fn safe_write_to_slot(&mut self, elem : uint) -> Result<(), &str> {
/main.rs:22     }
               ^
main.rs:37:9: 37:29 error: cannot assign to immutable dereference (dereference is implicit, due to indexing)
main.rs:37         self.elems[elem] = 1;
                   ^~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
Could not compile `borrow`.

To learn more, run the command again with --verbose.

Upvotes: 2

Views: 439

Answers (1)

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65732

Lifetime inference is causing the issue here.

The get_slot method is interpreted as:

pub fn get_slot<'a>(&'a self) -> Result<uint, &'a str> {

The result is bound to the same lifetime as self, which causes self to remain frozen until the result is dropped. However, you don't want to link the lifetime of self to &str, because you're only returning string literals. By changing &str to &'static str in get_slot and safe_write_to_slot, you won't get the error anymore, because self will not be considered borrowed anymore when calling unsafe_write_to_slot.

Upvotes: 4

Related Questions