Delay mutable borrows to destructured in if let and match expressions without boilerplate

struct A
{
}

struct B
{
}

struct C
{
    a: Option<A>,
    b: B,
}

fn test(_: &C) -> bool
{
  return true;
}

fn write(_: &mut A)
{
    
}

fn write_if(c: &mut C)
{
    if let Some(a) = &mut c.a {
        if (test(c)) {
            write(a);
        }
    }
}

The code above does not compile but I am unable to find a way to conditionaly mutate c.a without matching twice:


fn write_if(c: &mut C)
{
    if let Some(a) = &c.a {
        if (test(c)) {
            if let Some(a) = &mut c.a {
                write(a);
            }
        }
    }
}

The function test should not take a reference to the entire C, only it's field b. (If you also need the field a, that would be unsound.)

Such workaround is not feasible if test() requires access to both b and 'a'.
And there may be other workarounds for some specific circumstances.

Is it possible for the borrow check to figure out that the match expression in the above case does not mutate anything and the borrowing starts only when required (write()).

NLL does not seem to cover such cases.

After crawling through the documentation I am in the impression that it is a limitation of the borrow checker.

Not without some new mechanism like a "macro fn" or annotation that the accesses performed in the function body can be leaked to callers, etc. The signature of a function is a contract that describes what the caller and callee can and cannot assume, and there's currently no way to describe "this function accesses some fields but not others", say.[1]

Things would be too fragile if borrowing considerations leaked by default; changes to the function body which don't conflict with the signature would suddenly cause borrow errors downstream.

See also, view types and partial borrows.


  1. Without changing the type passed in, etc. ↩︎

That's specifically addressed by my 2nd phrase. That would be unsound. What you want would be incorrect.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.