-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
As @eddyb explained here, constants (const
items) no longer behave as rvalues when taken by immutable reference (or by mutable reference in case of zero-sized constants).
Yet they still behave as rvalues and create a temporary on the stack when taken by mutable reference:
const C: u8 = 0;
fn main() {
let c = &mut C; // A mutable temporary is created
*c = 1;
}
One more example where the mutable borrowing is implicit and the result is very confusing:
const A: [u8; 3] = [1, 2, 3];
fn main() {
A[0] = 4; // Surprise!
}
I suggest to prohibit taking constants by mutable reference.
If necessary, the mutable temporary can be created explicitly.
It is rarely needed and the prohibition would not affect ergonomics.
The achieved explicitness would be beneficial for both a reader (it's clearly visible that the reference doesn't bind directly and temporary is created) and a writer (no potential mistakes with surprising consequences) of the code.
A more radical solution would be to disallow taking all rvalues by mutable reference, like C++ does.
If you know the history, early C++ allowed it for a long time, but in the end it was prohibited anyway during the standardization. The consequences are still visible today - Visual C++ still has to allow binding mutable references to temporaries to preserve backward compatibility with older code.