1

I'm trying to write some code which unwraps an Option<&mut T> and provides an error message in the panic, however the error message itself comes from the type I'm mutably borrowing for the Option<&mut T>.

Contrived example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d938c198418f346d7ffd570cda4268a4

struct Foo {
    bar: Bar,
}

struct Bar {
    value: String,
    error: String,
}

impl Bar {
    fn get_value(&mut self) -> Option<&mut String> {
        if self.error.len() > 0 {
            None
        } else {
            Some(&mut self.value)
        }
    }
}

impl Foo {
    fn get_value_or_panic_with_error(&mut self) -> &mut String {
        match self.bar.get_value() {
            Some(reference) => reference,
            None => panic!("{:?}", self.bar.error)
        }
    }
}

fn main() {
    (Foo {
        bar: Bar {
            value: "a".to_owned(),
            error: "".to_owned(),
        }
    }).get_value_or_panic_with_error();
}

I can understand why the borrow checker doesn't like this because it sees me taking a mutable borrow to get my Option<&mut String> and then taking an immutable borrow on the same thing, however I can't seem to find any way to end the mutable borrow early for the None case as far as the borrow checker is concerned. I've tried dropping the Option if it's None before making the immutable borrow but the borrow checker still complains with the same error.

Dominik
  • 6,078
  • 8
  • 37
  • 61
Skeletonxf
  • 341
  • 2
  • 7
  • 1
    It's a common issue, probably the major outstanding borrow checker bug and affectionately(?) known as "Problem Case #3" from the blog post that is linked in one of the answers. On nightly you can test the experimental borrow checker by providing `-Z polonius` to rustc; however, for now we have to make do with some awkward workarounds. – trent Oct 07 '21 at 21:24
  • 1
    [Here's a workaround of the "check first" variety](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=090666e253852a04a22162770a075f5f). The `if has_value() { get_value().unwrap() }` pattern is awkward and unfortunate here but it works. – trent Oct 07 '21 at 21:29
  • Thanks, unfortunately for the code where I hit this problem I can't write a `has_value()` function but useful to know this is being worked on – Skeletonxf Oct 08 '21 at 21:15

0 Answers0