Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promotion of non-ZST mutable references is incompatible with const_mut_refs #75556

Closed
RalfJung opened this issue Aug 15, 2020 · 1 comment · Fixed by #75585
Closed

Promotion of non-ZST mutable references is incompatible with const_mut_refs #75556

RalfJung opened this issue Aug 15, 2020 · 1 comment · Fixed by #75585
Labels
A-const-eval Area: constant evaluation (mir interpretation) C-bug Category: This is a bug. F-const_mut_refs `#![feature(const_mut_refs)]` requires-nightly This issue requires a nightly compiler in some way.

Comments

@RalfJung
Copy link
Member

RalfJung commented Aug 15, 2020

Consider the following code:

#![feature(const_mut_refs)]

static mut TEST: () = {
    let x = &mut [1,2,3];
    x[0] += 1;
};

This should just work. But instead it throws an error:

error[E0080]: could not evaluate static initializer
 --> src/lib.rs:5:5
  |
5 |     x[0] += 1;
  |     ^^^^^^^^^ modifying a static's initial value from another static's initializer

The reason for this is that &mut [1,2,3] gets lifetime extended via promotion, so this reference now points to a separate mutable static -- but mutable statics cannot be mutated during CTFE.

I see no way to fix this, other than stopping to promote mutable references -- which we should IMO do anyway, they are a very strange and unprincipled special case. Just imagine doing this in a loop, suddenly all these different and mutable allocations share the same address...

Cc @rust-lang/wg-const-eval

@RalfJung RalfJung added A-const-eval Area: constant evaluation (mir interpretation) C-bug Category: This is a bug. F-const_mut_refs `#![feature(const_mut_refs)]` requires-nightly This issue requires a nightly compiler in some way. labels Aug 15, 2020
@eddyb
Copy link
Member

eddyb commented Aug 16, 2020

Ugh, that's an ancient rule (believe it or not, it's a workaround for not being able to write static mut Foo: [T; _] = ...; and have the length be inferred!) and it was never meant to get this far, I guess I didn't think it through properly when adding the "outermost scope" rule, which is the only position where allowing it makes sense.

In the current implementation, it should've never been promoted, only allowed, my bad!

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Sep 7, 2020
Do not promote &mut of a non-ZST ever

Since ~pre-1.0~ 1.36, we have accepted code like this:
```rust
static mut TEST: &'static mut [i32] = {
    let x = &mut [1,2,3];
    x
};
```
I tracked it back to rust-lang#21744, but unfortunately could not find any discussion or RFC that would explain why we thought this was a good idea. And it's not, it breaks all sorts of things -- see rust-lang#75556.

To fix rust-lang#75556, we have to stop promoting non-ZST mutable references no matter the context, which is what this PR does. It's a breaking change.

Notice that this still works, since it does not rely on promotion:
```rust
static mut TEST: &'static mut [i32] = &mut [0,1,2];
```

Cc @rust-lang/wg-const-eval
@bors bors closed this as completed in e82584a Sep 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: constant evaluation (mir interpretation) C-bug Category: This is a bug. F-const_mut_refs `#![feature(const_mut_refs)]` requires-nightly This issue requires a nightly compiler in some way.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants