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

Do not promote &mut of a non-ZST ever #75585

Merged
merged 2 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions compiler/rustc_mir/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,15 +364,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
// is allowed right now, and only in functions.
if self.const_kind
== Some(hir::ConstContext::Static(hir::Mutability::Mut))
{
// Inside a `static mut`, &mut [...] is also allowed.
match ty.kind() {
ty::Array(..) | ty::Slice(_) => {}
_ => return Err(Unpromotable),
}
} else if let ty::Array(_, len) = ty.kind() {
if let ty::Array(_, len) = ty.kind() {
// FIXME(eddyb) the `self.is_non_const_fn` condition
// seems unnecessary, given that this is merely a ZST.
match len.try_eval_usize(self.tcx, self.param_env) {
Expand Down Expand Up @@ -673,13 +665,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
// is allowed right now, and only in functions.
if self.const_kind == Some(hir::ConstContext::Static(hir::Mutability::Mut)) {
// Inside a `static mut`, &mut [...] is also allowed.
match ty.kind() {
ty::Array(..) | ty::Slice(_) => {}
_ => return Err(Unpromotable),
}
} else if let ty::Array(_, len) = ty.kind() {
if let ty::Array(_, len) = ty.kind() {
// FIXME(eddyb): We only return `Unpromotable` for `&mut []` inside a
// const context which seems unnecessary given that this is merely a ZST.
match len.try_eval_usize(self.tcx, self.param_env) {
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/consts/promote-no-mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// ignore-tidy-linelength
// We do not promote mutable references.
static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed

static mut TEST2: &'static mut [i32] = {
let x = &mut [1,2,3]; //~ ERROR temporary value dropped while borrowed
x
};

fn main() {}
23 changes: 23 additions & 0 deletions src/test/ui/consts/promote-no-mut.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-no-mut.rs:3:50
|
LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
| ----------^^^^^^^^^-
| | | |
| | | temporary value is freed at the end of this statement
| | creates a temporary which is freed while still in use
| using this value as a static requires that borrow lasts for `'static`

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-no-mut.rs:6:18
|
LL | let x = &mut [1,2,3];
| ^^^^^^^ creates a temporary which is freed while still in use
LL | x
| - using this value as a static requires that borrow lasts for `'static`
LL | };
| - temporary value is freed at the end of this statement

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0716`.
17 changes: 17 additions & 0 deletions src/test/ui/consts/promotion-mutable-ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// run-pass
#![feature(const_mut_refs)]

static mut TEST: i32 = {
// We must not promote this, as CTFE needs to be able to mutate it later.
let x = &mut [1,2,3];
x[0] += 1;
x[0]
};

// This still works -- it's not done via promotion.
#[allow(unused)]
static mut TEST2: &'static mut [i32] = &mut [0,1,2];

fn main() {
assert_eq!(unsafe { TEST }, 2);
}