Lifetime in match if let and while let

I just discovered this behavior yesterday and then opened (and closed) an issue. It's a genuine footgun, and it makes using both Mutex and RefCell slightly harder, as if they weren't hard enough!

Consider this snippet:

let x = RefCell::new(0i32);

// Panics
match x.borrow().is_negative() {
    _ => { *x.borrow_mut() = 0 },
}

// Succeeds
let tmp = x.borrow().is_negative();
match tmp {
    _ => { *x.borrow_mut() = 0 },
}

The former match statement panics while the latter does not, but I suspect very few Rust users would have guessed this outcome without already knowing the answer. It violates the substitution principle, which says that simply assigning to an intermediate variable should produce an equivalent program.

Lifetime extension is useful and works well when assigning a temporary reference to a variable, but the issue here is that match statements are activating lifetime extension all the time and not just when necessary. Imagine we had this kind of desugaring going on:

// Before
match <expression> { ... }
// After
{
    let tmp = <expression>;
    match tmp { ... }
}

Then, the regular rules for activating lifetime extension would be used rather than having match statements be a weird exception where it's forced on at all times.

It's a breaking change, but I think if someone wants a temporary to live longer, they should be explicit about it and assign it to a variable instead of relying on a hard-to-discover rule.