Skip to content

Disallow taking non zero-sized constants by mutable reference #885

@petrochenkov

Description

@petrochenkov

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.breaking-changeThe RFC proposes a breaking change.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions