this is a know limitation of current borrow checker, search keyword polonius for full explanation. the short answer is, when a borrowed value is conditional returned, the borrow checker thinks the value must be alive across the entire function body, and extends the borrow lifetime accordingly.
it requires unsafe to work around it, but it is recommended to use this crate instead of writing the unsafe yourself:
use a raw pointer to "cheat" the lifetime analysis.
pub fn change(&mut self) -> Option<&u32> {
// save `self` as a raw pointer for later use
// raw pointers don't have lifetime associated with them
let selfp = self as *mut Self;
if let Some(a) = self.vec.get() {
return Some(a);
}
// be careful when dereferencing the raw pointer
// especially for *exclusive* reborrow, a.k.a. `mut` reference
// must not break the aliasing rule
unsafe {
(*selfp).vec.change();
}
None
}
in this example, it may seem simple enough, but always use miri to check you didn't break the rule.
UPDATE:
there's a better solution than my method, see the follow up by @robofinch:
Well, the answer to your literal question is never, AFAIK; I don't think the new Polonius borrow checker will be called NLL. Personally, I consider NLL to refer to the current pre-Polonius borrow checker.
I constrain the unsafe to within the if-let, and to check my work I usually add a polonius feature that fails to compile unless (and should compile if) the Polonius borrow checker is enabled:
if let Some(a) = self.vec.get() {
// SAFETY: This is only a lifetime cast. The aliasing rules are satisfied,
// as proven by how this compiles safely under Polonius.
#[cfg(not(feature = "polonius")]
let a = unsafe {
transmute::<&u32, &u32>(a)
};
return Some(a);
}