Mutability and Recursion

Your code will compile under the next generation borrow checker:

Polonius


Since it is currently experimental, you can only use it with the nightly-only -Zpolonius rust flag. So what I like to do in this situation is the following pattern (beware that doctests only work on lib.rs crates, not on main.rs):

fn var_mut_at (self: &'_ mut Self, level: usize, name: &'_ str)
  -> Option<&'_ mut Var>
{
    let var: Option<&mut Var> =
        self.stack[level]
            .map
            .get_mut(name)
    ;
    #[cfg(not(feature = "polonius"))]
    let var: Option<&mut Var> = unsafe {
        ::core::mem::transmute(var)
    };
    doc_test! {
        assert!(
            ::std::process::Command::new("cargo")
                .arg("+nightly")
                .arg("rustc")
                .arg("--features").arg("polonius")
                .arg("--")
                .arg("-Zpolonius")
                .status()
                .expect("Failed to run command")
                .sucess()
        );
    }
    if let Some(&mut Var::Level(at)) = var {
        self.var_mut_at(at, name)
    } else {
        var
    }
}
  • Playground

  • If you test it on your machine (with

    [features]
    polonius = []
    

    on your Cargo.toml), you will see that cargo test --doc passes, meaning that cargo +nightly rustc --features polonius -- -Z polonius succeeds.

1 Like