0

Given two snippets, which tries to return reference to a member value from self, I really can't understand why the one with separate function doesn't compile.

This works (godbolt):

struct Foo {
    a: bool,
    b: u32,
}

impl Foo {
    fn get(&mut self) -> &u32 {
        if self.a {
            return &self.b;
        }
        
        self.a = true;
        self.b = 10;
        
        return &self.b;
    }
}

While this doesn't (godbolt):

struct Foo {
    a: bool,
    b: u32,
}

impl Foo {
    fn try_get(&self) -> Option<&u32> {
        if self.a {
            return Some(&self.b);
        }
        return None;
    }
    
    fn get(&mut self) -> &u32 {
        if let Some(val) = self.try_get() {
            return val;
        }
        
        self.a = true;
        self.b = 10;
        
        return &self.b;
    }
}

Error:

error[E0506]: cannot assign to `self.a` because it is borrowed
  --> src/lib.rs:19:9
   |
14 |     fn get(&mut self) -> &u32 {
   |            - let's call the lifetime of this reference `'1`
15 |         if let Some(val) = self.try_get() {
   |                            -------------- borrow of `self.a` occurs here
16 |             return val;
   |                    --- returning this value requires that `*self` is borrowed for `'1`
...
19 |         self.a = true;
   |         ^^^^^^^^^^^^^ assignment to borrowed `self.a` occurs here

As I understand, it can't see, that reference at the top will be released before mutable change, but why? It can prove it without the function, why can't it do it with?
Is there any way to make function call work?
For me this really looks like a bug

Masafi
  • 151
  • 2
  • 15

1 Answers1

0

I didn't see similar answer before, but after edits stackoverflow found: Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?

TLDR: yes, it is a known bug and will be fixed, and in such implementation there is no (useful) way to use function
https://github.com/rust-lang/rust/issues/21906#issuecomment-73296543

Masafi
  • 151
  • 2
  • 15