Skip to content

Commit bc543d7

Browse files
committed
Allow assignments in const contexts
1 parent 7e82eda commit bc543d7

9 files changed

+143
-22
lines changed

src/librustc_mir/transform/qualify_consts.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,29 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
243243
return;
244244
}
245245

246+
if self.tcx.features().const_let {
247+
let mut dest = dest;
248+
let index = loop {
249+
match dest {
250+
Place::Local(index) => break *index,
251+
Place::Projection(proj) => dest = &proj.base,
252+
Place::Promoted(..) | Place::Static(..) => {
253+
// Catch more errors in the destination.
254+
self.visit_place(
255+
dest,
256+
PlaceContext::MutatingUse(MutatingUseContext::Store),
257+
location
258+
);
259+
return;
260+
}
261+
}
262+
};
263+
debug!("store to var {:?}", index);
264+
self.local_qualif[index] = Some(self.qualif);
265+
return;
266+
}
267+
246268
match *dest {
247-
Place::Local(index) if (self.mir.local_kind(index) == LocalKind::Var ||
248-
self.mir.local_kind(index) == LocalKind::Arg) &&
249-
self.tcx.sess.features_untracked().const_let => {
250-
debug!("store to var {:?}", index);
251-
self.local_qualif[index] = Some(self.qualif);
252-
}
253269
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp ||
254270
self.mir.local_kind(index) == LocalKind::ReturnPointer => {
255271
debug!("store to {:?} (temp or return pointer)", index);
@@ -478,6 +494,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
478494

479495
// Only allow statics (not consts) to refer to other statics.
480496
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
497+
if context.is_mutating_use() {
498+
self.tcx.sess.span_err(
499+
self.span,
500+
"cannot mutate statics in the initializer of another static",
501+
);
502+
}
481503
return;
482504
}
483505
self.add(Qualif::NOT_CONST);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// New test for #53818: modifying static memory at compile-time is not allowed.
12+
// The test should never compile successfully
13+
14+
#![feature(const_raw_ptr_deref)]
15+
#![feature(const_let)]
16+
17+
use std::cell::UnsafeCell;
18+
19+
struct Foo(UnsafeCell<u32>);
20+
21+
unsafe impl Send for Foo {}
22+
unsafe impl Sync for Foo {}
23+
24+
static FOO: Foo = Foo(UnsafeCell::new(42));
25+
26+
static BAR: () = unsafe {
27+
*FOO.0.get() = 5;
28+
};
29+
30+
static mut FOO2: u32 = 42;
31+
static BOO2: () = unsafe {
32+
FOO2 = 5;
33+
};
34+
35+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: cannot mutate statics in the initializer of another static
2+
--> $DIR/assign-to-static-within-other-static.rs:32:5
3+
|
4+
LL | FOO2 = 5;
5+
| ^^^^^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/consts/const-eval/mod-static-with-const-fn.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
// New test for #53818: modifying static memory at compile-time is not allowed.
12-
// The test should never succeed.
12+
// The test should never compile successfully
1313

1414
#![feature(const_raw_ptr_deref)]
1515
#![feature(const_let)]
@@ -27,9 +27,6 @@ fn foo() {}
2727

2828
static BAR: () = unsafe {
2929
*FOO.0.get() = 5;
30-
//~^ ERROR statements in statics are unstable (see issue #48821)
31-
// This error is caused by a separate bug that the feature gate error is reported
32-
// even though the feature gate "const_let" is active.
3330

3431
foo();
3532
//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
1-
error[E0658]: statements in statics are unstable (see issue #48821)
2-
--> $DIR/mod-static-with-const-fn.rs:29:5
3-
|
4-
LL | *FOO.0.get() = 5;
5-
| ^^^^^^^^^^^^^^^^
6-
|
7-
= help: add #![feature(const_let)] to the crate attributes to enable
8-
91
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
10-
--> $DIR/mod-static-with-const-fn.rs:34:5
2+
--> $DIR/mod-static-with-const-fn.rs:31:5
113
|
124
LL | foo();
135
| ^^^^^
146

15-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
168

17-
Some errors occurred: E0015, E0658.
18-
For more information about an error, try `rustc --explain E0015`.
9+
For more information about this error, try `rustc --explain E0015`.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// compile-pass
2+
3+
#![feature(const_let)]
4+
5+
struct S(i32);
6+
7+
const A: () = {
8+
let mut s = S(0);
9+
s.0 = 1;
10+
};
11+
12+
fn main() {}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// compile-pass
2+
3+
#![feature(const_let)]
4+
#![feature(const_fn)]
5+
6+
pub struct AA {
7+
pub data: [u8; 10],
8+
}
9+
10+
impl AA {
11+
pub const fn new() -> Self {
12+
let mut res: AA = AA { data: [0; 10] };
13+
res.data[0] = 5;
14+
res
15+
}
16+
}
17+
18+
static mut BB: AA = AA::new();
19+
20+
fn main() {
21+
let ptr = unsafe { &mut BB };
22+
for a in ptr.data.iter() {
23+
println!("{}", a);
24+
}
25+
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(const_let)]
2+
#![feature(const_fn)]
3+
4+
struct S {
5+
state: u32,
6+
}
7+
8+
impl S {
9+
const fn foo(&mut self, x: u32) {
10+
self.state = x;
11+
}
12+
}
13+
14+
const FOO: S = {
15+
let mut s = S { state: 42 };
16+
s.foo(3); //~ ERROR references in constants may only refer to immutable values
17+
s
18+
};
19+
20+
fn main() {
21+
assert_eq!(FOO.state, 3);
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0017]: references in constants may only refer to immutable values
2+
--> $DIR/const_let_assign3.rs:16:5
3+
|
4+
LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values
5+
| ^ constants require immutable values
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0017`.

0 commit comments

Comments
 (0)