Borrow checker won't let me call getter after calling setter

Viewed 136

I have been working on a simple lexer in rust. However, I have ran into the error[E0502]: cannot borrow 'a_rule' as immutable because it is also borrowed as mutable problem. I have checked other answers and I can't seem to find the reason.

pub struct Rule<'a> {
    selector: &'a str,
}

impl<'a> Rule<'a> {
    pub fn new(selector: &'a str) -> Self {
        Self {
            selector
        }
    }

    pub fn get_selector(&'a self) -> &'a str {
        self.selector
    }

    pub fn set_selector(&'a mut self, selector: &'a str) {
        self.selector = selector
    }
}

#[cfg(test)]
mod tests {
    use super::Rule;

    #[test]
    fn set_selector_test() {
        let mut a_rule = Rule::new(".foo");
        a_rule.set_selector(".bar");

        assert_eq!(a_rule.get_selector(), ".bar")
    }
}

Error:

error[E0502]: cannot borrow `a_rule` as immutable because it is also borrowed as mutable
  --> src/lib.rs:30:20
   |
28 |         a_rule.set_selector(".bar");
   |         ------ mutable borrow occurs here
29 | 
30 |         assert_eq!(a_rule.get_selector(), ".bar")
   |                    ^^^^^^
   |                    |
   |                    immutable borrow occurs here
   |                    mutable borrow later used here

(Playground)

I would also like to use the opportunity to ask if it is recommended or not to use java like get and set methods or just set the members within a struct as public.

Please feel free to call out any other dumb mistakes.

1 Answers

You’ve tied the lifetime of your rule to the lifetime of your string by making get_selector and set_selector take &'a self/&'a mut self, but that’s not the correct relationship between them. You can produce &'a strs without needing your self to live that long (or be borrowed mutably for that long) because self.selector is already an &'a str.

Remove the 'a on the self references:

pub fn get_selector(&self) -> &'a str {
    self.selector
}

pub fn set_selector(&mut self, selector: &'a str) {
    self.selector = selector;
}

(but do you need this getter and setter at all? consider immutability!)

Related